轻松快捷开发 MetaTrader 程序的函数库(第十七部分):函数库对象之间的交互
内容
在之前的文章中,我们已创建了所有函数库对象的基准对象。 现在,从基准对象继承的任何对象都拥有事件功能,这令我们能够轻松跟踪基准对象衍生类中发生的事件。
如今,我们将走得更远,为对象(以及所有其他函数库对象)赋予更强劲的能力,即根据其变化、变化规模和对象属性值级别等外部条件来设置需要控制的属性。 因此,所有函数库对象将获得与用户进行交互的功能。
例如,假设我们要检查点差和价位以便开仓。 我们可以轻松设置可控的点差大小,跟踪价格达到指定水平并开仓。 所有我们要做的就是以编程设置点差大小,在该阈值以下允许进行交易,并设置一个价位,达到该价位后,来自交易品种对象的事件将被发送到程序,以便按点差和价位执行交易。
另一个重要的事情是,我们可以剔除使用事件标志的要求(这对跟踪事件施加了限制,且需为每个对象的所有可能事件类型保存枚举列表)。 现在,可能发生的事件数量将与对象属性的数量相对应 — 整数型和实数型。 勿需跟踪的属性以 LONG_MAX 初始化,并且不参与对象事件的搜索。
由于函数库对象存储在它们的集合中,所以利用函数库的 Refresh() 方法在计时器中刷新集合中的对象属性,而保存在集合列表中的对象也会调用自身的 Refresh() 方法。 如果我们在基准对象的 Refresh() 方法中跟踪衍生对象的变化,则可为每个函数库对象创建一个简单的事件模型。 每个对象都将其事件列表发送到 CEngine 函数库主对象。
因此,基于函数库的程序始终能够掌控任何集合里任何对象发生的所有事件。 此外,我们始终能够编程设置和修改任何集合里每个对象的任意属性的受控数值。
所有这些都是由所有函数库对象的基准对象的简单类实现的。
函数库基准对象事件的控制方法
操控函数库基准对象事件的布局如下:以前,为了定义某个类的事件,我们为其实现了单独的事件控制方法,创建了事件标志并列举出可能的对象事件。 现在,将衍生类事件的控制安排在它们的基类中,我们需要实现通用事件控制,而不必在意这是品种事件、帐户事件,亦或是以后将创建的任何其他类的事件。 所以,这是控制对象属性状态(整数型和实数型)变化的合适位置。 在每个衍生类中,它们的列表都是唯一的,并代表一个事件 ID。 另外,我们需要考虑属性变化的方向 — 递增或递减属性值(我们称其为事件原因),以及对象属性的变化值。 事件 ID、原因和变化值将写入对象基准事件的简单类中,并保存在同时发生的事件列表中。
我们已经认同将拥有严格指定参数(事件 ID,'long','double' 和 'string' 数值)的事件发送到程序。 在 'long' 参数中,我们发送的是以毫秒为单位的事件时间。 现在,由于事件定义的变更,我们需要按照事件的某些参数来精确定义事件:
- 事件 ID — 对象的属性已变化。 每个对象都有其独特的属性。 程序不知道对象属性的变化,也不知晓变化后的属性状态(无论是整数型还是实数型),所以不可能依照事件 ID 对其进行准确定义。
- 事件原因 — 增加或减少属性值,或与一个受控价位交叉。 该值也不能令我们准确地判断事件。 但是事件 ID 和原因令我们可以定义某个对象属性已经增加或减少,或者已经穿越了指定的受控值。 因此,我们需要指定发生事件的对象类 ID,以便准确识别事件。
集合列表非常适合这种情况,因为它可以准确定义对象所属的类 — 品种、帐户或将来创建的其他集合对象。 因此,以下数据也应附带发送给事件:
- 集合 ID — 如此这般,上面提到的三个 ID 令我们能够准确地定义事件。
- 事件字符串型属性 — 发生事件的对象名称。
因此,为了定义事件,我们需要获取三个整数型参数,以及获取事件名称,该名称也由 'long' 值传递。 我们只有一个 'long' 事件属性。 我们应该怎样做? 解决方案很简单:我们将在单个 'long' 参数中传递三个“ushort”类型的整数型事件。 'long' 类型有 8 个字节,而 'ushort' 类型有 2 个字节。 因此,'long' 容器允许我们存储三个 “ushort” 数字,分别写在 'long' 数字的字节 0-1,字节 2-3,字节 4-5 中,而我们还有两个字节 6-7,如果以后需要,可传递另一个 'ushort' 值。
为了定义事件时间,我们只需要在 'long' 参数的字节 0-1 中传递毫秒单位的时间。
- 当处理事件时,可利用 TimeCurrent() 获取事件日期和时间,并在事件的 'long' 值的字节 0-1 中传递毫秒数。
- 事件原因是在事件 'long' 参数的字节 2-3 中设置的,而
- 类 ID 设置在事件 'long' 参数的字节 4-5 之中。
因此,当收到一个事件时,我们从 'long' 参数中提取三个 'ushort' 值来定义事件时间,并从事件 ID 里得到准确的事件识别符,将其作为 'ushort' 参数 custom_event_id 传递给 EventChartCustom(),并用事件 ID 和另外从 lparam 中提取到的两个数值构造一个发生事件的精准 ID。
在父对象计时器中,检查每个对象属性的当前状态,并将其与先前状态进行比较,以定义衍生对象属性中的事件。 首先,检查将要与属性变化进行比较的数值是否已被设置。 如果将要检查的数值尚未设置(此刻设置为 LONG_MAX),则忽略此属性。
由于我们检查 'long' 和 'double' 类型的对象属性列表,因此用二维数组而非结构来存储对象属性的当前和先前状态更为合理。 数组的第一个维度是存储对象属性索引,而第二个维度则存储第一个维度中所设索引对应的数值,属性变化值,以及属性事件的受控值和标志。
我来解释一下为什么用数组而不是结构更方便:
我们事先不知道所要检查的属性是何类型。 然而,我们可以在属性索引中看到其类型('double' 型对象属性始终位于 'long' 型对象之后)。 这意味着对于相同对象属性值的 “long” 和 “double” 值,我们不需要在结构中为其保留重叠的字段。 我们只要将控制对象属性状态的必要数据按其正确类型写入对应类型的数组(与属性索引定义对应的属性类型)。 因此,无需为要传递的数值选择对应的结构字段(long 或 double)。
一旦定义了任何对象属性的变化,就将其添加到基准对象事件列表中(由于搜索是在基准对象中进行的,而事件是基础,不应将其与由基准事件列表定义,并由基准事件创建的衍生类事件混淆,指针为其在列表中的存储位置)。
在每个基准对象的衍生类的计时器里 Refresh() 方法检查属性变化列表(基准事件列表)。 如果对象列表包含这些事件,则每个事件都将转换为函数库事件,然后发送到控制程序。
为了令画面完整,我们需要创建一些方法,令我们能够编程控制任何基于基准对象的函数库对象的任意属性变化值。 这将令我们能够随时从必要对象快速修改生成事件的基本条件。
此处采取的所有措施集合,旨在改善函数库基准对象,令我们不必顾虑为所有后续生成的对象创建事件控制。 相反,我们将利用现成的功能。
我们动手吧。
由于我们要操控所有函数库对象的基准对象中的事件,因此我们需要创建事件原因枚举,以便识别事件。
在 \MQL5\Include\DoEasy\Defines.mqh 文件中,在时间选项之后,添加可能的基准对象事件原因枚举:
//+------------------------------------------------------------------+ //| Possible options of selecting by time | //+------------------------------------------------------------------+ enum ENUM_SELECT_BY_TIME { SELECT_BY_TIME_OPEN, // By open time (in milliseconds) SELECT_BY_TIME_CLOSE, // By close time (in milliseconds) }; //+------------------------------------------------------------------+ //| Possible event reasons of the object library base object | //+------------------------------------------------------------------+ enum ENUM_BASE_EVENT_REASON { BASE_EVENT_REASON_INC, // Increase in the object property value BASE_EVENT_REASON_DEC, // Decrease in the object property value BASE_EVENT_REASON_MORE_THEN, // Object property value exceeds the control value BASE_EVENT_REASON_LESS_THEN, // Object property value is less than the control value BASE_EVENT_REASON_EQUALS // Object property value is equal to the control value }; //+------------------------------------------------------------------+
由于我们不再需要事件标志,因此在市场观察窗口中将品种事件标志列表替换为可能的品种事件列表:
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of possible symbol events in the Market Watch window | //+------------------------------------------------------------------+ enum ENUM_MW_EVENT { MARKET_WATCH_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // No event MARKET_WATCH_EVENT_SYMBOL_ADD, // Adding a symbol to the Market Watch window MARKET_WATCH_EVENT_SYMBOL_DEL, // Removing a symbol from the Market Watch window MARKET_WATCH_EVENT_SYMBOL_SORT, // Sorting symbols in the Market Watch window }; #define SYMBOL_EVENTS_NEXT_CODE (MARKET_WATCH_EVENT_SYMBOL_SORT+1) // The code of the next event after the last symbol event code //+------------------------------------------------------------------+
删除可能的品种事件列表,因为不再需要它:
//+------------------------------------------------------------------+ //| List of possible symbol events | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_EVENT { SYMBOL_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // No event SYMBOL_EVENT_MW_ADD, // Adding a symbol to the Market Watch window SYMBOL_EVENT_MW_DEL, // Removing a symbol from the Market Watch window SYMBOL_EVENT_MW_SORT, // Sorting symbols in the Market Watch window SYMBOL_EVENT_TRADE_DISABLE, // Disable order execution SYMBOL_EVENT_TRADE_LONGONLY, // Allow buy only SYMBOL_EVENT_TRADE_SHORTONLY, // Allow sell only SYMBOL_EVENT_TRADE_CLOSEONLY, // Enable close only SYMBOL_EVENT_TRADE_FULL, // No trading limitations SYMBOL_EVENT_SESSION_DEALS_INC, // The increase in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_DEALS_DEC, // The decrease in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_INC, // The increase in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_DEC, // The decrease in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_INC, // The increase in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_DEC, // The decrease in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_VOLUME_INC, // Volume increase in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_DEC, // Volume decrease in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_INC, // The increase in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_DEC, // The decrease in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_INC, // The increase in the minimum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_DEC, // The decrease in the minimum volume per day exceeds the specified value SYMBOL_EVENT_SPREAD_INC, // The increase in a spread exceeds the specified change SYMBOL_EVENT_SPREAD_DEC, // The decrease in a spread exceeds the specified change SYMBOL_EVENT_STOPLEVEL_INC, // The increase of a Stop order level exceeds the specified value SYMBOL_EVENT_STOPLEVEL_DEC, // The decrease of a Stop order level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_INC, // The increase in the freeze level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_DEC, // The decrease in the freeze level exceeds the specified value SYMBOL_EVENT_BID_LAST_INC, // The increase in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_DEC, // The decrease in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_INC, // The increase in the maximum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_DEC, // The decrease in the maximum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_INC, // The increase in the minimum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_DEC, // The decrease in the minimum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_ASK_INC, // The increase in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_DEC, // The decrease in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_HIGH_INC, // The increase in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_HIGH_DEC, // The decrease in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_INC, // The increase in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_DEC, // The decrease in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_INC, // The increase in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_DEC, // The decrease in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_INC, // The increase in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_DEC, // The decrease in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_INC, // The increase in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_DEC, // The decrease in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_INC, // The increase in the strike price exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_DEC, // The decrease in the strike price exceeds the specified value SYMBOL_EVENT_VOLUME_LIMIT_INC, // The increase in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_VOLUME_LIMIT_DEC, // The decrease in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_SWAP_LONG_INC, // The increase in the swap long SYMBOL_EVENT_SWAP_LONG_DEC, // The decrease in the swap long SYMBOL_EVENT_SWAP_SHORT_INC, // The increase in the swap short SYMBOL_EVENT_SWAP_SHORT_DEC, // The decrease in the swap short SYMBOL_EVENT_SESSION_VOLUME_INC, // The increase in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_VOLUME_DEC, // The decrease in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_INC, // The increase in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_DEC, // The decrease in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_INC, // The increase in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_DEC, // The decrease in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_INC, // The increase in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_DEC, // The decrease in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_INC, // The increase in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_DEC, // The decrease in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_OPEN_INC, // The increase in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_OPEN_DEC, // The decrease in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_INC, // The increase in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_DEC, // The decrease in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_AW_INC, // The increase in the average weighted session price exceeds the specified value SYMBOL_EVENT_SESSION_AW_DEC, // The decrease in the average weighted session price exceeds the specified value }; #define SYMBOL_EVENTS_NEXT_CODE (SYMBOL_EVENT_SESSION_AW_DEC+1) // The code of the next event after the last symbol event code //+------------------------------------------------------------------+
下一个事件的代码已被 ENUM_MW_EVENT 枚举的 MARKET_WATCH_EVENT_SYMBOL_SORT 常量之后的值所替代。
现在,我们来实现计划好的功能。
在 \MQL5\Include\DoEasy\Objects\ BaseObj.mqh 基准对象文件中,添加基准事件的新类:
//+------------------------------------------------------------------+ //| Library object's base event class | //+------------------------------------------------------------------+ class CBaseEvent : public CObject { private: ENUM_BASE_EVENT_REASON m_reason; int m_event_id; double m_value; public: ENUM_BASE_EVENT_REASON Reason(void) const { return this.m_reason; } int ID(void) const { return this.m_event_id; } double Value(void) const { return this.m_value; } //--- Constructor CBaseEvent(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value) : m_reason(reason), m_event_id(event_id), m_value(value){} //--- Comparison method to search for identical event objects virtual int Compare(const CObject *node,const int mode=0) const { const CBaseEvent *compared=node; return ( this.Reason()>compared.Reason() ? 1 : this.Reason()<compared.Reason() ? -1 : this.ID()>compared.ID() ? 1 : this.ID()<compared.ID() ? -1 : 0 ); } }; //+------------------------------------------------------------------+
类的私密部分含有用于存储事件原因,事件 ID(与已变化对象属性的索引匹配)和事件属性变化值的变量。
类的公开部分提供了用于返回上面列出的类成员变量的方法。
类构造函数的形式参数接收属性值。 所传递的数值将立即分配给初始化清单中的相应类成员变量。
此外,该类还拥有比较两个类对象的方法,以便在我们多次讨论的指向对象的动态指针列表中进行搜索。
由于我们要将受控对象属性的列表存储在二维数组中,因此我们添加指向第二个数组维大小的宏替换。 在该类的私密部分中,声明两个变量,我们将在其中存储从该类派生对象的整数型属性数量和实数型属性数量( 因为基类对其子代拥有的属性数量一无所知,所以这些数量应显式出示)。 声明填充属性数组和搜索派生对象属性变化的方法。
//+------------------------------------------------------------------+ //| Base object class for all library objects | //+------------------------------------------------------------------+ #define CONTROLS_TOTAL (10) class CBaseObj : public CObject { private: int m_long_prop_total; int m_double_prop_total; //--- Fill in the object property array template<typename T> bool FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id); protected:
在类的受保护部分中,声明存储指向对象基准事件实例的指针列表,存储事件 ID 的变量,第一次启动标志和存储派生对象类型的变量。
我们还添加了四个二维数组,用于存储属性,并控制它们的变化(派生对象当前和先前的整数型和实数型属性),以及返回存储在其中的事件时间毫秒值的方法(对于 MQL4,返回 0,对于 MQL5,返回时间的 “long'' 值除以 1000 的余数)。
由于基类对派生对象属性的数量一无所知,因而应从衍生类(此刻已知它们的位置)设置大小,声明设置方法并检查数组的大小:
protected: CArrayObj m_list_events_base; // Object base event list CArrayObj m_list_events; // Object event list MqlTick m_tick; // Tick structure for receiving quote data double m_hash_sum; // Object data hash sum double m_hash_sum_prev; // Object data hash sum during the previous check int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code long m_chart_id; // Control program chart ID bool m_is_event; // Object event flag int m_event_code; // Object event code int m_event_id; // Event ID (equal to the object property value) string m_name; // Object name string m_folder_name; // Name of the folder storing CBaseObj descendant objects bool m_first_start; // First launch flag int m_type; // Object type (corresponds to the collection IDs) //--- Data in the array cells //--- Data for storing, controlling and returning tracked properties: //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level long m_long_prop_event[][CONTROLS_TOTAL]; // The array for storing object's integer properties values and controlled property change values double m_double_prop_event[][CONTROLS_TOTAL]; // The array for storing object's real properties values and controlled property change values long m_long_prop_event_prev[][CONTROLS_TOTAL]; // The array for storing object's controlled integer properties values during the previous check double m_double_prop_event_prev[][CONTROLS_TOTAL]; // The array for storing object's controlled real properties values during the previous check //--- Return (1) time in milliseconds, (2) milliseconds from the MqlTick time value long TickTime(void) const { return #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; } ushort MSCfromTime(const long time_msc) const { return #ifdef __MQL5__ ushort(this.TickTime()%1000) #else 0 #endif ; } //--- return the flag of the event code presence in the event object bool IsPresentEventFlag(const int change_code) const { return (this.m_event_code & change_code)==change_code; } //--- Return the number of decimal places of the account currency int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; //--- Set the size of the array of controlled (1) integer and (2) real object properties bool SetControlDataArraySizeLong(const int size); bool SetControlDataArraySizeDouble(const int size); //--- Check the array size of object properties bool CheckControlDataArraySize(bool check_long=true); //--- Set the (1) controlled value and (2) object property change value template<typename T> void SetControlledValue(const int property,const T value); template<typename T> void SetControlledChangedValue(const int property,const T value); //--- Set the value of the pbject property controlled (1) increase, (2) decrease, (3) control level template<typename T> void SetControlledValueINC(const int property,const T value); template<typename T> void SetControlledValueDEC(const int property,const T value); template<typename T> void SetControlledValueLEVEL(const int property,const T value); //--- Set the flag of a property change exceeding the (1) increase and (2) decrease values template<typename T> void SetControlledFlagINC(const int property,const T value); template<typename T> void SetControlledFlagDEC(const int property,const T value); //--- Set the flag of a property change (1) exceeding, (2) being less than the control level, (3) being equal to the level template<typename T> void SetControlledFlagMORE(const int property,const T value); template<typename T> void SetControlledFlagLESS(const int property,const T value); template<typename T> void SetControlledFlagEQUAL(const int property,const T value); //--- Return the set value of the controlled (1) integer and (2) real object properties increase long GetControlledValueLongINC(const int property) const { return this.m_long_prop_event[property][0]; } double GetControlledValueDoubleINC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][0]; } //--- Return the set value of the controlled (1) integer and (2) real object properties decrease long GetControlledValueLongDEC(const int property) const { return this.m_long_prop_event[property][1]; } double GetControlledValueDoubleDEC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][1]; } //--- Return the control level of object's (1) integer and (2) real properties long GetControlledValueLongLEVEL(const int property) const { return this.m_long_prop_event[property][2]; } double GetControlledValueDoubleLEVEL(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][2]; } //--- Return the value of the object (1) integer and (2) real property long GetControlledValueLong(const int property) const { return this.m_long_prop_event[property][3]; } double GetControlledValueDouble(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][3]; } //--- Return the change value of the controlled (1) integer and (2) real object property long GetControlledChangedValueLong(const int property) const { return this.m_long_prop_event[property][4]; } double GetControlledChangedValueDouble(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][4]; } //--- Return the flag of an (1) integer and (2) real property value change exceeding the increase value long GetControlledFlagLongINC(const int property) const { return this.m_long_prop_event[property][5]; } double GetControlledFlagDoubleINC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][5]; } //--- Return the flag of an (1) integer and (2) real property value change exceeding the decrease value long GetControlledFlagLongDEC(const int property) const { return this.m_long_prop_event[property][6]; } double GetControlledFlagDoubleDEC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][6]; } //--- Return the flag of an (1) integer and (2) real property value increase exceeding the control level long GetControlledFlagLongMORE(const int property) const { return this.m_long_prop_event[property][7]; } double GetControlledFlagDoubleMORE(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][7]; } //--- Return the flag of an (1) integer and (2) real property value decrease being less than the control level long GetControlledFlagLongLESS(const int property) const { return this.m_long_prop_event[property][8]; } double GetControlledFlagDoubleLESS(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][8]; } //--- Return the flag of an (1) integer and (2) real property being equal to the control level long GetControlledFlagLongEQUAL(const int property) const { return this.m_long_prop_event[property][9]; } double GetControlledFlagDoubleEQUAL(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][9]; } //--- (1) Pack a 'ushort' number to a passed 'long' number //--- (2) convert a 'ushort' value to a specified 'long' number byte long UshortToLong(const ushort ushort_value,const uchar index,long &long_value); long UshortToByte(const ushort value,const uchar index) const; public:
在类的私密部分还声明了设置并返回受控属性及其值的方法,以及通过索引将 “ushort” 数字包装到指定的 “long” 容器内字节处的方法。 (索引 0 => 字节 0-1, 索引 1 => 字节 2-3, 索引 2 => 字节 4-5)
在类的公开部分,声明重置已变化属性值和受控对象属性的值的方法, 将基准事件添加到列表的方法,按照索引从列表中接收基准对象的方法,返回列表中基准对象数量的方法,返回对象类型的虚拟方法,和返回基准事件的字符串描述的方法:
public: //--- Reset the variables of (1) tracked and (2) controlled object data (can be reset in the descendants) void ResetChangesParams(void); virtual void ResetControlsParams(void); //--- Add the (1) object event and (2) the object event reason to the list bool EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam); bool EventBaseAdd(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value); //--- Return the occurred event flag to the object data bool IsEvent(void) const { return this.m_is_event; } //--- Return (1) the list of events, (2) the object event code and (3) the global error code CArrayObj *GetListEvents(void) { return &this.m_list_events; } int GetEventCode(void) const { return this.m_event_code; } int GetError(void) const { return this.m_global_error; } //--- Return (1) an event object and (2) a base event by its number in the list CEventBaseObj *GetEvent(const int shift=WRONG_VALUE,const bool check_out=true); CBaseEvent *GetEventBase(const int index); //--- Return the number of (1) object events int GetEventsTotal(void) const { return this.m_list_events.Total(); } //--- (1) Set and (2) return the chart ID of the control program void SetChartID(const long id) { this.m_chart_id=id; } long GetChartID(void) const { return this.m_chart_id; } //--- (1) Set the sub-folder name, (2) return the folder name for storing descendant object files void SetSubFolderName(const string name) { this.m_folder_name=DIRECTORY+name; } string GetFolderName(void) const { return this.m_folder_name; } //--- Return the object name string GetName(void) const { return this.m_name; } //--- Update the object data to search for changes (Calling from the descendants: CBaseObj::Refresh()) virtual void Refresh(void); //--- Return an object type virtual int Type(void) const { return this.m_type; } //--- Return an object event description string EventDescription(const int property, const ENUM_BASE_EVENT_REASON reason, const int source, const string value, const string property_descr, const int digits); //--- Constructor CBaseObj(); }; //+------------------------------------------------------------------+
现在,我们简要回顾一下上面声明的所有方法。
类的构造函数:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CBaseObj::CBaseObj() : m_global_error(ERR_SUCCESS), m_hash_sum(0),m_hash_sum_prev(0), m_is_event(false),m_event_code(WRONG_VALUE), m_chart_id(::ChartID()), m_folder_name(DIRECTORY), m_name(__FUNCTION__), m_long_prop_total(0), m_double_prop_total(0), m_first_start(true) { ::ArrayResize(this.m_long_prop_event,0,100); ::ArrayResize(this.m_double_prop_event,0,100); ::ArrayResize(this.m_long_prop_event_prev,0,100); ::ArrayResize(this.m_double_prop_event_prev,0,100); ::ZeroMemory(this.m_tick); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); } //+------------------------------------------------------------------+
鉴于我们不再拥有之前从标志中收集来的事件代码,其中零值表示没有事件,我们需要在类的初始化清单中将事件代码初始化替换为非零值(因为零是对象整数型属性枚举的第一个属性,而正数值表示对象属性列表中的下一个事件,但是我们不能在父类中定义它们的编号)。 我们将事件代码设置为 -1。
对象名称按类名称初始化(名称在衍生类中重新分配)。 用零值初始化衍生对象的整数型和实数型属性,并设置首次启动的标志。
在类的主体中,将整数型和实数型属性的数组大小设置为零值,清除基准事件列表,设置已排序列表标志。
以前,该类的 Refresh() 虚拟方法只是简单声明,其实现由衍生类执行。 现在,我们为基准对象类创建并实现该方法,以便跟踪衍生对象属性的变化。 定义事件后,将创建基准事件,并将其添加到基准事件列表中,以便进行后续处理,并创建要发送给程序的对象事件:
//+------------------------------------------------------------------+ //| Update the object data to search changes in them | //| Call from descendants: CBaseObj::Refresh() | //+------------------------------------------------------------------+ void CBaseObj::Refresh(void) { //--- Check the size of the arrays, Exit if it is zero if(!this.CheckControlDataArraySize() || !this.CheckControlDataArraySize(false)) return; //--- Reset the event flag and clear all lists this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); //--- Fill in the array of integer properties and control their changes for(int i=0;i<this.m_long_prop_total;i++) if(!this.FillPropertySettings(i,this.m_long_prop_event,this.m_long_prop_event_prev,this.m_event_id)) continue; //--- Fill in the array of real properties and control their changes for(int i=0;i<this.m_double_prop_total;i++) if(!this.FillPropertySettings(i,this.m_double_prop_event,this.m_double_prop_event_prev,this.m_event_id)) continue; //--- First launch if(this.m_first_start) { ::ArrayCopy(this.m_long_prop_event_prev,this.m_long_prop_event); ::ArrayCopy(this.m_double_prop_event_prev,this.m_double_prop_event); this.m_hash_sum_prev=this.m_hash_sum; this.m_first_start=false; this.m_is_event=false; this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); return; } } //+------------------------------------------------------------------+
在此,所有动作都在代码注释中进行了描述,包括在方法中执行的动作,例如初步清除事件列表,并调用方法来填充衍生对象的整数型和实数型属性数组,并检查其变化。
如果这是首次启动,则将属性数组的当前状态复制为以前的状态(以避免它们之间的差异导致事件注册),重置首次启动标志,而在调用 FillPropertySettings() 方法时可能会创建基准事件列表 则被清除。
实现填充衍生对象属性的数组,并控制其变化的方法:
//+------------------------------------------------------------------+ //| Fill in the object property array | //+------------------------------------------------------------------+ template<typename T> bool CBaseObj::FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id) { //--- Data in the array cells //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level //--- If controlled values are not set, exit with 'false' if(this.m_first_start) return false; //--- Set the shift of the 'double' property index and the event ID event_id=index+(typename(T)=="double" ? this.m_long_prop_total : 0); //--- Reset all event flags for(int j=5;j<CONTROLS_TOTAL;j++) array[index][j]=false; //--- Property change value T value=array[index][3]-array_prev[index][3]; array[index][4]=value; //--- If the controlled property increase value is set if(array[index][0]<LONG_MAX) { //--- If the property change value exceeds the controlled increase value - there is an event, //--- add the event to the list, set the flag and save the new property value size if(value>0 && value>array[index][0]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_INC,value)) { array[index][5]=true; array_prev[index][4]=value; } } } //--- If the controlled property decrease value is set if(array[index][1]<LONG_MAX) { //--- If the property change value exceeds the controlled decrease value - there is an event, //--- add the event to the list, set the flag and save the new property value size if(value<0 && fabs(value)>array[index][1]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_DEC,value)) { array[index][6]=true; array_prev[index][4]=value; } } } //--- If the controlled level value is set if(array[index][2]<LONG_MAX) { value=array[index][3]-array[index][2]; //--- If a property value exceeds the control level, there is an event //--- add the event to the list and set the flag if(value>0 && array_prev[index][3]<=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_MORE_THEN,array[index][2])) array[index][7]=true; } //--- If a property value is less than the control level, there is an event, //--- add the event to the list and set the flag else if(value<0 && array_prev[index][3]>=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_LESS_THEN,array[index][2])) array[index][8]=true; } //--- If a property value is equal to the control level, there is an event, //--- add the event to the list and set the flag else if(value==0 && array_prev[index][3]!=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_EQUALS,array[index][2])) array[index][9]=true; } } //--- Save the current property value as a previous one array_prev[index][3]=array[index][3]; return true; } //+------------------------------------------------------------------+
此处,所有操作均在代码注释中描述。 我唯一要澄清的是为了接收事件 ID 要选择对象 “double” 属性索引偏移。 由于所有对象的实数型属性都位于整数型属性之后,因此第一个实数型属性的起始等于整数型属性的数量(如果 “long” 属性的数量等于 3,则第一个实数型属性的索引为 3(0,1,2,3))。 在数组中,计数从零开始。 所以,当操控 'double' 属性时,我们需要将对象整数型属性的数量添加到数组索引中。
设置衍生对象整数型和实数型属性数组大小的方法:
//+------------------------------------------------------------------+ //| Set the size of the arrays of the object integer properties | //+------------------------------------------------------------------+ bool CBaseObj::SetControlDataArraySizeLong(const int size) { int x=(#ifdef __MQL4__ CONTROLS_TOTAL #else 1 #endif ); this.m_long_prop_total=::ArrayResize(this.m_long_prop_event,size,100)/x; return((::ArrayResize(this.m_long_prop_event_prev,size,100)/x)==size && this.m_long_prop_total==size ? true : false); } //+------------------------------------------------------------------+ //| Set the size of the arrays of the object real properties | //+------------------------------------------------------------------+ bool CBaseObj::SetControlDataArraySizeDouble(const int size) { int x=(#ifdef __MQL4__ CONTROLS_TOTAL #else 1 #endif ); this.m_double_prop_total=::ArrayResize(this.m_double_prop_event,size,100)/x; return((::ArrayResize(this.m_double_prop_event_prev,size,100)/x)==size && this.m_double_prop_total==size ? true : false); } //+------------------------------------------------------------------+
这些方法判断所传递数组中的数值变化大小,并返回结果。
我应该着重强调一个在 MQL4 中更改多维数组大小的功能。 MQL4 中的 ArrayResize() 函数返回数组所有维度的大小总合。 在 MQL5 中,它返回第一维的大小,该大小可能会发生变化。 例如,如果第二维的尺寸为 2,那么如果第一维的尺寸更改为 10,该函数将返回 20,这是不合逻辑的(因为我们仅更改了第一维的尺寸)。 在 MQL5 中,该函数能返回正确的值。 如上面的示例,它按预期返回 10。
所以,这些方法针对 MQL4 进行切分,返回单独的数值(第二维的尺寸)。
检查衍生对象整数型和实数型属性数组大小的方法:
//+------------------------------------------------------------------+ //| Check the array size of object properties | //+------------------------------------------------------------------+ bool CBaseObj::CheckControlDataArraySize(bool check_long=true) { string txt1=""; string txt2=""; string txt3=""; string txt4=""; bool res=true; if(check_long) { if(this.m_long_prop_total==0) { txt1=TextByLanguage("Массив данных контролируемых integer-свойств имеет нулевой размер","Controlled integer properties data array has zero size"); txt2=TextByLanguage("Необходимо сначала установить размер массива равным количеству integer-свойств объекта","You should first set size of array equal to number of object integer properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeLong()","To do this, use CBaseObj::SetControlDataArraySizeLong() method"); txt4=TextByLanguage("со значением количества integer-свойств объекта в параметре \"size\"","with value of number of integer properties of object in \"size\" parameter"); res=false; } } else { if(this.m_double_prop_total==0) { txt1=TextByLanguage("Массив данных контролируемых double-свойств имеет нулевой размер","Controlled double properties data array has zero size"); txt2=TextByLanguage("Необходимо сначала установить размер массива равным количеству double-свойств объекта","You should first set size of array equal to number of object double properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeDouble()","To do this, use CBaseObj::SetControlDataArraySizeDouble() method"); txt4=TextByLanguage("со значением количества double-свойств объекта в параметре \"size\"","with value of number of double properties of object in \"size\" parameter"); res=false; } } if(res) return true; #ifdef __MQL5__ ::Print(DFUN,"\n",txt1,"\n",txt2,"\n",txt3,"\n",txt4); #else ::Print(DFUN); ::Print(txt1); ::Print(txt2); ::Print(txt3); ::Print(txt4); #endif this.m_global_error=ERR_ZEROSIZE_ARRAY; return false; } //+------------------------------------------------------------------+
该方法接收标志,该标志表示数组大小已检查。
若为 true,'long' 属性的数组已检查。 若为 false,则是 'double' 属性数组已检查。
如果未设置已检查数组大小,则生成消息文本,消息会显示在日志中,并返回 false。 如果已设置了数组大小,则返回 true。
重置对象属性控制值和跟踪数据变化值的方法:
//+------------------------------------------------------------------+ //| Reset the variables of controlled object data values | //+------------------------------------------------------------------+ void CBaseObj::ResetControlsParams(void) { if(!this.CheckControlDataArraySize(true) || !this.CheckControlDataArraySize(false)) return; //--- Data in the array cells //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level for(int i=this.m_long_prop_total-1;i>WRONG_VALUE;i--) for(int j=0; j<3; j++) this.m_long_prop_event[i][j]=LONG_MAX; for(int i=this.m_double_prop_total-1;i>WRONG_VALUE;i--) for(int j=0; j<3; j++) this.m_double_prop_event[i][j]=(double)LONG_MAX; } //+------------------------------------------------------------------+ //| Reset the variables of tracked object data | //+------------------------------------------------------------------+ void CBaseObj::ResetChangesParams(void) { if(!this.CheckControlDataArraySize(true) || !this.CheckControlDataArraySize(false)) return; this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); //--- Data in the array cells //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the controlled value for(int i=this.m_long_prop_total-1;i>WRONG_VALUE;i--) for(int j=3; j<CONTROLS_TOTAL; j++) this.m_long_prop_event[i][j]=(j<5 ? LONG_MAX : 0); for(int i=this.m_double_prop_total-1;i>WRONG_VALUE;i--) for(int j=3; j<CONTROLS_TOTAL; j++) this.m_double_prop_event[i][j]=(j<5 ? (double)LONG_MAX : 0); } //+------------------------------------------------------------------+
方法通过两次循环,为衍生对象的整数型和实数型属性数组的单元格(第二维)设置初始化数值。 初始化的单元格在代码注释中标注。
将基准事件添加到对象基准事件列表的方法:
//+------------------------------------------------------------------+ //| Add the object base event to the list | //+------------------------------------------------------------------+ bool CBaseObj::EventBaseAdd(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value) { CBaseEvent* event=new CBaseEvent(event_id,reason,value); if(event==NULL) return false; this.m_list_events_base.Sort(); if(this.m_list_events_base.Search(event)>WRONG_VALUE) { delete event; return false; } return this.m_list_events_base.Add(event); } //+------------------------------------------------------------------+
该方法接收事件 ID,事件原因和衍生对象属性变化值。
然后,创建一个新的基准事件,并且如果已有相同事件存在于基准事件列表中,则将其删除并返回 false — 不添加事件。 否则,返回添加新事件到基准对象事件列表的结果。
该方法按其在基准对象事件列表中的索引返回基准事件:
//+------------------------------------------------------------------+ //| Return a base event by its index in the list | //+------------------------------------------------------------------+ CBaseEvent *CBaseObj::GetEventBase(const int index) { int total=this.m_list_events_base.Total(); if(total==0 || index<0 || index>total-1) return NULL; CBaseEvent *event=this.m_list_events_base.At(index); return(event!=NULL ? event : NULL); } //+------------------------------------------------------------------+
方法接收所需事件的索引。 如果列表大小为零,或索引超出了基准事件列表,则返回 NULL。 否则,按索引从列表中接收事件,然后返回指向所获对象的指针。
我们需要为对象基类创建方法,以便快速设置必要的属性变化。 超过变化值则会导致事件的产生。 我们还需要一些方法,来为衍生对象属性设置新值,并返回有关“受控”对象事件已发生的标志。 由于基类对其衍生类的属性一无所知,因此我们需要创建通用方法,令我们能够针对所需衍生对象属性进行更改。 由于我们将声明每个衍生类的整数型和实数型属性的数量,因而我们很容易就可为其属性定义设置值。 我们只需检查变化后的属性索引。 如果索引小于整数型属性的数量,则变化发生在对象的整数型属性,否则实数型属性发生变化。
设置衍生对象受控属性的方法实现:
//+------------------------------------------------------------------+ //| Methods of setting controlled parameters | //+------------------------------------------------------------------+ //--- Data for storing, controlling and returning tracked properties: //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level //+------------------------------------------------------------------+ //| Set the value of the controlled increase of object properties | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueINC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][0]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][0]=(double)value; } //+------------------------------------------------------------------+ //| Set the value of the controlled decrease of object properties | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueDEC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][1]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][1]=(double)value; } //+------------------------------------------------------------------+ //| Set the control level of object properties | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueLEVEL(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][2]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][2]=(double)value; } //+------------------------------------------------------------------+ //| Set the object property value | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValue(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][3]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][3]=(double)value; } //+------------------------------------------------------------------+ //| Set the object property change value | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledChangedValue(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][4]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][4]=(double)value; } //+------------------------------------------------------------------+ //| Set the flag of the property value change | //| exceeding the increase value | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagINC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][5]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][5]=(double)value; } //+------------------------------------------------------------------+ //| Set the flag of the property value change | //| exceeding the decrease value | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagDEC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][6]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][6]=(double)value; } //+------------------------------------------------------------------+ //| Set the flag of the property value increase | //| exceeding the control level | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagMORE(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][7]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][7]=(double)value; } //+------------------------------------------------------------------+ //| Set the flag of the property value decrease | //| being less than the control level | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagLESS(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][8]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][8]=(double)value; } //+------------------------------------------------------------------+ //| Set the flag of the property value being equal to the | //| control level | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagEQUAL(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][9]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][9]=(double)value; } //+------------------------------------------------------------------+
我们看一下最后一个方法接收属性,该方法添加了模板标记 template<typename T>。 如果属性索引小于衍生对象整数型属性的数量,则 T 值将被添加到对象整数型属性数组的必要单元格当中,否则计算索引,此索引为该属性在实数型属性数组中的存储位置 (同一属性的 'double' 索引总是大于其整数型数量),并 将 T 值添加到对象实数型属性数组的必要单元格中。 方法清单之前列出了每种方法所对应的数组第二维单元格。
该方法将 'ushort' 值转换为 'long' 值,并按其字节编号移位,以便随后封装到 'long' 容器中:
//+------------------------------------------------------------------+ //| Convert a 'ushort' value to a specified 'long' number byte | //+------------------------------------------------------------------+ long CBaseObj::UshortToByte(const ushort value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } return(long)value<<(16*index); } //+------------------------------------------------------------------+
假设我们有一个八字节的 'long' 值,以每单元格两个字节切分(为该类型的每个单元格分配了唯一索引):
字节 6-7 (索引 3) |
字节 4-5 (索引 2) | 字节 2-3 (索引 1) |
字节 0-1 (索引 0) |
---|---|---|---|
ushort 4 |
ushort 3 |
ushort 2 |
ushort 1 |
我们可以在其上安置四个 “ushort” 数字。 每个顺序数字应向左移动 16 位 * 索引(1 字节 = 8 位)。 然后,将获得的值添加到 'long' 数字中。 因此,我们在 “long” 容器中封装了几个 “ushort” 值。
该方法接收 'ushort' 数字和索引,应按该索引将 'ushort' 值存储在 'long' 容器的相应位置。
检查索引,如果索引超过 3,则会显示错误索引消息,并返回 0。
如果索引正确,则将'ushort' 数字向左移 16 位 * 索引(一个字节包含 8 位,而我们要将 'ushort' 数字位移两个字节),之后方法返回位移结果。
该方法将 “ushort” 值位移必要字节数,并封装到 “long” 容器中:
//+------------------------------------------------------------------+ //| Pack a 'ushort' number to a passed 'long' number | //+------------------------------------------------------------------+ long CBaseObj::UshortToLong(const ushort ushort_value,const uchar index,long &long_value) { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } return(long_value |= UshortToByte(ushort_value,index)); } //+------------------------------------------------------------------+
方法接收一个 'ushort' 数字,该数字应按字节索引封装到通过链接传递给该方法的 'long' 容器的相应位置。
与上述方法相似,检查索引,如果检查成功,则利用 UshortToByte() 方法将 'ushort' 值位移所需的字节数,并利用按位 “或(OR)” 加到 'long' 数字中,结果返回给调用程序。
该方法返回衍生对象事件的字符串描述:
//+------------------------------------------------------------------+ //| Return an object event description | //+------------------------------------------------------------------+ string CBaseObj::EventDescription(const int property, const ENUM_BASE_EVENT_REASON reason, const int source, const string value, const string property_descr, const int digits) { //--- Depending on the collection ID, create th object type description string type= ( this.Type()==COLLECTION_SYMBOLS_ID ? TextByLanguage("символа: ","symbol property: ") : this.Type()==COLLECTION_ACCOUNT_ID ? TextByLanguage("аккаунта: ","account property: ") : "" ); //--- Depending on the property type, create the property change value description string level= ( property<this.m_long_prop_total ? ::DoubleToString(this.GetControlledValueLongLEVEL(property),digits) : ::DoubleToString(this.GetControlledValueDoubleLEVEL(property),digits) ); //--- Depending on the event reason, create the event description text string res= ( reason==BASE_EVENT_REASON_INC ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" увеличено на "," increased by ")+value : reason==BASE_EVENT_REASON_DEC ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" уменьшено на "," decreased by ")+value : reason==BASE_EVENT_REASON_MORE_THEN ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" стало больше "," became more than ")+level : reason==BASE_EVENT_REASON_LESS_THEN ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" стало меньше "," became less than ")+level : reason==BASE_EVENT_REASON_EQUALS ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" равно "," is equal to ")+level : TextByLanguage("Неизвестное событие ","Unknown ")+type ); //--- Return the object name+created event description text return this.m_name+": "+res; } //+------------------------------------------------------------------+
由于基准对象类对其衍生类一无所知,我们需要指定事件发生的衍生对象,以便说明衍生类中的事件。
为此,该方法接收
- 被检测事件的一个对象属性 ,
- 事件原因 — 按指定值增加/减少属性值,按属性值穿越一个指定的价位,
- 事件源 — 发生事件的对象所属集合的 ID,
- 此数值,为发生变化的对象属性,
- 衍生对象属性的文本描述(在衍生类中可用),和
- 在已变化属性的数字表示形式中的小数位数(也在衍生类中可用)。
创建衍生对象的所有步骤均在代码注释中进行了说明。 我相信,它们足够全面。
我们已经对基准对象类进行了所有必要的修改(将来函数库开发和创建新集合期间,会将新集合 ID 添加到最后一个方法中,以便创建正确的事件描述)。
改造品种类和品种集合
在此,我们依照记忆中的新基准对象事件,修订品种类和品种集合的操作。 我们对品种和品种集合类进行一些修改。
打开 \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh 并加以修改。
由于基准对象的所有衍生对象事件现已在父类中定义,因此无需控制衍生类中对象属性的变化。 因此,现在无需跟踪对象属性的数据结构。
我们从品种对象类中删除结构,和两个包含结构类型的对象:
struct MqlDataSymbol
{
//--- Symbol integer properties
ENUM_SYMBOL_TRADE_MODE trade_mode; // SYMBOL_TRADE_MODE Order filling modes
long session_deals; // SYMBOL_SESSION_DEALS The number of deals in the current session
long session_buy_orders; // SYMBOL_SESSION_BUY_ORDERS The total number of current buy orders
long session_sell_orders; // SYMBOL_SESSION_SELL_ORDERS The total number of current sell orders
long volume; // SYMBOL_VOLUME Last deal volume
long volume_high_day; // SYMBOL_VOLUMEHIGH Maximum volume within a day
long volume_low_day; // SYMBOL_VOLUMELOW Minimum volume within a day
int spread; // SYMBOL_SPREAD Spread in points
int stops_level; // SYMBOL_TRADE_STOPS_LEVEL Minimum distance in points from the current close price for setting Stop orders
int freeze_level; // SYMBOL_TRADE_FREEZE_LEVEL Freeze distance for trading operations (in points)
//--- Symbol real properties
double bid_last; // SYMBOL_BID/SYMBOL_LAST Bid - the best sell offer/Last deal price
double bid_last_high; // SYMBOL_BIDHIGH/SYMBOL_LASTHIGH Maximum Bid within the day/Maximum Last per day
double bid_last_low; // SYMBOL_BIDLOW/SYMBOL_LASTLOW Minimum Bid within the day/Minimum Last per day
double ask; // SYMBOL_ASK Ask - nest buy offer
double ask_high; // SYMBOL_ASKHIGH Maximum Ask of the day
double ask_low; // SYMBOL_ASKLOW Minimum Ask of the day
double volume_real_day; // SYMBOL_VOLUME_REAL Real Volume of the day
double volume_high_real_day; // SYMBOL_VOLUMEHIGH_REAL Maximum real Volume of the day
double volume_low_real_day; // SYMBOL_VOLUMELOW_REAL Minimum real Volume of the day
double option_strike; // SYMBOL_OPTION_STRIKE Strike price
double volume_limit; // SYMBOL_VOLUME_LIMIT Maximum permissible total volume for a position and pending orders in one direction
double swap_long; // SYMBOL_SWAP_LONG Long swap value
double swap_short; // SYMBOL_SWAP_SHORT Short swap value
double session_volume; // SYMBOL_SESSION_VOLUME The total volume of deals in the current session
double session_turnover; // SYMBOL_SESSION_TURNOVER The total turnover in the current session
double session_interest; // SYMBOL_SESSION_INTEREST The total volume of open positions
double session_buy_ord_volume; // SYMBOL_SESSION_BUY_ORDERS_VOLUME The total volume of Buy orders at the moment
double session_sell_ord_volume; // SYMBOL_SESSION_SELL_ORDERS_VOLUME The total volume of Sell orders at the moment
double session_open; // SYMBOL_SESSION_OPEN Session open price
double session_close; // SYMBOL_SESSION_CLOSE Session close price
double session_aw; // SYMBOL_SESSION_AW The average weighted price of the session
};
MqlDataSymbol m_struct_curr_symbol; // Current symbol data
MqlDataSymbol m_struct_prev_symbol; // Previous symbol data
//---
删除所有用于存储受控和变化的品种对象属性的类成员变量 — 现在,所有这些数据都存储在基准对象类的数组中:
//--- Current session deals
long m_control_session_deals_inc; // Controlled value of the growth of the number of deals
long m_control_session_deals_dec; // Controlled value of the decrease in the number of deals
long m_changed_session_deals_value; // Value of change in the number of deals
bool m_is_change_session_deals_inc; // Flag of a change in the number of deals exceeding the growth value
bool m_is_change_session_deals_dec; // Flag of a change in the number of deals exceeding the decrease value
//--- Buy orders of the current session
long m_control_session_buy_ord_inc; // Controlled value of the increase of the number of Buy orders
long m_control_session_buy_ord_dec; // Controlled value of the decrease in the number of Buy orders
long m_changed_session_buy_ord_value; // Buy orders change value
bool m_is_change_session_buy_ord_inc; // Flag of a change in the number of Buy orders exceeding the increase value
bool m_is_change_session_buy_ord_dec; // Flag of a change in the number of Buy orders being less than the increase value
//--- Sell orders of the current session
long m_control_session_sell_ord_inc; // Controlled value of the increase of the number of Sell orders
long m_control_session_sell_ord_dec; // Controlled value of the decrease in the number of Sell orders
long m_changed_session_sell_ord_value; // Sell orders change value
bool m_is_change_session_sell_ord_inc; // Flag of a change in the number of Sell orders exceeding the increase value
bool m_is_change_session_sell_ord_dec; // Flag of a change in the number of Sell orders exceeding the decrease value
//--- Volume of the last deal
long m_control_volume_inc; // Controlled value of the volume increase in the last deal
long m_control_volume_dec; // Controlled value of the volume decrease in the last deal
long m_changed_volume_value; // Value of the volume change in the last deal
bool m_is_change_volume_inc; // Flag of the volume change in the last deal exceeding the increase value
bool m_is_change_volume_dec; // Flag of the volume change in the last deal being less than the increase value
//--- Maximum volume within a day
long m_control_volume_high_day_inc; // Controlled value of the maximum volume increase for a day
long m_control_volume_high_day_dec; // Controlled value of the maximum volume decrease for a day
long m_changed_volume_high_day_value; // Maximum volume change value within a day
bool m_is_change_volume_high_day_inc; // Flag of the maximum day volume exceeding the increase value
bool m_is_change_volume_high_day_dec; // Flag of the maximum day volume exceeding the decrease value
//--- Minimum volume within a day
long m_control_volume_low_day_inc; // Controlled value of the minimum volume increase for a day
long m_control_volume_low_day_dec; // Controlled value of the minimum volume decrease for a day
long m_changed_volume_low_day_value; // Minimum volume change value within a day
bool m_is_change_volume_low_day_inc; // Flag of the minimum day volume exceeding the increase value
bool m_is_change_volume_low_day_dec; // Flag of the minimum day volume exceeding the decrease value
//--- Spread
int m_control_spread_inc; // Controlled spread increase value in points
int m_control_spread_dec; // Controlled spread decrease value in points
int m_changed_spread_value; // Spread change value in points
bool m_is_change_spread_inc; // Flag of spread change in points exceeding the increase value
bool m_is_change_spread_dec; // Flag of spread change in points exceeding the decrease value
//--- StopLevel
int m_control_stops_level_inc; // Controlled StopLevel increase value in points
int m_control_stops_level_dec; // Controlled StopLevel decrease value in points
int m_changed_stops_level_value; // StopLevel change value in points
bool m_is_change_stops_level_inc; // Flag of StopLevel change in points exceeding the increase value
bool m_is_change_stops_level_dec; // Flag of StopLevel change in points exceeding the decrease value
//--- Freeze distance
int m_control_freeze_level_inc; // Controlled FreezeLevel increase value in points
int m_control_freeze_level_dec; // Controlled FreezeLevel decrease value in points
int m_changed_freeze_level_value; // FreezeLevel change value in points
bool m_is_change_freeze_level_inc; // Flag of FreezeLevel change in points exceeding the increase value
bool m_is_change_freeze_level_dec; // Flag of FreezeLevel change in points exceeding the decrease value
//--- Bid/Last
double m_control_bid_last_inc; // Controlled value of Bid or Last price increase
double m_control_bid_last_dec; // Controlled value of Bid or Last price decrease
double m_changed_bid_last_value; // Bid or Last price change value
bool m_is_change_bid_last_inc; // Flag of Bid or Last price change exceeding the increase value
bool m_is_change_bid_last_dec; // Flag of Bid or Last price change exceeding the decrease value
//--- Maximum Bid/Last of the day
double m_control_bid_last_high_inc; // Controlled increase value of the maximum Bid or Last price of the day
double m_control_bid_last_high_dec; // Controlled decrease value of the maximum Bid or Last price of the day
double m_changed_bid_last_high_value; // Maximum Bid or Last change value for the day
bool m_is_change_bid_last_high_inc; // Flag of the maximum Bid or Last price change for the day exceeding the increase value
bool m_is_change_bid_last_high_dec; // Flag of the maximum Bid or Last price change for the day exceeding the decrease value
//--- Minimum Bid/Last of the day
double m_control_bid_last_low_inc; // Controlled increase value of the minimum Bid or Last price of the day
double m_control_bid_last_low_dec; // Controlled decrease value of the minimum Bid or Last price of the day
double m_changed_bid_last_low_value; // Minimum Bid or Last change value for the day
bool m_is_change_bid_last_low_inc; // Flag of the minimum Bid or Last price change for the day exceeding the increase value
bool m_is_change_bid_last_low_dec; // Flag of the minimum Bid or Last price change for the day exceeding the decrease value
//--- Ask
double m_control_ask_inc; // Controlled value of the Ask price increase
double m_control_ask_dec; // Controlled value of the Ask price decrease
double m_changed_ask_value; // Ask price change value
bool m_is_change_ask_inc; // Flag of the Ask price change exceeding the increase value
bool m_is_change_ask_dec; // Flag of the Ask price change exceeding the decrease value
//--- Maximum Ask price for the day
double m_control_ask_high_inc; // Controlled increase value of the maximum Ask price of the day
double m_control_ask_high_dec; // Controlled decrease value of the maximum Ask price of the day
double m_changed_ask_high_value; // Maximum Ask price change value for the day
bool m_is_change_ask_high_inc; // Flag of the maximum Ask price change for the day exceeding the increase value
bool m_is_change_ask_high_dec; // Flag of the maximum Ask price change for the day exceeding the decrease value
//--- Minimum Ask price for the day
double m_control_ask_low_inc; // Controlled increase value of the minimum Ask price of the day
double m_control_ask_low_dec; // Controlled decrease value of the minimum Ask price of the day
double m_changed_ask_low_value; // Minimum Ask price change value for the day
bool m_is_change_ask_low_inc; // Flag of the minimum Ask price change for the day exceeding the increase value
bool m_is_change_ask_low_dec; // Flag of the minimum Ask price change for the day exceeding the decrease value
//--- Real Volume for the day
double m_control_volume_real_inc; // Controlled value of the real volume increase of the day
double m_control_volume_real_dec; // Controlled value of the real volume decrease of the day
double m_changed_volume_real_value; // Real volume change value of the day
bool m_is_change_volume_real_inc; // Flag of the real volume change for the day exceeding the increase value
bool m_is_change_volume_real_dec; // Flag of the real volume change for the day exceeding the decrease value
//--- Maximum real volume for the day
double m_control_volume_high_real_day_inc; // Controlled value of the maximum real volume increase of the day
double m_control_volume_high_real_day_dec; // Controlled value of the maximum real volume decrease of the day
double m_changed_volume_high_real_day_value; // Maximum real volume change value of the day
bool m_is_change_volume_high_real_day_inc; // Flag of the maximum real volume change for the day exceeding the increase value
bool m_is_change_volume_high_real_day_dec; // Flag of the maximum real volume change for the day exceeding the decrease value
//--- Minimum real volume for the day
double m_control_volume_low_real_day_inc; // Controlled value of the minimum real volume increase of the day
double m_control_volume_low_real_day_dec; // Controlled value of the minimum real volume decrease of the day
double m_changed_volume_low_real_day_value; // Minimum real volume change value of the day
bool m_is_change_volume_low_real_day_inc; // Flag of the minimum real volume change for the day exceeding the increase value
bool m_is_change_volume_low_real_day_dec; // Flag of the minimum real volume change for the day exceeding the decrease value
//--- Strike price
double m_control_option_strike_inc; // Controlled value of the strike price increase
double m_control_option_strike_dec; // Controlled value of the strike price decrease
double m_changed_option_strike_value; // Strike price change value
bool m_is_change_option_strike_inc; // Flag of the strike price change exceeding the increase value
bool m_is_change_option_strike_dec; // Flag of the strike price change exceeding the decrease value
//--- Total volume of positions and orders
double m_changed_volume_limit_value; // Minimum total volume change value
bool m_is_change_volume_limit_inc; // Flag of the minimum total volume increase
bool m_is_change_volume_limit_dec; // Flag of the minimum total volume decrease
//--- Swap long
double m_changed_swap_long_value; // Swap long change value
bool m_is_change_swap_long_inc; // Flag of the swap long increase
bool m_is_change_swap_long_dec; // Flag of the swap long decrease
//--- Swap short
double m_changed_swap_short_value; // Swap short change value
bool m_is_change_swap_short_inc; // Flag of the swap short increase
bool m_is_change_swap_short_dec; // Flag of the swap short decrease
//--- The total volume of deals in the current session
double m_control_session_volume_inc; // Controlled value of the total trade volume increase in the current session
double m_control_session_volume_dec; // Controlled value of the total trade volume decrease in the current session
double m_changed_session_volume_value; // The total deal volume change value in the current session
bool m_is_change_session_volume_inc; // Flag of total trade volume change in the current session exceeding the increase value
bool m_is_change_session_volume_dec; // Flag of total trade volume change in the current session exceeding the decrease value
//--- The total turnover in the current session
double m_control_session_turnover_inc; // Controlled value of the total turnover increase in the current session
double m_control_session_turnover_dec; // Controlled value of the total turnover decrease in the current session
double m_changed_session_turnover_value; // Total turnover change value in the current session
bool m_is_change_session_turnover_inc; // Flag of total turnover change in the current session exceeding the increase value
bool m_is_change_session_turnover_dec; // Flag of total turnover change in the current session exceeding the decrease value
//--- The total volume of open positions
double m_control_session_interest_inc; // Controlled value of the total open position volume increase in the current session
double m_control_session_interest_dec; // Controlled value of the total open position volume decrease in the current session
double m_changed_session_interest_value; // Change value of the open positions total volume in the current session
bool m_is_change_session_interest_inc; // Flag of total open positions' volume change in the current session exceeding the increase value
bool m_is_change_session_interest_dec; // Flag of total open positions' volume change in the current session exceeding the decrease value
//--- The total volume of Buy orders at the moment
double m_control_session_buy_ord_volume_inc; // Controlled value of the current total buy order volume increase
double m_control_session_buy_ord_volume_dec; // Controlled value of the current total buy order volume decrease
double m_changed_session_buy_ord_volume_value; // Change value of the current total buy order volume
bool m_is_change_session_buy_ord_volume_inc; // Flag of changing the current total buy orders volume exceeding the increase value
bool m_is_change_session_buy_ord_volume_dec; // Flag of changing the current total buy orders volume exceeding the decrease value
//--- The total volume of Sell orders at the moment
double m_control_session_sell_ord_volume_inc; // Controlled value of the current total sell order volume increase
double m_control_session_sell_ord_volume_dec; // Controlled value of the current total sell order volume decrease
double m_changed_session_sell_ord_volume_value; // Change value of the current total sell order volume
bool m_is_change_session_sell_ord_volume_inc; // Flag of changing the current total sell orders volume exceeding the increase value
bool m_is_change_session_sell_ord_volume_dec; // Flag of changing the current total sell orders volume exceeding the decrease value
//--- Session open price
double m_control_session_open_inc; // Controlled value of the session open price increase
double m_control_session_open_dec; // Controlled value of the session open price decrease
double m_changed_session_open_value; // Session open price change value
bool m_is_change_session_open_inc; // Flag of the session open price change exceeding the increase value
bool m_is_change_session_open_dec; // Flag of the session open price change exceeding the decrease value
//--- Session close price
double m_control_session_close_inc; // Controlled value of the session close price increase
double m_control_session_close_dec; // Controlled value of the session close price decrease
double m_changed_session_close_value; // Session close price change value
bool m_is_change_session_close_inc; // Flag of the session close price change exceeding the increase value
bool m_is_change_session_close_dec; // Flag of the session close price change exceeding the decrease value
//--- The average weighted session price
double m_control_session_aw_inc; // Controlled value of the average weighted session price increase
double m_control_session_aw_dec; // Controlled value of the average weighted session price decrease
double m_changed_session_aw_value; // The average weighted session price change value
bool m_is_change_session_aw_inc; // Flag of the average weighted session price change value exceeding the increase value
bool m_is_change_session_aw_dec; // Flag of the average weighted session price change value exceeding the decrease value
删除以下高亮标示的冗余方法:
//--- Initialize the variables of (1) tracked, (2) controlled symbol data virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- Check symbol changes, return a change code virtual int SetEventCode(void); //--- Set an event type and fill in the event list virtual void SetTypeEvent(void); //--- Return description of symbol events string EventDescription(const ENUM_SYMBOL_EVENT event);
声明检查品种属性中的变化,并创建事件的方法,替代修改品种属性代码的虚拟方法:
//--- Initialize the variables of controlled symbol data virtual void InitControlsParams(void); //--- Check the list of symbol property changes and create an event void CheckEvents(void);
在类的公开部分中,添加设置跟踪值并返回跟踪属性受控值,以及属性变化值和标志的方法声明:
public: //--- Set the change value of the controlled symbol property template<typename T> void SetControlChangedValue(const int property,const T value); //--- Set the value of the controlled symbol property (1) increase, (2) decrease and (3) control level template<typename T> void SetControlPropertyINC(const int property,const T value); template<typename T> void SetControlPropertyDEC(const int property,const T value); template<typename T> void SetControlPropertyLEVEL(const int property,const T value); //--- Set the flag of a symbol property change exceeding the (1) increase and (2) decrease values template<typename T> void SetControlFlagINC(const int property,const T value); template<typename T> void SetControlFlagDEC(const int property,const T value); //--- Return the set value of the (1) integer and (2) real symbol property controlled increase long GetControlParameterINC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledValueLongINC(property); } double GetControlParameterINC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledValueDoubleINC(property); } //--- Return the set value of the (1) integer and (2) real symbol property controlled decrease long GetControlParameterDEC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledValueLongDEC(property); } double GetControlParameterDEC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledValueDoubleDEC(property); } //--- Return the flag of an (1) integer and (2) real symbol property value change exceeding the increase value long GetControlFlagINC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledFlagLongINC(property); } double GetControlFlagINC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledFlagDoubleINC(property); } //--- Return the flag of an (1) integer and (2) real symbol property value change exceeding the decrease value bool GetControlFlagDEC(const ENUM_SYMBOL_PROP_INTEGER property) const { return (bool)this.GetControlledFlagLongDEC(property); } bool GetControlFlagDEC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return (bool)this.GetControlledFlagDoubleDEC(property); } //--- Return the change value of the controlled (1) integer and (2) real object property long GetControlChangedValue(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledChangedValueLong(property); } double GetControlChangedValue(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledChangedValueDouble(property); } //+------------------------------------------------------------------+
每个方法都以两个重载方法的形式编写,它们调用基准对象相应类型的方法来设置/检查品种对象属性。
之气,我们已开发出简化访问某些品种对象属性的方法。 我们还要添加设置属性受控价位的方法,并声明设置/接收出价(Bid) /最后价(Last)和相关参数数据的方法(之前,出价(Bid)或最后价(Last) 会根据图表的价格自动选择。 现在,我们需要创建用于操控此数据的方法):
//+------------------------------------------------------------------+ //| Get and set the parameters of tracked property changes | //+------------------------------------------------------------------+ //--- Execution //--- Flag of changing the trading mode for a symbol bool IsChangedTradeMode(void) const { return this.m_is_change_trade_mode; } //--- Current session deals //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the number of deals during the current session //--- getting (3) the number of deals change value during the current session, //--- getting the flag of the number of deals change during the current session exceeding the (4) increase, (5) decrease value void SetControlSessionDealsInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } void SetControlSessionDealsDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } void SetControlSessionDealsLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } long GetValueChangedSessionDeals(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_DEALS); } bool IsIncreasedSessionDeals(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_DEALS); } bool IsDecreasedSessionDeals(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_DEALS); } //--- Buy orders of the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current number of Buy orders //--- getting (4) the current number of Buy orders change value, //--- getting the flag of the current Buy orders' number change exceeding the (5) growth, (6) decrease value void SetControlSessionBuyOrdInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } void SetControlSessionBuyOrdDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } void SetControlSessionBuyOrdLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } long GetValueChangedSessionBuyOrders(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_BUY_ORDERS); } bool IsIncreasedSessionBuyOrders(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_BUY_ORDERS); } bool IsDecreasedSessionBuyOrders(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_BUY_ORDERS); } //--- Sell orders of the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current number of Sell orders //--- getting (4) the current number of Sell orders change value, //--- getting the flag of the current Sell orders' number change exceeding the (5) growth, (6) decrease value void SetControlSessionSellOrdInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value)); } void SetControlSessionSellOrdDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value)); } void SetControlSessionSellOrdLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value));} long GetValueChangedSessionSellOrders(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_SELL_ORDERS); } bool IsIncreasedSessionSellOrders(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_SELL_ORDERS); } bool IsDecreasedSessionSellOrders(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_SELL_ORDERS); } //--- Volume of the last deal //--- setting the last deal volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) volume change values in the last deal, //--- getting the flag of the volume change in the last deal exceeding the (5) growth, (6) decrease value void SetControlVolumeInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } void SetControlVolumeDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } void SetControlVolumeLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } long GetValueChangedVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME); } bool IsIncreasedVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME); } bool IsDecreasedVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME); } //--- Maximum volume within a day //--- setting the maximum day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the maximum volume change value within a day, //--- getting the flag of the maximum day volume change exceeding the (5) growth, (6) decrease value void SetControlVolumeHighInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } void SetControlVolumeHighDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } void SetControlVolumeHighLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } long GetValueChangedVolumeHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMEHIGH); } bool IsIncreasedVolumeHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMEHIGH); } bool IsDecreasedVolumeHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMEHIGH); } //--- Minimum volume within a day //--- setting the minimum day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the minimum volume change value within a day, //--- getting the flag of the minimum day volume change exceeding the (5) growth, (6) decrease value void SetControlVolumeLowInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } void SetControlVolumeLowDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } void SetControlVolumeLowLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } long GetValueChangedVolumeLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMELOW); } bool IsIncreasedVolumeLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMELOW); } bool IsDecreasedVolumeLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMELOW); } //--- Spread //--- setting the controlled spread (1) increase, (2) decrease value and (3) control level in points //--- getting (4) spread change value in points, //--- getting the flag of the spread change in points exceeding the (5) growth, (6) decrease value void SetControlSpreadInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } void SetControlSpreadDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } void SetControlSpreadLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } int GetValueChangedSpread(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_SPREAD); } bool IsIncreasedSpread(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SPREAD); } bool IsDecreasedSpread(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SPREAD); } //--- StopLevel //--- setting the controlled StopLevel (1) increase, (2) decrease value and (3) control level in points //--- getting (4) StopLevel change value in points, //--- getting the flag of StopLevel change in points exceeding the (5) growth, (6) decrease value void SetControlStopLevelInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } void SetControlStopLevelDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } void SetControlStopLevelLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } int GetValueChangedStopLevel(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_TRADE_STOPS_LEVEL); } bool IsIncreasedStopLevel(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_TRADE_STOPS_LEVEL); } bool IsDecreasedStopLevel(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_TRADE_STOPS_LEVEL); } //--- Freeze distance //--- setting the controlled FreezeLevel (1) increase, (2) decrease value and (3) control level in points //--- getting (4) FreezeLevel change value in points, //--- getting the flag of FreezeLevel change in points exceeding the (5) growth, (6) decrease value void SetControlFreezeLevelInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } void SetControlFreezeLevelDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } void SetControlFreezeLevelLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } int GetValueChangedFreezeLevel(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } bool IsIncreasedFreezeLevel(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } bool IsDecreasedFreezeLevel(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } //--- Bid //--- setting the controlled Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BID,::fabs(value)); } void SetControlBidDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BID,::fabs(value)); } void SetControlBidLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BID,::fabs(value)); } double GetValueChangedBid(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BID); } bool IsIncreasedBid(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BID); } bool IsDecreasedBid(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BID); } //--- The highest Bid price of the day //--- setting the controlled maximum Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BIDHIGH,::fabs(value)); } void SetControlBidHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BIDHIGH,::fabs(value)); } void SetControlBidHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BIDHIGH,::fabs(value)); } double GetValueChangedBidHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BIDHIGH); } bool IsIncreasedBidHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDHIGH); } bool IsDecreasedBidHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDHIGH); } //--- The lowest Bid price of the day //--- setting the controlled minimum Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BIDLOW,::fabs(value)); } void SetControlBidLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BIDLOW,::fabs(value)); } void SetControlBidLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BIDLOW,::fabs(value)); } double GetValueChangedBidLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BIDLOW); } bool IsIncreasedBidLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDLOW); } bool IsDecreasedBidLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDLOW); } //--- Last //--- setting the controlled Last price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlLastInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LAST,::fabs(value)); } void SetControlLastDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LAST,::fabs(value)); } void SetControlLastLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LAST,::fabs(value)); } double GetValueChangedLast(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LAST); } bool IsIncreasedLast(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LAST); } bool IsDecreasedLast(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LAST); } //--- The highest Last price of the day //--- setting the controlled maximum Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlLastHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LASTHIGH,::fabs(value)); } void SetControlLastHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LASTHIGH,::fabs(value)); } void SetControlLastHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LASTHIGH,::fabs(value)); } double GetValueChangedLastHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LASTHIGH); } bool IsIncreasedLastHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTHIGH); } bool IsDecreasedLastHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTHIGH); } //--- The lowest Last price of the day //--- setting the controlled minimum Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlLastLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LASTLOW,::fabs(value)); } void SetControlLastLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LASTLOW,::fabs(value)); } void SetControlLastLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LASTLOW,::fabs(value)); } double GetValueChangedLastLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LASTLOW); } bool IsIncreasedLastLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTLOW); } bool IsDecreasedLastLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTLOW); } //--- Bid/Last //--- setting the controlled Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidLastInc(const double value); void SetControlBidLastDec(const double value); void SetControlBidLastLevel(const double value); double GetValueChangedBidLast(void) const; bool IsIncreasedBidLast(void) const; bool IsDecreasedBidLast(void) const; //--- Maximum Bid/Last of the day //--- setting the controlled maximum Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidLastHighInc(const double value); void SetControlBidLastHighDec(const double value); void SetControlBidLastHighLevel(const double value); double GetValueChangedBidLastHigh(void) const; bool IsIncreasedBidLastHigh(void) const; bool IsDecreasedBidLastHigh(void) const; //--- Minimum Bid/Last of the day //--- setting the controlled minimum Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value void SetControlBidLastLowInc(const double value); void SetControlBidLastLowDec(const double value); void SetControlBidLastLowLevev(const double value); double GetValueChangedBidLastLow(void) const; bool IsIncreasedBidLastLow(void) const; bool IsDecreasedBidLastLow(void) const; //--- Ask //--- setting the controlled Ask price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Ask price change value, //--- getting the flag of the Ask price change exceeding the (5) growth, (6) decrease value void SetControlAskInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASK,::fabs(value)); } void SetControlAskDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASK,::fabs(value)); } void SetControlAskLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASK,::fabs(value)); } double GetValueChangedAsk(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASK); } bool IsIncreasedAsk(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASK); } bool IsDecreasedAsk(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASK); } //--- Maximum Ask price for the day //--- setting the maximum day Ask controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the maximum Ask change value within a day, //--- getting the flag of the maximum day Ask change exceeding the (5) growth, (6) decrease value void SetControlAskHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASKHIGH,::fabs(value)); } void SetControlAskHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASKHIGH,::fabs(value)); } void SetControlAskHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASKHIGH,::fabs(value)); } double GetValueChangedAskHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASKHIGH); } bool IsIncreasedAskHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASKHIGH); } bool IsDecreasedAskHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASKHIGH); } //--- Minimum Ask price for the day //--- setting the minimum day Ask controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the minimum Ask change value within a day, //--- getting the flag of the minimum day Ask change exceeding the (5) growth, (6) decrease value void SetControlAskLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASKLOW,::fabs(value)); } void SetControlAskLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASKLOW,::fabs(value)); } void SetControlAskLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASKLOW,::fabs(value)); } double GetValueChangedAskLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASKLOW); } bool IsIncreasedAskLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASKLOW); } bool IsDecreasedAskLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASKLOW); } //--- Real Volume for the day //--- setting the real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the real day volume, //--- getting the flag of the real day volume change exceeding the (5) growth, (6) decrease value void SetControlVolumeRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } void SetControlVolumeRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } void SetControlVolumeRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } double GetValueChangedVolumeReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME_REAL); } bool IsIncreasedVolumeReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME_REAL); } bool IsDecreasedVolumeReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME_REAL); } //--- Maximum real volume for the day //--- setting the maximum real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the maximum real day volume, //--- getting the flag of the maximum real day volume change exceeding the (5) growth, (6) decrease value void SetControlVolumeHighRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } void SetControlVolumeHighRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } void SetControlVolumeHighRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } double GetValueChangedVolumeHighReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMEHIGH_REAL); } bool IsIncreasedVolumeHighReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMEHIGH_REAL); } bool IsDecreasedVolumeHighReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMEHIGH_REAL); } //--- Minimum real volume for the day //--- setting the minimum real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the minimum real day volume, //--- getting the flag of the minimum real day volume change exceeding the (5) growth, (6) decrease value void SetControlVolumeLowRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } void SetControlVolumeLowRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } void SetControlVolumeLowRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } double GetValueChangedVolumeLowReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMELOW_REAL); } bool IsIncreasedVolumeLowReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMELOW_REAL); } bool IsDecreasedVolumeLowReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMELOW_REAL); } //--- Strike price //--- setting the controlled strike price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) the change value of the strike price, //--- getting the flag of the strike price change exceeding the (5) growth, (6) decrease value void SetControlOptionStrikeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } void SetControlOptionStrikeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } void SetControlOptionStrikeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } double GetValueChangedOptionStrike(void) const { return this.GetControlChangedValue(SYMBOL_PROP_OPTION_STRIKE); } bool IsIncreasedOptionStrike(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_OPTION_STRIKE); } bool IsDecreasedOptionStrike(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_OPTION_STRIKE); } //--- Maximum allowed total volume of unidirectional positions and orders //--- (1) Setting the control level //--- (2) getting the change value of the maximum allowed total volume of unidirectional positions and orders, //--- getting the flag of (3) increasing, (4) decreasing the maximum allowed total volume of unidirectional positions and orders void SetControlVolumeLimitLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME_LIMIT,::fabs(value)); } double GetValueChangedVolumeLimit(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME_LIMIT); } bool IsIncreasedVolumeLimit(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME_LIMIT); } bool IsDecreasedVolumeLimit(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME_LIMIT); } //--- Swap long //--- (1) Setting the control level //--- (2) getting the swap long change value, //--- getting the flag of (3) increasing, (4) decreasing the swap long void SetControlSwapLongLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SWAP_LONG,::fabs(value)); } double GetValueChangedSwapLong(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SWAP_LONG); } bool IsIncreasedSwapLong(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SWAP_LONG); } bool IsDecreasedSwapLong(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SWAP_LONG); } //--- Swap short //--- (1) Setting the control level //--- (2) getting the swap short change value, //--- getting the flag of (3) increasing, (4) decreasing the swap short void SetControlSwapShortLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SWAP_SHORT,::fabs(value)); } double GetValueChangedSwapShort(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SWAP_SHORT); } bool IsIncreasedSwapShort(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SWAP_SHORT); } bool IsDecreasedSwapShort(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SWAP_SHORT); } //--- The total volume of deals in the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total volume of deals during the current session //--- getting (4) the total deal volume change value in the current session, //--- getting the flag of the total deal volume change during the current session exceeding the (5) growth, (6) decrease value void SetControlSessionVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } void SetControlSessionVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } void SetControlSessionVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } double GetValueChangedSessionVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_VOLUME); } bool IsIncreasedSessionVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_VOLUME); } bool IsDecreasedSessionVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_VOLUME); } //--- The total turnover in the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total turnover during the current session //--- getting (4) the total turnover change value in the current session, //--- getting the flag of the total turnover change during the current session exceeding the (5) growth, (6) decrease value void SetControlSessionTurnoverInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } void SetControlSessionTurnoverDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } void SetControlSessionTurnoverLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } double GetValueChangedSessionTurnover(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_TURNOVER); } bool IsIncreasedSessionTurnover(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_TURNOVER); } bool IsDecreasedSessionTurnover(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_TURNOVER); } //--- The total volume of open positions //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total volume of open positions during the current session //--- getting (4) the change value of the open positions total volume in the current session, //--- getting the flag of the open positions total volume change during the current session exceeding the (5) growth, (6) decrease value void SetControlSessionInterestInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } void SetControlSessionInterestDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } void SetControlSessionInterestLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } double GetValueChangedSessionInterest(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_INTEREST); } bool IsIncreasedSessionInterest(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_INTEREST); } bool IsDecreasedSessionInterest(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_INTEREST); } //--- The total volume of Buy orders at the moment //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current total buy order volume //--- getting (4) the change value of the current total buy order volume, //--- getting the flag of the current total buy orders' volume change exceeding the (5) growth, (6) decrease value void SetControlSessionBuyOrdVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionBuyOrdVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionBuyOrdVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value));} double GetValueChangedSessionBuyOrdVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } bool IsIncreasedSessionBuyOrdVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } bool IsDecreasedSessionBuyOrdVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } //--- The total volume of Sell orders at the moment //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current total sell order volume //--- getting (4) the change value of the current total sell order volume, //--- getting the flag of the current total sell orders' volume change exceeding the (5) growth, (6) decrease value void SetControlSessionSellOrdVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionSellOrdVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionSellOrdVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value));} double GetValueChangedSessionSellOrdVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } bool IsIncreasedSessionSellOrdVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } bool IsDecreasedSessionSellOrdVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } //--- Session open price //--- setting the controlled session open price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the session open price, //--- getting the flag of the session open price change exceeding the (5) growth, (6) decrease value void SetControlSessionPriceOpenInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } void SetControlSessionPriceOpenDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } void SetControlSessionPriceOpenLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } double GetValueChangedSessionPriceOpen(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_OPEN); } bool IsIncreasedSessionPriceOpen(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_OPEN); } bool IsDecreasedSessionPriceOpen(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_OPEN); } //--- Session close price //--- setting the controlled session close price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the session close price, //--- getting the flag of the session close price change exceeding the (5) growth, (6) decrease value void SetControlSessionPriceCloseInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } void SetControlSessionPriceCloseDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } void SetControlSessionPriceCloseLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } double GetValueChangedSessionPriceClose(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_CLOSE); } bool IsIncreasedSessionPriceClose(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_CLOSE); } bool IsDecreasedSessionPriceClose(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_CLOSE); } //--- The average weighted session price //--- setting the controlled session average weighted price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the average weighted session price, //--- getting the flag of the average weighted session price change exceeding the (5) growth, (6) decrease value void SetControlSessionPriceAWInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_AW,::fabs(value)); } void SetControlSessionPriceAWDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_AW,::fabs(value)); } void SetControlSessionPriceAWLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_AW,::fabs(value)); } double GetValueChangedSessionPriceAW(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_AW); } bool IsIncreasedSessionPriceAW(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_AW); } bool IsDecreasedSessionPriceAW(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_AW); } //---
我们研究所声明方法的实现,并修改现有的方法。
在类构造函数中进行一些微调:
//+------------------------------------------------------------------+ //| Closed parametric constructor | //+------------------------------------------------------------------+ CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index) { this.m_name=name; this.m_type=COLLECTION_SYMBOLS_ID; if(!this.Exist()) { ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\"",": ",TextByLanguage("Ошибка. Такого символа нет на сервере","Error. No such symbol on the server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } bool select=::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); ::ResetLastError(); if(!select) { if(!this.SetToMarketWatch()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in market watch. Error: "),this.m_global_error); } } ::ResetLastError(); if(!::SymbolInfoTick(this.m_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); } //--- Initialize control data this.SetControlDataArraySizeLong(SYMBOL_PROP_INTEGER_TOTAL); this.SetControlDataArraySizeDouble(SYMBOL_PROP_DOUBLE_TOTAL); this.ResetChangesParams(); this.ResetControlsParams(); //--- Initialize symbol data this.Reset(); this.InitMarginRates(); #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "),this.m_global_error); return; } #endif //--- Save integer properties this.m_long_prop[SYMBOL_PROP_STATUS] = symbol_status; this.m_long_prop[SYMBOL_PROP_INDEX_MW] = index; this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_DIGITS] = ::SymbolInfoInteger(this.m_name,SYMBOL_DIGITS); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_SPREAD_FLOAT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD_FLOAT); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_TRADE_MODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_MODE); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_EXEMODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_EXEMODE); this.m_long_prop[SYMBOL_PROP_SWAP_ROLLOVER3DAYS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SWAP_ROLLOVER3DAYS); this.m_long_prop[SYMBOL_PROP_TIME] = this.TickTime(); this.m_long_prop[SYMBOL_PROP_EXIST] = this.SymbolExists(); this.m_long_prop[SYMBOL_PROP_CUSTOM] = this.SymbolCustom(); this.m_long_prop[SYMBOL_PROP_MARGIN_HEDGED_USE_LEG] = this.SymbolMarginHedgedUseLEG(); this.m_long_prop[SYMBOL_PROP_ORDER_MODE] = this.SymbolOrderMode(); this.m_long_prop[SYMBOL_PROP_FILLING_MODE] = this.SymbolOrderFillingMode(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); this.m_long_prop[SYMBOL_PROP_ORDER_GTC_MODE] = this.SymbolOrderGTCMode(); this.m_long_prop[SYMBOL_PROP_OPTION_MODE] = this.SymbolOptionMode(); this.m_long_prop[SYMBOL_PROP_OPTION_RIGHT] = this.SymbolOptionRight(); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); this.m_long_prop[SYMBOL_PROP_CHART_MODE] = this.SymbolChartMode(); this.m_long_prop[SYMBOL_PROP_TRADE_CALC_MODE] = this.SymbolCalcMode(); this.m_long_prop[SYMBOL_PROP_SWAP_MODE] = this.SymbolSwapMode(); //--- Save real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_POINT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_POINT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Save string properties this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_name,SYMBOL_PATH); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BASIS)] = this.SymbolBasis(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BANK)] = this.SymbolBank(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_ISIN)] = this.SymbolISIN(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_FORMULA)] = this.SymbolFormula(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PAGE)] = this.SymbolPage(); //--- Save additional integer properties this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------------------------------------------------+ //|Compare CSymbol objects by all possible properties (for sorting lists by a specified symbol object property)| //+------------------------------------------------------------------------------------------------------------+
若要在基准对象类中准确定义对象事件,将品种集合 ID 分配给品种对象类型,并设置整数型和实数型数据数组的大小,以便依据基准父对象跟踪品种对象属性中的事件。 接下来,在整数型和实数型属性数组中初始化可编辑和控制参数。
品种对象的 Refresh() 方法也已修改:
//+------------------------------------------------------------------+ //| Update all symbol data | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { //--- Update quote data if(!this.RefreshRates()) return; #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Initialize event data this.m_is_event=false; this.m_hash_sum=0; //--- Update integer properties this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Fill in the symbol current data for(int i=0;i<SYMBOL_PROP_INTEGER_TOTAL;i++) this.m_long_prop_event[i][3]=this.m_long_prop[i]; for(int i=0;i<SYMBOL_PROP_DOUBLE_TOTAL;i++) this.m_double_prop_event[i][3]=this.m_double_prop[i]; CBaseObj::Refresh(); this.CheckEvents(); } //+------------------------------------------------------------------+
鉴于我们不再需要创建存储当前和先前品种属性状态的结构,因此删除了填充当前品种状态数据的结构。 取而代之的是,我们在基准对象中布置填充整数型和实数型属性数组。
数组填充完毕之后,我们需要调用 CBaseObj 基准对象的 Refresh() 方法,在其中执行搜索已发生的变化,并创建衍生对象基准事件的列表。
在父类中创建基准事件列表之后(如果有事件生成条件),利用 CheckEvents() 方法检查基准事件。 如果它们存在,则创建品种事件列表。
检查事件的方法实现:
//+------------------------------------------------------------------+ //| Check the list of symbol property changes and create an event | //+------------------------------------------------------------------+ void CSymbol::CheckEvents(void) { int total=this.m_list_events_base.Total(); if(total==0) return; for(int i=0;i<total;i++) { CBaseEvent *event=this.GetEventBase(i); if(event==NULL) continue; long lvalue=0; this.UshortToLong(this.MSCfromTime(this.TickTime()),0,lvalue); this.UshortToLong(event.Reason(),1,lvalue); this.UshortToLong(COLLECTION_SYMBOLS_ID,2,lvalue); if(this.EventAdd((ushort)event.ID(),lvalue,event.Value(),this.Name())) this.m_is_event=true; } } //+------------------------------------------------------------------+
如果基准事件列表为空,则退出。
依据基准事件列表进行的循环中,接收下一个事件。 如果收到事件,则创建一个品种事件:
- 从当前时间的毫秒格式里仅提取毫秒值,并将它们加入 至事件 'long' 参数的前两个字节当中
- 获取事件原因 (增加/减少/高于价位/低于价位) 并 将其加入至事件 ‘long' 参数的 第二个双字节
- 品种集合 ID 也被加到事件 ‘long' 参数的第三个双字节
- 将品种事件添加到品种事件列表中,并为品种设置代表事件存在的标志
初始化受控品种数据变量的方法:
//+------------------------------------------------------------------+ //| Initialize the variables of controlled symbol data | //+------------------------------------------------------------------+ void CSymbol::InitControlsParams(void) { this.ResetControlsParams(); } //+------------------------------------------------------------------+
只需调用上述重置受控对象数据值变量的方法即可。
设置控制值和发生变化标志的方法,以及接收发生变化和标志大小的方法:
//+------------------------------------------------------------------+ //| Set the value of the controlled property increase | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyINC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueINC(property,(long)value); else this.SetControlledValueINC(property,(double)value); } //+------------------------------------------------------------------+ //| Set the value of the controlled property decrease | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyDEC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueDEC(property,(long)value); else this.SetControlledValueDEC(property,(double)value); } //+------------------------------------------------------------------+ //| Set the value of the controlled property level | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyLEVEL(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueLEVEL(property,(long)value); else this.SetControlledValueLEVEL(property,(double)value); } //+------------------------------------------------------------------+ //| Set the flag of the symbol property value change | //| exceeding the increase value | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlFlagINC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledFlagINC(property,(long)value); else this.SetControlledFlagINC(property,(double)value); } //+------------------------------------------------------------------+ //| Set the flag of the symbol property value change | //| exceeding the decrease value | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlFlagDEC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledFlagDEC(property,(long)value); else this.SetControlledFlagDEC(property,(double)value); } //+------------------------------------------------------------------+ //| Set the change value of the controlled symbol property | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlChangedValue(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledChangedValue(property,(long)value); else this.SetControlledChangedValue(property,(double)value); } //+------------------------------------------------------------------+ //| Set the Bid or Last price controlled increase | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //|Set the Bid or Last price controlled decrease | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BID) : this.GetControlChangedValue(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Return the flag of the Bid or Last price change | //| exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Return the flag of the Bid or Last price change | //| exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Set the controlled increase value | //| of the maximum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the controlled decrease value | //| of the maximum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the maximum Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the maximum Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDHIGH) : this.GetControlChangedValue(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the maximum | //| Bid or Last price exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the maximum | //| Bid or Last price exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Set the controlled increase value | //| of the minimum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the controlled decrease value | //| of the minimum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the minimum Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowLevev(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the minimum Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDLOW) : this.GetControlChangedValue(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the minimum | //| Bid or Last price exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the minimum | //| Bid or Last price exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+
在改进基准对象类时,我们已经研究过类似的方法。 在此,取决于所需的品种对象属性,调用所研究的方法。
至此,品种对象类的改进完毕。
现在只需稍微完善一下品种集合类即可。
打开 \MQL5\Include\DoEasy\Collections\SymbolsCollection.mqh 文件,并进行必要的修改。
由于我们不再需要为每个对象创建单独的事件枚举,那么为 “最后一个品种事件” 变量和 GetLastEvent()方法设置 “int” 类型来取代以前的 ENUM_SYMBOL_EVENT 类型:
int m_last_event; // The last event
int GetLastEvent(void) const { return this.m_last_event; }
由于现在所有品种事件(以及任何衍生对象的事件)都在基准对象类中处理,因此将 EventDescription() 方法重命名为 EventMWDescription(),并将存有“市场观察”窗口事件枚举类型的变量传递给方法:
//--- Return the description of the (1) Market Watch window event, (2) mode of working with symbols string EventMWDescription(const ENUM_MW_EVENT event); string ModeSymbolsListDescription(void);
由于枚举名称已更改,操控“市场观察”窗口的方法进行了小幅修改(枚举名称和事件变量类型已替换):
//+------------------------------------------------------------------+ //| Working with market watch window events | //+------------------------------------------------------------------+ void CSymbolsCollection::MarketWatchEventsControl(const bool send_events=true) { ::ResetLastError(); //--- If no current prices are received, exit if(!::SymbolInfoTick(::Symbol(),this.m_tick)) { this.m_global_error=::GetLastError(); return; } uchar array[]; int sum=0; this.m_hash_sum=0; //--- Calculate the hash sum of all visible symbols in the Market Watch window this.m_total_symbols=this.SymbolsTotalVisible(); //--- In the loop by all Market Watch window symbols int total_symbols=::SymbolsTotal(true); for(int i=0;i<total_symbols;i++) { //--- get a symbol name by index string name=::SymbolName(i,true); //--- skip if invisible if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- write symbol name (characters) codes to the uchar array ::StringToCharArray(name,array); //--- in a loop by the resulting array, sum up the values of all array cells creating the symbol code for(int j=::ArraySize(array)-1;j>WRONG_VALUE;j--) sum+=array[j]; //--- add the symbol code and the loop index specifying the symbol index in the market watch list to the hash sum m_hash_sum+=i+sum; } //--- If sending events is disabled, create the collection list and exit saving the current hash some as the previous one if(!send_events) { //--- Clear the list this.m_list_all_symbols.Clear(); //--- Clear the collection list this.CreateSymbolsList(true); //--- Clear the market watch window snapshot this.CopySymbolsNames(); //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; return; } //--- If the hash sum of symbols in the Market Watch window has changed if(this.m_hash_sum!=this.m_hash_sum_prev) { //--- Define the Market Watch window event this.m_delta_symbol=this.m_total_symbols-this.m_total_symbol_prev; ushort event_id= (ushort( this.m_total_symbols>this.m_total_symbol_prev ? MARKET_WATCH_EVENT_SYMBOL_ADD : this.m_total_symbols<this.m_total_symbol_prev ? MARKET_WATCH_EVENT_SYMBOL_DEL : MARKET_WATCH_EVENT_SYMBOL_SORT) ); //--- Adding a symbol to the Market Watch window if(event_id==MARKET_WATCH_EVENT_SYMBOL_ADD) { string name=""; //--- In the loop by all Market Watch window symbols int total=::SymbolsTotal(true), index=WRONG_VALUE; for(int i=0;i<total;i++) { //--- get the symbol name and check its "visibility". Skip it if invisible name=::SymbolName(i,true); if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- If there is no symbol in the collection symbol list yet if(!this.IsPresentSymbolInList(name)) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- create the symbol collection snapshot this.CopySymbolsNames(); //--- get a new symbol index in the Market Watch window index=this.GetSymbolIndexByName(name); //--- If the "Adding a new symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),index,name)) { //--- send the event to the chart: //--- long value = event time in milliseconds, double value = symbol index, string value = added symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,name); } } } //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Remove a symbol from the Market Watch window else if(event_id==MARKET_WATCH_EVENT_SYMBOL_DEL) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- In a loop by the market watch window snapshot int total=this.m_list_names.Total(); for(int i=0; i<total;i++) { //--- get a symbol name string name=this.m_list_names.At(i); if(name==NULL) continue; //--- if no symbol with such a name exists in the collection symbol list if(!this.IsPresentSymbolInList(name)) { //--- If the "Removing a symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),WRONG_VALUE,name)) { //--- send the event to the chart: //--- long value = event tine in milliseconds, double value = -1 for an absent symbol, string value = a removed symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),WRONG_VALUE,name); } } } //--- Recreate the market watch snapshot this.CopySymbolsNames(); //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Sorting symbols in the Market Watch window else if(event_id==MARKET_WATCH_EVENT_SYMBOL_SORT) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- set sorting of the collection list as sorting by index this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); //--- recreate the collection list this.CreateSymbolsList(true); //--- get the current symbol index in the Market Watch window int index=this.GetSymbolIndexByName(Symbol()); //--- send the event to the chart: //--- long value = event time in milliseconds, double value = current symbol index, string value = current symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,::Symbol()); } //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
事件变量类型也已在操控品种集合事件列表的方法中进行了修改:
//+------------------------------------------------------------------+ //| Working with the events of the collection symbol list | //+------------------------------------------------------------------+ void CSymbolsCollection::SymbolsEventsControl(void) { this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); //--- The full update of all collection symbols int total=this.m_list_all_symbols.Total(); for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.Refresh(); if(!symbol.IsEvent()) continue; this.m_is_event=true; CArrayObj *list=symbol.GetListEvents(); if(list==NULL) continue; this.m_event_code=symbol.GetEventCode(); int n=list.Total(); for(int j=0; j<n; j++) { CEventBaseObj *event=list.At(j); if(event==NULL) continue; ushort event_id=event.ID(); this.m_last_event=event_id; if(this.EventAdd((ushort)event.ID(),event.LParam(),event.DParam(),event.SParam())) { ::EventChartCustom(this.m_chart_id,(ushort)event_id,event.LParam(),event.DParam(),event.SParam()); } } } } //+------------------------------------------------------------------+
在返回市场观察窗口事件字符串描述的方法中,也将事件枚举常量的名称做了修改:
//+------------------------------------------------------------------+ //| Return the Market Watch window event description | //+------------------------------------------------------------------+ string CSymbolsCollection::EventMWDescription(const ENUM_MW_EVENT event) { return ( event==MARKET_WATCH_EVENT_SYMBOL_ADD ? TextByLanguage("В окно \"Обзор рынка\" добавлен символ","Added symbol to \"Market Watch\" window") : event==MARKET_WATCH_EVENT_SYMBOL_DEL ? TextByLanguage("Из окна \"Обзор рынка\" удалён символ","Removed symbol from \"Market Watch\" window") : event==MARKET_WATCH_EVENT_SYMBOL_SORT ? TextByLanguage("Изменено расположение символов в окне \"Обзор рынка\"","Changed arrangement of symbols in \"Market Watch\" window") : EnumToString(event) ); } //+------------------------------------------------------------------+
现在我们来改进 CEngine 类。 打开 \MQL5\Include\DoEasy\Engine.mqh 文件,并进行必要的修改:
在品种属性中存储最后事件的变量,以及返回变量值的方法,其类型均为 'int':
int m_last_symbol_event; // Last event in the symbol properties
int LastSymbolsEvent(void) const { return this.m_last_symbol_event; }
在类的公开部分,添加从 'long' 参数容器中按指定存储索引提取 'ushort' 数值的方法:
//--- Retrieve a necessary 'ushort' number from the packed 'long' value ushort LongToUshortFromByte(const long source_value,const uchar index) const;
另外,编写三种方法,可立即从事件 “ long” 参数返回事件毫秒、原因和源头:
//--- Return event (1) milliseconds, (2) reason and (3) source from its 'long' value ushort EventMSC(const long lparam) const { return this.LongToUshortFromByte(lparam,0); } ushort EventReason(const long lparam) const { return this.LongToUshortFromByte(lparam,1); } ushort EventSource(const long lparam) const { return this.LongToUshortFromByte(lparam,2); }
由于零值是任何对象的第一个整数型属性,因此在类的构造函数初始化清单中 修改存储最后一个品种事件初始值的变量 — 现在将使用负数值对其进行初始化:
//+------------------------------------------------------------------+ //| CEngine constructor | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true), m_last_trade_event(TRADE_EVENT_NO_EVENT), m_last_account_event(ACCOUNT_EVENT_NO_EVENT), m_last_symbol_event(WRONG_VALUE), m_global_error(ERR_SUCCESS) {
从 'long' 容器当中按字节索引自相应位置提取 “ushort” 数值的方法:
//+------------------------------------------------------------------+ //| Retrieve a necessary 'ushort' number from the packed 'long' value| //+------------------------------------------------------------------+ ushort CEngine::LongToUshortFromByte(const long source_value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } long res=source_value>>(16*index); return ushort(res &=0xFFFF); } //+------------------------------------------------------------------+
方法接收一个 'long' 值,可从其内提取 'ushort' 数值,和该数值所处的字节索引(上述已考虑了 “ushort” 数值在 ’long' 容器内的位置映射表)。 然后,检查索引规范的有效性。 如果索引无效,则会显示错误消息,并返回 0。
接着,将 'long' 数值按位右移 16 * 索引,应用掩码来“湮灭”其余的高位,并返回以这种方式获取的 “ushort” 数值。
若要在 MQL4 中工作,我们需要通知编译器 ERR_ZEROSIZE_ARRAY 数组零大小错误。
已知 MQL4 编译器最适合数组零大小的错误是“无效数组”。 我们将其设置为数组零大小错误的替代方法。
打开 \MQL5\Include\DoEasy\ToMQL4.mqh 文件,并针对 MQL4 编译器,加入未知的错误代码:
//+------------------------------------------------------------------+ //| ToMQL4.mqh | //| Copyright 2017, Artem A. Trishkin, Skype artmedia70 | //| https://www.mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70" #property link "https://www.mql5.com/en/users/artmedia70" #property strict #ifdef __MQL4__ //+------------------------------------------------------------------+ //| Error codes | //+------------------------------------------------------------------+ #define ERR_SUCCESS (ERR_NO_ERROR) #define ERR_MARKET_UNKNOWN_SYMBOL (ERR_UNKNOWN_SYMBOL) #define ERR_ZEROSIZE_ARRAY (ERR_ARRAY_INVALID) //+------------------------------------------------------------------+
这些就是我们要做的所有更改,以便 CBaseObj 对象及其所有衍生类在启动后能够操控新事件。
测试所有函数库对象的基准对象的事件功能
为了测试基准对象的新事件功能,取用上一篇文章中的 EA,并将其命名为 TestDoEasyPart17.mq5,并保存在 \MQL5\Experts\TestDoEasy\Part17 文件夹里。
我们来测试当前品种的点差变化,范围 4 个点(增加和减少),并将点差大小控制在 15 个点。 对于出价(Bid),将其值增加/减少 +/- 10 个点,并跟踪价格与 1.13700 价位的交叉。
若要设置上述监控值,只需在此示例的 OnInit() 处理函数中添加以下代码:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Calling the function displays the list of enumeration constants in the journal //--- (the list is set in the strings 22 and 25 of the DELib.mqh file) for checking the constants validity //EnumNumbersTest(); //--- Set EA global variables prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_"; for(int i=0;i<TOTAL_BUTT;i++) { butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i); butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i); } lot=NormalizeLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0)); magic_number=InpMagic; stoploss=InpStopLoss; takeprofit=InpTakeProfit; distance_pending=InpDistance; distance_stoplimit=InpDistanceSL; slippage=InpSlippage; trailing_stop=InpTrailingStop*Point(); trailing_step=InpTrailingStep*Point(); trailing_start=InpTrailingStart; stoploss_to_modify=InpStopLossModify; takeprofit_to_modify=InpTakeProfitModify; //--- Check if working with the full list is selected used_symbols_mode=InpModeUsedSymbols; if((ENUM_SYMBOLS_MODE)used_symbols_mode==SYMBOLS_MODE_ALL) { int total=SymbolsTotal(false); string ru_n="\nКоличество символов на сервере "+(string)total+".\nМаксимальное количество: "+(string)SYMBOLS_COMMON_TOTAL+" символов."; string en_n="\nThe number of symbols on server "+(string)total+".\nMaximal number: "+(string)SYMBOLS_COMMON_TOTAL+" symbols."; string caption=TextByLanguage("Внимание!","Attention!"); string ru="Выбран режим работы с полным списком.\nВ этом режиме первичная подготовка списка коллекции символов может занять длительное время."+ru_n+"\nПродолжить?\n\"Нет\" - работа с текущим символом \""+Symbol()+"\""; string en="Full list mode selected.\nIn this mode, the initial preparation of the collection symbols list may take a long time."+en_n+"\nContinue?\n\"No\" - working with the current symbol \""+Symbol()+"\""; string message=TextByLanguage(ru,en); int flags=(MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2); int mb_res=MessageBox(message,caption,flags); switch(mb_res) { case IDNO : used_symbols_mode=SYMBOLS_MODE_CURRENT; break; default: break; } } //--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,used_symbols,array_used_symbols); //--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Displaying the selected mode of working with the symbol object collection Print(engine.ModeSymbolsListDescription(),TextByLanguage(". Количество используемых символов: ",". Number of symbols used: "),engine.GetSymbolsCollectionTotal()); //--- Set controlled values for the current symbol CSymbol* symbol=engine.GetSymbolCurrent(); if(symbol!=NULL) { //--- Set control of the current symbol price increase by 10 points symbol.SetControlBidInc(10*Point()); //--- Set control of the current symbol price decrease by 10 points symbol.SetControlBidDec(10*Point()); //--- Set control of the current symbol spread increase by 4 points symbol.SetControlSpreadInc(4); //--- Set control of the current symbol spread decrease by 4 points symbol.SetControlSpreadDec(4); //--- Set control of the current spread by the value of 15 points symbol.SetControlSpreadLevel(15); //--- Set control of the price crossing the level of 1.13700 symbol.SetControlBidLevel(1.13700); } //--- Check and remove remaining EA graphical objects if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel if(!CreateButtons(InpButtShiftX,InpButtShiftY)) return INIT_FAILED; //--- Set trailing activation button status ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on); //--- Set CTrade trading class parameters #ifdef __MQL5__ trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); #endif //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
这是设置跟踪品种参数的测试示例,因此我们立即在 OnInit() 中设置所需的控制值。
然而,由于所有方法都存在于基准对象中,因此无可阻止我们在操作过程中基于某些当前标准快速更改所跟踪的品种值。 只剩下获取自 CBaseObj 继承的任何对象的访问权,以便获取设置受控参数的方法,和接收已变化参数的方法,还有根据程序内置的逻辑修改控制值的方法 — 即可以编程方式,或或从随后创建的函数库图形外壳中获取。
从 EA 的 OnTick() 处理程序中,删除存储最后一个品种事件的变量。 我们还有其他工具可以跟踪品种事件,而不是简单比较当前状态和先前状态。
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Initializing the last events static ENUM_TRADE_EVENT last_trade_event=WRONG_VALUE; static ENUM_ACCOUNT_EVENT last_account_event=WRONG_VALUE; static ENUM_SYMBOL_EVENT last_symbol_event=WRONG_VALUE; //--- If working in the tester if(MQLInfoInteger(MQL_TESTER)) {
更改函数库关于品种集合事件的处理程序:
//+------------------------------------------------------------------+ //| Handling DoEasy library events | //+------------------------------------------------------------------+ void OnDoEasyEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { int idx=id-CHARTEVENT_CUSTOM; string event="::"+string(idx); //--- Retrieve (1) event time milliseconds, (2) reason and (3) source from lparam, as well as (4) set the exact event time ushort msc=engine.EventMSC(lparam); ushort reason=engine.EventReason(lparam); ushort source=engine.EventSource(lparam); long time=TimeCurrent()*1000+msc; //--- Handling market watch window events if(idx>MARKET_WATCH_EVENT_NO_EVENT && idx<SYMBOL_EVENTS_NEXT_CODE) { string name=""; //--- Market Watch window event string descr=engine.GetMWEventDescription((ENUM_MW_EVENT)idx); name=(idx==MARKET_WATCH_EVENT_SYMBOL_SORT ? "" : ": "+sparam); Print(TimeMSCtoString(lparam)," ",descr,name); } //--- Handling symbol events if(source==COLLECTION_SYMBOLS_ID) { CSymbol *symbol=engine.GetSymbolObjByName(sparam); if(symbol==NULL) return; //--- Number of decimal places in the event value - in case of a 'long' event, it is 0, otherwise - Digits() of a symbol int digits=(idx<SYMBOL_PROP_INTEGER_TOTAL ? 0 : symbol.Digits()); //--- Event text description string id_descr=(idx<SYMBOL_PROP_INTEGER_TOTAL ? symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_INTEGER)idx) : symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_DOUBLE)idx)); //--- Property change text value string value=DoubleToString(dparam,digits); //--- Check event reasons and display its description in the journal if(reason==BASE_EVENT_REASON_INC) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_DEC) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_MORE_THEN) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_LESS_THEN) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_EQUALS) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } } //--- Handling trading events if(idx>TRADE_EVENT_NO_EVENT && idx<TRADE_EVENTS_NEXT_CODE) { event=EnumToString((ENUM_TRADE_EVENT)ushort(idx)); int digits=(int)SymbolInfoInteger(sparam,SYMBOL_DIGITS); } //--- Handling account events else if(idx>ACCOUNT_EVENT_NO_EVENT && idx<ACCOUNT_EVENTS_NEXT_CODE) { Print(TimeMSCtoString(lparam)," ",sparam,": ",engine.GetAccountEventDescription((ENUM_ACCOUNT_EVENT)idx)); //--- if this is an equity increase if((ENUM_ACCOUNT_EVENT)idx==ACCOUNT_EVENT_EQUITY_INC) { //--- Close a position with the highest profit exceeding zero when the equity exceeds the value, //--- specified in the CAccountsCollection::InitControlsParams() method for //--- the m_control_equity_inc variable tracking the equity increase by 15 units (by default) //--- AccountCollection file, InitControlsParams() method, string 1199 //--- Get the list of all open positions CArrayObj* list_positions=engine.GetListMarketPosition(); //--- Select positions with the profit exceeding zero list_positions=CSelect::ByOrderProperty(list_positions,ORDER_PROP_PROFIT_FULL,0,MORE); if(list_positions!=NULL) { //--- Sort the list by profit considering commission and swap list_positions.Sort(SORT_BY_ORDER_PROFIT_FULL); //--- Get the position index with the highest profit int index=CSelect::FindOrderMax(list_positions,ORDER_PROP_PROFIT_FULL); if(index>WRONG_VALUE) { COrder* position=list_positions.At(index); if(position!=NULL) { //--- Get a ticket of a position with the highest profit and close the position by a ticket #ifdef __MQL5__ trade.PositionClose(position.Ticket()); #else PositionClose(position.Ticket(),position.Volume()); #endif } } } } } } //+------------------------------------------------------------------+
所有修改都在代码中加上注释,且仅与从品种对象获取事件描述,并将其显示在日志中有关,这取决于事件原因。 在非测试处理程序中,添加正常事件处理程序,取代日志中显示消息。
编译并在测试器中启动 EA:
如我们所见,当点差增加或减少超过指定的控制值时,会将相应的记录发送到日志。 出价(Bid)的变化(其涨跌幅度超过 10 点)也会伴有日志记录。 最后,当出价(Bid)与指定的控制价位交叉时,也会发送一个事件,并显示日志记录。
所以,我们已创建了基准对象,从而可以跟踪其任何衍生对象的事件,并将其发送到控制程序,在该程序中,可以对其进行跟踪,并根据其内置逻辑做出响应,设置新的跟踪值,且程序操作逻辑可灵活管理这些价位。
下一步是什么?
在下一篇文章中,我们将基于 CBaseObj 基准对象类的事件功能来实现帐户对象及其事件的操控。
文后附有当前版本含糊库的所有文件,以及测试 EA 文件,供您测试和下载。
请在评论中留下您的问题、意见和建议。
系列中的前几篇文章:
第一部分 概念,数据管理
第二部分 历史订单和成交集合
第三部分 在场订单和持仓集合,安排搜索
第四部分 交易事件, 概念
第五部分 交易事件类和集合。 将事件发送至程序
第六部分 净持帐户事件
第七部分 StopLimit 挂单激活事件,为订单和持仓修改事件准备功能
第八部分 订单和持仓修改事件
第九部分 与 MQL4 的兼容性 - 准备数据
第十部分 与 MQL4 的兼容性 - 开仓和激活挂单事件
第十一部分 与 MQL4 的兼容性 - 平仓事件
第十二部分 帐户对象类和帐户对象集合
第十三部分 账户对象事件
第十四部分 品种对象
第十五部份 品种对象集合
第十六部分 品种集合事件
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/7124