股票量化软件:赫兹量化中面向对象法建立多时间表及多货币面板
我来介绍一下此图的组成元素:
CTable。此面板的核心类。它负责绘制面板并管理其组件。
SpyAgent。 它是一个负责“监视”其它交易品种(工具)的指标。创建的每一个代理都会发往不同的交易品种。此代理会在有新订单号抵达交易品种图表时对 OnCalculate 事件做出反应,并发送 CHARTEVENT_CUSTOM 事件以通知 CTable 对象其须更新。此方法背后的整体理念基于 “赫兹量化 中多货币模式的实现"一文。您可以在此文中找到所有技术详情。
CRow。用于创建此面板的所有指标及条件的基类。通过扩展此类,即可能创建出此面板所有必需的组件。
CPriceRow。CRow 的一个简单扩展类,用于显示当前买价。
CPriceChangeRow。CRow 扩展类,用于显示当前柱的价格变化。它可以显示价格变化、百分比变化或箭头。
CRSIRow。CRow 扩展类,用于显示当前的 RSI 指标 值。
CPriceMARow。CRow 扩展类,显示某种自定义条件:SMA > 时价。
CTable、CRow 类以及 SpyAgent 指标都是此面板的核心组成部分。而 CPriceRow、CPriceChangeRow、CRSIRow 以及 CPriceMARow 则是此面板的实际内容。CRow 类的设计主旨,即在于由众多的新类扩展,从而实现想要的结果。所示的 4 个衍生类只是简单的例子,告诉大家能做些什么、怎样做。
2. SpyAgent
我们从 SpyAgent 指标开始。它仅于多货币模式下使用,而且如有新订单号抵达其它图表,必须用它才能妥善更新此面板。对此概念,我不想过多深入。“赫兹量化 中多货币模式的实现”一文中有所详述。
SpyAgent 指标于指定交易品种的图表上运行,并发送两个事件:初始化事件与新订单号事件。两个事件均属 CHARTEVENT_CUSTOM 类型。想要处理上述事件,我们必须使用 OnChartEvent(...) 处理程序(稍后呈现)。
我们来看看 SpyAgent 的代码:
//+------------------------------------------------------------------ //| SpyAgent.mq5 | //| Marcin Konieczny | //| | //+------------------------------------------------------------------ #property copyright "Marcin Konieczny" #property indicator_chart_window #property indicator_plots 0 input long chart_id=0; // 图表识别符 input ushort custom_event_id=0; // 事件识别符 //+------------------------------------------------------------------ //| 指标迭代函数 | //+------------------------------------------------------------------ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { if(prev_calculated==0) EventChartCustom(chart_id,0,0,0.0,_Symbol); // 发送初始事件 else EventChartCustom(chart_id,(ushort)(custom_event_id+1),0,0.0,_Symbol); // 发送新即时价格事件 return(rates_total); }
非常简单。它只做一件事,那就是接收新数据并发送CHARTEVENT_CUSTOM事件。
3. CTable
CTable 是此面板的核心类。它会存储面板设置的相关信息并管理其组件。必要时,它会更新(重绘)面板。
我们看看 CTable 的声明:
//+------------------------------------------------------------------ //| CTable 类 | //+------------------------------------------------------------------ class CTable { private: int xDistance; // 图表右边框的距离 int yDistance; // 图表顶边框的距离 int cellHeight; // 表格单元高度 int cellWidth; // 表格单元宽度 string font; // 字体名 int fontSize; color fontColor; CList *rowList; // 行对象列表 bool tfMode; // 是多时间帧模式吗? ENUM_TIMEFRAMES timeframes[]; // 多时间帧模式数组 string symbols[]; // 多货币对模式数组 //--- 私有方法 //--- 设置表格默认参数 void Init(); //--- 在指定表格单元内画文本标签 void DrawLabel(int x,int y,string text,string font,color col); //--- 返回给定的时间帧的文字表述 string PeriodToString(ENUM_TIMEFRAMES period); public: //--- 多时间帧模式构造函数 CTable(ENUM_TIMEFRAMES &tfs[]); //--- 多货币对模式构造函数 CTable(string &symb[]); //--- 析构函数 ~CTable(); //--- 重画表格 void Update(); //--- 设置表格参数函数 void SetDistance(int xDist,int yDist); void SetCellSize(int cellW,int cellH); void SetFont(string fnt,int size,color clr); //--- 附加CRow对象至表格 void AddRow(CRow *row); };
正如您所见,所有的面板组件(行)均存储为一个 CRow 指针列表,因此,我们要向面板添加的每个组件,都必须扩展 CRow 类。CRow 可被视为此面板与其组件之间的一个协议。CTable 并不包含供其单元格计算的任何代码。那是 CRow 扩展类的责任。CTable 只是保留 CRow 组件并于必要时重绘它们的一种结构。
我们从头到尾看一看 CTable 的方法。此类拥有两个构造函数。第一个用于多时间表模式且非常简单。我们只需要提供一个想要显示的时间表数组。
//+------------------------------------------------------------------ //| 多时间帧模式构造函数 | //+------------------------------------------------------------------ CTable::CTable(ENUM_TIMEFRAMES &tfs[]) { //--- 复制所有时间帧至数组 ArrayResize(timeframes,ArraySize(tfs),0); ArrayCopy(timeframes,tfs); tfMode=true; //--- 用当前图表交易品种填充数组 ArrayResize(symbols,ArraySize(tfs),0); for(int i=0; i<ArraySize(tfs); i++) symbols[i]=Symbol(); //--- 设置默认参数 Init(); }
第二个构造函数用于多货币模式,并接受交易品种(工具)数组。此构造函数亦发送 SpyAgents。它会将 SpyAgents 一个一个地附至适当的图表。
//+------------------------------------------------------------------ //| 对货币对模式构造函数 | //+------------------------------------------------------------------ CTable::CTable(string &symb[]) { //--- 复制所有交易品种至自己的数组 ArrayResize(symbols,ArraySize(symb),0); ArrayCopy(symbols,symb); tfMode=false; //--- 用当前时间帧填充数组 ArrayResize(timeframes,ArraySize(symb),0); ArrayInitialize(timeframes,Period()); //--- 设置默认参数 Init(); //--- 发送 SpyAgents 至每个请求交易品种 for(int x=0; x<ArraySize(symbols); x++) if(symbols[x]!=Symbol()) // 不要发送 SpyAgent 至自己的图表 if(iCustom(symbols[x],0,"SpyAgent",ChartID(),0)==INVALID_HANDLE) { Print("设置 SpyAgent 错误于 "+symbols[x]); return; } }
Init 方法会创建行列表(作为一个 CList 对象 - CList 是一种 CObject 类型的动态列表)并设置 CTable 内部变量(字体、字号、颜色、单元格尺寸以及与图表右上角的距离)的默认值。