MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第13部): 口座オブジェクトイベント
内容
口座イベントの概念
以前(第9部~第11部)、注文イベントとポジションイベントを追跡し、検出された変更に関するデータをCEngineメインライブラリオブジェクトに送信する個別のクラスを作成しました。
口座イベントを追跡するには、別のメソッドを使用します。イベントは単一の口座(端末が現在接続されている口座)でのみ追跡できるため、そのための別のクラスは冗長になります。代わりに、口座コレクションクラスでイベントを直接操作するメソッドを作成します。
口座プロパティの変更を検出するには、現在の口座プロパティを以前のステータスと比較します。変更が検出されると、イベントが管理プログラムチャートに送信されます。
口座イベントを追跡するための機能のいくつかは、前の記事で口座オブジェクトコレクションを開発するときに既に実装しています。本稿では、既存の機能を改善して完全に使用できるようにします。
口座イベントを使用するためのメソッド
必要な列挙とマクロ置換をDefines.mqhファイルで作成することから始めましょう。口座の文字列プロパティに割り当てられた実際のサイズをバイト単位で開発者から受け取ったため、CAccountクラスコードでそれらを厳密に設定し、口座オブジェクトの文字列プロパティを格納するためのuchar配列サイズを設定するマクロ置換の必要性を排除します。 Defines.mqhからマクロ置換を 削除します。
#define UCHAR_ARRAY_SIZE (64) // Size of uchar arrays for storing string properties
また、口座イベントコードだけでなく実装された取引イベントもプログラムに送信するため、口座オブジェクトを使用するのに必要なすべての列挙とマクロ置換を、取引イベントを使用するためのデータの後に、ファイルの最後に追加することにしました 。つまり、口座イベントコードは、最後の取引イベントコード+1から始まります。取引イベントの数が増えた場合、口座イベントコードの値を書き換えないですむように、すべての取引イベントの総数を含むマクロ置換を宣言します。また、他のイベント(銘柄イベントなど)の実装に備えて、口座イベントの総数を指定するマクロ置換を設定します。この場合、これらの新しいイベントのコードは、口座イベントの総数+1から始まります。
口座で可能な取引イベントのリストの最後に、最後の取引イベント+1の数値に対応する値を指定してマクロ置換を挿入します。
//+------------------------------------------------------------------+ //| 口座で可能な取引イベントのリスト | //+------------------------------------------------------------------+ enum ENUM_TRADE_EVENT { TRADE_EVENT_NO_EVENT = 0, // No trading event TRADE_EVENT_PENDING_ORDER_PLASED, // 未決注文が出された TRADE_EVENT_PENDING_ORDER_REMOVED, // 未決注文の削除 //--- ENUM_DEAL_TYPE列挙体メンバに一致する列挙体メンバ //--- (constant order below should not be changed, no constants should be added/deleted) TRADE_EVENT_ACCOUNT_CREDIT = DEAL_TYPE_CREDIT, // Accruing credit (3) TRADE_EVENT_ACCOUNT_CHARGE, // 追加の課金 TRADE_EVENT_ACCOUNT_CORRECTION, // エントリの修正 TRADE_EVENT_ACCOUNT_BONUS, // Accruing bonuses TRADE_EVENT_ACCOUNT_COMISSION, // 追加手数料 TRADE_EVENT_ACCOUNT_COMISSION_DAILY, // Commission charged at the end of a trading day TRADE_EVENT_ACCOUNT_COMISSION_MONTHLY, // Commission charged at the end of a trading month TRADE_EVENT_ACCOUNT_COMISSION_AGENT_DAILY, // 取引日の終わりに請求されるエージェント手数料 TRADE_EVENT_ACCOUNT_COMISSION_AGENT_MONTHLY, // 月末に請求される代理人手数料 TRADE_EVENT_ACCOUNT_INTEREST, // Accrued interest on free funds TRADE_EVENT_BUY_CANCELLED, // キャンセルされた買い取引 TRADE_EVENT_SELL_CANCELLED, // キャンセルされた売り取引 TRADE_EVENT_DIVIDENT, // Accruing dividends TRADE_EVENT_DIVIDENT_FRANKED, // Accruing franked dividends TRADE_EVENT_TAX = DEAL_TAX, // Tax //--- constants related to the DEAL_TYPE_BALANCE deal type from the DEAL_TYPE_BALANCE enumeration TRADE_EVENT_ACCOUNT_BALANCE_REFILL = DEAL_TAX+1, // Replenishing account balance TRADE_EVENT_ACCOUNT_BALANCE_WITHDRAWAL = DEAL_TAX+2, // Withdrawing funds from an account //--- Remaining possible trading events//--- (constant order below can be changed, constants can be added/deleted) TRADE_EVENT_PENDING_ORDER_ACTIVATED = DEAL_TAX+3, // Pending order activated by price TRADE_EVENT_PENDING_ORDER_ACTIVATED_PARTIAL, // 格による未決注文の部分的な発動 TRADE_EVENT_POSITION_OPENED, // ポジションが開いた TRADE_EVENT_POSITION_OPENED_PARTIAL, // ポジションが部分的に開いた TRADE_EVENT_POSITION_CLOSED, // ポジションが閉じた TRADE_EVENT_POSITION_CLOSED_BY_POS, // 反対方向のポジションによってポジションが閉じた TRADE_EVENT_POSITION_CLOSED_BY_SL, // ストップロスによってポジションが閉じた TRADE_EVENT_POSITION_CLOSED_BY_TP, // テイクプロフィットによってポジションが閉じた TRADE_EVENT_POSITION_REVERSED_BY_MARKET, // Position reversal by a new deal (netting) TRADE_EVENT_POSITION_REVERSED_BY_PENDING, // Position reversal by activating a pending order (netting) TRADE_EVENT_POSITION_REVERSED_BY_MARKET_PARTIAL, // Position reversal by partial market order execution (netting) TRADE_EVENT_POSITION_REVERSED_BY_PENDING_PARTIAL, // Position reversal by partial pending order activation (netting) TRADE_EVENT_POSITION_VOLUME_ADD_BY_MARKET, // Added volume to a position by a new deal (netting) TRADE_EVENT_POSITION_VOLUME_ADD_BY_MARKET_PARTIAL, // Added volume to a position by partial activation of an order (netting) TRADE_EVENT_POSITION_VOLUME_ADD_BY_PENDING, // Added volume to a position by activating a pending order (netting) TRADE_EVENT_POSITION_VOLUME_ADD_BY_PENDING_PARTIAL, // Added volume to a position by partial activation of a pending order (netting) TRADE_EVENT_POSITION_CLOSED_PARTIAL, // ポジションが部分的に閉じた TRADE_EVENT_POSITION_CLOSED_PARTIAL_BY_POS, // Position closed partially by an opposite one TRADE_EVENT_POSITION_CLOSED_PARTIAL_BY_SL, // ストップロスによってポジションが部分的に閉じた TRADE_EVENT_POSITION_CLOSED_PARTIAL_BY_TP, // テイクプロフィットによってポジションが部分的に閉じた TRADE_EVENT_TRIGGERED_STOP_LIMIT_ORDER, // StopLimit order activation TRADE_EVENT_MODIFY_ORDER_PRICE, // Changing order price TRADE_EVENT_MODIFY_ORDER_PRICE_STOP_LOSS, // Changing order and StopLoss price TRADE_EVENT_MODIFY_ORDER_PRICE_TAKE_PROFIT, // Changing order and TakeProfit price TRADE_EVENT_MODIFY_ORDER_PRICE_STOP_LOSS_TAKE_PROFIT, // Changing order, StopLoss and TakeProfit price TRADE_EVENT_MODIFY_ORDER_STOP_LOSS_TAKE_PROFIT, // Changing order's StopLoss and TakeProfit price TRADE_EVENT_MODIFY_ORDER_STOP_LOSS, // Changing order Stop Loss TRADE_EVENT_MODIFY_ORDER_TAKE_PROFIT, // Changing order Take Profit TRADE_EVENT_MODIFY_POSITION_STOP_LOSS_TAKE_PROFIT, // Changing position StopLoss and TakeProfit TRADE_EVENT_MODIFY_POSITION_STOP_LOSS, // Changing position StopLoss TRADE_EVENT_MODIFY_POSITION_TAKE_PROFIT, // Changing position TakeProfit }; #define TRADE_EVENTS_NEXT_CODE (TRADE_EVENT_MODIFY_POSITION_TAKE_PROFIT+1)// The code of the next event after the last trading event code //+------------------------------------------------------------------+
口座イベントコードはここで始まります。
前の記事では、口座の整数、実数、文字列プロパティと可能な並び替え基準を設定して、口座のイベントを使用するためのデータの前に配置しました。ここでは、これらを最後に移動して、口座イベントを処理するための追加データ(口座イベントフラグと可能な口座イベントのリスト)を提供します。
//+------------------------------------------------------------------+ //| Data for working with accounts | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of account event flags | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_EVENT_FLAGS { ACCOUNT_EVENT_FLAG_NO_EVENT = 0, // No event ACCOUNT_EVENT_FLAG_LEVERAGE = 1, // Changing the leverage ACCOUNT_EVENT_FLAG_LIMIT_ORDERS = 2, // Changing the maximum allowed number of active pending orders ACCOUNT_EVENT_FLAG_TRADE_ALLOWED = 4, // Changing permission to trade for the account ACCOUNT_EVENT_FLAG_TRADE_EXPERT = 8, // Changing permission for auto trading for the account ACCOUNT_EVENT_FLAG_BALANCE = 16, // The balance exceeds the specified change value +/- ACCOUNT_EVENT_FLAG_EQUITY = 32, // The equity exceeds the specified change value +/- ACCOUNT_EVENT_FLAG_PROFIT = 64, // The profit exceeds the specified change value +/- ACCOUNT_EVENT_FLAG_CREDIT = 128, // Changing the credit in a deposit currency ACCOUNT_EVENT_FLAG_MARGIN = 256, // The reserved margin on an account in the deposit currency exceeds the specified change value +/- ACCOUNT_EVENT_FLAG_MARGIN_FREE = 512, // The free funds available for opening a position in a deposit currency exceed the specified change value +/- ACCOUNT_EVENT_FLAG_MARGIN_LEVEL = 1024, // The margin level on an account in % exceeds the specified change value +/- ACCOUNT_EVENT_FLAG_MARGIN_INITIAL = 2048, // The funds reserved on an account to ensure a guarantee amount for all pending orders exceed the specified change value +/- ACCOUNT_EVENT_FLAG_MARGIN_MAINTENANCE = 4096, // The funds reserved on an account to ensure a minimum amount for all open positions exceed the specified change value +/- ACCOUNT_EVENT_FLAG_MARGIN_SO_CALL = 8192, // Changing the Margin Call level ACCOUNT_EVENT_FLAG_MARGIN_SO_SO = 16384, // Changing the Stop Out level ACCOUNT_EVENT_FLAG_ASSETS = 32768, // The current assets on an account exceed the specified change value +/- ACCOUNT_EVENT_FLAG_LIABILITIES = 65536, // The current liabilities on an account exceed the specified change value +/- ACCOUNT_EVENT_FLAG_COMISSION_BLOCKED = 131072, // The current sum of blocked commissions on an account exceeds the specified change value +/- }; //+------------------------------------------------------------------+ //| List of possible account events | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_EVENT { ACCOUNT_EVENT_NO_EVENT = TRADE_EVENTS_NEXT_CODE, // No event ACCOUNT_EVENT_LEVERAGE_INC, // Increasing the leverage ACCOUNT_EVENT_LEVERAGE_DEC, // Decreasing the leverage ACCOUNT_EVENT_LIMIT_ORDERS_INC, // Increasing the maximum allowed number of active pending orders ACCOUNT_EVENT_LIMIT_ORDERS_DEC, // Decreasing the maximum allowed number of active pending orders ACCOUNT_EVENT_TRADE_ALLOWED_ON, // Enabling trading for the account ACCOUNT_EVENT_TRADE_ALLOWED_OFF, // Disabling trading for the account ACCOUNT_EVENT_TRADE_EXPERT_ON, // Enabling auto trading for the account ACCOUNT_EVENT_TRADE_EXPERT_OFF, // Disabling auto trading for the account ACCOUNT_EVENT_BALANCE_INC, // The balance exceeds the specified value ACCOUNT_EVENT_BALANCE_DEC, // The balance falls below the specified value ACCOUNT_EVENT_EQUITY_INC, // The equity exceeds the specified value ACCOUNT_EVENT_EQUITY_DEC, // The equity falls below the specified value ACCOUNT_EVENT_PROFIT_INC, // The profit exceeds the specified value ACCOUNT_EVENT_PROFIT_DEC, // The profit falls below the specified value ACCOUNT_EVENT_CREDIT_INC, // The credit exceeds the specified value ACCOUNT_EVENT_CREDIT_DEC, // The credit falls below the specified value ACCOUNT_EVENT_MARGIN_INC, // Increasing the reserved margin on an account in the deposit currency ACCOUNT_EVENT_MARGIN_DEC, // Decreasing the reserved margin on an account in the deposit currency ACCOUNT_EVENT_MARGIN_FREE_INC, // Increasing the free funds available for opening a position in a deposit currency ACCOUNT_EVENT_MARGIN_FREE_DEC, // Decreasing the free funds available for opening a position in a deposit currency ACCOUNT_EVENT_MARGIN_LEVEL_INC, // Increasing the margin level on an account in % ACCOUNT_EVENT_MARGIN_LEVEL_DEC, // Decreasing the margin level on an account in % ACCOUNT_EVENT_MARGIN_INITIAL_INC, // Increasing the funds reserved on an account to ensure a guarantee amount for all pending orders ACCOUNT_EVENT_MARGIN_INITIAL_DEC, // Decreasing the funds reserved on an account to ensure a guarantee amount for all pending orders ACCOUNT_EVENT_MARGIN_MAINTENANCE_INC, // Increasing the funds reserved on an account to ensure a minimum amount for all open positions ACCOUNT_EVENT_MARGIN_MAINTENANCE_DEC, // Decreasing the funds reserved on an account to ensure a minimum amount for all open positions ACCOUNT_EVENT_MARGIN_SO_CALL_INC, // Increasing the Margin Call level ACCOUNT_EVENT_MARGIN_SO_CALL_DEC, // Decreasing the Margin Call level ACCOUNT_EVENT_MARGIN_SO_SO_INC, // Increasing the Stop Out level ACCOUNT_EVENT_MARGIN_SO_SO_DEC, // Decreasing the Stop Out level ACCOUNT_EVENT_ASSETS_INC, // Increasing the current asset size on the account ACCOUNT_EVENT_ASSETS_DEC, // Decreasing the current asset size on the account ACCOUNT_EVENT_LIABILITIES_INC, // Increasing the current liabilities on the account ACCOUNT_EVENT_LIABILITIES_DEC, // Decreasing the current liabilities on the account ACCOUNT_EVENT_COMISSION_BLOCKED_INC, // Increasing the current sum of blocked commissions on an account ACCOUNT_EVENT_COMISSION_BLOCKED_DEC, // Decreasing the current sum of blocked commissions on an account< }; #define ACCOUNT_EVENTS_NEXT_CODE (ACCOUNT_EVENT_COMISSION_BLOCKED_DEC+1) // The code of the next event after the last account event code //+------------------------------------------------------------------+ //| Account integer properties | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_PROP_INTEGER { ACCOUNT_PROP_LOGIN, // Account number ACCOUNT_PROP_TRADE_MODE, // Trading account type ACCOUNT_PROP_LEVERAGE, // Provided leverage ACCOUNT_PROP_LIMIT_ORDERS, // Maximum allowed number of active pending orders ACCOUNT_PROP_MARGIN_SO_MODE, // Mode of setting the minimum available margin level ACCOUNT_PROP_TRADE_ALLOWED, // Permission to trade for the current account from the server side ACCOUNT_PROP_TRADE_EXPERT, // Permission to trade for an EA from the server side ACCOUNT_PROP_MARGIN_MODE, // Margin calculation mode ACCOUNT_PROP_CURRENCY_DIGITS, // Number of digits for an account currency necessary for accurate display of trading results ACCOUNT_PROP_SERVER_TYPE // Trade server type (MetaTrader 5, MetaTrader 4) }; #define ACCOUNT_PROP_INTEGER_TOTAL (10) // Total number of account's integer properties #define ACCOUNT_PROP_INTEGER_SKIP (0) // Number of account's integer properties not used in sorting //+------------------------------------------------------------------+ //| Account real properties | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_PROP_DOUBLE { ACCOUNT_PROP_BALANCE = ACCOUNT_PROP_INTEGER_TOTAL, // Account balance in a deposit currency ACCOUNT_PROP_CREDIT, // Credit in a deposit currency ACCOUNT_PROP_PROFIT, // Current profit on an account in the account currency ACCOUNT_PROP_EQUITY, // Equity on an account in the deposit currency ACCOUNT_PROP_MARGIN, // Reserved margin on an account in a deposit currency ACCOUNT_PROP_MARGIN_FREE, // Free funds available for opening a position in a deposit currency ACCOUNT_PROP_MARGIN_LEVEL, // Margin level on an account in % ACCOUNT_PROP_MARGIN_SO_CALL, // Margin Call level ACCOUNT_PROP_MARGIN_SO_SO, // Stop Out level ACCOUNT_PROP_MARGIN_INITIAL, // Funds reserved on an account to ensure a guarantee amount for all pending orders ACCOUNT_PROP_MARGIN_MAINTENANCE, // Funds reserved on an account to ensure a minimum amount for all open positions ACCOUNT_PROP_ASSETS, // Current assets on an account ACCOUNT_PROP_LIABILITIES, // Current liabilities on an account ACCOUNT_PROP_COMMISSION_BLOCKED // Current sum of blocked commissions on an account }; #define ACCOUNT_PROP_DOUBLE_TOTAL (14) // Total number of account's real properties #define ACCOUNT_PROP_DOUBLE_SKIP (0) // Number of account's real properties not used in sorting //+------------------------------------------------------------------+ //| Account string properties | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_PROP_STRING { ACCOUNT_PROP_NAME = (ACCOUNT_PROP_INTEGER_TOTAL+ACCOUNT_PROP_DOUBLE_TOTAL), // Client name ACCOUNT_PROP_SERVER, // Trade server name ACCOUNT_PROP_CURRENCY, // Deposit currency ACCOUNT_PROP_COMPANY // Name of a company serving an account }; #define ACCOUNT_PROP_STRING_TOTAL (4) // Total number of account's string properties #define ACCOUNT_PROP_STRING_SKIP (0) // Number of account string properties not used in sorting //+------------------------------------------------------------------+ //| Possible account sorting criteria | //+------------------------------------------------------------------+ #define FIRST_ACC_DBL_PROP (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP) #define FIRST_ACC_STR_PROP (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP+ACCOUNT_PROP_DOUBLE_TOTAL-ACCOUNT_PROP_DOUBLE_SKIP) enum ENUM_SORT_ACCOUNT_MODE { SORT_BY_ACCOUNT_LOGIN = 0, // Sort by account number SORT_BY_ACCOUNT_TRADE_MODE = 1, // Sort by trading account type SORT_BY_ACCOUNT_LEVERAGE = 2, // Sort by leverage SORT_BY_ACCOUNT_LIMIT_ORDERS = 3, // Sort by maximum acceptable number of existing pending orders SORT_BY_ACCOUNT_MARGIN_SO_MODE = 4, // Sort by mode for setting the minimum acceptable margin level SORT_BY_ACCOUNT_TRADE_ALLOWED = 5, // Sort by permission to trade for the current account SORT_BY_ACCOUNT_TRADE_EXPERT = 6, // Sort by permission to trade for an EA SORT_BY_ACCOUNT_MARGIN_MODE = 7, // Sort by margin calculation mode SORT_BY_ACCOUNT_CURRENCY_DIGITS = 8, // Sort by number of digits for an account currency SORT_BY_ACCOUNT_SERVER_TYPE = 9, // Sort by trade server type (MetaTrader 5, MetaTrader 4) SORT_BY_ACCOUNT_BALANCE = FIRST_ACC_DBL_PROP, // Sort by an account balance in the deposit currency SORT_BY_ACCOUNT_CREDIT = FIRST_ACC_DBL_PROP+1, // Sort by credit in a deposit currency SORT_BY_ACCOUNT_PROFIT = FIRST_ACC_DBL_PROP+2, // Sort by the current profit on an account in the deposit currency SORT_BY_ACCOUNT_EQUITY = FIRST_ACC_DBL_PROP+3, // Sort by an account equity in the deposit currency SORT_BY_ACCOUNT_MARGIN = FIRST_ACC_DBL_PROP+4, // Sort by an account reserved margin in the deposit currency SORT_BY_ACCOUNT_MARGIN_FREE = FIRST_ACC_DBL_PROP+5, // Sort by account free funds available for opening a position in the deposit currency SORT_BY_ACCOUNT_MARGIN_LEVEL = FIRST_ACC_DBL_PROP+6, // Sort by account margin level in % SORT_BY_ACCOUNT_MARGIN_SO_CALL = FIRST_ACC_DBL_PROP+7, // Sort by margin level requiring depositing funds to an account (Margin Call) SORT_BY_ACCOUNT_MARGIN_SO_SO = FIRST_ACC_DBL_PROP+8, // Sort by margin level, at which the most loss-making position is closed (Stop Out) SORT_BY_ACCOUNT_MARGIN_INITIAL = FIRST_ACC_DBL_PROP+9, // Sort by funds reserved on an account to ensure a guarantee amount for all pending orders SORT_BY_ACCOUNT_MARGIN_MAINTENANCE = FIRST_ACC_DBL_PROP+10, // Sort by funds reserved on an account to ensure a minimum amount for all open positions SORT_BY_ACCOUNT_ASSETS = FIRST_ACC_DBL_PROP+11, // Sort by the amount of the current assets on an account SORT_BY_ACCOUNT_LIABILITIES = FIRST_ACC_DBL_PROP+12, // Sort by the current liabilities on an account SORT_BY_ACCOUNT_COMMISSION_BLOCKED = FIRST_ACC_DBL_PROP+13, // Sort by the current amount of blocked commissions on an account SORT_BY_ACCOUNT_NAME = FIRST_ACC_STR_PROP, // Sort by a client name SORT_BY_ACCOUNT_SERVER = FIRST_ACC_STR_PROP+1, // Sort by a trade server name SORT_BY_ACCOUNT_CURRENCY = FIRST_ACC_STR_PROP+2, // Sort by a deposit currency SORT_BY_ACCOUNT_COMPANY = FIRST_ACC_STR_PROP+3 // Sort by a name of a company serving an account }; //+------------------------------------------------------------------+
複数の口座プロパティを一度に変更することができるため、発生した変更を1つも逃さないようにイベントフラグのセットを操作します。フラグはイベントコード変数に追加されます。次に、変数内の特定のフラグの存在が確認されます。イベントコードに存在するフラグに基づいて、口座プロパティで正確に何が起こったかを定義します。検出されたすべてのイベントは配列に保存され、これにアクセスする機能は、CEngineクラス、および後でプログラムで提供されます。
ご覧のように、口座の整数プロパティのリストにはもう1つのプロパティ(取引サーバの種類)を備えており、整数プロパティの総数が9
から10に変更されています。
この口座プロパティは、口座がMetaTrader 5に属するかMetaTrader
4に属するかを定義します。このプロパティを追加することにしたのは、プログラムがこれまでに接続したすべての口座のリストがすべての口座(ライブラリベースのプログラムが両方の端末で起動された場合、MetaTrader 5とMetaTrader
4の両方)を受け取るためです。このプロパティにより、取引サーバのタイプを区別できるため、CAccountクラスのPrintShort()メソッドによって操作ログに表示される口座の説明に追加したり、口座オブジェクトをプラットフォーム別に並べ替えたりすることができます。
Acount.mqhファイルに移りましょう。口座データ構造体のprivateセクションで、新しいプロパティを追加して口座の文字列プロパティを保存するための配列の正確なサイズを設定します。
//+------------------------------------------------------------------+ //| Account class | //+------------------------------------------------------------------+ class CAccount : public CObject { private: struct SData { //--- Account integer properties long login; // ACCOUNT_LOGIN (Account number) int trade_mode; // ACCOUNT_TRADE_MODE (Trading account type) long leverage; // ACCOUNT_LEVERAGE (Leverage) int limit_orders; // ACCOUNT_LIMIT_ORDERS (Maximum allowed number of active pending orders) int margin_so_mode; // ACCOUNT_MARGIN_SO_MODE (Mode of setting the minimum available margin level) bool trade_allowed; // ACCOUNT_TRADE_ALLOWED (Permission to trade for the current account from the server side) bool trade_expert; // ACCOUNT_TRADE_EXPERT (Permission to trade for an EA from the server side) int margin_mode; // ACCOUNT_MARGIN_MODE (Margin calculation mode) int currency_digits; // ACCOUNT_CURRENCY_DIGITS (Number of digits for an account currency) int server_type; // Trade server type (MetaTrader 5, MetaTrader 4) //--- Account real properties double balance; // ACCOUNT_BALANCE (Account balance in the deposit currency) double credit; // ACCOUNT_CREDIT (Credit in the deposit currency) double profit; // ACCOUNT_PROFIT (Current profit on an account in the deposit currency) double equity; // ACCOUNT_EQUITY (Equity on an account in the deposit currency) double margin; // ACCOUNT_MARGIN (Reserved margin on an account in the deposit currency) double margin_free; // ACCOUNT_MARGIN_FREE (Free funds available for opening a position in the deposit currency) double margin_level; // ACCOUNT_MARGIN_LEVEL (Margin level on an account in %) double margin_so_call; // ACCOUNT_MARGIN_SO_CALL (Margin Call level) double margin_so_so; // ACCOUNT_MARGIN_SO_SO (Stop Out level) double margin_initial; // ACCOUNT_MARGIN_INITIAL (Funds reserved on an account to ensure a guarantee amount for all pending orders) double margin_maintenance; // ACCOUNT_MARGIN_MAINTENANCE (Funds reserved on an account to ensure a minimum amount for all open positions) double assets; // ACCOUNT_ASSETS (Current assets on an account) double liabilities; // ACCOUNT_LIABILITIES (Current liabilities on an account) double comission_blocked; // ACCOUNT_COMMISSION_BLOCKED (Current sum of blocked commissions on an account) //--- Account string properties uchar name[128]; // ACCOUNT_NAME (Client name) uchar server[64]; // ACCOUNT_SERVER (Trade server name) uchar currency[32]; // ACCOUNT_CURRENCY (Deposit currency) uchar company[128]; // ACCOUNT_COMPANY (Name of a company serving an account) }; SData m_struct_obj; // Account object structure uchar m_uchar_array[]; // uchar array of the account object structure
クラスのpublicセクションでは、口座オブジェクトプロパティへのアクセスを単純化して取引サーバタイプを返すさらに別のメソッドを追加します。
//+------------------------------------------------------------------+ //| Methods of a simplified access to the account object properties | //+------------------------------------------------------------------+ //--- Return the account's integer propertie ENUM_ACCOUNT_TRADE_MODE TradeMode(void) const { return (ENUM_ACCOUNT_TRADE_MODE)this.GetProperty(ACCOUNT_PROP_TRADE_MODE); } ENUM_ACCOUNT_STOPOUT_MODE MarginSOMode(void) const { return (ENUM_ACCOUNT_STOPOUT_MODE)this.GetProperty(ACCOUNT_PROP_MARGIN_SO_MODE); } ENUM_ACCOUNT_MARGIN_MODE MarginMode(void) const { return (ENUM_ACCOUNT_MARGIN_MODE)this.GetProperty(ACCOUNT_PROP_MARGIN_MODE); } long Login(void) const { returnthis.GetProperty(ACCOUNT_PROP_LOGIN); } long Leverage(void) const { returnthis.GetProperty(ACCOUNT_PROP_LEVERAGE); } long LimitOrders(void) const { returnthis.GetProperty(ACCOUNT_PROP_LIMIT_ORDERS); } long TradeAllowed(void) const { returnthis.GetProperty(ACCOUNT_PROP_TRADE_ALLOWED); } long TradeExpert(void) const { returnthis.GetProperty(ACCOUNT_PROP_TRADE_EXPERT); } long CurrencyDigits(void) const { returnthis.GetProperty(ACCOUNT_PROP_CURRENCY_DIGITS); } long ServerType(void) const { returnthis.GetProperty(ACCOUNT_PROP_SERVER_TYPE); }
口座プロパティの記述メソッドに、取引サーバタイプの説明を返すメソッドを追加します。
//+------------------------------------------------------------------+ //| Descriptions of the account object properties | //+------------------------------------------------------------------+ //--- Return the description of the account's (1) integer, (2) real and (3) string properties string GetPropertyDescription(ENUM_ACCOUNT_PROP_INTEGER property); string GetPropertyDescription(ENUM_ACCOUNT_PROP_DOUBLE property); string GetPropertyDescription(ENUM_ACCOUNT_PROP_STRING property); //--- Return the trading account type name (demo, contest, real) string TradeModeDescription(void) const; //--- Return the trade server type name (MetaTrader 5, MetaTrader 4) string ServerTypeDescription(void) const; //--- Return the description of the mode for setting the minimum available margin level string MarginSOModeDescription(void) const; //--- Return the description of the margin calculation mode string MarginModeDescription(void) const; //--- Display the description of the account properties in the journal (full_prop=true - all properties, false - supported ones only) void Print(constbool full_prop=false); //--- Display a short account description in the journal void PrintShort(void);
クラスコンストラクタで、プロパティに書き入れて取引サーバタイプを格納します。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CAccount::CAccount(void) { //--- 整数型プロパティを保存する this.m_long_prop[ACCOUNT_PROP_LOGIN] = ::AccountInfoInteger(ACCOUNT_LOGIN); this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = ::AccountInfoInteger(ACCOUNT_TRADE_MODE); this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = ::AccountInfoInteger(ACCOUNT_LEVERAGE); this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = ::AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = ::AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT); this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_MARGIN_MODE) #else ACCOUNT_MARGIN_MODE_RETAIL_HEDGING#endif ; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2#endif ; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = (::TerminalInfoString(TERMINAL_NAME)=="MetaTrader 5" ? 5 : 4); //--- 実数型プロパティを保存する this.m_double_prop[this.IndexProp(ACCOUNT_PROP_BALANCE)] = ::AccountInfoDouble(ACCOUNT_BALANCE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_CREDIT)] = ::AccountInfoDouble(ACCOUNT_CREDIT); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_PROFIT)] = ::AccountInfoDouble(ACCOUNT_PROFIT); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_EQUITY)] = ::AccountInfoDouble(ACCOUNT_EQUITY); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN)] = ::AccountInfoDouble(ACCOUNT_MARGIN); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_FREE)] = ::AccountInfoDouble(ACCOUNT_MARGIN_FREE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_LEVEL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_CALL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_SO)] = ::AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_INITIAL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_MAINTENANCE)]=::AccountInfoDouble(ACCOUNT_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_ASSETS)] = ::AccountInfoDouble(ACCOUNT_ASSETS); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_LIABILITIES)] = ::AccountInfoDouble(ACCOUNT_LIABILITIES); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_COMMISSION_BLOCKED)]=::AccountInfoDouble(ACCOUNT_COMMISSION_BLOCKED); //--- 文字列プロパティを保存する this.m_string_prop[this.IndexProp(ACCOUNT_PROP_NAME)] = ::AccountInfoString(ACCOUNT_NAME); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_SERVER)] = ::AccountInfoString(ACCOUNT_SERVER); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_CURRENCY)] = ::AccountInfoString(ACCOUNT_CURRENCY); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_COMPANY)] = ::AccountInfoString(ACCOUNT_COMPANY); } //+-------------------------------------------------------------------+
ここでは単に端末名を読み取って、MetaTrader 5の場合は「5」、それ以外の場合は「4」に設定します。
オブジェクト構造を作成するためのObjectToStruct()メソッドに、新しいプロパティへの書き入れを追加します。
//+------------------------------------------------------------------+ //| Create the account object structure | //+------------------------------------------------------------------+ bool CAccount::ObjectToStruct(void) { //--- Save the integer properties this.m_struct_obj.login=this.Login(); this.m_struct_obj.trade_mode=this.TradeMode(); this.m_struct_obj.leverage=this.Leverage(); this.m_struct_obj.limit_orders=(int)this.LimitOrders(); this.m_struct_obj.margin_so_mode=this.MarginSOMode(); this.m_struct_obj.trade_allowed=this.TradeAllowed(); this.m_struct_obj.trade_expert=this.TradeExpert(); this.m_struct_obj.margin_mode=this.MarginMode(); this.m_struct_obj.currency_digits=(int)this.CurrencyDigits(); this.m_struct_obj.server_type=(int)this.ServerType(); //--- Save the real properties this.m_struct_obj.balance=this.Balance(); this.m_struct_obj.credit=this.Credit(); this.m_struct_obj.profit=this.Profit(); this.m_struct_obj.equity=this.Equity(); this.m_struct_obj.margin=this.Margin(); this.m_struct_obj.margin_free=this.MarginFree(); this.m_struct_obj.margin_level=this.MarginLevel(); this.m_struct_obj.margin_so_call=this.MarginSOCall(); this.m_struct_obj.margin_so_so=this.MarginSOSO(); this.m_struct_obj.margin_initial=this.MarginInitial(); this.m_struct_obj.margin_maintenance=this.MarginMaintenance(); this.m_struct_obj.assets=this.Assets(); this.m_struct_obj.liabilities=this.Liabilities(); this.m_struct_obj.comission_blocked=this.ComissionBlocked(); //--- Save the string properties ::StringToCharArray(this.Name(),this.m_struct_obj.name); ::StringToCharArray(this.Server(),this.m_struct_obj.server); ::StringToCharArray(this.Currency(),this.m_struct_obj.currency); ::StringToCharArray(this.Company(),this.m_struct_obj.company); //--- Save the structure to the uchar array ::ResetLastError(); if(!::StructToCharArray(this.m_struct_obj,this.m_uchar_array)) { ::Print(DFUN,TextByLanguage("Не удалось сохранить структуру объекта в uchar-массив, ошибка ","Failed to save object structure to uchar array, error "),(string)::GetLastError()); returnfalse; } returntrue; } //+------------------------------------------------------------------+
一方、StructToObject()構造体からオブジェクトを作成するメソッドは、構造体からプロパティを取得します。
//+------------------------------------------------------------------+ //| Create the account object from the structure | //+------------------------------------------------------------------+ void CAccount::StructToObject(void) { //--- 整数型プロパティを保存する this.m_long_prop[ACCOUNT_PROP_LOGIN] = this.m_struct_obj.login; this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = this.m_struct_obj.trade_mode; this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = this.m_struct_obj.leverage; this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = this.m_struct_obj.limit_orders; this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = this.m_struct_obj.margin_so_mode; this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = this.m_struct_obj.trade_allowed; this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = this.m_struct_obj.trade_expert; this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = this.m_struct_obj.margin_mode; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = this.m_struct_obj.currency_digits; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = this.m_struct_obj.server_type; //--- 実数型プロパティを保存する this.m_double_prop[this.IndexProp(ACCOUNT_PROP_BALANCE)] = this.m_struct_obj.balance; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_CREDIT)] = this.m_struct_obj.credit; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_PROFIT)] = this.m_struct_obj.profit; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_EQUITY)] = this.m_struct_obj.equity; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN)] = this.m_struct_obj.margin; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_FREE)] = this.m_struct_obj.margin_free; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_LEVEL)] = this.m_struct_obj.margin_level; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_CALL)] = this.m_struct_obj.margin_so_call; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_SO)] = this.m_struct_obj.margin_so_so; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_INITIAL)] = this.m_struct_obj.margin_initial; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_MAINTENANCE)]=this.m_struct_obj.margin_maintenance; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_ASSETS)] = this.m_struct_obj.assets; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_LIABILITIES)] = this.m_struct_obj.liabilities; this.m_double_prop[this.IndexProp(ACCOUNT_PROP_COMMISSION_BLOCKED)]=this.m_struct_obj.comission_blocked; //--- 文字列プロパティを保存する this.m_string_prop[this.IndexProp(ACCOUNT_PROP_NAME)] = ::CharArrayToString(this.m_struct_obj.name); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_SERVER)] = ::CharArrayToString(this.m_struct_obj.server); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_CURRENCY)] = ::CharArrayToString(this.m_struct_obj.currency); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_COMPANY)] = ::CharArrayToString(this.m_struct_obj.company); } //+------------------------------------------------------------------+
口座プロパティの簡単な説明を表示するメソッドに、取引サーバタイプの表示を追加します。
//+------------------------------------------------------------------+ //| Display a short account description in the journal | //+------------------------------------------------------------------+ void CAccount::PrintShort(void) { string mode=(this.MarginMode()==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING ? ", Hedge" : this.MarginMode()==ACCOUNT_MARGIN_MODE_EXCHANGE ? ", Exhange" : ""); string names=TextByLanguage("Счёт ","Account ")+(string)this.Login()+": "+this.Name()+" ("+this.Company()+" "; string values=::DoubleToString(this.Balance(),(int)this.CurrencyDigits())+" "+this.Currency()+", 1:"+(string)+this.Leverage()+mode+", "+this.TradeModeDescription()+" "+this.ServerTypeDescription()+")"; ::Print(names,values); } //+------------------------------------------------------------------+
口座の整数プロパティの説明を返すメソッドに新しいプロパティの説明を追加します。
//+------------------------------------------------------------------+ //| Display a description of an account integer property | //+------------------------------------------------------------------+ string CAccount::GetPropertyDescription(ENUM_ACCOUNT_PROP_INTEGER property) { return ( property==ACCOUNT_PROP_LOGIN ? TextByLanguage("Номер счёта","Account number")+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_TRADE_MODE ? TextByLanguage("Тип торгового счета","Account trade mode")+": "+this.TradeModeDescription() : property==ACCOUNT_PROP_LEVERAGE ? TextByLanguage("Размер предоставленного плеча","Account leverage")+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_LIMIT_ORDERS ? TextByLanguage("Максимально допустимое количество действующих отложенных ордеров","Maximum allowed number of active pending orders")+": "+ (string)this.GetProperty(property) : property==ACCOUNT_PROP_MARGIN_SO_MODE ? TextByLanguage("Режим задания минимально допустимого уровня залоговых средств","Mode for setting the minimal allowed margin")+": "+ this.MarginSOModeDescription() : property==ACCOUNT_PROP_TRADE_ALLOWED ? TextByLanguage("Разрешенность торговли для текущего счета","Allowed trade for the current account")+": "+ (this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) : property==ACCOUNT_PROP_TRADE_EXPERT ? TextByLanguage("Разрешенность торговли для эксперта","Allowed trade for an Expert Advisor")+": "+ (this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) : property==ACCOUNT_PROP_MARGIN_MODE ? TextByLanguage("Режим расчета маржи","Margin calculation mode")+": "+ this.MarginModeDescription() : property==ACCOUNT_PROP_CURRENCY_DIGITS ? TextByLanguage("Количество знаков после запятой для валюты счета","Number of decimal places in account currency")+": "+ (string)this.GetProperty(property) : property==ACCOUNT_PROP_SERVER_TYPE ? TextByLanguage("Тип торгового сервера","Type of trading server")+": "+ (string)this.GetProperty(property) : "" ); } //+------------------------------------------------------------------+
取引サーバタイプの名前を返すメソッドを実装します。
//+------------------------------------------------------------------+ //| Return the trading server type name | //+------------------------------------------------------------------+ string CAccount::ServerTypeDescription(void) const { return(this.ServerType()==5 ? "MetaTrader5" : "MetaTrader4"); } //+------------------------------------------------------------------+
これでCAccountクラスの改善は終わりです。
Now let's introduce the necessary changes to the account collection class since we decided to track events from the CAccountCollectionクラスからイベントを追跡することにしたので、ここで口座コレクションクラスに必要な変更を導入しましょう。同時に発生したすべての検出された変更は、int配列に書き込まれます。これを達成するには、CArrayInt標準ライブラリのintまたはuint型変数の動的配列の既製クラスを使用します。
クラスファイルをAccountsCollection.mqhライブラリファイルにインクルードします。
//+------------------------------------------------------------------+ //| AccountsCollection.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright"Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include <Arrays\ArrayInt.mqh> #include "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Accounts\Account.mqh" //+------------------------------------------------------------------+ //| Account collection | //+------------------------------------------------------------------+ class CAccountsCollection : public CListObj {
ここで何を達成したいのかを決めましょう。一部の口座プロパティが変更された瞬間を知る必要があります。プロパティは有効または無効にできます。たとえば、一般的な口座で取引する許可や、取引にEAを使用する許可などです。このプロパティが変更されたかどうかを知る必要があります。同様に、MarginCallまたはStopOutレベルを変更すると、ドローダウンなどを維持する際のEAの効率に影響する場合があります。さらに、特定のEA関連の決定を行うために、資金と残高の増減を追跡する必要もあります。
たとえば、一定の数のポジションがあり、特定の利害に達したときにそれらの一部を決済したいとします。まず、特定のしきい値を設定する必要があります。これを超えると、イベントが生成されます。次に、指定された値を上回る/下回る資金の増加または減少が発生しているかどうかに応じて、特定の決定を行う必要があります。同じロジックは、現在の口座での利益、残高、余剰証拠金、預金にも適用できます。
したがって、一部のプロパティについては、増加/減少のしきい値と現在のプロパティ値が必要ですが、その他のプロパティについては、有効化/無効化または変更/不変の値のみが必要です。
必要なすべてのクラスメンバ変数をクラスのprivateセクションに追加して、追跡するプロパティの増加/減少値とその現在の値を保存します。冗長であることが判明したSavePrevValues()メソッドを削除し、追跡および管理された口座データを初期化するメソッド、口座の変更を確認して変更コードを返すメソッド、イベントタイプを設定してイベントリストに書き込むメソッド、そして口座イベントでフラグの存在を返すメソッドを追加します。
//--- Save the current data status values of the current account as previous ones void SavePrevValues(void) //+------------------------------------------------------------------+ //| Account collection | //+------------------------------------------------------------------+ class CAccountsCollection : public CListObj { private: struct MqlDataAccount { double hash_sum; // Account data hash sum //--- Account integer properties long login; // ACCOUNT_LOGIN (Account number) long leverage; // ACCOUNT_LEVERAGE (Leverage) int limit_orders; // ACCOUNT_LIMIT_ORDERS (Maximum allowed number of active pending orders) bool trade_allowed; // ACCOUNT_TRADE_ALLOWED (Permission to trade for the current account from the server side) bool trade_expert; // ACCOUNT_TRADE_EXPERT (Permission to trade for an EA from the server side) //--- Account real properties double balance; // ACCOUNT_BALANCE (Account balance in a deposit currency) double credit; // ACCOUNT_CREDIT (Credit in a deposit currency) double profit; // ACCOUNT_PROFIT (Current profit on an account in the account currency) double equity; // ACCOUNT_EQUITY (Equity on an account in the deposit currency) double margin; // ACCOUNT_MARGIN (Reserved margin on an account in a deposit currency) double margin_free; // ACCOUNT_MARGIN_FREE (Free funds available for opening a position in a deposit currency) double margin_level; // ACCOUNT_MARGIN_LEVEL (Margin level on an account in %) double margin_so_call; // ACCOUNT_MARGIN_SO_CALL (Margin Call) double margin_so_so; // ACCOUNT_MARGIN_SO_SO (Stop Out) double margin_initial; // ACCOUNT_MARGIN_INITIAL (Funds reserved on an account to ensure a guarantee amount for all pending orders) double margin_maintenance; // ACCOUNT_MARGIN_MAINTENANCE (Funds reserved on an account to ensure a minimum amount for all open positions) double assets; // ACCOUNT_ASSETS (Current assets on an account) double liabilities; // ACCOUNT_LIABILITIES (Current liabilities on an account) double comission_blocked; // ACCOUNT_COMMISSION_BLOCKED (Current sum of blocked commissions on an account) }; MqlDataAccount m_struct_curr_account; // Account current data MqlDataAccount m_struct_prev_account; // Account previous data MqlTick m_tick; // Tick structure string m_symbol; // Current symbol long m_chart_id; // Control program chart ID CListObj m_list_accounts; // Account object list CArrayInt m_list_changes; // Account change list string m_folder_name; // Name of the folder storing the account objects int m_index_current; // Index of an account object featuring the current account data //--- Tracking account changes bool m_is_account_event; // Event flag in the account data int m_change_code; // Account change code //--- Leverage long m_changed_leverage_value; // Leverage change value bool m_is_change_leverage_inc; // Leverage increase flag bool m_is_change_leverage_dec; // Leverage decrease flag //--- Number of active pending orders int m_changed_limit_orders_value; // Change value of the maximum allowed number of active pending orders bool m_is_change_limit_orders_inc; // Increase flag of the maximum allowed number of active pending orders bool m_is_change_limit_orders_dec; // Decrease flag of the maximum allowed number of active pending orders //--- Trading on an account bool m_is_change_trade_allowed_on; // The flag allowing to trade for the current account from the server side bool m_is_change_trade_allowed_off; // The flag prohibiting trading for the current account from the server side //--- Auto trading on an account bool m_is_change_trade_expert_on; // The flag allowing to trade for an EA from the server side bool m_is_change_trade_expert_off; //The flag prohibiting trading for an EA from the server side //--- Balance double m_control_balance_inc; // Tracked balance growth value double m_control_balance_dec; // Tracked balance decrease value double m_changed_balance_value; // Balance change value bool m_is_change_balance_inc; // The flag of the balance change exceeding the growth value bool m_is_change_balance_dec; // The flag of the balance change exceeding the decrease value //--- Credit double m_changed_credit_value; // Credit change value bool m_is_change_credit_inc; // Credit increase flag bool m_is_change_credit_dec; // Credit decrease flag //--- Profit double m_control_profit_inc; // Tracked profit growth value double m_control_profit_dec; // Tracked profit decrease value double m_changed_profit_value; // Profit change value bool m_is_change_profit_inc; // The flag of the profit change exceeding the growth value bool m_is_change_profit_dec; // The flag of the profit change exceeding the decrease value //--- Funds (equity) double m_control_equity_inc; // Tracked funds growth value double m_control_equity_dec; // Tracked funds decrease value double m_changed_equity_value; // Funds change value bool m_is_change_equity_inc; // The flag of the funds change exceeding the growth value bool m_is_change_equity_dec; // The flag of the funds change exceeding the decrease value //--- Margin double m_control_margin_inc; // Tracked margin growth value double m_control_margin_dec; // Tracked margin decrease value double m_changed_margin_value; // Margin change value bool m_is_change_margin_inc; // The flag of the margin change exceeding the growth value bool m_is_change_margin_dec; // The flag of the margin change exceeding the decrease value //--- Free margin double m_control_margin_free_inc; // Tracked free margin growth value double m_control_margin_free_dec; // Tracked free margin decrease value< double m_changed_margin_free_value; // Free margin change value bool m_is_change_margin_free_inc; // The flag of the free margin change exceeding the growth value bool m_is_change_margin_free_dec; // The flag of the free margin change exceeding the decrease value //--- Margin level double m_control_margin_level_inc; // Tracked margin level growth value double m_control_margin_level_dec; // Tracked margin level decrease value double m_changed_margin_level_value; // Margin level change value bool m_is_change_margin_level_inc; // The flag of the margin level change exceeding the growth value bool m_is_change_margin_level_dec; // The flag of the margin level change exceeding the decrease value //--- Margin Call double m_changed_margin_so_call_value; // Margin Call level change value bool m_is_change_margin_so_call_inc; // Margin Call level increase value bool m_is_change_margin_so_call_dec; // Margin Call level decrease value //--- MarginStopOut double m_changed_margin_so_so_value; // Margin StopOut level change value bool m_is_change_margin_so_so_inc; // Margin StopOut level increase flag bool m_is_change_margin_so_so_dec; // Margin StopOut level decrease flag //--- Guarantee sum for pending orders double m_control_margin_initial_inc; // Tracked growth value of the reserved funds for providing the guarantee sum for pending orders double m_control_margin_initial_dec; // Tracked decrease value of the reserved funds for providing the guarantee sum for pending orders double m_changed_margin_initial_value; // The change value of the reserved funds for providing the guarantee sum for pending orders bool m_is_change_margin_initial_inc; // The flag of the reserved funds for providing the guarantee sum for pending orders exceeding the growth value bool m_is_change_margin_initial_dec; // The flag of the reserved funds for providing the guarantee sum for pending orders exceeding the decrease value //--- Guarantee sum for open positions double m_control_margin_maintenance_inc; // The tracked increase value of the funds reserved on an account to ensure a minimum amount for all open positions double m_control_margin_maintenance_dec; // The tracked decrease value of the funds reserved on an account to ensure a minimum amount for all open positions double m_changed_margin_maintenance_value; // The change value of the funds reserved on an account to ensure a minimum amount for all open positions bool m_is_change_margin_maintenance_inc; // The flag of the funds reserved on an account to ensure a minimum amount for all open positions exceeding the growth value bool m_is_change_margin_maintenance_dec; // The flag of the funds reserved on an account to ensure a minimum amount for all open positions exceeding the decrease value //--- Assets double m_control_assets_inc; // Tracked assets growth value double m_control_assets_dec; // Tracked assets decrease value double m_changed_assets_value; // Assets change value bool m_is_change_assets_inc; // The flag of the assets change exceeding the growth value bool m_is_change_assets_dec; // The flag of the assets change exceeding the decrease value //--- Liabilities double m_control_liabilities_inc; // Tracked liabilities growth value double m_control_liabilities_dec; // Tracked liabilities decrease value double m_changed_liabilities_value; // Liabilities change values bool m_is_change_liabilities_inc; // The flag of the liabilities change exceeding the growth value bool m_is_change_liabilities_dec; // The flag of the liabilities change exceeding the decrease value //--- Blocked commissions double m_control_comission_blocked_inc; // Tracked blocked commissions growth value double m_control_comission_blocked_dec; // Tracked blocked commissions decrease value double m_changed_comission_blocked_value; // Blocked commissions changed value bool m_is_change_comission_blocked_inc; // The flag of the tracked commissions change exceeding the growth value bool m_is_change_comission_blocked_dec; // The flag of the tracked commissions change exceeding the decrease value //--- Initialize the variables of (1) tracked, (2) controlled account data void InitChangesParams(void); void InitControlsParams(void); //--- Check account changes, return a change code int SetChangeCode(void); //--- Set an event type and fill in the event list void SetTypeEvent(void); //--- return the flag presence in the account event bool IsPresentEventFlag(constint change_code) const { return (this.m_change_code & change_code)==change_code; } //--- Write the current account data to the account object properties void SetAccountsParams(CAccount* account); //--- Check the account object presence in the collection list bool IsPresent(CAccount* account); //--- Find and return the account object index with the current account data int Index(void); public:
SavePrevValues()メソッドは冗長であることが判明しています。口座プロパティの変更を定義する場合、変更されたプロパティの以前のステータスのデータを格納する構造体に新しいプロパティ値を直ちに書き込む必要があります。残りのプロパティは、実際に変更するまでは前回の確認時と同じままにしておく必要があります。SavePrevValues()メソッドは、すべての口座プロパティを以前のプロパティとして保存するため、追跡値を設定する特定の方法を使用して個別に設定できる追跡プロパティごとにデフォルトで設定される特定の変更値の追跡に違反します。
クラス本体の外部で追跡データを初期化するメソッドを書きましょう。
//+------------------------------------------------------------------+ //| Initialize the variables of tracked account data | //+------------------------------------------------------------------+ void CAccountsCollection::InitChangesParams(void) { //--- List and code of changes this.m_list_changes.Clear(); // Clear the change list this.m_list_changes.Sort(); // Sort the change list //--- Leverage this.m_changed_leverage_value=0; // Leverage change value this.m_is_change_leverage_inc=false; // Leverage increase flag this.m_is_change_leverage_dec=false; // Leverage decrease flag //--- Number of active pending orders this.m_changed_limit_orders_value=0; // Change value of the maximum allowed number of active pending orders this.m_is_change_limit_orders_inc=false; // Increase flag of the maximum allowed number of active pending orders this.m_is_change_limit_orders_dec=false; // Decrease flag of the maximum allowed number of active pending orders //--- Trading on an account this.m_is_change_trade_allowed_on=false; // The flag allowing to trade for the current account from the server side this.m_is_change_trade_allowed_off=false; // The flag prohibiting trading for the current account from the server side //--- Auto trading on an account this.m_is_change_trade_expert_on=false; // The flag allowing to trade for an EA from the server side this.m_is_change_trade_expert_off=false; // The flag prohibiting trading for an EA from the server side //--- Balance this.m_changed_balance_value=0; // Balance change value this.m_is_change_balance_inc=false; // The flag of the balance change exceeding the growth value this.m_is_change_balance_dec=false; // The flag of the balance change exceeding the decrease value //--- Credit this.m_changed_credit_value=0; // Credit change value this.m_is_change_credit_inc=false; // Credit increase flag this.m_is_change_credit_dec=false; // Credit decrease flag //--- Profit this.m_changed_profit_value=0; // Profit change value this.m_is_change_profit_inc=false; // The flag of the profit change exceeding the growth value this.m_is_change_profit_dec=false; // The flag of the profit change exceeding the decrease value //--- Funds this.m_changed_equity_value=0; // Funds change value this.m_is_change_equity_inc=false; // The flag of the funds change exceeding the growth value this.m_is_change_equity_dec=false; // The flag of the funds change exceeding the decrease value //--- Margin this.m_changed_margin_value=0; // Margin change value this.m_is_change_margin_inc=false; // The flag of the margin change exceeding the growth value this.m_is_change_margin_dec=false; // The flag of the margin change exceeding the decrease value //--- Free margin this.m_changed_margin_free_value=0; // Free margin change value this.m_is_change_margin_free_inc=false; // The flag of the free margin change exceeding the growth value this.m_is_change_margin_free_dec=false; // The flag of the free margin change exceeding the decrease value //--- Margin level this.m_changed_margin_level_value=0; // Margin level change value this.m_is_change_margin_level_inc=false; // The flag of the margin level change exceeding the growth value this.m_is_change_margin_level_dec=false; // The flag of the margin level change exceeding the decrease value //--- Margin Call level this.m_changed_margin_so_call_value=0; // Margin Call level change value this.m_is_change_margin_so_call_inc=false; // Margin Call level increase flag this.m_is_change_margin_so_call_dec=false; // Margin Call level decrease flag //--- Margin StopOut level this.m_changed_margin_so_so_value=0; // Margin StopOut level change value this.m_is_change_margin_so_so_inc=false; // Margin StopOut level increase flag this.m_is_change_margin_so_so_dec=false; // Margin StopOut level decrease flag //--- Guarantee sum for pending orders this.m_changed_margin_initial_value=0; // The change value of the reserved funds for providing the guarantee sum for pending orders this.m_is_change_margin_initial_inc=false; // The flag of the reserved funds for providing the guarantee sum for pending orders exceeding the growth value this.m_is_change_margin_initial_dec=false; // The flag of the reserved funds for providing the guarantee sum for pending orders exceeding the decrease value //--- Guarantee sum for open positions this.m_changed_margin_maintenance_value=0; // The change value of the funds reserved on an account to ensure a minimum amount for all open positions this.m_is_change_margin_maintenance_inc=false; // The flag of the funds reserved on an account to ensure a minimum amount for all open positions exceeding the growth value this.m_is_change_margin_maintenance_dec=false; // The flag of the funds reserved on an account to ensure a minimum amount for all open positions exceeding the decrease value //--- Assets this.m_changed_assets_value=0; // Assets change value this.m_is_change_assets_inc=false; // The flag of the assets change exceeding the growth value this.m_is_change_assets_dec=false; // The flag of the assets change exceeding the decrease value //--- Liabilities this.m_changed_liabilities_value=0; // Liabilities change value this.m_is_change_liabilities_inc=false; // The flag of the liabilities change exceeding the growth value this.m_is_change_liabilities_dec=false; // The flag of the liabilities change exceeding the decrease value //--- Blocked commissions this.m_changed_comission_blocked_value=0; // Blocked commissions change value this.m_is_change_comission_blocked_inc=false; // The flag of the tracked commissions change exceeding the growth value this.m_is_change_comission_blocked_dec=false; // The flag of the tracked commissions change exceeding the decrease value } //+------------------------------------------------------------------+
以下は、管理されたデータを初期化するメソッドです。
//+------------------------------------------------------------------+ //| Initialize the variables of controlled account data | //+------------------------------------------------------------------+ void CAccountsCollection::InitControlsParams(void) { //--- Balance this.m_control_balance_inc=50; // Tracked balance growth value this.m_control_balance_dec=50; // Tracked balance decrease value //--- Profit this.m_control_profit_inc=20; // Tracked profit growth value this.m_control_profit_dec=20; // Tracked profit decrease value //--- Funds (equity) this.m_control_equity_inc=15; // Tracked funds growth value this.m_control_equity_dec=15; // Tracked funds decrease value //--- Margin this.m_control_margin_inc=1000; // Tracked margin growth value this.m_control_margin_dec=1000; // Tracked margin decrease value //--- Free margin this.m_control_margin_free_inc=1000; // Tracked free margin growth value this.m_control_margin_free_dec=1000; // Tracked free margin decrease value //--- Margin level this.m_control_margin_level_inc=10000; // Tracked margin level growth value this.m_control_margin_level_dec=500; // Tracked margin level decrease value //--- Guarantee sum for pending orders this.m_control_margin_initial_inc=1000; // Tracked growth value of the reserved funds for providing the guarantee sum for pending orders this.m_control_margin_initial_dec=1000; // Tracked decrease value of the reserved funds for providing the guarantee sum for pending orders //--- Guarantee sum for open positions this.m_control_margin_maintenance_inc=1000; // The tracked increase value of the funds reserved on an account to ensure a minimum amount for all open positions this.m_control_margin_maintenance_dec=1000; // The tracked decrease value of the funds reserved on an account to ensure a minimum amount for all open positions //--- Assets this.m_control_assets_inc=1000; // Tracked assets growth value this.m_control_assets_dec=1000; // Tracked assets decrease value //--- Liabilities this.m_control_liabilities_inc=1000; // Tracked liabilities growth value this.m_control_liabilities_dec=1000; // Tracked liabilities decrease value //--- Blocked commissions this.m_control_comission_blocked_inc=1000; // Tracked blocked commissions growth value this.m_control_comission_blocked_dec=1000; // Tracked blocked commissions decrease value } //+------------------------------------------------------------------+
このメソッドでは、変数をデフォルト値で初期化するだけです。プロパティが変数に設定された値を超えると、適切な口座イベントが生成されます。これらのプロパティは、管理された口座プロパティを設定する適切なメソッドを直接呼び出すことによっても設定できます。
口座のプロパティを変更するメソッドを変更し、適切なフラグをイベントコードに入力します。
//+------------------------------------------------------------------+ //| Check account changes, return the change code | //+------------------------------------------------------------------+ int CAccountsCollection::SetChangeCode(void) { this.m_change_code=ACCOUNT_EVENT_FLAG_NO_EVENT; if(this.m_struct_curr_account.trade_allowed!=this.m_struct_prev_account.trade_allowed) this.m_change_code+=ACCOUNT_EVENT_FLAG_TRADE_ALLOWED; if(this.m_struct_curr_account.trade_expert!=this.m_struct_prev_account.trade_expert) this.m_change_code+=ACCOUNT_EVENT_FLAG_TRADE_EXPERT; if(this.m_struct_curr_account.leverage-this.m_struct_prev_account.leverage!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_LEVERAGE; if(this.m_struct_curr_account.limit_orders-this.m_struct_prev_account.limit_orders!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_LIMIT_ORDERS; if(this.m_struct_curr_account.balance-this.m_struct_prev_account.balance!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_BALANCE; if(this.m_struct_curr_account.credit-this.m_struct_prev_account.credit!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_CREDIT; if(this.m_struct_curr_account.profit-this.m_struct_prev_account.profit!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_PROFIT; if(this.m_struct_curr_account.equity-this.m_struct_prev_account.equity!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_EQUITY; if(this.m_struct_curr_account.margin-this.m_struct_prev_account.margin!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN; if(this.m_struct_curr_account.margin_free-this.m_struct_prev_account.margin_free!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_FREE; if(this.m_struct_curr_account.margin_level-this.m_struct_prev_account.margin_level!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_LEVEL; if(this.m_struct_curr_account.margin_so_call-this.m_struct_prev_account.margin_so_call!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_SO_CALL; if(this.m_struct_curr_account.margin_so_so-this.m_struct_prev_account.margin_so_so!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_SO_SO; if(this.m_struct_curr_account.margin_initial-this.m_struct_prev_account.margin_initial!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_INITIAL; if(this.m_struct_curr_account.margin_maintenance-this.m_struct_prev_account.margin_maintenance!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_MARGIN_MAINTENANCE; if(this.m_struct_curr_account.assets-this.m_struct_prev_account.assets!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_ASSETS; if(this.m_struct_curr_account.liabilities-this.m_struct_prev_account.liabilities!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_LIABILITIES; if(this.m_struct_curr_account.comission_blocked-this.m_struct_prev_account.comission_blocked!=0) this.m_change_code+=ACCOUNT_EVENT_FLAG_COMISSION_BLOCKED; //--- returnthis.m_change_code; } //+------------------------------------------------------------------+
まず、メソッドでイベントコードがリセットされます。次に、現在のデータの構造体と以前のデータの構造体で、管理された口座パラメータ値が比較されます。データが同じでなければ、イベントコードに適切なフラグが追加されます。
以下は、イベントタイプを設定してイベントを口座での変化のリストに追加するメソッドです。
//+------------------------------------------------------------------+ //| Set the account object event type | //+------------------------------------------------------------------+ void CAccountsCollection::SetTypeEvent(void) { this.InitChangesParams(); ENUM_ACCOUNT_EVENT event=ACCOUNT_EVENT_NO_EVENT; //--- Changing permission to trade for the account if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_TRADE_ALLOWED)) { if(!this.m_struct_curr_account.trade_allowed) { this.m_is_change_trade_allowed_off=true; event=ACCOUNT_EVENT_TRADE_ALLOWED_OFF; this.m_struct_prev_account.trade_allowed=this.m_struct_curr_account.trade_allowed; } else { this.m_is_change_trade_allowed_on=true; event=ACCOUNT_EVENT_TRADE_ALLOWED_ON; this.m_struct_prev_account.trade_allowed=this.m_struct_curr_account.trade_allowed; } if(this.m_list_changes.Search(event)==WRONG_VALUE) this.m_list_changes.Add(event); } //--- Changing permission for auto trading for the account if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_TRADE_EXPERT)) { if(!this.m_struct_curr_account.trade_expert) { this.m_is_change_trade_expert_off=true; event=ACCOUNT_EVENT_TRADE_EXPERT_OFF; this.m_struct_prev_account.trade_expert=false; } else { this.m_is_change_trade_expert_on=true; event=ACCOUNT_EVENT_TRADE_EXPERT_ON; this.m_struct_prev_account.trade_expert=true; } if(this.m_list_changes.Search(event)==WRONG_VALUE) this.m_list_changes.Add(event); } //--- Change the leverage if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_LEVERAGE)) { this.m_changed_leverage_value=this.m_struct_curr_account.leverage-this.m_struct_prev_account.leverage; if(this.m_changed_leverage_value>0) { this.m_is_change_leverage_inc=true; event=ACCOUNT_EVENT_LEVERAGE_INC; } else { this.m_is_change_leverage_dec=true; event=ACCOUNT_EVENT_LEVERAGE_DEC; } if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.leverage=this.m_struct_curr_account.leverage; } //--- Changing the maximum allowed number of active pending orders if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_LIMIT_ORDERS)) { this.m_changed_limit_orders_value=this.m_struct_curr_account.limit_orders-this.m_struct_prev_account.limit_orders; if(this.m_changed_limit_orders_value>0) { this.m_is_change_limit_orders_inc=true; event=ACCOUNT_EVENT_LIMIT_ORDERS_INC; } else { this.m_is_change_limit_orders_dec=true; event=ACCOUNT_EVENT_LIMIT_ORDERS_DEC; } if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.limit_orders=this.m_struct_curr_account.limit_orders; } //--- Changing the credit in a deposit currency if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_CREDIT)) { this.m_changed_credit_value=this.m_struct_curr_account.credit-this.m_struct_prev_account.credit; if(this.m_changed_credit_value>0) { this.m_is_change_credit_inc=true; event=ACCOUNT_EVENT_CREDIT_INC; } else { this.m_is_change_credit_dec=true; event=ACCOUNT_EVENT_CREDIT_DEC; } if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.credit=this.m_struct_curr_account.credit; } //--- Changing the Margin Call level if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_SO_CALL)) { this.m_changed_margin_so_call_value=this.m_struct_curr_account.margin_so_call-this.m_struct_prev_account.margin_so_call; if(this.m_changed_margin_so_call_value>0) { this.m_is_change_margin_so_call_inc=true; event=ACCOUNT_EVENT_MARGIN_SO_CALL_INC; } else { this.m_is_change_margin_so_call_dec=true; event=ACCOUNT_EVENT_MARGIN_SO_CALL_DEC; } if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_so_call=this.m_struct_curr_account.margin_so_call; } //--- Changing the Stop Out level if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_SO_SO)) { this.m_changed_margin_so_so_value=this.m_struct_curr_account.margin_so_so-this.m_struct_prev_account.margin_so_so; if(this.m_changed_margin_so_so_value>0) { this.m_is_change_margin_so_so_inc=true; event=ACCOUNT_EVENT_MARGIN_SO_SO_INC; } else { this.m_is_change_margin_so_so_dec=true; event=ACCOUNT_EVENT_MARGIN_SO_SO_DEC; } if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_so_so=this.m_struct_curr_account.margin_so_so; } //--- The balance exceeds the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_BALANCE)) { this.m_changed_balance_value=this.m_struct_curr_account.balance-this.m_struct_prev_account.balance; if(this.m_changed_balance_value>this.m_control_balance_inc) { this.m_is_change_balance_inc=true; event=ACCOUNT_EVENT_BALANCE_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.balance=this.m_struct_curr_account.balance; } elseif(this.m_changed_balance_value<-this.m_control_balance_dec) { this.m_is_change_balance_dec=true; event=ACCOUNT_EVENT_BALANCE_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.balance=this.m_struct_curr_account.balance; } } //--- The profit exceeds the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_PROFIT)) { this.m_changed_profit_value=this.m_struct_curr_account.profit-this.m_struct_prev_account.profit; if(this.m_changed_profit_value>this.m_control_profit_inc) { this.m_is_change_profit_inc=true; event=ACCOUNT_EVENT_PROFIT_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.profit=this.m_struct_curr_account.profit; } elseif(this.m_changed_profit_value<-this.m_control_profit_dec) { this.m_is_change_profit_dec=true; event=ACCOUNT_EVENT_PROFIT_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.profit=this.m_struct_curr_account.profit; } } //--- The equity exceeds the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_EQUITY)) { this.m_changed_equity_value=this.m_struct_curr_account.equity-this.m_struct_prev_account.equity; if(this.m_changed_equity_value>this.m_control_equity_inc) { this.m_is_change_equity_inc=true; event=ACCOUNT_EVENT_EQUITY_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.equity=this.m_struct_curr_account.equity; } elseif(this.m_changed_equity_value<-this.m_control_equity_dec) { this.m_is_change_equity_dec=true; event=ACCOUNT_EVENT_EQUITY_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.equity=this.m_struct_curr_account.equity; } } //--- The reserved margin on an account in the deposit currency change exceeds the specified value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN)) { this.m_changed_margin_value=this.m_struct_curr_account.margin-this.m_struct_prev_account.margin; if(this.m_changed_margin_value>this.m_control_margin_inc) { this.m_is_change_margin_inc=true; event=ACCOUNT_EVENT_MARGIN_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin=this.m_struct_curr_account.margin; } elseif(this.m_changed_margin_value<-this.m_control_margin_dec) { this.m_is_change_margin_dec=true; event=ACCOUNT_EVENT_MARGIN_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin=this.m_struct_curr_account.margin; } } //--- The free funds available for opening a position in a deposit currency exceed the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_FREE)) { this.m_changed_margin_free_value=this.m_struct_curr_account.margin_free-this.m_struct_prev_account.margin_free; if(this.m_changed_margin_free_value>this.m_control_margin_free_inc) { this.m_is_change_margin_free_inc=true; event=ACCOUNT_EVENT_MARGIN_FREE_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_free=this.m_struct_curr_account.margin_free; } elseif(this.m_changed_margin_free_value<-this.m_control_margin_free_dec) { this.m_is_change_margin_free_dec=true; event=ACCOUNT_EVENT_MARGIN_FREE_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_free=this.m_struct_curr_account.margin_free; } } //--- The margin level on an account in % exceeds the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_LEVEL)) { this.m_changed_margin_level_value=this.m_struct_curr_account.margin_level-this.m_struct_prev_account.margin_level; if(this.m_changed_margin_level_value>this.m_control_margin_level_inc) { this.m_is_change_margin_level_inc=true; event=ACCOUNT_EVENT_MARGIN_LEVEL_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_level=this.m_struct_curr_account.margin_level; } elseif(this.m_changed_margin_level_value<-this.m_control_margin_level_dec) { this.m_is_change_margin_level_dec=true; event=ACCOUNT_EVENT_MARGIN_LEVEL_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_level=this.m_struct_curr_account.margin_level; } } //--- The funds reserved on an account to ensure a guarantee amount for all pending orders exceed the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_INITIAL)) { this.m_changed_margin_initial_value=this.m_struct_curr_account.margin_initial-this.m_struct_prev_account.margin_initial; if(this.m_changed_margin_initial_value>this.m_control_margin_initial_inc) { this.m_is_change_margin_initial_inc=true; event=ACCOUNT_EVENT_MARGIN_INITIAL_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_initial=this.m_struct_curr_account.margin_initial; } elseif(this.m_changed_margin_initial_value<-this.m_control_margin_initial_dec) { this.m_is_change_margin_initial_dec=true; event=ACCOUNT_EVENT_MARGIN_INITIAL_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_initial=this.m_struct_curr_account.margin_initial; } } //--- The funds reserved on an account to ensure a minimum amount for all open positions exceed the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_MARGIN_MAINTENANCE)) { this.m_changed_margin_maintenance_value=this.m_struct_curr_account.margin_maintenance-this.m_struct_prev_account.margin_maintenance; if(this.m_changed_margin_maintenance_value>this.m_control_margin_maintenance_inc) { this.m_is_change_margin_maintenance_inc=true; event=ACCOUNT_EVENT_MARGIN_MAINTENANCE_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_maintenance=this.m_struct_curr_account.margin_maintenance; } elseif(this.m_changed_margin_maintenance_value<-this.m_control_margin_maintenance_dec) { this.m_is_change_margin_maintenance_dec=true; event=ACCOUNT_EVENT_MARGIN_MAINTENANCE_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.margin_maintenance=this.m_struct_curr_account.margin_maintenance; } } //--- The current assets on an account exceed the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_ASSETS)) { this.m_changed_assets_value=this.m_struct_curr_account.assets-this.m_struct_prev_account.assets; if(this.m_changed_assets_value>this.m_control_assets_inc) { this.m_is_change_assets_inc=true; event=ACCOUNT_EVENT_ASSETS_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.assets=this.m_struct_curr_account.assets; } elseif(this.m_changed_assets_value<-this.m_control_assets_dec) { this.m_is_change_assets_dec=true; event=ACCOUNT_EVENT_ASSETS_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.assets=this.m_struct_curr_account.assets; } } //--- The current liabilities on an account exceed the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_LIABILITIES)) { this.m_changed_liabilities_value=this.m_struct_curr_account.liabilities-this.m_struct_prev_account.liabilities; if(this.m_changed_liabilities_value>this.m_control_liabilities_inc) { this.m_is_change_liabilities_inc=true; event=ACCOUNT_EVENT_LIABILITIES_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.liabilities=this.m_struct_curr_account.liabilities; } elseif(this.m_changed_liabilities_value<-this.m_control_liabilities_dec) { this.m_is_change_liabilities_dec=true; event=ACCOUNT_EVENT_LIABILITIES_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.liabilities=this.m_struct_curr_account.liabilities; } } //--- The current sum of blocked commissions on an account exceeds the specified change value +/- if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_COMISSION_BLOCKED)) { this.m_changed_comission_blocked_value=this.m_struct_curr_account.comission_blocked-this.m_struct_prev_account.comission_blocked; if(this.m_changed_comission_blocked_value>this.m_control_comission_blocked_inc) { this.m_is_change_comission_blocked_inc=true; event=ACCOUNT_EVENT_COMISSION_BLOCKED_INC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.comission_blocked=this.m_struct_curr_account.comission_blocked; } elseif(this.m_changed_comission_blocked_value<-this.m_control_comission_blocked_dec) { this.m_is_change_comission_blocked_dec=true; event=ACCOUNT_EVENT_COMISSION_BLOCKED_DEC; if(this.m_list_changes.Search(event)==WRONG_VALUE && this.m_list_changes.Add(event)) this.m_struct_prev_account.comission_blocked=this.m_struct_curr_account.comission_blocked; } } } //+------------------------------------------------------------------+
このメソッドは、2種類のイベント定義ロジックを備えています。
- プロパティの許可/変更の簡単な追跡
- 指定された値を超える変化をその増加/減少の方向に追跡
メソッドは非常にかさばるので、2つのタイプの口座イベント定義を例として使用します。
まず、すべての変更フラグとデータがリセットされ、イベントタイプがゼロに設定されます。
次に、最初のロジックタイプの場合(口座の取引許可を使用)は、以下を実行します。
- イベントコードで口座の取引許可のフラグを確認します
- 現在取引が禁止されている場合、許可は無効にされたばかりです
- 口座での取引を禁止するフラグを設定します
- 「口座での取引の無効化」イベントを設定します
- 後続の確認のために、以前のデータ構造体に口座プロパティの現在のステータスを保存します
- そうでない場合、現在取引が許可されている場合
- 口座での取引を有効にするフラグを設定します
- 「口座での取引の有効化」イベントを設定します
- 後続の確認のために、以前のデータ構造体に口座プロパティの現在のステータスを保存します
- 変更リストにそのようなイベントがない場合
- リストにイベントを追加します
2番目のロジックタイプの場合(ブロックされた手数料の合計の変更を例として使用)は、以下を実行します。
- ブロックされた手数料の合計を変更するフラグを確認します
- ブロックされた手数料の合計の変化を計算します
- 変更値が増加のしきい値を超える場合
- ブロックされた手数料の合計増加のフラグを設定します
- 「ブロックされた手数料の増加の合計が指定された値を超える」イベントを設定します
- 変更リストにそのようなイベントがなく、イベントがリストに正常に追加された場合
- 後続の確認のために、以前のデータ構造体に口座プロパティの現在のステータスを保存します
- 変更値が減少のしきい値を超える場合
- ブロックされた手数料の合計減少のフラグを設定します
- 「ブロックされた手数料の減少の合計が指定された値を超える」イベントを設定します
- 変更リストにそのようなイベントがなく、イベントがリストに正常に追加された場合
- 後続の確認のために、以前のデータ構造体に口座プロパティの現在のステータスを保存します
クラスのpublicセクションに、口座イベントコード、口座イベントリスト、
リストでのインデックスによる口座イベントを返すメソッド、銘柄を設定し返すメソッド、管理プログラムのチャートIDを返すメソッド、口座イベントの説明を返すメソッドを追加します。また、追跡された変更のパラメータを受信および設定するためのメソッドも追加します。
public: //--- Return the full account collection list "as is" CArrayObj *GetList(void) { return &this.m_list_accounts; } //--- 比較された基準を満たす選択された(1)整数、(2)実数、(3)文字列プロパティののリストを返す CArrayObj *GetList(ENUM_ACCOUNT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByAccountProperty(this.GetList(),property,value,mode);} CArrayObj *GetList(ENUM_ACCOUNT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByAccountProperty(this.GetList(),property,value,mode);} CArrayObj *GetList(ENUM_ACCOUNT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByAccountProperty(this.GetList(),property,value,mode);} //--- Return the (1) current account object index, (2) the flag of the event occurred in the account data, (3) event type int IndexCurrentAccount(void) const { return this.m_index_current; } bool IsAccountEvent(void) const { return this.m_is_account_event; } //--- Return the (1) object account event code, (2) event list, (3) account event by its number in the list int GetEventCode(void) const { return this.m_change_code; } CArrayInt *GetListChanges(void) { return &this.m_list_changes; } ENUM_ACCOUNT_EVENT GetEvent(constint shift=WRONG_VALUE); //--- (1) Set and (2) return the current symbol void SetSymbol(conststring symbol) { this.m_symbol=symbol; } string GetSymbol(void) const { return this.m_symbol; } //--- Set the control program chart ID void SetChartID(constlong id) { this.m_chart_id=id; } //--- Constructor, destructor CAccountsCollection(); ~CAccountsCollection(); //--- Add the account object to the list bool AddToList(CAccount* account); //--- (1) Save account objects from the list to the files //--- (2) Save account objects from the files to the list bool SaveObjects(void); bool LoadObjects(void); //--- Return the account event description string EventDescription(const ENUM_ACCOUNT_EVENT event); //--- Update the current account data void Refresh(void); //--- Get and set the parameters of tracked changes //--- Leverage: //--- (1) Leverage change value, (2) Leverage increase flag, (3) Leverage decrease flag long GetValueChangedLeverage(void) const { return this.m_changed_leverage_value; } bool IsIncreaseLeverage(void) const { return this.m_is_change_leverage_inc; } bool IsDecreaseLeverage(void) const { return this.m_is_change_leverage_dec; } //--- Number of active pending orders: //--- (1) Change value, (2) Increase flag, (3) Decrease flag int GetValueChangedLimitOrders(void) const { return this.m_changed_limit_orders_value; } bool IsIncreaseLimitOrders(void) const { return this.m_is_change_limit_orders_inc; } bool IsDecreaseLimitOrders(void) const { return this.m_is_change_limit_orders_dec; } //--- Trading on an account: //--- (1) The flag allowing to trade for the current account, (2) The flag prohibiting trading for the current account from the server side bool IsOnTradeAllowed(void) const { return this.m_is_change_trade_allowed_on; } bool IsOffTradeAllowed(void) const { return this.m_is_change_trade_allowed_off; } //--- Auto trading on an account: //--- (1) The flag allowing to trade for an EA, (2) The flag prohibiting trading for an EA from the server side bool IsOnTradeExpert(void) const { return this.m_is_change_trade_expert_on; } bool IsOffTradeExpert(void) const { return this.m_is_change_trade_expert_off; } //--- Balance: //--- setting the tracked value of the balance (1) growth, (2) decrease //--- getting (3) the balance change value, //--- getting the flag of the balance change exceeding the (4) growth value, (5) decrease value void SetControlBalanceInc(const double value) { this.m_control_balance_inc=::fabs(value); } void SetControlBalanceDec(const double value) { this.m_control_balance_dec=::fabs(value); } double GetValueChangedBalance(void) const { return this.m_changed_balance_value; } bool IsIncreaseBalance(void) const { return this.m_is_change_balance_inc; } bool IsDecreaseBalance(void) const { return this.m_is_change_balance_dec; } //--- Credit: //--- getting (1) the credit change value, (2) credit increase flag, (3) decrease flag double GetValueChangedCredit(void) const { return this.m_changed_credit_value; } bool IsIncreaseCredit(void) const { return this.m_is_change_credit_inc; } bool IsDecreaseCredit(void) const { return this.m_is_change_credit_dec; } //--- Profit: //--- setting the tracked profit (1) growth, (2) decrease value //--- getting the (3) profit change value, //--- getting the flag of the profit change exceeding the (4) growth, (5) decrease value void SetControlProfitInc(const double value) { this.m_control_profit_inc=::fabs(value); } void SetControlProfitDec(const double value) { this.m_control_profit_dec=::fabs(value); } double GetValueChangedProfit(void) const { return this.m_changed_profit_value; } bool IsIncreaseProfit(void) const { return this.m_is_change_profit_inc; } bool IsDecreaseProfit(void) const { return this.m_is_change_profit_dec; } //--- Equity: //--- setting the tracked equity (1) growth, (2) decrease value //--- getting the (3) equity change value, //--- getting the flag of the equity change exceeding the (4) growth, (5) decrease value void SetControlEquityInc(const double value) { this.m_control_equity_inc=::fabs(value); } void SetControlEquityDec(const double value) { this.m_control_equity_dec=::fabs(value); } double GetValueChangedEquity(void) const { return this.m_changed_equity_value; } bool IsIncreaseEquity(void) const { return this.m_is_change_equity_inc; } bool IsDecreaseEquity(void) const { return this.m_is_change_equity_dec; } //--- Margin: //--- setting the tracked margin (1) growth, (2) decrease value //--- getting the (3) margin change value, //--- getting the flag of the margin change exceeding the (4) growth, (5) decrease value void SetControlMarginInc(const double value) { this.m_control_margin_inc=::fabs(value); } void SetControlMarginDec(const double value) { this.m_control_margin_dec=::fabs(value); } double GetValueChangedMargin(void) const { return this.m_changed_margin_value; } bool IsIncreaseMargin(void) const { return this.m_is_change_margin_inc; } bool IsDecreaseMargin(void) const { return this.m_is_change_margin_dec; } //--- Free margin: //--- setting the tracked free margin (1) growth, (2) decrease value //--- getting the (3) free margin change value, //--- getting the flag of the free margin change exceeding the (4) growth, (5) decrease value void SetControlMarginFreeInc(const double value) { this.m_control_margin_free_inc=::fabs(value); } void SetControlMarginFreeDec(const double value) { this.m_control_margin_free_dec=::fabs(value); } double GetValueChangedMarginFree(void) const { return this.m_changed_margin_free_value; } bool IsIncreaseMarginFree(void) const { return this.m_is_change_margin_free_inc; } bool IsDecreaseMarginFree(void) const { return this.m_is_change_margin_free_dec; } //--- Margin level: //--- setting the tracked margin level (1) growth, (2) decrease value //--- getting the (3) margin level change value, //--- getting the flag of the margin level change exceeding the (4) growth, (5) decrease value void SetControlMarginLevelInc(const double value) { this.m_control_margin_level_inc=::fabs(value); } void SetControlMarginLevelDec(const double value) { this.m_control_margin_level_dec=::fabs(value); } double GetValueChangedMarginLevel(void) const { return this.m_changed_margin_level_value; } bool IsIncreaseMarginLevel(void) const { return this.m_is_change_margin_level_inc; } bool IsDecreaseMarginLevel(void) const { return this.m_is_change_margin_level_dec; } //--- Margin Call: //--- getting (1) Margin Call change value, (2) increase flag, (3) decrease flag double GetValueChangedMarginCall(void) const { return this.m_changed_margin_so_call_value; } bool IsIncreaseMarginCall(void) const { return this.m_is_change_margin_so_call_inc; } bool IsDecreaseMarginCall(void) const { return this.m_is_change_margin_so_call_dec; } //--- Margin StopOut: //--- getting (1) Margin StopOut change value, (2) increase flag, (3) decrease flag double GetValueChangedMarginStopOut(void) const { return this.m_changed_margin_so_so_value; } bool IsIncreaseMarginStopOut(void) const { return this.m_is_change_margin_so_so_inc; } bool IsDecreasMarginStopOute(void) const { return this.m_is_change_margin_so_so_dec; } //--- Guarantee sum for pending orders: //--- setting the tracked value of the reserved funds for providing the guarantee sum for pending orders (1) growth, (2) decrease //--- getting the change value of the (3) reserved funds for providing the guarantee sum, //--- getting the flag of the reserved funds for providing the guarantee sum for pending orders exceeding the (4) growth, (5) decrease value void SetControlMarginInitialInc(const double value) { this.m_control_margin_initial_inc=::fabs(value); } void SetControlMarginInitialDec(const double value) { this.m_control_margin_initial_dec=::fabs(value); } double GetValueChangedMarginInitial(void) const { return this.m_changed_margin_initial_value; } bool IsIncreaseMarginInitial(void) const { return this.m_is_change_margin_initial_inc; } bool IsDecreaseMarginInitial(void) const { return this.m_is_change_margin_initial_dec; } //--- Guarantee sum for open positions: //--- setting the tracked value of the funds reserved on an account to ensure a minimum amount for all open positions (1) growth, (2) decrease //--- getting the change value of the (3) funds reserved on an account to ensure a minimum amount for all open positions, //--- getting the flag of the funds reserved on an account to ensure a minimum amount for all open positions exceeding the (4) growth, (5) decrease value void SetControlMarginMaintenanceInc(const double value) { this.m_control_margin_maintenance_inc=::fabs(value); } void SetControlMarginMaintenanceDec(const double value) { this.m_control_margin_maintenance_dec=::fabs(value); } double GetValueChangedMarginMaintenance(void) const { return this.m_changed_margin_maintenance_value; } bool IsIncreaseMarginMaintenance(void) const { return this.m_is_change_margin_maintenance_inc; } bool IsDecreaseMarginMaintenance(void) const { return this.m_is_change_margin_maintenance_dec; } //--- Assets: //--- setting the tracked value of the assets (1) growth, (2) decrease //--- getting (3) the assets change value, //--- getting the flag of the change exceeding the (4) growth, (5) decrease value void SetControlAssetsInc(const double value) { this.m_control_assets_inc=::fabs(value); } void SetControlAssetsDec(const double value) { this.m_control_assets_dec=::fabs(value); } double GetValueChangedAssets(void) const { return this.m_changed_assets_value; } bool IsIncreaseAssets(void) const { return this.m_is_change_assets_inc; } bool IsDecreaseAssets(void) const { return this.m_is_change_assets_dec; } //--- Liabilities: //--- setting the tracked value of the liabilities (1) growth, (2) decrease //--- getting (3) the liabilities change value, //--- getting the flag of the liabilities change exceeding the (4) growth, (5) decrease value void SetControlLiabilitiesInc(const double value) { this.m_control_liabilities_inc=::fabs(value); } void SetControlLiabilitiesDec(const double value) { this.m_control_liabilities_dec=::fabs(value); } double GetValueChangedLiabilities(void) const { return this.m_changed_liabilities_value; } bool IsIncreaseLiabilities(void) const { return this.m_is_change_liabilities_inc; } bool IsDecreaseLiabilities(void) const { return this.m_is_change_liabilities_dec; } //--- Blocked commissions: //--- setting the tracked blocked commissions (1) growth, (2) decrease value //--- getting (3) the blocked commissions change value, //--- getting the flag of the tracked commissions change exceeding the (4) growth, (5) decrease value void SetControlComissionBlockedInc(const double value) { this.m_control_comission_blocked_inc=::fabs(value); } void SetControlComissionBlockedDec(const double value) { this.m_control_comission_blocked_dec=::fabs(value); } double GetValueChangedComissionBlocked(void) const { return this.m_changed_comission_blocked_value; } bool IsIncreaseComissionBlocked(void) const { return this.m_is_change_comission_blocked_inc; } bool IsDecreaseComissionBlocked(void) const { return this.m_is_change_comission_blocked_dec; } }; //+------------------------------------------------------------------+
クラス本体の外で、リスト内の番号によって口座イベントを返すメソッドを実装します。
//+------------------------------------------------------------------+ //| Return the account event by its number in the list | //+------------------------------------------------------------------+ ENUM_ACCOUNT_EVENT CAccountsCollection::GetEvent(constint shift=WRONG_VALUE) { int total=this.m_list_changes.Total(); if(total==0) return ACCOUNT_EVENT_NO_EVENT; int index=(shift<0 || shift>total-1 ? total-1 : total-shift-1); int event=this.m_list_changes.At(index); return ENUM_ACCOUNT_EVENT(event!=NULL ? event : ACCOUNT_EVENT_NO_EVENT); } //+------------------------------------------------------------------+
口座プロパティの変更のリストのイベントは追加順に配置されています。最初のイベントのインデックスは0、最後のイベントのインデックスは(list_size-1)です。ただし、目的のイベントを時系列でのように取得できるようにするために、ゼロインデックスには最後のイベントが含まれている必要があります。これを達成するために、このメソッドでのインデックスは「index = (list_size -
desired_event_number-1)」として計算されています。この場合、0を渡すと、リストの最後のイベントが返されます。1の場合は最後から2つ目のイベントが返されます。数がリストのサイズを超える場合は、最後のイベントが返されます。
したがって、目的のイベントのインデックスがメソッドに渡されます。
まず、リスト内のイベントの数を確認します。イベントがない場合は「イベントなし」を返します。
次に、目的のイベントインデックスを確認します。渡された値がゼロより小さいか、配列サイズを超える場合には、インデックスはリストの最後のイベントを指定し、そうでない場合は、ルール(0がメソッドに渡された場合は(時系列のように)最後のイベントを取得し、1の場合は最後から2番目のイベントを取得するなど)に従ってリストのイベントインデックスを計算します。または、最後のイベントを取得する必要がある場合は、インデックス入力として-1を渡します。
次に、計算されたインデックスによってリストからイベントを取得して返します。
イベントが受信されない場合はNULLが返されるため、メソッド操作の結果を使用する前にその有効性を確認する必要があります。
口座イベントの説明を返すメソッドを実装します。
//+------------------------------------------------------------------+ //| Return an account event description | //+------------------------------------------------------------------+ string CAccountsCollection::EventDescription(const ENUM_ACCOUNT_EVENT event) { int total=this.m_list_accounts.Total(); if(total==0) return(DFUN+TextByLanguage("Ошибка. Список изменений пуст","Error. List of changes is empty")); CAccount* account=this.m_list_accounts.At(this.m_index_current); if(account==NULL) return(DFUN+TextByLanguage("Ошибка. Не удалось получить данные аккаунта","Error. Failed to get account data")); constint dg=(account.MarginSOMode()==ACCOUNT_STOPOUT_MODE_MONEY ? (int)account.CurrencyDigits() : 2); conststring curency=" "+account.Currency(); conststring mode_lev=(account.IsPercentsForSOLevels() ? "%" : " "+curency); return ( event==ACCOUNT_EVENT_NO_EVENT ? TextByLanguage("Нет события","No event") : event==ACCOUNT_EVENT_TRADE_ALLOWED_ON ? TextByLanguage("Торговля на счёте разрешена","Trading on account allowed now") : event==ACCOUNT_EVENT_TRADE_ALLOWED_OFF ? TextByLanguage("Торговля на счёте запрещена","Trading on account prohibited now") : event==ACCOUNT_EVENT_TRADE_EXPERT_ON ? TextByLanguage("Автоторговля на счёте разрешена","Autotrading on account allowed now") : event==ACCOUNT_EVENT_TRADE_EXPERT_OFF ? TextByLanguage("Автоторговля на счёте запрещена","Autotrade on account prohibited now") : event==ACCOUNT_EVENT_LEVERAGE_INC ? TextByLanguage("Плечо увеличено на ","Leverage increased by ")+(string)this.GetValueChangedLeverage()+" (1:"+(string)account.Leverage()+")" : event==ACCOUNT_EVENT_LEVERAGE_DEC ? TextByLanguage("Плечо уменьшено на ","Leverage decreased by ")+(string)this.GetValueChangedLeverage()+" (1:"+(string)account.Leverage()+")" : event==ACCOUNT_EVENT_LIMIT_ORDERS_INC ? TextByLanguage("Максимально допустимое количество действующих отложенных ордеров увеличено на","Maximum allowable number of active pending orders increased by ")+(string)this.GetValueChangedLimitOrders()+" ("+(string)account.LimitOrders()+")" : event==ACCOUNT_EVENT_LIMIT_ORDERS_DEC ? TextByLanguage("Максимально допустимое количество действующих отложенных ордеров уменьшено на","Maximum allowable number of active pending orders decreased by ")+(string)this.GetValueChangedLimitOrders()+" ("+(string)account.LimitOrders()+")" : event==ACCOUNT_EVENT_BALANCE_INC ? TextByLanguage("Баланс счёта увеличен на ","Account balance increased by ")+::DoubleToString(this.GetValueChangedBalance(),dg)+curency+" ("+::DoubleToString(account.Balance(),dg)+curency+")" : event==ACCOUNT_EVENT_BALANCE_DEC ? TextByLanguage("Баланс счёта уменьшен на ","Account balance decreased by ")+::DoubleToString(this.GetValueChangedBalance(),dg)+curency+" ("+::DoubleToString(account.Balance(),dg)+curency+")" : event==ACCOUNT_EVENT_EQUITY_INC ? TextByLanguage("Средства увеличены на ","Equity increased by ")+::DoubleToString(this.GetValueChangedEquity(),dg)+curency+" ("+::DoubleToString(account.Equity(),dg)+curency+")" : event==ACCOUNT_EVENT_EQUITY_DEC ? TextByLanguage("Средства уменьшены на ","Equity decreased by ")+::DoubleToString(this.GetValueChangedEquity(),dg)+curency+" ("+::DoubleToString(account.Equity(),dg)+curency+")" : event==ACCOUNT_EVENT_PROFIT_INC ? TextByLanguage("Текущая прибыль счёта увеличена на ","Account current profit increased by ")+::DoubleToString(this.GetValueChangedProfit(),dg)+curency+" ("+::DoubleToString(account.Profit(),dg)+curency+")" : event==ACCOUNT_EVENT_PROFIT_DEC ? TextByLanguage("Текущая прибыль счёта уменьшена на ","Account current profit decreased by ")+::DoubleToString(this.GetValueChangedProfit(),dg)+curency+" ("+::DoubleToString(account.Profit(),dg)+curency+")" : event==ACCOUNT_EVENT_CREDIT_INC ? TextByLanguage("Предоставленный кредит увеличен на ","Credit increased by ")+::DoubleToString(this.GetValueChangedCredit(),dg)+curency+" ("+::DoubleToString(account.Credit(),dg)+curency+")" : event==ACCOUNT_EVENT_CREDIT_DEC ? TextByLanguage("Предоставленный кредит уменьшен на ","Credit decreased by ")+::DoubleToString(this.GetValueChangedCredit(),dg)+curency+" ("+::DoubleToString(account.Credit(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_INC ? TextByLanguage("Залоговые средства увеличены на ","Margin increased by ")+::DoubleToString(this.GetValueChangedMargin(),dg)+curency+" ("+::DoubleToString(account.Margin(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_DEC ? TextByLanguage("Залоговые средства уменьшены на ","Margin decreased by ")+::DoubleToString(this.GetValueChangedMargin(),dg)+curency+" ("+::DoubleToString(account.Margin(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_FREE_INC ? TextByLanguage("Свободные средства увеличены на ","Free margin increased by ")+::DoubleToString(this.GetValueChangedMarginFree(),dg)+curency+" ("+::DoubleToString(account.MarginFree(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_FREE_DEC ? TextByLanguage("Свободные средства уменьшены на ","Free margin decreased by ")+::DoubleToString(this.GetValueChangedMarginFree(),dg)+curency+" ("+::DoubleToString(account.MarginFree(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_LEVEL_INC ? TextByLanguage("Уровень залоговых средств увеличен на ","Margin level increased by ")+::DoubleToString(this.GetValueChangedMarginLevel(),dg)+"%"+" ("+::DoubleToString(account.MarginLevel(),dg)+"%)" : event==ACCOUNT_EVENT_MARGIN_LEVEL_DEC ? TextByLanguage("Уровень залоговых средств уменьшен на ","Margin level decreased by ")+::DoubleToString(this.GetValueChangedMarginLevel(),dg)+"%"+" ("+::DoubleToString(account.MarginLevel(),dg)+"%)" : event==ACCOUNT_EVENT_MARGIN_INITIAL_INC ? TextByLanguage("Гарантийная сумма по отложенным ордерам увеличена на ","Guarantee sum for pending orders increased by ")+::DoubleToString(this.GetValueChangedMarginInitial(),dg)+curency+" ("+::DoubleToString(account.MarginInitial(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_INITIAL_DEC ? TextByLanguage("Гарантийная сумма по отложенным ордерам уменьшена на ","Guarantee sum for pending orders decreased by ")+::DoubleToString(this.GetValueChangedMarginInitial(),dg)+curency+" ("+::DoubleToString(account.MarginInitial(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_MAINTENANCE_INC ? TextByLanguage("Гарантийная сумма по позициям увеличена на ","Guarantee sum for positions increased by ")+::DoubleToString(this.GetValueChangedMarginMaintenance(),dg)+curency+" ("+::DoubleToString(account.MarginMaintenance(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_MAINTENANCE_DEC ? TextByLanguage("Гарантийная сумма по позициям уменьшена на ","Guarantee sum for positions decreased by ")+::DoubleToString(this.GetValueChangedMarginMaintenance(),dg)+curency+" ("+::DoubleToString(account.MarginMaintenance(),dg)+curency+")" : event==ACCOUNT_EVENT_MARGIN_SO_CALL_INC ? TextByLanguage("Увеличен уровень Margin Call на ","Increased Margin Call level by ")+::DoubleToString(this.GetValueChangedMarginCall(),dg)+mode_lev+" ("+::DoubleToString(account.MarginSOCall(),dg)+mode_lev+")" : event==ACCOUNT_EVENT_MARGIN_SO_CALL_DEC ? TextByLanguage("Уменьшен уровень Margin Call на ","Decreased Margin Call level by ")+::DoubleToString(this.GetValueChangedMarginCall(),dg)+mode_lev+" ("+::DoubleToString(account.MarginSOCall(),dg)+mode_lev+")" : event==ACCOUNT_EVENT_MARGIN_SO_SO_INC ? TextByLanguage("Увеличен уровень Stop Out на ","Increased Margin Stop Out level by ")+::DoubleToString(this.GetValueChangedMarginStopOut(),dg)+mode_lev+" ("+::DoubleToString(account.MarginSOSO(),dg)+mode_lev+")" : event==ACCOUNT_EVENT_MARGIN_SO_SO_DEC ? TextByLanguage("Уменьшен уровень Stop Out на ","Decreased Margin Stop Out level by ")+::DoubleToString(this.GetValueChangedMarginStopOut(),dg)+mode_lev+" ("+::DoubleToString(account.MarginSOSO(),dg)+mode_lev+")" : event==ACCOUNT_EVENT_ASSETS_INC ? TextByLanguage("Размер активов увеличен на ","Assets increased by ")+::DoubleToString(this.GetValueChangedAssets(),dg)+" ("+::DoubleToString(account.Assets(),dg)+")" : event==ACCOUNT_EVENT_ASSETS_DEC ? TextByLanguage("Размер активов уменьшен на ","Assets decreased by ")+::DoubleToString(this.GetValueChangedAssets(),dg)+" ("+::DoubleToString(account.Assets(),dg)+")" : event==ACCOUNT_EVENT_LIABILITIES_INC ? TextByLanguage("Размер обязательств увеличен на ","Liabilities increased by ")+::DoubleToString(this.GetValueChangedLiabilities(),dg)+" ("+::DoubleToString(account.Liabilities(),dg)+")" : event==ACCOUNT_EVENT_LIABILITIES_DEC ? TextByLanguage("Размер обязательств уменьшен на ","Liabilities decreased by ")+::DoubleToString(this.GetValueChangedLiabilities(),dg)+" ("+::DoubleToString(account.Liabilities(),dg)+")" : event==ACCOUNT_EVENT_COMISSION_BLOCKED_INC ? TextByLanguage("Размер заблокированных комиссий увеличен на ","Blocked commissions increased by ")+::DoubleToString(this.GetValueChangedComissionBlocked(),dg)+" ("+::DoubleToString(account.ComissionBlocked(),dg)+")" : event==ACCOUNT_EVENT_COMISSION_BLOCKED_DEC ? TextByLanguage("Размер заблокированных комиссий уменьшен на ","Blocked commissions decreased by ")+::DoubleToString(this.GetValueChangedComissionBlocked(),dg)+" ("+::DoubleToString(account.ComissionBlocked(),dg)+")" : ::EnumToString(event) ); } //+------------------------------------------------------------------+
ここでは、説明を取得するメソッドに口座イベントが渡されます。口座オブジェクトリストのサイズを確認します。空の場合、エラーの説明を返します。追跡できるイベントは現在の口座のもののみであるため、現在の口座オブジェクトのインデックスによって口座リストから現在の口座オブジェクトを取得します。オブジェクトが受信されない場合は、エラーの説明も返します。
次に、イベントの説明を正しく表示するのに必要な口座プロパティを取得して、イベントを確認してその説明を返します。
クラスコンストラクタの初期化リストで、銘柄変数とプログラムチャートIDをデフォルト値(現在の銘柄と現在のチャート)で初期化し、イベント時間を定義するのに必要なティック構造体をクリアして、
変更可能および管理された口座パラメータを初期化します。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CAccountsCollection::CAccountsCollection(void) : m_folder_name(DIRECTORY+"Accounts"), m_is_account_event(false), m_symbol(::Symbol()), m_chart_id(::ChartID()) { this.m_list_accounts.Clear(); this.m_list_accounts.Sort(SORT_BY_ACCOUNT_LOGIN); this.m_list_accounts.Type(COLLECTION_ACCOUNT_ID); ::ZeroMemory(this.m_struct_prev_account); ::ZeroMemory(this.m_tick); this.InitChangesParams(); this.InitControlsParams(); //--- Create the folder for storing account files ::ResetLastError(); if(!::FolderCreate(this.m_folder_name,FILE_COMMON)) Print(DFUN,TextByLanguage("Не удалось создать папку хранения файлов. Ошибка ","Could not create file storage folder. Error "),::GetLastError()); //--- Create the current account object and add it to the list CAccount* account=new CAccount(); if(account!=NULL) { if(!this.AddToList(account)) { Print(DFUN_ERR_LINE,TextByLanguage("Ошибка. Не удалось добавить текущий объект-аккаунт в список-коллекцию.","Error. Failed to add current account object to collection list.")); delete account; } else account.PrintShort(); } else Print(DFUN,TextByLanguage("Ошибка. Не удалось создать объект-аккаунт с данными текущего счёта.","Error. Failed to create an account object with current account data.")); //--- Download account objects from the files to the collection this.LoadObjects(); //--- Save the current account index this.m_index_current=this.Index(); } //+------------------------------------------------------------------+
最後に、口座データを更新するメソッドに口座の変化の追跡を追加します。
//+------------------------------------------------------------------+ //| Update the current account data | //+------------------------------------------------------------------+ void CAccountsCollection::Refresh(void) { this.m_is_account_event=false; if(this.m_index_current==WRONG_VALUE) return; CAccount* account=this.m_list_accounts.At(this.m_index_current); if(account==NULL) return; ::ZeroMemory(this.m_struct_curr_account); this.SetAccountsParams(account); //--- 初回実行 if(!this.m_struct_prev_account.login) { this.m_struct_prev_account=this.m_struct_curr_account; return; } //--- f the account hash sum changed if(this.m_struct_curr_account.hash_sum!=this.m_struct_prev_account.hash_sum) { this.m_change_code=this.SetChangeCode(); this.SetTypeEvent(); int total=this.m_list_changes.Total(); if(total>0) { this.m_is_account_event=true; for(int i=0;i<total;i++) { ENUM_ACCOUNT_EVENT event=this.GetEvent(i); if(event==NULL || !::SymbolInfoTick(this.m_symbol,this.m_tick)) continue; string sparam=TimeMSCtoString(this.m_tick.time_msc)+": "+this.EventDescription(event); Print(sparam); ::EventChartCustom(this.m_chart_id,(ushort)event,this.m_tick.time_msc,(double)i,sparam); } } this.m_struct_prev_account.hash_sum=this.m_struct_curr_account.hash_sum; } } //+------------------------------------------------------------------+まず、口座イベントフラグをリセットします。SavePrevValues()メソッドを削除したため、代わりにその文字列を追加します最初の起動時に、以前のデータ構造体に現在のデータ構造体を保存します。ハッシュを変更するときは、イベントコードと発生したイベントタイプをを確認して設定します。
イベントタイプを設定するメソッドでは、口座プロパティで同時に発生したすべてのイベントが変更リストに渡されます。したがって、まず変更リストのサイズを確認します。空でない場合は、変更発生フラグを設定し、リストデータのループでイベントを受信し、ミリ秒単位の時間とイベントの説明で構成される文字列での説明を設定し、操作ログにイベントの説明を一時的に表示します(この機能は将来削除されます。すべてのライブラリシステムメッセージは、ロギングが有効な場合にのみ操作ログ表示されます)。最後に、EventChartCustom()を使用して管理プログラムにイベントを送信します。
EventChartCustom()関数のパラメータで、次を渡します。
- イベント ->event_id
- ミリ秒単位でのイベント時間 ->lparam
- 同時に発生した口座変更リスト内のイベントインデックス ->dparam
- イベントの文字列での説明 ->sparam
メソッドの最後で、後続の検証のために必ず現在のハッシュを前のハッシュとして保存してください。
これでCAccountsCollectionクラスの改善は終わりです。
ライブラリのアルファとオメガであるCEngineクラスに移りましょう。口座イベントを操作するために必要なすべての機能を追加する必要があります。
クラスのprivateセクションで、口座イプロパティ変更イベントのフラグを保存するための変数と口座で最後に発生したイベントの変数を追加します。publicセクションに、同時に発生した口座イベントのリストを返すメソッドと最後の口座イベントを返すメソッドを追加します。
//+------------------------------------------------------------------+ //| ライブラリ基本クラス | //+------------------------------------------------------------------+ class CEngine : public CObject { private: CHistoryCollection m_history; // 過去の注文と取引のコレクション CMarketCollection m_market; // 注文と取引のコレクション CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CArrayObj m_list_counters; // タイマーカウンタのリスト bool m_first_start; // 初期実行フラグ bool m_is_hedge; // ヘッジ勘定フラグ bool m_is_tester; // Flag of working in the tester bool m_is_market_trade_event; // 口座取引イベントフラグ bool m_is_history_trade_event; // 口座過去の取引イベントフラグ bool m_is_account_event; // Account change event flag ENUM_TRADE_EVENT m_last_trade_event; // Account last trading event ENUM_ACCOUNT_EVENT m_last_account_event; // Last event in account properties //--- IDによるカウンタインデックスを返す int CounterIndex(constint id) const; //--- Return (1) the first launch flag, (2) the flag presence in a trading event bool IsFirstStart(void); //--- Working with (1) order, deal and position, as well as (2) account events void TradeEventsControl(void); void AccountEventsControl(void); //--- 直近の(1)市場未決注文、(2)成行注文、(3)直近のポジション、(4)チケット別ポジションを返す COrder* GetLastMarketPending(void); COrder* GetLastMarketOrder(void); COrder* GetLastPosition(void); COrder* GetPosition(constulong ticket); //--- Return the last (1) removed pending order, (2) historical market order, (3) historical order (market or pending) by its ticket COrder* GetLastHistoryPending(void); COrder* GetLastHistoryOrder(void); COrder* GetHistoryOrder(constulong ticket); //--- (1)すべてのポジション注文のリストからの最初および(2)直近の成行注文、(3)直近の取引を返す COrder* GetFirstOrderPosition(constulong position_id); COrder* GetLastOrderPosition(constulong position_id); COrder* GetLastDeal(void); public: //--- 市場の(1)ポジション、(2)未決注文、(3)成行注文のリストを返す CArrayObj* GetListMarketPosition(void); CArrayObj* GetListMarketPendings(void); CArrayObj* GetListMarketOrders(void); //--- 過去の(1)注文、(2)削除済み未決注文、(3)取引、(4)ID別の成行注文のポジションリストを返す CArrayObj* GetListHistoryOrders(void); CArrayObj* GetListHistoryPendings(void); CArrayObj* GetListDeals(void); CArrayObj* GetListAllOrdersByPosID(constulong position_id); //--- Return the list of (1) accounts, (2) account events CArrayObj* GetListAllAccounts(void) { returnthis.m_accounts.GetList(); } CArrayInt* GetListAccountEvents(void) { returnthis.m_accounts.GetListChanges(); } //--- Return the list of order, deal and position events CArrayObj* GetListAllOrdersEvents(void) { returnthis.m_events.GetList(); } //--- 直近の取引イベントをリセットする void ResetLastTradeEvent(void) { this.m_events.ResetLastTradeEvent(); } //--- Return the (1) last trading event, (2) the last event in the account properties, (3) hedging account flag, (4) flag of working in the tester ENUM_TRADE_EVENT LastTradeEvent(void) const { returnthis.m_last_trade_event; } ENUM_ACCOUNT_EVENT LastAccountEvent(void) const { returnthis.m_last_account_event; } bool IsHedge(void) const { returnthis.m_is_hedge; } bool IsTester(void) const { returnthis.m_is_tester; } //--- タイマーカウンタを作成する void CreateCounter(constint id,constulong frequency,constulong pause); //--- タイマー void OnTimer(void); //--- Constructor/Destructor CEngine(); ~CEngine(); }; //+------------------------------------------------------------------+
クラスコンストラクタの初期化リストに最後の口座イベントの初期化を追加します。
//+------------------------------------------------------------------+ //| CEngineコンストラクタ | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true),m_last_trade_event(TRADE_EVENT_NO_EVENT),m_last_account_event(ACCOUNT_EVENT_NO_EVENT) {
AccountEventsControl()メソッドを追加します。これは、以前は、口座コレクションクラスのRefresh()メソッドの呼び出しにのみ使用されていました。
//+------------------------------------------------------------------+ //| Check account events | //+------------------------------------------------------------------+ void CEngine::AccountEventsControl(void) { //--- Check account property changes and set the flag of the account change events this.m_accounts.Refresh(); this.m_is_account_event=this.m_accounts.IsAccountEvent(); //--- If there are account property changes if(this.m_is_account_event) { //--- Get the last event of the account property change this.m_last_account_event=this.m_accounts.GetEvent(); } } //+------------------------------------------------------------------+
ここではすべてが簡単です。まず、 口座データを更新します。口座のプロパティのいずれかが変更された場合、単に最後のイベントを変数に書き込みます。イベントに関する残りのデータはすべて、ライブラリベースの管理プログラムで取得されます。
口座イベントのテスト
口座イベントをテストするには、ライブラリが独自にすべての口座プロパティを検出し、チャートイベントに適切なメッセージを送信し、操作ログに発生した口座の説明を表示するため、前の記事のEAを使用できます。
しかし、ライブラリの「サンドボックス」を超えて、プログラムの一部の口座イベント(たとえば、エクイティの増加)を処理してみてください。
現在、外部からのプログラム機能へのアクセスは非常に制限されています。ただし、これは、必要なデータを収集して処理するまでです。ライブラリは、作成されたクラス、収集されたデータ、および追跡されたイベントの正確性をテストするために操作ログにさまざまなイベントを表示します。さらに、ライブラリデータへの簡単で便利なアクセスを導入して、プログラムからの検索を大幅に簡素化します。
口座プロパティの変更に関するデータをすぐに取得するには、CEngineクラスを少し改善してみましょう。現在の口座オブジェクトとイベントにアクセスする必要があります。
これを行うには、必要なメソッドをCEngineクラスのpublicセクション(Engine.mqhファイル)に追加します。
public: //--- 市場の(1)ポジション、(2)未決注文、(3)成行注文のリストを返す CArrayObj* GetListMarketPosition(void); CArrayObj* GetListMarketPendings(void); CArrayObj* GetListMarketOrders(void); //--- 過去の(1)注文、(2)削除済み未決注文、(3)取引、(4)ID別の成行注文のポジションリストを返す CArrayObj* GetListHistoryOrders(void); CArrayObj* GetListHistoryPendings(void); CArrayObj* GetListDeals(void); CArrayObj* GetListAllOrdersByPosID(constulong position_id); //--- Return the list of (1) accounts, (2) account events, (3) account change event by its index in the list //--- (4) the current account, (5) event description CArrayObj* GetListAllAccounts(void) { return this.m_accounts.GetList(); } CArrayInt* GetListAccountEvents(void) { return this.m_accounts.GetListChanges(); } ENUM_ACCOUNT_EVENT GetAccountEventByIndex(const int index) { return this.m_accounts.GetEvent(index); } CAccount* GetAccountCurrent(void); string GetAccountEventDescription(ENUM_ACCOUNT_EVENT event);
ここでは、変更リストのインデックスによって口座イベントを受信するメソッド, 現在の口座オブジェクトを受信するメソッド、口座イベントの説明を受信するメソッドを追加しました。
インデックスによって口座イベントを受信するメソッド
は、単に口座コレクションクラスで前述のGetEvent()メソッドの操作結果を返します。
コードの最後に現在の口座オブジェクトを受け取るためのメソッドを実装します。
//+------------------------------------------------------------------+ //| Return the current account | //+------------------------------------------------------------------+ CAccount* CEngine::GetAccountCurrent(void) { int index=this.m_accounts.IndexCurrentAccount(); if(index==WRONG_VALUE) return NULL; CArrayObj* list=this.m_accounts.GetList(); return(list!=NULL ? (list.At(index)!=NULL ? list.At(index) : NULL) : NULL); } //+------------------------------------------------------------------+
まず、口座コレクションクラスから現在の口座のインデックスを取得します。インデックスが受信されなかった場合はNULLを返します。次に、口座の完全なリストを取得し、口座リストのインデックスで必要な現在の口座を返します。リストまたは口座のエラーが発生した場合はNULLを返します。
また、口座イベントの説明を返すメソッドを実装しましょう。
//+------------------------------------------------------------------+ //| Return the account event description | //+------------------------------------------------------------------+ string CEngine::GetAccountEventDescription(ENUM_ACCOUNT_EVENT event) { return this.m_accounts.EventDescription(event); } //+------------------------------------------------------------------+
メソッドは、口座イベントの説明を返す口座コレクションクラスメソッドの操作結果を返します。
口座イベントをテストするには、 \MQL5\Experts\TestDoEasy\Part12\にある前の記事からのEAであるTestDoEasyPart12_2.mq5を\MQL5\Experts\TestDoEasy\Part13で TestDoEasyPart13.mq5として保存します。
次の入力を削除します。
inputbool InpFullProperties = false;// Show full accounts properties
OnInit()ハンドラでの口座コレクションの高速確認も削除します。
//--- Fast check of the account object collection CArrayObj* list=engine.GetListAllAccounts(); if(list!=NULL) { int total=list.Total(); if(total>0) Print("\n",TextByLanguage("=========== Список сохранённых аккаунтов ===========","=========== List of saved accounts ===========")); for(int i=0;i<total;i++) { CAccount* account=list.At(i); if(account==NULL) continue; Sleep(100); if(InpFullProperties) account.Print(); else account.PrintShort(); } } //---
口座オブジェクトの構造体を変更したため(口座の文字列プロパティを保存するためのuchar配列のサイズを変更し、別の整数プロパティを追加)、以前に保存したすべての口座オブジェクトファイルは正しくダウンロードされなくなりました。これらが共通端末フォルダの\Files\DoEasy\Accounts\に存在する場合は、テストEAを起動する前に削除してください。口座から別の口座に切り替えたときに、すでに新しいオブジェクト構造体サイズで作成されます。
OnInit()ハンドラは次のようになります。
//+------------------------------------------------------------------+ //| エキスパート初期化関数 | //+------------------------------------------------------------------+ 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 and remove remaining EA graphical objects if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel if(!CreateButtons(InpButtShiftX,InpButtShiftY)) returnINIT_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); } //+------------------------------------------------------------------+
ライブラリからプログラムに到着するすべてのイベントを処理し、内蔵のOnChartEvent()が煩雑になるのを防ぐために、個別のOnDoEasyEvent()ハンドラを実装して、取得したすべてのイベントを処理します。これによりコードが読みやすくなり、さらに重要なことは、テスターでイベントを処理できるようになります。これはまさに「指定された増加値を超える株式の増加」口座イベントを処理するためです。それを達成するためにはテスターですべてを確認する方がずっと速くて簡単です。
OnTick()ハンドラで口座イベントを処理するために必要な機能を追加しましょう。
//+------------------------------------------------------------------+ //| エキスパートティック関数 | //+------------------------------------------------------------------+ void OnTick() { //--- Initialize the last events static ENUM_TRADE_EVENT last_trade_event=WRONG_VALUE; static ENUM_ACCOUNT_EVENT last_account_event=WRONG_VALUE; //--- If working in the tester if(MQLInfoInteger(MQL_TESTER)) { engine.OnTimer(); PressButtonsControl(); } //--- If the last trading event changed if(engine.LastTradeEvent()!=last_trade_event) { last_trade_event=engine.LastTradeEvent(); Comment("\nLast trade event: ",EnumToString(last_trade_event)); } //--- If the last account event changed if(engine.LastAccountEvent()!=last_account_event) { last_account_event=engine.LastAccountEvent(); //--- If this is a tester if(MQLInfoInteger(MQL_TESTER)) { //--- Get the list of all account events occurred simultaneously CArrayInt* list=engine.GetListAccountEvents(); if(list!=NULL) { //--- Get the next event in a loop int total=list.Total(); for(int i=0;i<total;i++) { ENUM_ACCOUNT_EVENT event=(ENUM_ACCOUNT_EVENT)list.At(i); if(event==NULL) continue; string sparam=engine.GetAccountEventDescription(event); long lparam=TimeCurrent()*1000; double dparam=(double)i; //--- Send an event to the event handler OnDoEasyEvent(CHARTEVENT_CUSTOM+event,lparam,dparam,sparam); } } } Comment("\nLast account event: ",EnumToString(last_account_event)); } //--- If the trailing flag is set if(trailing_on) { TrailingPositions(); TrailingOrders(); } } //+------------------------------------------------------------------+
ここでは、最後の口座イベントのタイプを格納する新しい変数を導入しました。CAccountsCollectionクラスによって返された最後のイベントのタイプに関連する現在のステータスを確認します。ステータスが変更された場合、口座イベントが発生しました。次に、テスター専用の同時に発生したイベントの口座リストに従ってループで新しいイベントを取得し、ライブラリイベントハンドラに送信します。イベントを受信してハンドラに送信するためのすべてのアクションはコメントされています。テスターで作業する場合、ミリ秒単位のイベント時間のデータにはアクセスできないため、単にcurrent time * 1000を送信します。
さて、OnChartEvent()イベントハンドラを改善しましょう。
//+------------------------------------------------------------------+ //| ChartEvent関数 | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(MQLInfoInteger(MQL_TESTER)) return; if(id==CHARTEVENT_OBJECT_CLICK && StringFind(sparam,"BUTT_")>0) { PressButtonEvents(sparam); } //--- DoEasy library event if(id>=CHARTEVENT_CUSTOM) { OnDoEasyEvent(id,lparam,dparam,sparam); } } //+------------------------------------------------------------------+
ここでは、イベントIDがライブラリイベントを示す場合にライブラリイベントハンドラの呼び出しを追加しました。
最後に、ライブラリイベントハンドラを実装します。
//+------------------------------------------------------------------+ //| 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); int digits=Digits(); //--- Handling trading events if(idx<TRADE_EVENTS_NEXT_CODE) { event=EnumToString((ENUM_TRADE_EVENT)ushort(idx)); digits=(int)SymbolInfoInteger(sparam,SYMBOL_DIGITS); } //--- Handling account events else if(idx<ACCOUNT_EVENTS_NEXT_CODE) { event=EnumToString((ENUM_ACCOUNT_EVENT)ushort(idx)); digits=0; //--- if this is an equity increase if((ENUM_ACCOUNT_EVENT)idx==ACCOUNT_EVENT_EQUITY_INC) { Print(DFUN,sparam); //--- Close a position with the highest profit when the equity exceeds the value //--- specified in the CAccountsCollection::InitControlsParams() method for //--- the m_control_equity_inc variable tracking the equity growth by 15 units (by default) //--- AccountCollection file, InitControlsParams() method, string 1199 //--- すべてのポジションのリストを取得する CArrayObj* list_positions=engine.GetListMarketPosition(); //--- 手数料とスワップを考慮して、リストを利益順に並べ替える 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 } } } } } //+------------------------------------------------------------------+
イベントを制御プログラムチャートに送信すると、1000に等しいCHARTEVENT_CUSTOMの値がコードに追加されます。 したがって、本当のコードを受け取るには、 取得したコードからCHARTEVENT_CUSTOM値を減算する必要があります。 イベントの数値がTRADE_EVENTS_NEXT_CODEからACCOUNT_EVENTS_NEXT_CODE-1の範囲内にある場合、口座プロパティ変更イベントが到着したことを意味します。 エクイティが設定で指定された値(デフォルトの増加値は15以上)を超えて増加したときに最も収益性の高いポジションを決済するために 「指定された値を超えるエクイティ」イベントを確認 し、操作ログにイベントの説明を表示し、最も収益性の高いポジションを決済します。コードには必要なコメントが付いています。
チャートで今EAを起動すれば、しばらくしてから有効/無効にされている取引に関する操作ログエントリが表示されます。
2019.06.1010:56:33.8772019.06.1006:55:29.279: Trading on the account is prohibited now 2019.06.1011:08:56.5492019.06.1007:08:51.900: Trading on the account is allowed now
MetaQuotes-Demoでは、このような有効化/無効化を1日に数回観察することができ、ライブラリがデモ口座でそのようなイベントを定義する方法を確認できます。
テスターでEAを起動してより多くのポジションを開けば、エクイティ増加イベントに続いて最も収益性の高いポジションが決済されるのをすぐに見ることができます。
ご覧のとおり、エクイティが指定値を超えると、最も収益性の高いポジションが自動的に決済されて、操作ログには、追跡された口座イベントに関するメッセージが表示されます。
次の段階
次の部分では、銘柄での作業を開始し、銘柄オブジェクト、銘柄オブジェクトコレクション、銘柄イベントを実装します。
現在のバージョンのライブラリのすべてのファイルは、テスト用EAファイルと一緒に以下に添付されているので、テストするにはダウンロードしてください。
質問、コメント、提案はコメント欄にお願いします。
シリーズのこれまでの記事:
第1部: 概念、データ管理
第2部:
過去の注文と取引のコレクション
第3部:注文と取引のコレクション、検索と並び替え
第4部:
取引イベント概念
第5部: 取引イベントのクラスとコレクション取引イベントのプログラムへの送信
第6部:
ネッティング勘定イベント
第7部: StopLimit注文発動イベント、注文およびポジション変更イベントの機能の準備
第8部:
注文とポジションの変更イベント。第9部:MQL4との互換性 - データの準備
第10部:MQL4との互換性
- ポジションオープンイベントと指値注文発動イベント
第11部:MQL4との互換性 - ポジション決済イベント
第12部:口座オブジェクトクラスと口座オブジェクトコレクション
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/6995
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索