量化交易软件:跨平台智能交易系统时间过滤器
概述
时间过滤仅在定义了特定时间段时方可使用, 智能交易系统必须检查给定时间是否在所述时间段内。当条件满足或不满足时, 可以启用或禁用某些功能。若智能交易系统的给定功能设置为非全时运作 (周期性地, 或在少数例外发生后全时运作) 这一功能是非常有用的。以下是可以应用时间过滤的一些示例:
规避某些时间段 (如, 横盘走势或高波动的时间段)
为市场订单或持仓设置 "到期" 时间 (在 "到期" 时离场)
交易周结束时平仓。
这些是交易者最常使用的功能, 当然还有其它变体。

目标
理解并应用最常用的时间过滤方法
允许智能交易系统轻松使用多个时间过滤器
与 MQL4 和 MQL5 兼容
基类
名为 CTime 的类将作为我们的智能交易系统中其它所要讨论的时间过滤器对象的基类。类 CTimeBase (其基于 CTime) 的定义显示在以下代码片段中:
class CTimeBase : public CObject { protected: bool m_active; bool m_reverse; CSymbolManager *m_symbol_man; CEventAggregator *m_event_man; CObject *m_container; public: CTimeBase(void); ~CTimeBase(void); virtual int Type(void) const {return CLASS_TYPE_TIME;} //--- 初始化 virtual bool Init(CSymbolManager*,CEventAggregator*); virtual CObject *GetContainer(void); virtual void SetContainer(CObject*); virtual bool Validate(void); //--- 赋值与取值 bool Active(void) const; void Active(const bool); bool Reverse(void); void Reverse(const bool); //--- 检查 virtual bool Evaluate(datetime)=0; };
基类有 3 个基元数据类型的成员。m_active 用于启用或禁用类对象。m_reverse 用于反转类对象的输出 (如果原本输出为 false 则返回 true, 如果原本输出为 true, 则返回 false)。m_time_start 用于引用创建的类实例, 无论是在 OnInit 中创建还是在执行智能交易系统之后创建。
时间过滤器类和类型
按特定日期范围进行时间过滤
这是最简单的时间过滤方法。要使用此方法检查时间, 只需要开始和结束日期, 如果时间设置处于这些日期之间, 则输出为 true。否则, 输出为 false。
此方法已实现为 CTimeRange。以下代码显示了 CTimeRangeBase 的定义, 而 CTimeRange 正是有基于此:
class CTimeRangeBase : public CTime { protected: datetime m_begin; datetime m_end; public: CTimeRangeBase(void); CTimeRangeBase(datetime,datetime); ~CTimeRangeBase(void); //--- 初始化 datetime,datetime virtual bool Set(datetime,datetime); virtual bool Validate(void); //--- 赋值与取值 datetime Begin(void) const; void Begin(const datetime); datetime End(void) const; void End(const datetime); //--- 处理 virtual bool Evaluate(datetime); };
在类构造函数中, 应指定开始和结束时间。在调用类方法 Evaluate 时设置的实际时间将会与这两个值进行比较。如果时间未设置或为零, 则该方法会使用调用时的当前时间:
bool CTimeRangeBase::Evaluate(datetime current=0) { if(!Active()) return true; if(current==0) current=TimeCurrent(); bool result=current>=m_begin && current<m_end; return Reverse()?!result:result; }
按周内所在日进行时间过滤
按周内所在日进行过滤是最简单且最常用的时间过滤方法之一。通常使用此时间过滤器针对智能交易系统的某些功能在周内的某些日子里进行限制或允许。
现在, 这个特定的类可按多种方式实现。一种方法是提供自定义的函数 TimeDayOfWeek, 该函数在 MQL4 中可用, 但不能用在 MQL5 中。另一种方法将所检查的时间转换为结构 MqlDateTime, 然后检查其 day_of_week 参数是否匹配预设值的标志。推荐选择后一种方法, 因为它可令赫兹量化将所有可用的类方法放在基类中。
此方法在赫兹量化的智能交易系统中体现为 CTimeDays。以下代码显示 CTimeDaysBase 的定义, 而 CTimeDays 正是有基于此:
class CTimeDaysBase : public CTime { protected: long m_day_flags; public: CTimeDaysBase(void); CTimeDaysBase(const bool sun=false,const bool mon=true,const bool tue=true,const bool wed=true, const bool thu=true,const bool fri=true,const bool sat=false); ~CTimeDaysBase(void); //--- 初始化 virtual bool Validate(void); virtual bool Evaluate(datetime); virtual void Set(const bool,const bool,const bool,const bool,const bool,const bool,const bool); //--- 赋值与取值 bool Sunday(void) const; void Sunday(const bool); bool Monday(void) const; void Monday(const bool); bool Tuesday(void) const; void Tuesday(const bool); bool Wednesday(void) const; void Wednesday(const bool); bool Thursday(void) const; void Thursday(const bool); bool Friday(void) const; void Friday(const bool); bool Saturday(void) const; void Saturday(const bool); };
如定义所示, 该类只有一个类型为 long 的类成员。这一类成员是设置所在日标志时使用的, 其值为评估时应返回 true 的所在日 (周内的 7 天)。这意味着我们将使用按位操作, 所以赫兹量化还必须声明一个自定义枚举, 其成员将代表 7 天中的每一天:
enum ENUM_TIME_DAY_FLAGS { TIME_DAY_FLAG_SUN=1<<0, TIME_DAY_FLAG_MON=1<<1, TIME_DAY_FLAG_TUE=1<<2, TIME_DAY_FLAG_WED=1<<3, TIME_DAY_FLAG_THU=1<<4, TIME_DAY_FLAG_FRI=1<<5, TIME_DAY_FLAG_SAT=1<<6 };
使用 Set 方法设置 (或清除) 周内所在日标志。为防止尚未设置标志的情况下意外调用类实例进行评估, 出于便利起见, 采用的措施是该方法在其类构造函数之一中被调用。