内容目录
- 概述
- 改进库类
- 指标对象类
- 指标对象集合
- 测试
- 下一步是什么?
概述
在上一篇文章中,曾研究过基准抽象指标对象的创建。 今天,将依据指定的特定指标对象的信息创建其衍生对象。 将所有这些对象放置到指标集合中,可从中获取每个所创建指标的数据和属性。
衍生对象的概念与函数库中对象构造及其互连的概念完全对应。 其中,指标集合能够快速为所有指标对象添加事件功能。 这允许为指标轻松设置需跟踪的事件,并在我们的程序中使用这些事件。
改进库类
如往常一样,从往函数库里添加必要文本消息开始。
在文件 \MQL5\Include\DoEasy\Data.mqh 里加入新的消息索引:
//--- CIndicatorDE MSG_LIB_TEXT_IND_TEXT_STATUS, // Indicator status MSG_LIB_TEXT_IND_TEXT_STATUS_STANDART, // Standard indicator MSG_LIB_TEXT_IND_TEXT_STATUS_CUSTOM, // Custom indicator MSG_LIB_TEXT_IND_TEXT_TYPE, // Indicator type MSG_LIB_TEXT_IND_TEXT_TIMEFRAME, // Indicator timeframe MSG_LIB_TEXT_IND_TEXT_HANDLE, // Indicator handle MSG_LIB_TEXT_IND_TEXT_GROUP, // Indicator group MSG_LIB_TEXT_IND_TEXT_GROUP_TREND, // Trend indicator MSG_LIB_TEXT_IND_TEXT_GROUP_OSCILLATOR, // Oscillator MSG_LIB_TEXT_IND_TEXT_GROUP_VOLUMES, // Volumes MSG_LIB_TEXT_IND_TEXT_GROUP_ARROWS, // Arrow indicator MSG_LIB_TEXT_IND_TEXT_EMPTY_VALUE, // Empty value for plotting where nothing will be drawn MSG_LIB_TEXT_IND_TEXT_SYMBOL, // Indicator symbol MSG_LIB_TEXT_IND_TEXT_NAME, // Indicator name MSG_LIB_TEXT_IND_TEXT_SHORTNAME, // Indicator short name //--- CIndicatorsCollection MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST, // Error. Failed to add indicator object to list }; //+------------------------------------------------------------------+
接下来,添加新消息与新添加的索引相对应:
{"Indicator status"}, {"Standard indicator"}, {"Custom indicator"}, {"Indicator type"}, {"Indicator timeframe"}, {"Indicator handle"}, {"Indicator group"}, {"Trend indicator"}, {"Solid lineOscillator"}, {"Volumes"}, {"Arrow indicator"}, {,"Empty value for plotting, for which there is no drawing"}, {"Indicator symbol"}, {"Indicator name"}, {"Indicator shortname"}, {"Error. Failed to add indicator object to list"}, }; //+---------------------------------------------------------------------+
在上一篇文章中,于创建抽象指标对象类期间,我们没有添加一个对象的整数型属性 - 标准指标类型。 此类型将对应于枚举类型 ENUM_INDICATOR ,且搜索特定指标时会需要它。
如果我们要在集合中查找存储的所有 MACD 指标,我们首先要获取集合内所有 MACD 指标的列表。 为此,我们必须针对指标集合的完整列表按 IND_MACD 类型进行排序。 然后,在仅包含 IND_MACD 的结果列表中,依据其他目标属性进行选择。
把新的指标对象属性加入文件 \MQL5\Include\DoEasy\Defines.mqh:
//+------------------------------------------------------------------+ //| Indicator integer properties | //+------------------------------------------------------------------+ enum ENUM_INDICATOR_PROP_INTEGER { INDICATOR_PROP_STATUS = 0, // Indicator status (from enumeration ENUM_INDICATOR_STATUS) INDICATOR_PROP_TYPE, // Indicator type (from enumeration ENUM_INDICATOR) INDICATOR_PROP_TIMEFRAME, // Indicator timeframe INDICATOR_PROP_HANDLE, // Indicator handle INDICATOR_PROP_GROUP, // Indicator group }; #define INDICATOR_PROP_INTEGER_TOTAL (5) // Total number of indicator integer properties #define INDICATOR_PROP_INTEGER_SKIP (0) // Number of indicator properties not used in sorting //+------------------------------------------------------------------+
并增加整数型属性的总数从 4 到 5。
为对象添加新属性时,必须设置按该属性搜索和排序对象的功能。
在枚举里添加新的排序标准:
//+------------------------------------------------------------------+ //| Possible indicator sorting criteria | //+------------------------------------------------------------------+ #define FIRST_INDICATOR_DBL_PROP (INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP) #define FIRST_INDICATOR_STR_PROP (INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP+INDICATOR_PROP_DOUBLE_TOTAL-INDICATOR_PROP_DOUBLE_SKIP) enum ENUM_SORT_INDICATOR_MODE { //--- Sort by integer properties SORT_BY_INDICATOR_INDEX_STATUS = 0, // Sort by indicator status SORT_BY_INDICATOR_TYPE, // Sort by indicator type SORT_BY_INDICATOR_TIMEFRAME, // Sort by indicator timeframe SORT_BY_INDICATOR_HANDLE, // Sort by indicator handle SORT_BY_INDICATOR_GROUP, // Sort by indicator group //--- Sort by real properties SORT_BY_INDICATOR_EMPTY_VALUE = FIRST_INDICATOR_DBL_PROP,// Sort by the empty value for plotting where nothing will be drawn //--- Sort by string properties SORT_BY_INDICATOR_SYMBOL = FIRST_INDICATOR_STR_PROP, // Sort by indicator symbol SORT_BY_INDICATOR_NAME, // Sort by indicator name SORT_BY_INDICATOR_SHORTNAME, // Sort by indicator short name }; //+------------------------------------------------------------------+
略微改善了抽象指标对象类 \MQL5\Include\DoEasy\Objects\Indicators\IndicatorDE.mqh。
将指标参数结构数组从类的私密部分移至受保护部分(此数组现在已可用于衍生类),并在私密部分中声明一个存储指标类型描述的变量:
//+------------------------------------------------------------------+ //| Abstract indicator class | //+------------------------------------------------------------------+ class CIndicatorDE : public CBaseObj { protected: MqlParam m_mql_param[]; // Array of indicator parameters private: long m_long_prop[INDICATOR_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[INDICATOR_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[INDICATOR_PROP_STRING_TOTAL]; // String properties string m_ind_type; // Indicator type description
在类的公开部分中,添加两个方法 — 返回指标类型和返回指标类型描述:
public: //--- Default constructor CIndicatorDE(void){;} //--- Destructor ~CIndicatorDE(void); //--- Set buffer's (1) integer, (2) real and (3) string property void SetProperty(ENUM_INDICATOR_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_INDICATOR_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_INDICATOR_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return (1) integer, (2) real and (3) string buffer property from the properties array long GetProperty(ENUM_INDICATOR_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_INDICATOR_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_INDICATOR_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Return description of buffer's (1) integer, (2) real and (3) string property string GetPropertyDescription(ENUM_INDICATOR_PROP_INTEGER property); string GetPropertyDescription(ENUM_INDICATOR_PROP_DOUBLE property); string GetPropertyDescription(ENUM_INDICATOR_PROP_STRING property); //--- Return the flag of the buffer supporting the property virtual bool SupportProperty(ENUM_INDICATOR_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_INDICATOR_PROP_STRING property) { return true; } //--- Compare CIndicatorDE objects by all possible properties (for sorting the lists by a specified indicator object property) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CIndicatorDE objects by all properties (to search for equal indicator objects) bool IsEqual(CIndicatorDE* compared_obj) const; //--- Set indicator’s (1) group, (2) empty value of buffers, (3) name, (4) short name void SetGroup(const ENUM_INDICATOR_GROUP group) { this.SetProperty(INDICATOR_PROP_GROUP,group); } void SetEmptyValue(const double value) { this.SetProperty(INDICATOR_PROP_EMPTY_VALUE,value); } void SetName(const string name) { this.SetProperty(INDICATOR_PROP_NAME,name); } void SetShortName(const string shortname) { this.SetProperty(INDICATOR_PROP_SHORTNAME,shortname); } //--- Return indicator’s (1) status, (2) group, (3) timeframe, (4) handle, (5) empty value of buffers, (6) name, (7) short name, (8) symbol, (9) type ENUM_INDICATOR_STATUS Status(void) const { return (ENUM_INDICATOR_STATUS)this.GetProperty(INDICATOR_PROP_STATUS);} ENUM_INDICATOR_GROUP Group(void) const { return (ENUM_INDICATOR_GROUP)this.GetProperty(INDICATOR_PROP_GROUP); } ENUM_TIMEFRAMES Timeframe(void) const { return (ENUM_TIMEFRAMES)this.GetProperty(INDICATOR_PROP_TIMEFRAME); } ENUM_INDICATOR TypeIndicator(void) const { return (ENUM_INDICATOR)this.GetProperty(INDICATOR_PROP_TYPE); } int Handle(void) const { return (int)this.GetProperty(INDICATOR_PROP_HANDLE); } double EmptyValue(void) const { return this.GetProperty(INDICATOR_PROP_EMPTY_VALUE); } string Name(void) const { return this.GetProperty(INDICATOR_PROP_NAME); } string ShortName(void) const { return this.GetProperty(INDICATOR_PROP_SHORTNAME); } string Symbol(void) const { return this.GetProperty(INDICATOR_PROP_SYMBOL); } //--- Return description of indicator’s (1) type, (2) status, (3) group, (4) timeframe, (5) empty value string GetTypeDescription(void) const { return m_ind_type; } string GetStatusDescription(void) const; string GetGroupDescription(void) const; string GetTimeframeDescription(void) const; string GetEmptyValueDescription(void) const; //--- Display the description of indicator object properties in the journal (full_prop=true - all properties, false - supported ones only) void Print(const bool full_prop=false); //--- Display a short description of indicator object in the journal (implementation in the descendants) virtual void PrintShort(void) {;} }; //+------------------------------------------------------------------+
在封闭的参数型构造函数中,从指标类型输入提取子串以便仅保留指标名称(例如,仅 MACD 保留在 IND_MACD 中,其将作为指标类型描述),并在对象属性中写入指标类型:
//+------------------------------------------------------------------+ //| Closed parametric constructor | //+------------------------------------------------------------------+ CIndicatorDE::CIndicatorDE(ENUM_INDICATOR ind_type, string symbol, ENUM_TIMEFRAMES timeframe, ENUM_INDICATOR_STATUS status, ENUM_INDICATOR_GROUP group, string name, string shortname, MqlParam &mql_params[]) { //--- Set collection ID to the object this.m_type=COLLECTION_INDICATORS_ID; //--- Write description of indicator type this.m_ind_type=::StringSubstr(::EnumToString(ind_type),4); //--- If parameter array size passed to constructor is more than zero //--- fill in the array of object parameters with data from the array passed to constructor int count=::ArrayResize(m_mql_param,::ArraySize(mql_params)); for(int i=0;i<count;i++) { this.m_mql_param[i].type=mql_params[i].type; this.m_mql_param[i].double_value=mql_params[i].double_value; this.m_mql_param[i].integer_value=mql_params[i].integer_value; this.m_mql_param[i].string_value=mql_params[i].string_value; } //--- Create indicator handle int handle=::IndicatorCreate(symbol,timeframe,ind_type,count,this.m_mql_param); //--- Save integer properties this.m_long_prop[INDICATOR_PROP_STATUS] = status; this.m_long_prop[INDICATOR_PROP_TYPE] = ind_type; this.m_long_prop[INDICATOR_PROP_GROUP] = group; this.m_long_prop[INDICATOR_PROP_TIMEFRAME] = timeframe; this.m_long_prop[INDICATOR_PROP_HANDLE] = handle; //--- Save real properties this.m_double_prop[this.IndexProp(INDICATOR_PROP_EMPTY_VALUE)]=EMPTY_VALUE; //--- Save string properties this.m_string_prop[this.IndexProp(INDICATOR_PROP_SYMBOL)] = (symbol==NULL || symbol=="" ? ::Symbol() : symbol); this.m_string_prop[this.IndexProp(INDICATOR_PROP_NAME)] = name; this.m_string_prop[this.IndexProp(INDICATOR_PROP_SHORTNAME)]= shortname; } //+------------------------------------------------------------------+
在返回指标整数属性的方法描述里,添加返回指标类型描述的代码模块:
//+------------------------------------------------------------------+ //| Return description of indicator's integer property | //+------------------------------------------------------------------+ string CIndicatorDE::GetPropertyDescription(ENUM_INDICATOR_PROP_INTEGER property) { return ( property==INDICATOR_PROP_STATUS ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_STATUS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.GetStatusDescription() ) : property==INDICATOR_PROP_TYPE ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TYPE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.GetTypeDescription() ) : property==INDICATOR_PROP_GROUP ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_GROUP)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.GetGroupDescription() ) : property==INDICATOR_PROP_TIMEFRAME ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TIMEFRAME)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.GetTimeframeDescription() ) : property==INDICATOR_PROP_HANDLE ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_HANDLE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : "" ); } //+------------------------------------------------------------------+
指标对象类
现在,创建基准抽象指标的衍生对象,该对象将指定有关所创建指标对象的所有信息。 且这些类将用于创建不同类型的指标,并从中获取数据。
在目录 \MQL5\Include\DoEasy\Objects\Indicators\ 里创建一个新的文件夹 Standart,并在其中创建一个新文件 IndAC.mqh,其中包含加速振荡器标准指标的 CIndAC 类,它继承自抽象指标基类,该文件与这个类的列表连接。
由于该类并不太大,因此我们来分析其完整清单:
//+------------------------------------------------------------------+ //| IndAC.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\\IndicatorDE.mqh" //+------------------------------------------------------------------+ //| Standard indicator Accelerator Oscillator | //+------------------------------------------------------------------+ class CIndAC : public CIndicatorDE { private: public: //--- Constructor CIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : CIndicatorDE(IND_AC,symbol,timeframe, INDICATOR_STATUS_STANDART, INDICATOR_GROUP_OSCILLATOR, "Accelerator Oscillator", "AC("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {} //--- Supported indicator properties (1) real, (2) integer virtual bool SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property); //--- Display a short description of indicator object in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+ //| Return 'true' if indicator supports a passed | //| integer property, otherwise return 'false' | //+------------------------------------------------------------------+ bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_INTEGER property) { return true; } //+------------------------------------------------------------------+ //| Return 'true' if indicator supports a passed | //| real property, otherwise return 'false' | //+------------------------------------------------------------------+ bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property) { return true; } //+------------------------------------------------------------------+ //--- Display a short description of indicator object in the journal | //+------------------------------------------------------------------+ void CIndAC::PrintShort(void) { ::Print(GetStatusDescription()," ",this.Name()," ",this.Symbol()," ",TimeframeDescription(this.Timeframe())); } //+------------------------------------------------------------------+
总共,我们必须制作 38 个这样的类 - 根据标准指标的数量来(我尚未创建自定义指标,因为其实现会略有不同)。
所有这些类均拥有相同的方法,它们的区别仅在于从其构造函数传递给父类的参数有所不同:
//--- Constructor CIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : CIndicatorDE(IND_AC,symbol,timeframe, INDICATOR_STATUS_STANDART, INDICATOR_GROUP_OSCILLATOR, "Accelerator Oscillator", "AC("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}
在类的输入中,我传递品种名称、时间帧、及已填充指标参数的结构(在此示例中为加速振荡器)。
在初始化清单中传递给父类的封闭参数型构造函数(按顺序):
- 指标类型 — IND_AC, 品种名称,时间帧
- 指标状态 - 标准
- 指标分组 - 振荡器
- 指标名称 - 加速振荡器
- 指标简称 - AC (品种, 时间帧) 和已填充的指标参数结构
我们已知以前创建的函数库对象其余的所有方法,且它们执行相同的任务。
方法返回对象所支持整数型和实数型属性的标志,若返回 true — 指标对象支持所有属性。
返回指标简述的方法返回以下字符串类型:
Standard indicator Accelerator Oscillator EURUSD H4
在与指标对象类相似的所有其余文件中,区别仅在于类构造函数当中 - 将与指标对应的参数传递给父类的构造函数。
例如,对于指标建仓/派发,类构造函数将如下所示:
//--- Constructor CIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : CIndicatorDE(IND_AD,symbol,timeframe, INDICATOR_STATUS_STANDART, INDICATOR_GROUP_VOLUMES, "Accumulation/Distribution", "AD("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}
如我们所见,此处传递的参数与标准指标 AD 相对应:
- 指标类型 — IND_AD, 品种名称, 时间帧
- 指标状态 - 标准
- 指标分组 -交易量
- 指标名称 - Accumulation/Distribution
- 指标简称 - AC (品种, 时间帧) 和已填充的指标参数结构
抽象指标基类衍生类的所有文件都已实现,可在文章附件中的 \MQL5\Include\DoEasy\Objects\Indicators\Standart 文件夹中查看它们。
指标对象集合
按照现在的函数库对象构建和存储的一般概念,我们必须将所有创建的指标对象放入集合列表之中。 从此列表中,我们总能按指定属性获得指向所需指标的指针,或含有相同属性的指标列表。 依据得到的指标指针,我们将能够获取指标返回的所有数据,以便进一步的计算。
在文件夹 \MQL5\Include\DoEasy\Collections\ 下,名为 IndicatorsCollection.mqh 的文件里创建一个新类。
除了从集合中返回所需对象列表的函数库标准方法之外,该类还包含一个创建指标对象的私密方法,和多个根据其类型创建特定指标对象的方法;以及多个依据类型获取指向已创建指标对象指针的方法。 每个分组的所有方法据其逻辑都彼此相同,因此,仅取其中一些作为示例。
如此,指标的集合类即可访问我们在上面创建的指标类,它们必须被连接到文件清单:
//+------------------------------------------------------------------+ //| IndicatorsCollection.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "ListObj.mqh" #include "..\Objects\Indicators\Standart\IndAC.mqh" #include "..\Objects\Indicators\Standart\IndAD.mqh" #include "..\Objects\Indicators\Standart\IndADX.mqh" #include "..\Objects\Indicators\Standart\IndADXW.mqh" #include "..\Objects\Indicators\Standart\IndAlligator.mqh" #include "..\Objects\Indicators\Standart\IndAMA.mqh" #include "..\Objects\Indicators\Standart\IndAO.mqh" #include "..\Objects\Indicators\Standart\IndATR.mqh" #include "..\Objects\Indicators\Standart\IndBands.mqh" #include "..\Objects\Indicators\Standart\IndBears.mqh" #include "..\Objects\Indicators\Standart\IndBulls.mqh" #include "..\Objects\Indicators\Standart\IndBWMFI.mqh" #include "..\Objects\Indicators\Standart\IndCCI.mqh" #include "..\Objects\Indicators\Standart\IndChaikin.mqh" #include "..\Objects\Indicators\Standart\IndDEMA.mqh" #include "..\Objects\Indicators\Standart\IndDeMarker.mqh" #include "..\Objects\Indicators\Standart\IndEnvelopes.mqh" #include "..\Objects\Indicators\Standart\IndForce.mqh" #include "..\Objects\Indicators\Standart\IndFractals.mqh" #include "..\Objects\Indicators\Standart\IndFRAMA.mqh" #include "..\Objects\Indicators\Standart\IndGator.mqh" #include "..\Objects\Indicators\Standart\IndIchimoku.mqh" #include "..\Objects\Indicators\Standart\IndMA.mqh" #include "..\Objects\Indicators\Standart\IndMACD.mqh" #include "..\Objects\Indicators\Standart\IndMFI.mqh" #include "..\Objects\Indicators\Standart\IndMomentum.mqh" #include "..\Objects\Indicators\Standart\IndOBV.mqh" #include "..\Objects\Indicators\Standart\IndOsMA.mqh" #include "..\Objects\Indicators\Standart\IndRSI.mqh" #include "..\Objects\Indicators\Standart\IndRVI.mqh" #include "..\Objects\Indicators\Standart\IndSAR.mqh" #include "..\Objects\Indicators\Standart\IndStDev.mqh" #include "..\Objects\Indicators\Standart\IndStoch.mqh" #include "..\Objects\Indicators\Standart\IndTEMA.mqh" #include "..\Objects\Indicators\Standart\IndTRIX.mqh" #include "..\Objects\Indicators\Standart\IndVIDYA.mqh" #include "..\Objects\Indicators\Standart\IndVolumes.mqh" #include "..\Objects\Indicators\Standart\IndWPR.mqh" //+------------------------------------------------------------------+
进而,查看类主体的完整清单,然后分析每个分组的两个方法。
//+------------------------------------------------------------------+ //| Indicator collection | //+------------------------------------------------------------------+ class CIndicatorsCollection : public CObject { private: CListObj m_list; // Indicator object list MqlParam m_mql_param[]; // Array of indicator parameters //--- Create a new indicator object CIndicatorDE *CreateIndicator(const ENUM_INDICATOR ind_type,MqlParam &mql_param[],const string symbol_name=NULL,const ENUM_TIMEFRAMES period=PERIOD_CURRENT); public: //--- Return (1) itself, (2) indicator list, (3) list of indicators by type CIndicatorsCollection *GetObject(void) { return &this; } CArrayObj *GetList(void) { return &this.m_list; } //--- Return indicator list by (1) status, (2) type, (3) timeframe, (4) group, (5) symbol, (6) name, (7) short name CArrayObj *GetListIndByStatus(const ENUM_INDICATOR_STATUS status) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_STATUS,status,EQUAL); } CArrayObj *GetListIndByType(const ENUM_INDICATOR type) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TYPE,type,EQUAL); } CArrayObj *GetListIndByTimeframe(const ENUM_TIMEFRAMES timeframe) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL); } CArrayObj *GetListIndByGroup(const ENUM_INDICATOR_GROUP group) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_GROUP,group,EQUAL); } CArrayObj *GetListIndBySymbol(const string symbol) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SYMBOL,symbol,EQUAL); } CArrayObj *GetListIndByName(const string name) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_NAME,name,EQUAL); } CArrayObj *GetListIndByShortname(const string shortname) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SHORTNAME,shortname,EQUAL); } //--- Return the list of indicator objects by type of indicator, symbol and timeframe CArrayObj *GetListAC(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListAD(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListADX(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListAMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListAO(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListATR(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListBands(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListCCI(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListForce(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListFractals(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListGator(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListMFI(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListMACD(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListOBV(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListSAR(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListRSI(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListRVI(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListTriX(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListWPR(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe); CArrayObj *GetListVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe); //--- Return the pointer to indicator object in the collection by indicator type and by its parameters CIndicatorDE *GetIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe); CIndicatorDE *GetIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndADX(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period); CIndicatorDE *GetIndADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period); CIndicatorDE *GetIndAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe, const int jaw_period, const int jaw_shift, const int teeth_period, const int teeth_shift, const int lips_period, const int lips_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndAMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ama_period, const int fast_ema_period, const int slow_ema_period, const int ama_shift, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndAO(const string symbol,const ENUM_TIMEFRAMES timeframe); CIndicatorDE *GetIndATR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); CIndicatorDE *GetIndBands(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const double deviation, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); CIndicatorDE *GetIndBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); CIndicatorDE *GetIndChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ma_period, const int slow_ma_period, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndCCI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); CIndicatorDE *GetIndEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price, const double deviation); CIndicatorDE *GetIndForce(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndFractals(const string symbol,const ENUM_TIMEFRAMES timeframe); CIndicatorDE *GetIndFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndGator(const string symbol,const ENUM_TIMEFRAMES timeframe, const int jaw_period, const int jaw_shift, const int teeth_period, const int teeth_shift, const int lips_period, const int lips_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe, const int tenkan_sen, const int kijun_sen, const int senkou_span_b); CIndicatorDE *GetIndBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe, const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe, const int mom_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndMFI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ema_period, const int slow_ema_period, const int signal_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndMACD(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ema_period, const int slow_ema_period, const int signal_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndOBV(const string symbol,const ENUM_TIMEFRAMES timeframe, const ENUM_APPLIED_VOLUME applied_volume); CIndicatorDE *GetIndSAR(const string symbol,const ENUM_TIMEFRAMES timeframe, const double step, const double maximum); CIndicatorDE *GetIndRSI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndRVI(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); CIndicatorDE *GetIndStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe, const int Kperiod, const int Dperiod, const int slowing, const ENUM_MA_METHOD ma_method, const ENUM_STO_PRICE price_field); CIndicatorDE *GetIndTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndTriX(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndWPR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int calc_period); CIndicatorDE *GetIndVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int cmo_period, const int ema_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); CIndicatorDE *GetIndVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume); //--- Create a new indicator object by indicator type and places it to collection list int CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe); int CreateAD(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume); int CreateADX(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period); int CreateADXWilder(const string symbol,const ENUM_TIMEFRAMES timeframe,const int adx_period); int CreateAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe, const int jaw_period, const int jaw_shift, const int teeth_period, const int teeth_shift, const int lips_period, const int lips_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); int CreateAMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ama_period, const int fast_ema_period, const int slow_ema_period, const int ama_shift, const ENUM_APPLIED_PRICE applied_price); int CreateAO(const string symbol,const ENUM_TIMEFRAMES timeframe); int CreateATR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); int CreateBands(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const double deviation, const ENUM_APPLIED_PRICE applied_price); int CreateBearsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); int CreateBullsPower(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); int CreateChaikin(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ma_period, const int slow_ma_period, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_VOLUME applied_volume); int CreateCCI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); int CreateDEMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); int CreateDeMarker(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); int CreateEnvelopes(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price, const double deviation); int CreateForce(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_VOLUME applied_volume); int CreateFractals(const string symbol,const ENUM_TIMEFRAMES timeframe); int CreateFrAMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); int CreateGator(const string symbol,const ENUM_TIMEFRAMES timeframe, const int jaw_period, const int jaw_shift, const int teeth_period, const int teeth_shift, const int lips_period, const int lips_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); int CreateIchimoku(const string symbol,const ENUM_TIMEFRAMES timeframe, const int tenkan_sen, const int kijun_sen, const int senkou_span_b); int CreateBWMFI(const string symbol,const ENUM_TIMEFRAMES timeframe, const ENUM_APPLIED_VOLUME applied_volume); int CreateMomentum(const string symbol,const ENUM_TIMEFRAMES timeframe, const int mom_period, const ENUM_APPLIED_PRICE applied_price); int CreateMFI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_VOLUME applied_volume); int CreateMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); int CreateOsMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ema_period, const int slow_ema_period, const int signal_period, const ENUM_APPLIED_PRICE applied_price); int CreateMACD(const string symbol,const ENUM_TIMEFRAMES timeframe, const int fast_ema_period, const int slow_ema_period, const int signal_period, const ENUM_APPLIED_PRICE applied_price); int CreateOBV(const string symbol,const ENUM_TIMEFRAMES timeframe, const ENUM_APPLIED_VOLUME applied_volume); int CreateSAR(const string symbol,const ENUM_TIMEFRAMES timeframe, const double step, const double maximum); int CreateRSI(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); int CreateRVI(const string symbol,const ENUM_TIMEFRAMES timeframe,const int ma_period); int CreateStdDev(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price); int CreateStochastic(const string symbol,const ENUM_TIMEFRAMES timeframe, const int Kperiod, const int Dperiod, const int slowing, const ENUM_MA_METHOD ma_method, const ENUM_STO_PRICE price_field); int CreateTEMA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); int CreateTriX(const string symbol,const ENUM_TIMEFRAMES timeframe, const int ma_period, const ENUM_APPLIED_PRICE applied_price); int CreateWPR(const string symbol,const ENUM_TIMEFRAMES timeframe,const int calc_period); int CreateVIDYA(const string symbol,const ENUM_TIMEFRAMES timeframe, const int cmo_period, const int ema_period, const int ma_shift, const ENUM_APPLIED_PRICE applied_price); int CreateVolumes(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume); //--- Constructor CIndicatorsCollection(); }; //+------------------------------------------------------------------+
清单似乎令人印象深刻,但实际上,我们这里只有几组相似类型的方法,它们之间的区别在于所需指标的类型。
返回所需指标类型列表的方法已成为函数库的标准方法,我们已反复对其进行了分析:
//--- Return (1) itself, (2) indicator list, (3) list of indicators by type CIndicatorsCollection *GetObject(void) { return &this; } CArrayObj *GetList(void) { return &this.m_list; } //--- Return indicator list by (1) status, (2) type, (3) timeframe, (4) group, (5) symbol, (6) name, (7) short name CArrayObj *GetListIndByStatus(const ENUM_INDICATOR_STATUS status) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_STATUS,status,EQUAL); } CArrayObj *GetListIndByType(const ENUM_INDICATOR type) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TYPE,type,EQUAL); } CArrayObj *GetListIndByTimeframe(const ENUM_TIMEFRAMES timeframe) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL); } CArrayObj *GetListIndByGroup(const ENUM_INDICATOR_GROUP group) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_GROUP,group,EQUAL); } CArrayObj *GetListIndBySymbol(const string symbol) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SYMBOL,symbol,EQUAL); } CArrayObj *GetListIndByName(const string name) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_NAME,name,EQUAL); } CArrayObj *GetListIndByShortname(const string shortname) { return CSelect::ByIndicatorProperty(this.GetList(),INDICATOR_PROP_SHORTNAME,shortname,EQUAL); }
在类的构造函数中重置指标参数结构数组,清除集合列表,为列表设置排序列表标志,并分配指标集合的 ID:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CIndicatorsCollection::CIndicatorsCollection() { ::ArrayResize(this.m_mql_param,0); this.m_list.Clear(); this.m_list.Sort(); this.m_list.Type(COLLECTION_INDICATORS_ID); } //+------------------------------------------------------------------+
创建指标对象的私有方法简单地依据传递给该方法的指标类型来创建新的指标对象,然后将指针返回给创建的对象:
//+------------------------------------------------------------------+ //| Create a new indicator object | //+------------------------------------------------------------------+ CIndicatorDE *CIndicatorsCollection::CreateIndicator(const ENUM_INDICATOR ind_type,MqlParam &mql_param[],const string symbol_name=NULL,const ENUM_TIMEFRAMES period=PERIOD_CURRENT) { string symbol=(symbol_name==NULL || symbol_name=="" ? ::Symbol() : symbol_name); ENUM_TIMEFRAMES timeframe=(period==PERIOD_CURRENT ? ::Period() : period); CIndicatorDE *indicator=NULL; switch(ind_type) { case IND_AC : indicator=new CIndAC(symbol,timeframe,mql_param); break; case IND_AD : indicator=new CIndAD(symbol,timeframe,mql_param); break; case IND_ADX : indicator=new CIndADX(symbol,timeframe,mql_param); break; case IND_ADXW : indicator=new CIndADXW(symbol,timeframe,mql_param); break; case IND_ALLIGATOR : indicator=new CIndAlligator(symbol,timeframe,mql_param); break; case IND_AMA : indicator=new CIndAMA(symbol,timeframe,mql_param); break; case IND_AO : indicator=new CIndAO(symbol,timeframe,mql_param); break; case IND_ATR : indicator=new CIndATR(symbol,timeframe,mql_param); break; case IND_BANDS : indicator=new CIndBands(symbol,timeframe,mql_param); break; case IND_BEARS : indicator=new CIndBears(symbol,timeframe,mql_param); break; case IND_BULLS : indicator=new CIndBulls(symbol,timeframe,mql_param); break; case IND_BWMFI : indicator=new CIndBWMFI(symbol,timeframe,mql_param); break; case IND_CCI : indicator=new CIndCCI(symbol,timeframe,mql_param); break; case IND_CHAIKIN : indicator=new CIndCHO(symbol,timeframe,mql_param); break; case IND_DEMA : indicator=new CIndDEMA(symbol,timeframe,mql_param); break; case IND_DEMARKER : indicator=new CIndDeMarker(symbol,timeframe,mql_param); break; case IND_ENVELOPES : indicator=new CIndEnvelopes(symbol,timeframe,mql_param); break; case IND_FORCE : indicator=new CIndForce(symbol,timeframe,mql_param); break; case IND_FRACTALS : indicator=new CIndFractals(symbol,timeframe,mql_param); break; case IND_FRAMA : indicator=new CIndFRAMA(symbol,timeframe,mql_param); break; case IND_GATOR : indicator=new CIndGator(symbol,timeframe,mql_param); break; case IND_ICHIMOKU : indicator=new CIndIchimoku(symbol,timeframe,mql_param); break; case IND_MA : indicator=new CIndMA(symbol,timeframe,mql_param); break; case IND_MACD : indicator=new CIndMACD(symbol,timeframe,mql_param); break; case IND_MFI : indicator=new CIndMFI(symbol,timeframe,mql_param); break; case IND_MOMENTUM : indicator=new CIndMomentum(symbol,timeframe,mql_param); break; case IND_OBV : indicator=new CIndOBV(symbol,timeframe,mql_param); break; case IND_OSMA : indicator=new CIndOsMA(symbol,timeframe,mql_param); break; case IND_RSI : indicator=new CIndRSI(symbol,timeframe,mql_param); break; case IND_RVI : indicator=new CIndRVI(symbol,timeframe,mql_param); break; case IND_SAR : indicator=new CIndSAR(symbol,timeframe,mql_param); break; case IND_STDDEV : indicator=new CIndStDev(symbol,timeframe,mql_param); break; case IND_STOCHASTIC : indicator=new CIndStoch(symbol,timeframe,mql_param); break; case IND_TEMA : indicator=new CIndTEMA(symbol,timeframe,mql_param); break; case IND_TRIX : indicator=new CIndTRIX(symbol,timeframe,mql_param); break; case IND_VIDYA : indicator=new CIndVIDYA(symbol,timeframe,mql_param); break; case IND_VOLUMES : indicator=new CIndVolumes(symbol,timeframe,mql_param); break; case IND_WPR : indicator=new CIndWPR(symbol,timeframe,mql_param); break; case IND_CUSTOM : break; default: break; } return indicator; } //+------------------------------------------------------------------+
默认情况下,即使是暂时的,且对于自定义指标(其创建将在以下文章中实现),该方法返回 NULL。
创建加速振荡器指标对象的方法:
//+------------------------------------------------------------------+ //| Create a new indicator object Accelerator Oscillator | //| and place it to the collection list | //+------------------------------------------------------------------+ int CIndicatorsCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe) { //--- AC indicator possesses no parameters - resize the array of parameter structures ::ArrayResize(this.m_mql_param,0); //--- Create indicator object CIndicatorDE *indicator=this.CreateIndicator(IND_AC,this.m_mql_param,symbol,timeframe); if(indicator==NULL) return INVALID_HANDLE; int index=this.m_list.Search(indicator); //--- If such indicator is already in the list if(index!=WRONG_VALUE) { //--- Get indicator object from the list and return indicator handle indicator=this.m_list.At(index); return indicator.Handle(); } //--- If such indicator is not in the list else { //--- If failed to add indicator object to the list //--- display the appropriate message and return INVALID_HANDLE if(!this.m_list.Add(indicator)) { Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST)); return INVALID_HANDLE; } //--- Return the handle of a new indicator added to the list return indicator.Handle(); } //--- Return INVALID_HANDLE return INVALID_HANDLE; } //+------------------------------------------------------------------+
方法逻辑在其清单已有讲述,它不会引起任何问题。 请注意,指标对象是通过上面所分析的 CreateIndicator() 方法创建的。 该方法接收一个 IND_AC 指标的类型。 鉴于 AC 指标没有输入项,故此处不需要指标参数结构数组。 因此,数组被重置,这表明我们若用上一篇文章中已研究过的 CIndicatorDE 类创建指标时我们不需要该数组。
其余创建其他标准指标的方法与刚才分析的方法在逻辑上相同,它们的区别仅在于所需指标的规范,以及必要时,填充指标参数结构的数组。
例如,研究创建鳄嘴指标的方法,其中需要八个输入项,并根据鳄鱼嘴指标这些参数的顺序全部添加到指标参数数组当中,并将 IND_ALLIGATOR 类型传递给指标对象创建方法:
//+------------------------------------------------------------------+ //| Create new indicator object Alligator | //| and place it to the collection list | //+------------------------------------------------------------------+ int CIndicatorsCollection::CreateAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe, const int jaw_period, const int jaw_shift, const int teeth_period, const int teeth_shift, const int lips_period, const int lips_shift, const ENUM_MA_METHOD ma_method, const ENUM_APPLIED_PRICE applied_price) { //--- Add required indicator parameters to the array of parameter structures ::ArrayResize(this.m_mql_param,8); this.m_mql_param[0].type=TYPE_INT; this.m_mql_param[0].integer_value=jaw_period; this.m_mql_param[1].type=TYPE_INT; this.m_mql_param[1].integer_value=jaw_shift; this.m_mql_param[2].type=TYPE_INT; this.m_mql_param[2].integer_value=teeth_period; this.m_mql_param[3].type=TYPE_INT; this.m_mql_param[3].integer_value=teeth_shift; this.m_mql_param[4].type=TYPE_INT; this.m_mql_param[4].integer_value=lips_period; this.m_mql_param[5].type=TYPE_INT; this.m_mql_param[5].integer_value=lips_shift; this.m_mql_param[6].type=TYPE_INT; this.m_mql_param[6].integer_value=ma_method; this.m_mql_param[7].type=TYPE_INT; this.m_mql_param[7].integer_value=applied_price; //--- Create indicator object CIndicatorDE *indicator=this.CreateIndicator(IND_ALLIGATOR,this.m_mql_param,symbol,timeframe); if(indicator==NULL) return INVALID_HANDLE; int index=this.m_list.Search(indicator); //--- If such indicator is already in the list if(index!=WRONG_VALUE) { //--- Get indicator object from the list and return indicator handle indicator=this.m_list.At(index); return indicator.Handle(); } //--- If such indicator is not in the list else { //--- If failed to add indicator object to the list //--- display the appropriate message and return INVALID_HANDLE if(!this.m_list.Add(indicator)) { Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST)); return INVALID_HANDLE; } //--- Return the handle of a new indicator added to the list return indicator.Handle(); } //--- Return INVALID_HANDLE return INVALID_HANDLE; } //+------------------------------------------------------------------+
这些就是每种方法彼此之间的差异。 创建指标的剩余方法就不必分析了。 它们在文章所附的文件中已提供。
该方法按品种和时间帧返回集合列表中匹配加速振荡器的所有指标对象列表:
//+------------------------------------------------------------------+ //| Return the list of indicator objects Accelerator Oscillator | //| by symbol and timeframe | //+------------------------------------------------------------------+ CArrayObj *CIndicatorsCollection::GetListAC(const string symbol,const ENUM_TIMEFRAMES timeframe) { CArrayObj *list=GetListIndByType(IND_AC); list=CSelect::ByIndicatorProperty(list,INDICATOR_PROP_SYMBOL,symbol,EQUAL); return CSelect::ByIndicatorProperty(list,INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL); } //+------------------------------------------------------------------+
首先,获取集合列表中匹配加速振荡器的所有指标对象列表,
之后按品种将收到的列表排序,
并返回再次按时间帧排序后的列表。
其余方法与上面研究的完全相同,保留的事实在于:首先,我们依据方法设置获得所有必需指标的列表。
例如,为了获取集合列表中匹配“建仓/派发”的所有指标对象列表(按品种和时间帧),方法如下:
//+------------------------------------------------------------------+ //| Return the list of indicator objects Accumulation/Distribution | //| by symbol and timeframe | //+------------------------------------------------------------------+ CArrayObj *CIndicatorsCollection::GetListAD(const string symbol,const ENUM_TIMEFRAMES timeframe) { CArrayObj *list=GetListIndByType(IND_AD); list=CSelect::ByIndicatorProperty(list,INDICATOR_PROP_SYMBOL,symbol,EQUAL); return CSelect::ByIndicatorProperty(list,INDICATOR_PROP_TIMEFRAME,timeframe,EQUAL); } //+------------------------------------------------------------------+
在此,首先获取集合中所有 AD 指标的列表,然后按照上述方法,按品种和时间帧对列表进行排序。
今天,仅实现一个根据指标类型及其参数将指针返回指向集合中指标对象指针的方法 - 对于加速振荡器指标:
//+------------------------------------------------------------------+ //| Return pointer to indicator object Accelerator Oscillator | //+------------------------------------------------------------------+ CIndicatorDE *CIndicatorsCollection::GetIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe) { CArrayObj *list=GetListAC(symbol,timeframe); return(list==NULL || list.Total()==0 ? NULL : list.At(0)); } //+------------------------------------------------------------------+
由于该指标(和其他指标)没有输入项,因此当按照品种和时间帧从集合列表中选择它时,该列表将仅包含一个指标对象(索引为 0) ,对应于 IND_AC 类型,以及所请求的品种和时间帧。
而拥有输入项的指标,需要通过指标参数结构数组的其它搜索方法,该方法应按照指定参数实现搜索。 这会超出本文的范畴。 因此,将在下一篇文章中分析这些方法。
我将仅测试一个加速振荡器指标对象的创建,因为本文更倾向培训目的,故不会包揽全部。 在上一篇文章中,我已在缓冲区集合类中针对创建的 AC 指标对象进行了测试:
//+------------------------------------------------------------------+ //| Create multi-symbol multi-period AC | //+------------------------------------------------------------------+ int CBuffersCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe,const int id=WRONG_VALUE) { //--- To check it, create indicator object, print its data and remove it at once ::ArrayResize(this.m_mql_param,0); CIndicatorDE *indicator=new CIndicatorDE(IND_AC,symbol,timeframe,INDICATOR_STATUS_STANDART,INDICATOR_GROUP_OSCILLATOR,"Accelerator Oscillator","AC("+symbol+","+TimeframeDescription(timeframe)+")",this.m_mql_param); indicator.Print(); delete indicator; //--- Create indicator handle and set default ID
今天,我重复同样的事情:用相同的方法创建加速振荡器指标对象,但这次采用新添加的类。
展望未来:我们必须在时间序列的集合类中“查看”集合列表,如此,依据“位于”时间序列列表内的柱线对象创建的所有指标的数据存储函数,为我们开放。
因此,我们初步需要在文件 \MQL5\Include\DoEasy\Collections\TimeSeriesCollection.mqh 中将指标集合类包括到时间序列集合类:
//+------------------------------------------------------------------+ //| TimeSeriesCollection.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "ListObj.mqh" #include "..\Objects\Series\TimeSeriesDE.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "IndicatorsCollection.mqh" //+------------------------------------------------------------------+
进而,在类的私密部分中,声明指向指标集合类的指针:
//+------------------------------------------------------------------+ //| Symbol timeseries collection | //+------------------------------------------------------------------+ class CTimeSeriesCollection : public CBaseObjExt { private: CListObj m_list; // List of applied symbol timeseries CIndicatorsCollection *m_indicators; // Pointer to collection object of indicators //--- Return the timeseries index by symbol name int IndexTimeSeries(const string symbol); public:
在类列表的最后,创建初始化方法,通过该方法将指标集合对象的指针传递给 CEngine 库的主要对象里的类:
//--- Constructor CTimeSeriesCollection(); //--- Get pointers to the indicator collection (the method is called in CollectionOnInit() method of the CEngine object) void OnInit(CIndicatorsCollection *indicators) { this.m_indicators=indicators; } }; //+------------------------------------------------------------------+
在缓冲区集合类文件中 \MQL5\Include\DoEasy\Collections\BuffersCollection.mqh,还声明了指向指标集合对象的指针:
//+------------------------------------------------------------------+ //| Collection of indicator buffers | //+------------------------------------------------------------------+ class CBuffersCollection : public CObject { private: CListObj m_list; // Buffer object list CTimeSeriesCollection *m_timeseries; // Pointer to the timeseries collection object CIndicatorsCollection *m_indicators; // Pointer to collection object of indicators MqlParam m_mql_param[]; // Array of indicator parameters //--- Return the index of the (1) last, (2) next drawn and (3) basic buffer int GetIndexLastPlot(void); int GetIndexNextPlot(void); int GetIndexNextBase(void); //--- Create a new buffer object and place it to the collection list bool CreateBuffer(ENUM_BUFFER_STATUS status); //--- Get data of the necessary timeseries and bars for working with a single buffer bar, and return the number of bars int GetBarsData(CBuffer *buffer,const int series_index,int &index_bar_period); public:
在 OnInit() 类的方法添加此指针的设置,并由输入参数传递一个数值:
//--- Constructor CBuffersCollection(); //--- Get pointers to collections of timeseries and indicators (the method is called in CollectionOnInit() method of the CEngine object) void OnInit(CTimeSeriesCollection *timeseries,CIndicatorsCollection *indicators) { this.m_timeseries=timeseries; this.m_indicators=indicators; } }; //+------------------------------------------------------------------+
在创建 AC 指标的方法中,修改上一篇文章中指标对象的创建代码,替换为采用指标集合类创建与获取:
//+------------------------------------------------------------------+ //| Create multi-symbol multi-period AC | //+------------------------------------------------------------------+ int CBuffersCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe,const int id=WRONG_VALUE) { //--- To check it, create indicator object, print its data and remove it at once //--- Parameters are not needed for AC, therefore, reset the array of indicator parameter structures ::ArrayResize(this.m_mql_param,0); //--- Create AC indicator and add it to collection this.m_indicators.CreateAC(symbol,timeframe); //--- Get from collection of AC indicator object CIndicatorDE *indicator=this.m_indicators.GetIndAC(symbol,timeframe); //--- Display all data of the created indicator in the journal, display its short description and remove indicator object indicator.Print(); indicator.PrintShort(); delete indicator; //--- Create indicator handle and set default ID
现在,我们改进函数库主对象 CEngine 类。
在文件 \MQL5\Include\DoEasy\Engine.mqh 里加入将指标集合文件包含到类清单之中:
//+------------------------------------------------------------------+ //| Engine.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "Services\TimerCounter.mqh" #include "Collections\HistoryCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\EventsCollection.mqh" #include "Collections\AccountsCollection.mqh" #include "Collections\SymbolsCollection.mqh" #include "Collections\ResourceCollection.mqh" #include "Collections\TimeSeriesCollection.mqh" #include "Collections\BuffersCollection.mqh" #include "Collections\IndicatorsCollection.mqh" #include "TradingControl.mqh" //+------------------------------------------------------------------+
在类的私密部分,声明指标集合类的对象:
//+------------------------------------------------------------------+ //| Library basis class | //+------------------------------------------------------------------+ class CEngine { private: CHistoryCollection m_history; // Collection of historical orders and deals CMarketCollection m_market; // Collection of market orders and deals CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CSymbolsCollection m_symbols; // Symbol collection CTimeSeriesCollection m_time_series; // Timeseries collection CBuffersCollection m_buffers; // Collection of indicator buffers CIndicatorsCollection m_indicators; // Indicator collection CResourceCollection m_resource; // Resource list CTradingControl m_trading; // Trading control object CPause m_pause; // Pause object CArrayObj m_list_counters; // List of timer counters int m_global_error; // Global error code bool m_first_start; // First launch flag bool m_is_hedge; // Hedge account flag bool m_is_tester; // Flag of working in the tester bool m_is_market_trade_event; // Account trading event flag bool m_is_history_trade_event; // Account history trading event flag bool m_is_account_event; // Account change event flag bool m_is_symbol_event; // Symbol change event flag ENUM_TRADE_EVENT m_last_trade_event; // Last account trading event int m_last_account_event; // Last event in the account properties int m_last_symbol_event; // Last event in the symbol properties ENUM_PROGRAM_TYPE m_program; // Program type string m_name; // Program name //--- Return the counter index by id int CounterIndex(const int id) const; //--- Return the first launch flag bool IsFirstStart(void); //--- Work with (1) order, deal and position, (2) account events void TradeEventsControl(void); void AccountEventsControl(void); //--- (1) Working with a symbol collection and (2) symbol list events in the market watch window void SymbolEventsControl(void); void MarketWatchEventsControl(void); //--- Return the last (1) market pending order, (2) market order, (3) last position, (4) position by ticket COrder *GetLastMarketPending(void); COrder *GetLastMarketOrder(void); COrder *GetLastPosition(void); COrder *GetPosition(const ulong ticket); //--- Return the last (1) removed pending order, (2) historical market order, (3) historical order (market or pending one) by its ticket COrder *GetLastHistoryPending(void); COrder *GetLastHistoryOrder(void); COrder *GetHistoryOrder(const ulong ticket); //--- Return the (1) first and the (2) last historical market orders from the list of all position orders, (3) the last deal COrder *GetFirstOrderPosition(const ulong position_id); COrder *GetLastOrderPosition(const ulong position_id); COrder *GetLastDeal(void); //--- Retrieve a necessary 'ushort' number from the packed 'long' value ushort LongToUshortFromByte(const long source_value,const uchar index) const; public:
在公开部分中,编写两个方法,返回指向指标集合对象的指针和指向该集合的指标列表的指针:
//--- Return the bar index on the specified timeframe chart by the current chart's bar index int IndexBarPeriodByBarCurrent(const int series_index,const string symbol,const ENUM_TIMEFRAMES timeframe) { return this.m_time_series.IndexBarPeriodByBarCurrent(series_index,symbol,timeframe); } //--- Return (1) the indicator collection, (2) the indicator list from the collection CIndicatorsCollection *GetIndicatorsCollection(void) { return &this.m_indicators; } CArrayObj *GetListIndicators(void) { return this.m_indicators.GetList(); }
这些方法对于我们从程序中调用指标集合很有用处。
在 CollectionOnInit() 方法里添加指向指标集合的缓冲区集合类指针,和时间序列:
//--- Pass the pointers to all the necessary collections to the trading class and the indicator buffer collection class void CollectionOnInit(void) { this.m_trading.OnInit(this.GetAccountCurrent(),m_symbols.GetObject(),m_market.GetObject(),m_history.GetObject(),m_events.GetObject()); this.m_buffers.OnInit(this.m_time_series.GetObject(),this.m_indicators.GetObject()); this.m_time_series.OnInit(this.m_indicators.GetObject()); }
现在,在函数库初始化的情况下,指向指标集合对象的指针将传递给所有需要访问指标集合的类。 它们可用于操作此集合。
至此,这些就是创建指标集合类所必需的所有改进。
测试
为了进行测试,我们需要上一篇文章中的指标,且无需进行任何修改。
简单地将其保存在新文件夹 \MQL5\Indicators\TestDoEasy\Part54\ 之下,新名称为 TestDoEasyPart54.mq5。
编译指标,并在图表上启动它。
在日志中将显示以下内容: all parameters of created indicator Accelerator Oscillator in full , and then its short description:
Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10425.23 USD, 1:100, Hedge, Demo account MetaTrader 5 --- Initializing "DoEasy" library --- Working with the current symbol only. Number of used symbols: 1 "EURUSD" Working with the specified timeframe list: "H4" "H1" EURUSD symbol timeseries: - "EURUSD" H1 timeseries: Requested: 1000, Actually: 0, Created: 0, On the server: 0 - "EURUSD" H4 timeseries: Requested: 1000, Actually: 1000, Created: 1000, On the server: 6231 Time of library initializing: 00:00:00.156 ============= Beginning of the parameter list: "Standard indicator" ============= Indicator status: Standard indicator Indicator type: AC Indicator timeframe: H4 Indicator handle: 10 Indicator group: Oscillator ------ Empty value for plotting where nothing will be drawn: EMPTY_VALUE ------ Indicator symbol: EURUSD Indicator name: "Accelerator Oscillator" Indicator short name: "AC(EURUSD,H4)" ================== End of the parameter list: "Standard indicator" ================== Standard indicator Accelerator Oscillator EURUSD H4 Buffer (P0/B0/C1): Histogram from zero line EURUSD H4 Buffer [P0/B2/C2]: Calculated buffer "EURUSD" H1 timeseries created successfully: - "EURUSD" H1 timeseries: Requested: 1000, Actually: 1000, Created: 1000, On the server: 6256
下一步是什么?
在下一篇文章中,我们将继续研究指标集合类。
以下是该含糊库当前版本的所有文件,以及 MQL5 的测试指标文件。 您可以下载它们,并测试所有内容。
请注意,目前指标集合类正在开发当中,因此,强烈建议不要在程序中使用它。
请在文章的评论中留下您的评论、问题和建议。
返回内容目录
该系列中的先前文章:
DoEasy 函数库中的时间序列(第三十五部分):柱线对象和品种时间序列列表
DoEasy 函数库中的时间序列(第三十六部分):所有用到的品种周期的时间序列对象
DoEasy 函数库中的时间序列(第三十七部分):时间序列集合 - 按品种和周期的时间序列数据库
DoEasy 函数库中的时间序列(第三十八部分):时间序列集合 - 实时更新以及从程序访问数据
DoEasy 函数库中的时间序列(第三十九部分):基于函数库的指标 - 准备数据和时间序列事件
DoEasy 函数库中的时间序列(第四十部分):基于函数库的指标 - 实时刷新数据
DoEasy 函数库中的时间序列(第四十一部分):多品种多周期指标样品
DoEasy 函数库中的时间序列(第四十二部分):抽象指标缓冲区对象类
DoEasy 函数库中的时间序列(第四十三部分):指标缓冲区对象类
DoEasy 函数库中的时间序列(第四十四部分):指标缓冲区对象集合类
DoEasy 函数库中的时间序列(第四十五部分):多周期指标缓冲区
DoEasy 函数库中的时间序列(第四十六部分):多周期、多品种指标缓冲区
DoEasy 函数库中的时间序列(第四十七部分):多周期、多品种标准指标
DoEasy 函数库中的时间序列(第四十八部分):在单一子窗口里基于一个缓冲区的多周期、多品种指标
DoEasy 函数库中的时间序列(第四十九部分):多周期、多品种、多缓冲区标准指标
DoEasy 函数库中的时间序列(第五十部分):多周期、多品种带位移的标准指标
DoEasy 函数库中的时间序列(第五十一部分):复合多周期、多品种标准指标
DoEasy 函数库中的时间序列(第五十二部分):多周期、多品种单缓冲区标准指标的跨平台性质
DoEasy 函数库中的时间序列(第五十三部分):抽象基准指标类