MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第15部): 銘柄オブジェクトのコレクション
内容
銘柄コレクションの概念
第3部ではオブジェクトコレクションクラスを構築する概念を既に定義しています。ここでは、採用されているデータストレージ構造を順守します。つまり、銘柄コレクションのリストを作成する必要があります。このリストは、前の記事で作成された「symbol」クラスの子孫オブジェクトを保存するためのものです。抽象銘柄の子孫は、銘柄データを明確にし、プログラム内での基本的な銘柄オブジェクトプロパティの可用性を定義します。このような銘柄オブジェクトは、グループとの関係によって区別されます(銘柄ステータス)。
- 外為銘柄 — 以下の外国為替銘柄カテゴリに分類されないすべての外国為替銘柄です。
- Major外為銘柄 — 使用頻度の最も高い外国為替銘柄のカスタムカテゴリ
- Minor外為銘柄 — 使用頻度の低い外国為替銘柄のカスタムカテゴリ
- Exotic外為銘柄 — 使用頻度の非常に低い外国為替銘柄のカスタムカテゴリ
- 外為銘柄/RUB — RUBを備えた外国為替銘柄のカスタムカテゴリ
- 金属 — 金属銘柄のカスタムカテゴリ
- インデックス — インデックス銘柄のカスタムカテゴリ
- 指標 — 指標銘柄のカスタムカテゴリ
- 暗号通貨銘柄 — 暗号通貨銘柄のカスタムカテゴリ
- 商品銘柄 — 商品銘柄のカスタムカテゴリ
- 取引所銘柄 — 以下の取引所銘柄のカテゴリに分類されないすべての取引所銘柄です。
- 先物
- CFD
- 証券
- 債券
- オプション
- 非取引資産
- カスタム銘柄
- 一般カテゴリ — 上記のカテゴリに分類されない銘柄
銘柄が属するグループ(銘柄ステータス)を定義するために、カスタムデータセットを作成します。まず必要なのは、カテゴリを検索する銘柄名の配列です。カスタムカテゴリに銘柄が見つからない場合(名前がユーザ定義の銘柄名配列に存在しない)、カテゴリは銘柄の証拠金計算方法プロパティ( ENUM_SYMBOL_CALC_MODE )によって定義され、上記のカテゴリの一部に銘柄が属するかどうかを定義できるようになります。つまり、検索は2つのチェックとして実行されます。最初のチェックをカスタムカテゴリで実行して、カテゴリの定義に失敗した場合、銘柄の証拠金計算方法を使用した検索が行われます。以前、私は銘柄がサーバの銘柄ディレクトリツリーにあるフォルダの名前で定義するという、さらに別の方法を使用する予定でした。しかし、フォルダは任意の名前を持ち、同じ銘柄が異なるサーバに配置される可能性があるため、この方法はあまり信頼できないので、使用しないことにしました。
カスタムカテゴリの優先度は高くなります。ユーザが銘柄(たとえば、指標であるUSDUSC)を「major」カテゴリに配置したい場合、それを妨げるものは何もありません。
カテゴリを決定したので、必要な抽象銘柄の下位クラスを作成しましょう。抽象銘柄自体は、前の記事で作成されました。
すべての銘柄オブジェクトを保存するには、第5部でライブラリクラスの再配置を説明した際に考察した、CArrayObj標準ライブラリクラスから継承したCListObjクラスを使用する必要があります。 ライブラリに基づいたプログラムでは、使用する銘柄リストを選択する機能があります。
- 1つのみ — プログラムが接続されている現在の銘柄
- プログラムで指定された定義済みの銘柄セット
- [気配値表示]ウィンドウにある銘柄リストの使用
- サーバで使用可能な銘柄の完全なリストの使用
したがって、使用中の銘柄にアクセスするために必要なプログラミングタスクのほとんどが網羅されます。
ここで、次の2つのことに言及する必要があります。
- 気配値表示からの銘柄リストを使用する場合、[気配値表示]ウィンドウイベントの検索を使用して、タイムリーに変更に対応する必要があります(リストから銘柄を追加/削除し、 マウスで並び替え)
- サーバで使用可能な銘柄の完全なリストを使用する場合、サーバ上の銘柄の完全なリストは最初の起動時に表示できるため、使用可能な多数の銘柄の通常の処理を手配する必要があります。また、すべてのプロパティを受け取る必要がある銘柄オブジェクトが作成され、このプロセスには時間がかかります。私の場合、サーバにあるすべての銘柄のコレクションを作成するには、中間層のラップトップで約2分かかりました。
まず、この使用方法を選択する場合、少なくともユーザに初期情報の収集に費やされる時間について警告する必要があります。
それを行うとともに、後続の記事では銘柄追跡イベントと[気配値表示]ウィンドウイベントを実装します。とりあえず、コレクションリストを作成しましょう。
はじめに、ライブラリに必要なすべてのデータ(カスタム銘柄グループ、ファイル、画像、ライブラリに必要なその他のデータセットの配列)を保存する別のインクルードファイルを作成しましょう。
\MQL5\Include\DoEasy\ライブラリフォルダで、新しいDatas.mqhインクルードファイルを作成し、いくつかの配列の後に事前に準備した配列を追加し、[気配値表示]ウィンドウのツリー構造から異なるサーバに設定された銘柄グループのアカウントとデータを収集します。
//+------------------------------------------------------------------+ //| Datas.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" //+------------------------------------------------------------------+ //| Data sets | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Major Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXMajors[]= { "AUDCAD","AUDCHF","AUDJPY","AUDNZD","AUDUSD","CADCHF","CADJPY","CHFJPY","EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD", "EURUSD","GBPAUD","GBPCAD","GBPCHF","GBPJPY","GBPNZD","GBPUSD","NZDCAD","NZDCHF","NZDJPY","NZDUSD","USDCAD","USDCHF","USDJPY" }; //+------------------------------------------------------------------+ //| Minor Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXMinors[]= { "EURCZK","EURDKK","EURHKD","EURNOK","EURPLN","EURSEK","EURSGD","EURTRY","EURZAR","GBPSEK","GBPSGD" ,"NZDSGD","USDCZK","USDDKK","USDHKD","USDNOK","USDPLN","USDSEK","USDSGD","USDTRY","USDZAR" }; //+------------------------------------------------------------------+ //| Exotic Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXExotics[]= { "EURMXN","USDCNH","USDMXN","EURTRY","USDTRY" }; //+------------------------------------------------------------------+ //| Forex RUB symbols | //+------------------------------------------------------------------+ string DataSymbolsFXRub[]= { "EURRUB","USDRUB" }; //+------------------------------------------------------------------+ //| Indicative Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXIndicatives[]= { "EUREUC","USDEUC","USDUSC" }; //+------------------------------------------------------------------+ //| Metal symbols | //+------------------------------------------------------------------+ string DataSymbolsMetalls[]= { "XAGUSD","XAUUSD" }; //+------------------------------------------------------------------+ //| Commodity symbols | //+------------------------------------------------------------------+ string DataSymbolsCommodities[]= { "BRN","WTI","NG" }; //+------------------------------------------------------------------+ //| Indices | //+------------------------------------------------------------------+ string DataSymbolsIndexes[]= { "CAC40","HSI50","ASX200","STOXX50","NQ100","FTSE100","DAX30","IBEX35","SPX500","NIKK225" "Volatility 10 Index","Volatility 25 Index","Volatility 50 Index","Volatility 75 Index","Volatility 100 Index", "HF Volatility 10 Index","HF Volatility 50 Index","Crash 1000 Index","Boom 1000 Index","Step Index" }; //+------------------------------------------------------------------+ //| Cryptocurrency Symbols | //+------------------------------------------------------------------+ string DataSymbolsCrypto[]= { "BCHUSD","BTCEUR","BTCUSD","DSHUSD","EOSUSD","ETHEUR","ETHUSD","LTCUSD","XRPUSD" }; //+------------------------------------------------------------------+ //| Options | //+------------------------------------------------------------------+ string DataSymbolsOptions[]= { "BO Volatility 10 Index","BO Volatility 25 Index","BO Volatility 50 Index","BO Volatility 75 Index","BO Volatility 100 Index" }; //+------------------------------------------------------------------+
コードからわかるように、これは単に、各配列にある銘柄のグループを定義する必要な配列に銘柄名の列挙を追加しただけです。必要に応じて、これらの銘柄名の配列の内容は、名前を別の配列に送信したり追加/削除するなどして処理できます。
抽象銘柄オブジェクトの動作をより厳密にテストすると、SYMBOL_MARGIN_LONG、SYMBOL_MARGIN_SHORT、SYMBOL_MARGIN_STOP、SYMBOL_MARGIN_LIMIT、SYMBOL_MARGIN_STOPLIMIT定数を使用しても銘柄プロパティが得られないことがわかります。そこで、SymbolInfoMarginRate()関数を使用してプロパティの受信を実装する必要がありました。
注文タイプが関数に送信されるので、各注文タイプに対して、Defines.mqhファイルで銘柄オブジェクトの実数プロパティにカスタム定数を作成する必要がありました。
//+------------------------------------------------------------------+ //| Symbol real properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_DOUBLE { SYMBOL_PROP_BID = SYMBOL_PROP_INTEGER_TOTAL, // Bid - the best price at which a symbol can be sold SYMBOL_PROP_BIDHIGH, // The highest Bid price of the day SYMBOL_PROP_BIDLOW, // The lowest Bid price of the day SYMBOL_PROP_ASK, // Ask - best price, at which an instrument can be bought SYMBOL_PROP_ASKHIGH, // The highest Ask price of the day SYMBOL_PROP_ASKLOW, // The lowest Ask price of the day SYMBOL_PROP_LAST, // The price at which the last deal was executed SYMBOL_PROP_LASTHIGH, // The highest Last price of the day SYMBOL_PROP_LASTLOW, // The lowest Last price of the day SYMBOL_PROP_VOLUME_REAL, // Volume of the day SYMBOL_PROP_VOLUMEHIGH_REAL, // Maximum Volume within a day SYMBOL_PROP_VOLUMELOW_REAL, // Minimum Volume within a day SYMBOL_PROP_OPTION_STRIKE, // Option execution price SYMBOL_PROP_POINT, // One point value SYMBOL_PROP_TRADE_TICK_VALUE, // SYMBOL_TRADE_TICK_VALUE_PROFIT value SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT, // Calculated tick value for a winning position SYMBOL_PROP_TRADE_TICK_VALUE_LOSS, // Calculated tick value for a losing position SYMBOL_PROP_TRADE_TICK_SIZE, // Minimum price change SYMBOL_PROP_TRADE_CONTRACT_SIZE, // Trade contract size SYMBOL_PROP_TRADE_ACCRUED_INTEREST, // Accrued interest SYMBOL_PROP_TRADE_FACE_VALUE, // Face value – initial bond value set by an issuer SYMBOL_PROP_TRADE_LIQUIDITY_RATE, // Liquidity rate – the share of an asset that can be used for a margin SYMBOL_PROP_VOLUME_MIN, // Minimum volume for a deal SYMBOL_PROP_VOLUME_MAX, // Maximum volume for a deal SYMBOL_PROP_VOLUME_STEP, // Minimum volume change step for deal execution SYMBOL_PROP_VOLUME_LIMIT, // The maximum allowed total volume of an open position and pending orders in one direction (either buy or sell) SYMBOL_PROP_SWAP_LONG, // Long swap value SYMBOL_PROP_SWAP_SHORT, // Short swap value SYMBOL_PROP_MARGIN_INITIAL, // Initial margin SYMBOL_PROP_MARGIN_MAINTENANCE, // Maintenance margin for an instrument SYMBOL_PROP_MARGIN_LONG_INITIAL, // Initial margin requirement applicable to long positions SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL, // Initial margin requirement applicable to BuyStop orders SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL, // Initial margin requirement applicable to BuyLimit orders SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL, // Initial margin requirement applicable to BuyStopLimit orders SYMBOL_PROP_MARGIN_LONG_MAINTENANCE, // Maintenance margin requirement applicable to long positions SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE, // Maintenance margin requirement applicable to BuyStop orders SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE, // Maintenance margin requirement applicable to BuyLimit orders SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE, // Maintenance margin requirement applicable to BuyStopLimit orders SYMBOL_PROP_MARGIN_SHORT_INITIAL, // Initial margin requirement applicable to short positions SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL, // Initial margin requirement applicable to SellStop orders SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL, // Initial margin requirement applicable to SellLimit orders SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL, // Initial margin requirement applicable to SellStopLimit orders SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE, // Maintenance margin requirement applicable to short positions SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE, // Maintenance margin requirement applicable to SellStop orders SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE, // Maintenance margin requirement applicable to SellLimit orders SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE, // Maintenance margin requirement applicable to SellStopLimit orders SYMBOL_PROP_SESSION_VOLUME, // The total volume of deals in the current session SYMBOL_PROP_SESSION_TURNOVER, // The total turnover in the current session SYMBOL_PROP_SESSION_INTEREST, // The total volume of open positions SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME, // The total volume of Buy orders at the moment SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME, // The total volume of Sell orders at the moment SYMBOL_PROP_SESSION_OPEN, // Open price of the session SYMBOL_PROP_SESSION_CLOSE, // Close price of the session SYMBOL_PROP_SESSION_AW, // The average weighted price of the session SYMBOL_PROP_SESSION_PRICE_SETTLEMENT, // The settlement price of the current session SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN, // Minimum allowable price value for the session SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX, // Maximum allowable price value for the session SYMBOL_PROP_MARGIN_HEDGED // Size of a contract or margin for one lot of hedged positions (oppositely directed positions at one symbol). }; #define SYMBOL_PROP_DOUBLE_TOTAL (58) // Total number of real properties #define SYMBOL_PROP_DOUBLE_SKIP (0) // Number of real symbol properties not used in sorting //+------------------------------------------------------------------+
したがって、実数プロパティの総数は 58に増えました(以前の47の代わりに)。
また、対応する定数を銘柄の可能な並び替え基準の列挙に追加する必要がありました。
//+------------------------------------------------------------------+ //| Possible symbol sorting criteria | //+------------------------------------------------------------------+ #define FIRST_SYM_DBL_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP) #define FIRST_SYM_STR_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP+SYMBOL_PROP_DOUBLE_TOTAL-SYMBOL_PROP_DOUBLE_SKIP) enum ENUM_SORT_SYMBOLS_MODE { //--- 整数型プロパティによって並び替える SORT_BY_SYMBOL_STATUS = 0, // Sort by symbol status SORT_BY_SYMBOL_CUSTOM, // Sort by custom symbol property SORT_BY_SYMBOL_CHART_MODE, // Sort by price type for constructing bars – Bid or Last (from the ENUM_SYMBOL_CHART_MODE enumeration) SORT_BY_SYMBOL_EXIST, // Sort by the flag that a symbol with such a name exists SORT_BY_SYMBOL_SELECT, // Sort by the flag indicating that a symbol is selected in Market Watch SORT_BY_SYMBOL_VISIBLE, // Sort by the flag indicating that a selected symbol is displayed in Market Watch SORT_BY_SYMBOL_SESSION_DEALS, // Sort by the number of deals in the current session SORT_BY_SYMBOL_SESSION_BUY_ORDERS, // Sort by the total number of current buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS, // Sort by the total number of current sell orders SORT_BY_SYMBOL_VOLUME, // Sort by last deal volume SORT_BY_SYMBOL_VOLUMEHIGH, // Sort by maximum volume for a day SORT_BY_SYMBOL_VOLUMELOW, // Sort by minimum volume for a day SORT_BY_SYMBOL_TIME, // Sort by the last quote time SORT_BY_SYMBOL_DIGITS, // Sort by a number of decimal places SORT_BY_SYMBOL_DIGITS_LOT, // Sort by a number of decimal places in a lot SORT_BY_SYMBOL_SPREAD, // Sort by spread in points SORT_BY_SYMBOL_SPREAD_FLOAT, // Sort by floating spread SORT_BY_SYMBOL_TICKS_BOOKDEPTH, // Sort by a maximum number of requests displayed in the market depth SORT_BY_SYMBOL_TRADE_CALC_MODE, // Sort by contract price calculation method (from the ENUM_SYMBOL_CALC_MODE enumeration) SORT_BY_SYMBOL_TRADE_MODE, // Sort by order execution type (from the ENUM_SYMBOL_TRADE_MODE enumeration) SORT_BY_SYMBOL_START_TIME, // Sort by an instrument trading start date (usually used for futures) SORT_BY_SYMBOL_EXPIRATION_TIME, // Sort by an instrument trading end date (usually used for futures) SORT_BY_SYMBOL_TRADE_STOPS_LEVEL, // Sort by the minimum indent from the current close price (in points) for setting Stop orders SORT_BY_SYMBOL_TRADE_FREEZE_LEVEL, // Sort by trade operation freeze distance (in points) SORT_BY_SYMBOL_TRADE_EXEMODE, // Sort by trade execution mode (from the ENUM_SYMBOL_TRADE_EXECUTION enumeration) SORT_BY_SYMBOL_SWAP_MODE, // Sort by swap calculation model (from the ENUM_SYMBOL_SWAP_MODE enumeration) SORT_BY_SYMBOL_SWAP_ROLLOVER3DAYS, // Sort by week day for accruing a triple swap (from the ENUM_DAY_OF_WEEK enumeration) SORT_BY_SYMBOL_MARGIN_HEDGED_USE_LEG, // Sort by the calculation mode of a hedged margin using the larger leg (Buy or Sell) SORT_BY_SYMBOL_EXPIRATION_MODE, // Sort by flags of allowed order expiration modes SORT_BY_SYMBOL_FILLING_MODE, // Sort by flags of allowed order filling modes SORT_BY_SYMBOL_ORDER_MODE, // Sort by flags of allowed order types SORT_BY_SYMBOL_ORDER_GTC_MODE, // Sort by StopLoss and TakeProfit orders lifetime SORT_BY_SYMBOL_OPTION_MODE, // Sort by option type (from the ENUM_SYMBOL_OPTION_MODE enumeration) SORT_BY_SYMBOL_OPTION_RIGHT, // Sort by option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration) //--- 実数型プロパティによって並び替える SORT_BY_SYMBOL_BID = FIRST_SYM_DBL_PROP, // Sort by Bid SORT_BY_SYMBOL_BIDHIGH, // Sort by maximum Bid for a day SORT_BY_SYMBOL_BIDLOW, // Sort by minimum Bid for a day SORT_BY_SYMBOL_ASK, // Sort by Ask SORT_BY_SYMBOL_ASKHIGH, // Sort by maximum Ask for a day SORT_BY_SYMBOL_ASKLOW, // Sort by minimum Ask for a day SORT_BY_SYMBOL_LAST, // Sort by the last deal price SORT_BY_SYMBOL_LASTHIGH, // Sort by maximum Last for a day SORT_BY_SYMBOL_LASTLOW, // Sort by minimum Last for a day SORT_BY_SYMBOL_VOLUME_REAL, // Sort by Volume for a day SORT_BY_SYMBOL_VOLUMEHIGH_REAL, // Sort by maximum Volume for a day SORT_BY_SYMBOL_VOLUMELOW_REAL, // Sort by minimum Volume for a day SORT_BY_SYMBOL_OPTION_STRIKE, // Sort by an option execution price SORT_BY_SYMBOL_POINT, // Sort by a single point value SORT_BY_SYMBOL_TRADE_TICK_VALUE, // Sort by SYMBOL_TRADE_TICK_VALUE_PROFIT value SORT_BY_SYMBOL_TRADE_TICK_VALUE_PROFIT, // Sort by a calculated tick price for a profitable position SORT_BY_SYMBOL_TRADE_TICK_VALUE_LOSS, // Sort by a calculated tick price for a loss-making position SORT_BY_SYMBOL_TRADE_TICK_SIZE, // Sort by a minimum price change SORT_BY_SYMBOL_TRADE_CONTRACT_SIZE, // Sort by a trading contract size SORT_BY_SYMBOL_TRADE_ACCRUED_INTEREST, // Sort by accrued interest SORT_BY_SYMBOL_TRADE_FACE_VALUE, // Sort by face value SORT_BY_SYMBOL_TRADE_LIQUIDITY_RATE, // Sort by liquidity rate SORT_BY_SYMBOL_VOLUME_MIN, // Sort by a minimum volume for performing a deal SORT_BY_SYMBOL_VOLUME_MAX, // Sort by a maximum volume for performing a deal SORT_BY_SYMBOL_VOLUME_STEP, // Sort by a minimum volume change step for deal execution SORT_BY_SYMBOL_VOLUME_LIMIT, // Sort by a maximum allowed aggregate volume of an open position and pending orders in one direction SORT_BY_SYMBOL_SWAP_LONG, // Sort by a long swap value SORT_BY_SYMBOL_SWAP_SHORT, // Sort by a short swap value SORT_BY_SYMBOL_MARGIN_INITIAL, // Sort by an initial margin SORT_BY_SYMBOL_MARGIN_MAINTENANCE, // Sort by a maintenance margin for an instrument SORT_BY_SYMBOL_MARGIN_LONG_INITIAL, // Sort by initial margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_INITIAL, // Sort by initial margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_LONG_MAINTENANCE, // Sort by maintenance margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_INITIAL, // Sort by initial margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_INITIAL, // Sort by initial margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_INITIAL, // Sort by initial margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_MAINTENANCE, // Sort by maintenance margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_SESSION_VOLUME, // Sort by summary volume of the current session deals SORT_BY_SYMBOL_SESSION_TURNOVER, // Sort by the summary turnover of the current session SORT_BY_SYMBOL_SESSION_INTEREST, // Sort by the summary open interest SORT_BY_SYMBOL_SESSION_BUY_ORDERS_VOLUME, // Sort by the current volume of Buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS_VOLUME, // Sort by the current volume of Sell orders SORT_BY_SYMBOL_SESSION_OPEN, // Sort by a session Open price SORT_BY_SYMBOL_SESSION_CLOSE, // Sort by a session Close price SORT_BY_SYMBOL_SESSION_AW, // Sort by an average weighted price of the current session SORT_BY_SYMBOL_SESSION_PRICE_SETTLEMENT, // Sort by a settlement price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MIN, // Sort by a minimum price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MAX, // Sort by a maximum price of the current session SORT_BY_SYMBOL_MARGIN_HEDGED, // Sort by a contract size or a margin value per one lot of hedged positions //--- 文字列型プロパティによって並び替える SORT_BY_SYMBOL_NAME = FIRST_SYM_STR_PROP, // Sort by a symbol name SORT_BY_SYMBOL_BASIS, // Sort by an underlying asset of a derivative SORT_BY_SYMBOL_CURRENCY_BASE, // Sort by a base currency of a symbol SORT_BY_SYMBOL_CURRENCY_PROFIT, // Sort by a profit currency SORT_BY_SYMBOL_CURRENCY_MARGIN, // Sort by a margin currency SORT_BY_SYMBOL_BANK, // Sort by a feeder of the current quote SORT_BY_SYMBOL_DESCRIPTION, // Sort by a symbol string description SORT_BY_SYMBOL_FORMULA, // Sort by the formula used for custom symbol pricing SORT_BY_SYMBOL_ISIN, // Sort by the name of a symbol in the ISIN system SORT_BY_SYMBOL_PAGE, // Sort by an address of the web page containing symbol information SORT_BY_SYMBOL_PATH // Sort by a path in the symbol tree }; //+------------------------------------------------------------------+
Defines.mqhファイルを編集するので、理由を説明しながら必要なものをすべて追加していきます。
コレクション内のすべての銘柄のデータを更新するには、タイマーが必要です。銘柄イベントクラスで追跡するために変更される可能性のあるデータとともに、すべての銘柄の相場データを更新する必要があることに注意してください(詳細は次の記事で説明します)。タイマーでは、[気配値表示]ウィンドウの銘柄リストを確認して、その変更に応答し、タイムリーにコレクションリストを更新する必要があります。
相場データは[気配値表示]ウィンドウの残りの銘柄データとそのリストよりも頻繁に更新する必要があります。つまり、銘柄コレクションには、相場データタイマーと、銘柄リストで実行される他のアクションのタイマーの2つが必要です。
2つの銘柄コレクションタイマーに必要なマクロ置換を追加しましょう。
//--- Symbol collection timer 1 parameters #define COLLECTION_SYM_PAUSE1 (100) // Pause of the symbol collection timer 1 in milliseconds (for scanning market watch symbols) #define COLLECTION_SYM_COUNTER_STEP1 (16) // Increment of the symbol timer 1 counter #define COLLECTION_SYM_COUNTER_ID1 (3) // Symbol timer 1 counter ID //--- Symbol collection timer 2 parameters #define COLLECTION_SYM_PAUSE2 (300) // Pause of the symbol collection timer 2 in milliseconds (for events of the market watch symbol list) #define COLLECTION_SYM_COUNTER_STEP2 (16) // Increment of the symbol timer 2 counter #define COLLECTION_SYM_COUNTER_ID2 (4) // Symbol timer 2 counter ID
これらのデータの違いは、各タイマーの一時停止時間とそのIDのみです。最初のタイマーの一時停止は100ミリ秒で、2番目のタイマーの一時停止は300ミリ秒です。
IDはコレクションごとに個別です。銘柄コレクションも例外ではありません。
リストにカスタムIDを設定しましょう。
//--- Collection list IDs #define COLLECTION_HISTORY_ID (0x7778+1) // Historical collection list ID #define COLLECTION_MARKET_ID (0x7778+2) // Market collection list ID #define COLLECTION_EVENTS_ID (0x7778+3) // Event collection list ID #define COLLECTION_ACCOUNT_ID (0x7778+4) // Account collection list ID #define COLLECTION_SYMBOLS_ID (0x7778+5) // Symbol collection list ID
前の記事では、[気配値表示]ウィンドウで銘柄を強調表示するのに使用される背景色を定義してその文字列の説明を表示するために、色をclrWhiteと比較して、プロパティ値が色の「long」値を超えた場合、背景色は設定されていないとみなしました。
property==SYMBOL_PROP_BACKGROUND_COLOR ? TextByLanguage("Цвет фона символа в Market Watch","Background color of symbol in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : #ifdef __MQL5__ (this.GetProperty(property)>clrWhite ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+::ColorToString((color)this.GetProperty(property),true)) #else TextByLanguage(": Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) :
ただし、開発者によると、これは正しくありません。[気配値表示]ウィンドウの銘柄の背景の「long」値は、「white」色の「long」値を超える場合があるため、そのような確認は場合によっては誤った結果を返します。
背景色がないことを正しく識別するには、プロパティ値をCLR_DEFAULTおよびCLR_NONE値と比較する必要があります。
マクロ置換を使用して「デフォルト」の色を設定しましょう(色の「不在」を示すCLR_NONEはMQL5とMQL4にすでに存在します)。
//--- Symbol parameters #define CLR_DEFAULT (0xFF000000) // Default color //+------------------------------------------------------------------+
その結果、定義ファイルのマクロ置換のセクションは次のようになります。
//+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ //--- Describe the function with the error line number #define DFUN_ERR_LINE (__FUNCTION__+(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian" ? ", Page " : ", Line ")+(string)__LINE__+": ") #define DFUN (__FUNCTION__+": ") // "Function description" #define COUNTRY_LANG ("Russian") // Country language #define END_TIME (D'31.12.3000 23:59:59') // End date for account history data requests #define TIMER_FREQUENCY (16) // Minimal frequency of the library timer in milliseconds //--- Parameters of the orders and deals collection timer #define COLLECTION_ORD_PAUSE (250) // Orders and deals collection timer pause in milliseconds #define COLLECTION_ORD_COUNTER_STEP (16) // Increment of the orders and deals collection timer counter #define COLLECTION_ORD_COUNTER_ID (1) // Orders and deals collection timer counter ID //--- Parameters of the account collection timer #define COLLECTION_ACC_PAUSE (1000) // Account collection timer pause in milliseconds #define COLLECTION_ACC_COUNTER_STEP (16) // Account timer counter increment #define COLLECTION_ACC_COUNTER_ID (2) // Account timer counter ID //--- Symbol collection timer 1 parameters #define COLLECTION_SYM_PAUSE1 (100) // Pause of the symbol collection timer 1 in milliseconds (for scanning market watch symbols) #define COLLECTION_SYM_COUNTER_STEP1 (16) // Increment of the symbol timer 1 counter #define COLLECTION_SYM_COUNTER_ID1 (3) // Symbol timer 1 counter ID //--- Symbol collection timer 2 parameters #define COLLECTION_SYM_PAUSE2 (300) // Pause of the symbol collection timer 2 in milliseconds (for events of the market watch symbol list) #define COLLECTION_SYM_COUNTER_STEP2 (16) // Increment of the symbol timer 2 counter #define COLLECTION_SYM_COUNTER_ID2 (4) // Symbol timer 2 counter ID //--- Collection list IDs #define COLLECTION_HISTORY_ID (0x7778+1) // Historical collection list ID #define COLLECTION_MARKET_ID (0x7778+2) // Market collection list ID #define COLLECTION_EVENTS_ID (0x7778+3) // Event collection list ID #define COLLECTION_ACCOUNT_ID (0x7778+4) // Account collection list ID #define COLLECTION_SYMBOLS_ID (0x7778+5) // Symbol collection list ID //--- Data parameters for file operations #define DIRECTORY ("DoEasy\\") // Library directory for storing object folders //--- Symbol parameters #define CLR_DEFAULT (0xFF000000) // Default color //+------------------------------------------------------------------+
銘柄コレクションの使用モード(現在の銘柄の使用、プログラムで事前定義された銘柄のリストの使用、[気配値表示]ウィンドウの使用、サーバで利用可能な銘柄の完全なリストの使用 )については既に説明しました。
列挙でこれらのモードをすべて設定しましょう。
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Work with the current symbol only SYMBOLS_MODE_DEFINES, // Work with the specified symbol list SYMBOLS_MODE_MARKET_WATCH, // Work with the Market Watch window symbols SYMBOLS_MODE_ALL // Work with the full symbol list }; //+------------------------------------------------------------------+
前の記事では、銘柄の並び替えに使用される銘柄カテゴリを特定し、本稿の冒頭では、使用する銘柄カテゴリのわずかに拡張されたリストを調べました。
銘柄カテゴリ(ステータス)の列挙を追加しましょう。
//+------------------------------------------------------------------+ //| Abstract symbol type (status) | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_STATUS { SYMBOL_STATUS_FX, // Forex symbol SYMBOL_STATUS_FX_MAJOR, // Major Forex symbol SYMBOL_STATUS_FX_MINOR, // Minor Forex symbol SYMBOL_STATUS_FX_EXOTIC, // Exotic Forex symbol SYMBOL_STATUS_FX_RUB, // Forex symbol/RUB SYMBOL_STATUS_METAL, // Metal SYMBOL_STATUS_INDEX, // Index SYMBOL_STATUS_INDICATIVE, // Indicative SYMBOL_STATUS_CRYPTO, // Cryptocurrency symbol SYMBOL_STATUS_COMMODITY, // Commodity symbol SYMBOL_STATUS_EXCHANGE, // Exchange symbol SYMBOL_STATUS_FUTURES, // Futures SYMBOL_STATUS_CFD, // CFD SYMBOL_STATUS_STOCKS, // Security SYMBOL_STATUS_BONDS, // Bond SYMBOL_STATUS_OPTION, // Option SYMBOL_STATUS_COLLATERAL, // Non-tradable asset SYMBOL_STATUS_CUSTOM, // Custom symbol SYMBOL_STATUS_COMMON // General category }; //+------------------------------------------------------------------+
銘柄コレクションのデータを準備し、Defines.mqhファイルにすべての変更を加えました。
この変更は、前の記事で作成したCSymbolクラスにも影響しました。
リンクによって関数に渡された変数がそこから要求された値を返すために使用される一方、SymbolInfoMarginRate()関数を使用してさまざまな注文タイプの証拠金率のデータを受け取るようになったため、これらの変数を作成する必要があります。
8つの注文とそれぞれに2つの割合タイプ(当初証拠金と維持証拠金率)があると仮定すると、これらの値を受け取るための変数は16個あるはずです。したがって、2つのネストされた構造体で構成される構造体を作成すると便利です。1番目の構造体では、当初証拠金と維持証拠金率を格納するために2つのdouble変数が定義され、2番目の構造体には、割合を取得する注文タイプ別にデータを保存するための最初に宣言された構造体が含まれます。
Symbol.mqh銘柄クラスファイルのCSymbolクラスのprivateセクションで、これらの構造体と2番目の構造体型を持つクラスメンバー変数を宣言しましょう。
//+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CObject { private: struct SMarginRate { double Initial; // initial margin rate double Maintenance; // maintenance margin rate }; struct SMarginRateMode { SMarginRate Long; // MarginRate of long positions SMarginRate Short; // MarginRate of short positions SMarginRate BuyStop; // MarginRate of BuyStop orders SMarginRate BuyLimit; // MarginRate of BuyLimit orders SMarginRate BuyStopLimit; // MarginRate of BuyStopLimit orders SMarginRate SellStop; // MarginRate of SellStop orders SMarginRate SellLimit; // MarginRate of SellLimit orders SMarginRate SellStopLimit; // MarginRate of SellStopLimit orders }; SMarginRateMode m_margin_rate; // Margin ratio structure
各保証金率のすべての銘柄プロパティを埋めるメソッドとすべての保証金率を格納する構造体の変数を初期化するメソッドをクラスのprivateセクションに追加しましょう。また、現在の曜日を受信する補助メソッドと「double」値の小数点以下の桁数を受け取る補助メソッドの2つを追加しましょう。
SMarginRateMode m_margin_rate; // Margin ratio structure MqlTick m_tick; // Symbol tick structure MqlBookInfo m_book_info_array[]; // Array of the market depth data structures string m_symbol_name; // Symbol name long m_long_prop[SYMBOL_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[SYMBOL_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[SYMBOL_PROP_STRING_TOTAL]; // String properties int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code //--- Return the index of the array the symbol's (1) double and (2) string properties are located at int IndexProp(ENUM_SYMBOL_PROP_DOUBLE property) const { return(int)property-SYMBOL_PROP_INTEGER_TOTAL; } int IndexProp(ENUM_SYMBOL_PROP_STRING property) const { return(int)property-SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_DOUBLE_TOTAL; } //--- (1) Fill in all the "margin ratio" symbol properties, (2) initialize the ratios bool MarginRates(void); void InitMarginRates(void); //--- Reset all symbol object data void Reset(void); //--- Return the current day of the week ENUM_DAY_OF_WEEK CurrentDayOfWeek(void) const; //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; public:
クラスの同じprivateセクションで、各注文タイプの証拠金率に関するデータを返すメソッドを宣言します。
//--- Get and return real properties of a selected symbol from its parameters double SymbolBidHigh(void) const; double SymbolBidLow(void) const; double SymbolVolumeReal(void) const; double SymbolVolumeHighReal(void) const; double SymbolVolumeLowReal(void) const; double SymbolOptionStrike(void) const; double SymbolTradeAccruedInterest(void) const; double SymbolTradeFaceValue(void) const; double SymbolTradeLiquidityRate(void) const; double SymbolMarginHedged(void) const; bool SymbolMarginLong(void); bool SymbolMarginShort(void); bool SymbolMarginBuyStop(void); bool SymbolMarginBuyLimit(void); bool SymbolMarginBuyStopLimit(void); bool SymbolMarginSellStop(void); bool SymbolMarginSellLimit(void); bool SymbolMarginSellStopLimit(void); //--- Get and return string properties of a selected symbol from its parameters
場合によっては、プログラムはサーバに銘柄が存在するかどうかを知る必要があります。これは、銘柄名によって行うことができます。クラス銘柄でそのようなデータを返すExist()メソッドは既に存在するので、このメソッドをオーバーロードして、渡された銘柄名でデータを返すことができるようにします。これを行うには、クラスのprivateセクションでさらに別のメソッド呼び出しを宣言します。
//--- Search for a symbol and return the flag indicating its presence on the server bool Exist(void) const; bool Exist(const string name) const;
また、クラスのprotectedセクションでオーバーロードされたメソッドを宣言します。MQL5またはMQL4プログラムタイプに応じて、このメソッドは名前で銘柄値を返します。
protected: //--- 保護されたパラメトリックコンストラクタ CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name); //--- Get and return integer properties of a selected symbol from its parameters bool SymbolExists(const string name) const; long SymbolExists(void) const;
クラスのpublicセクションのプロパティ説明メソッドのサブセクションで、銘柄の短い説明を表示する仮想メソッドを宣言します。
この仮想メソッドをクラスの子孫で実装して、銘柄オブジェクトを明確化するデータを設定します。
//+------------------------------------------------------------------+ //| Description of symbol object properties | //+------------------------------------------------------------------+ //--- Get description of a symbol (1) integer, (2) real and (3) string properties string GetPropertyDescription(ENUM_SYMBOL_PROP_INTEGER property); string GetPropertyDescription(ENUM_SYMBOL_PROP_DOUBLE property); string GetPropertyDescription(ENUM_SYMBOL_PROP_STRING property); //--- Send description of symbol properties to the journal (full_prop=true - all properties, false - only supported ones) void Print(const bool full_prop=false); //--- Display a short symbol description in the journal (implementation in the descendants) virtual void PrintShort(void) {;} //--- Compare CSymbol objects by all possible properties (for sorting lists by a specified symbol object property)
前の記事では、銘柄オブジェクトを実装するときにいくつかのサービスメソッドを追加しました。
相場および取引セッションの開始および終了時間を返すメソッド、セッションの時間、分、秒の整数を返すプライベートメソッド、「HH:MM:SS」形式でセッション時間の説明を返すメソッドを追加しましょう。
//--- (1) Add, (2) remove a symbol from the Market Watch window, (3) return the data synchronization flag by a symbol bool SetToMarketWatch(void) const { return ::SymbolSelect(this.m_symbol_name,true); } bool RemoveFromMarketWatch(void) const { return ::SymbolSelect(this.m_symbol_name,false); } bool IsSynchronized(void) const { return ::SymbolIsSynchronized(this.m_symbol_name); } //--- Return the (1) start and (2) end time of the week day's quote session, (3) the start and end time of the required quote session long SessionQuoteTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; long SessionQuoteTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; bool GetSessionQuote(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to); //--- Return the (1) start and (2) end time of the week day's trading session, (3) the start and end time of the required trading session long SessionTradeTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; long SessionTradeTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; bool GetSessionTrade(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to); //--- (1) Arrange a (1) subscription to the market depth, (2) close the market depth, (3) fill in the market depth data to the structure array bool BookAdd(void) const; bool BookClose(void) const; //--- Return (1) a session duration description in the hh:mm:ss format, number of (1) hours, (2) minutes and (3) seconds in the session duration time string SessionDurationDescription(const ulong duration_sec) const; private: int SessionHours(const ulong duration_sec) const; int SessionMinutes(const ulong duration_sec) const; int SessionSeconds(const ulong duration_sec) const; public: //+------------------------------------------------------------------+
publicセクション内の銘柄オブジェクトプロパティへの単純化されたアクセスのためのメソッドのサブセクションで、サーバ上の銘柄存在のフラグを返すメソッドを呼び出す2番目の形式を追加します(以前は、サーバ上の銘柄を名前で検索し、検索結果のフラグを返すプライベートオーバーロードメソッドを宣言しました )。
//+------------------------------------------------------------------+ //| Methods of a simplified access to the order object properties | //+------------------------------------------------------------------+ //--- Integer properties long Status(void) const { return this.GetProperty(SYMBOL_PROP_STATUS); } bool IsCustom(void) const { return (bool)this.GetProperty(SYMBOL_PROP_CUSTOM); } color ColorBackground(void) const { return (color)this.GetProperty(SYMBOL_PROP_BACKGROUND_COLOR); } ENUM_SYMBOL_CHART_MODE ChartMode(void) const { return (ENUM_SYMBOL_CHART_MODE)this.GetProperty(SYMBOL_PROP_CHART_MODE); } bool IsExist(void) const { return (bool)this.GetProperty(SYMBOL_PROP_EXIST); } bool IsExist(const string name) const { return this.SymbolExists(name); } bool IsSelect(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SELECT); } bool IsVisible(void) const { return (bool)this.GetProperty(SYMBOL_PROP_VISIBLE); } long SessionDeals(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_DEALS); }
publicセクション内の銘柄の実数プロパティへの単純化されたアクセスのためのメソッドのサブセクションで、すべての保証金率を返すメソッドを追加します。
//--- Real properties double Bid(void) const { return this.GetProperty(SYMBOL_PROP_BID); } double BidHigh(void) const { return this.GetProperty(SYMBOL_PROP_BIDHIGH); } double BidLow(void) const { return this.GetProperty(SYMBOL_PROP_BIDLOW); } double Ask(void) const { return this.GetProperty(SYMBOL_PROP_ASK); } double AskHigh(void) const { return this.GetProperty(SYMBOL_PROP_ASKHIGH); } double AskLow(void) const { return this.GetProperty(SYMBOL_PROP_ASKLOW); } double Last(void) const { return this.GetProperty(SYMBOL_PROP_LAST); } double LastHigh(void) const { return this.GetProperty(SYMBOL_PROP_LASTHIGH); } double LastLow(void) const { return this.GetProperty(SYMBOL_PROP_LASTLOW); } double VolumeReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_REAL); } double VolumeHighReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH_REAL); } double VolumeLowReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW_REAL); } double OptionStrike(void) const { return this.GetProperty(SYMBOL_PROP_OPTION_STRIKE); } double Point(void) const { return this.GetProperty(SYMBOL_PROP_POINT); } double TradeTickValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE); } double TradeTickValueProfit(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT); } double TradeTickValueLoss(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS); } double TradeTickSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_SIZE); } double TradeContractSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_CONTRACT_SIZE); } double TradeAccuredInterest(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_ACCRUED_INTEREST); } double TradeFaceValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_FACE_VALUE); } double TradeLiquidityRate(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_LIQUIDITY_RATE); } double LotsMin(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MIN); } double LotsMax(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MAX); } double LotsStep(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_STEP); } double VolumeLimit(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_LIMIT); } double SwapLong(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_LONG); } double SwapShort(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SHORT); } double MarginInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_INITIAL); } double MarginMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_MAINTENANCE); } double MarginLongInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_INITIAL); } double MarginBuyStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL); } double MarginBuyLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL); } double MarginBuyStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL); } double MarginLongMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE); } double MarginBuyStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE); } double MarginBuyLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE); } double MarginBuyStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE); } double MarginShortInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_INITIAL); } double MarginSellStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL); } double MarginSellLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL); } double MarginSellStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL); } double MarginShortMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE); } double MarginSellStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE); } double MarginSellLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE); } double MarginSellStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE); } double SessionVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_VOLUME); } double SessionTurnover(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_TURNOVER); } double SessionInterest(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_INTEREST); } double SessionBuyOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } double SessionSellOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } double SessionOpen(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_OPEN); } double SessionClose(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_CLOSE); } double SessionAW(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_AW); } double SessionPriceSettlement(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT); } double SessionPriceLimitMin(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN); } double SessionPriceLimitMax(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX); } double MarginHedged(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED); } double NormalizedPrice(const double price) const; //--- String properties
銘柄プロパティのデータを取得するには、[気配値表示]ウィンドウで銘柄が選択されていることを確認してください。ウィンドウで選択されていない銘柄のプロパティが必要な場合、プロパティにアクセスする前に、[気配値表示]ウィンドウで銘柄が選択されたかどうかを示すフラグを作成する必要があります。次に、銘柄が選択されていない場合は選択し、プロパティを取得し、[気配値表示]ウィンドウから非表示にします。銘柄がすでに選択されている場合は、そのプロパティを取得します。
また、証拠金率データを初期化し、クラスコンストラクターでMQL5用に書き込む必要があります。MQL4にはそのようなデータはなく、値は初期化後もゼロのままです。
また、これらのプロパティをクラスプロパティフィールドに保存するためのメソッドの呼び出しを追加します。
これを実現するには、クラスコンストラクタに必要なコードを追加します。
//+------------------------------------------------------------------+ //| Closedパラメトリックコンストラクタ | //+------------------------------------------------------------------+ CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name) : m_global_error(ERR_SUCCESS) { this.m_symbol_name=name; if(!this.Exist()) { ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\"",": ",TextByLanguage("Ошибка. Такого символа нет на сервере","Error. There is no such symbol on the server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } bool select=::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); ::ResetLastError(); if(!select) { if(!this.SetToMarketWatch()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\": ",TextByLanguage("Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in the market watch. Error: "),this.m_global_error); } } ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); } //--- Initialize data ::ZeroMemory(this.m_tick); this.Reset(); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.InitMarginRates(); ::ResetLastError(); #ifdef __MQL5__ if(!this.MarginRates()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "),this.m_global_error); return; } #endif //--- 整数型プロパティを保存する this.m_long_prop[SYMBOL_PROP_STATUS] = symbol_status; this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_DIGITS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_DIGITS); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_SPREAD_FLOAT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD_FLOAT); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_TRADE_MODE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_MODE); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_EXEMODE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_EXEMODE); this.m_long_prop[SYMBOL_PROP_SWAP_ROLLOVER3DAYS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SWAP_ROLLOVER3DAYS); this.m_long_prop[SYMBOL_PROP_EXIST] = this.SymbolExists(); this.m_long_prop[SYMBOL_PROP_CUSTOM] = this.SymbolCustom(); this.m_long_prop[SYMBOL_PROP_MARGIN_HEDGED_USE_LEG] = this.SymbolMarginHedgedUseLEG(); this.m_long_prop[SYMBOL_PROP_ORDER_MODE] = this.SymbolOrderMode(); this.m_long_prop[SYMBOL_PROP_FILLING_MODE] = this.SymbolOrderFillingMode(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); this.m_long_prop[SYMBOL_PROP_ORDER_GTC_MODE] = this.SymbolOrderGTCMode(); this.m_long_prop[SYMBOL_PROP_OPTION_MODE] = this.SymbolOptionMode(); this.m_long_prop[SYMBOL_PROP_OPTION_RIGHT] = this.SymbolOptionRight(); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); this.m_long_prop[SYMBOL_PROP_CHART_MODE] = this.SymbolChartMode(); this.m_long_prop[SYMBOL_PROP_TRADE_CALC_MODE] = this.SymbolCalcMode(); this.m_long_prop[SYMBOL_PROP_SWAP_MODE] = this.SymbolSwapMode(); //--- 実数型プロパティを保存する this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_POINT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_POINT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- 文字列プロパティを保存する this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_symbol_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_PATH); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BASIS)] = this.SymbolBasis(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BANK)] = this.SymbolBank(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_ISIN)] = this.SymbolISIN(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_FORMULA)] = this.SymbolFormula(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PAGE)] = this.SymbolPage(); //--- 追加の整数型プロパティを保存する this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------+
次に、宣言されたすべてのメソッドの実装を記述する必要があります。
クラス本体の外で証拠金率を格納するすべての変数を書き込むメソッドを実装します 。
//+------------------------------------------------------------------+ //| Fill in the margin ratio variables | //+------------------------------------------------------------------+ bool CSymbol::MarginRates(void) { bool res=true; #ifdef __MQL5__ res &=this.SymbolMarginLong(); res &=this.SymbolMarginBuyStop(); res &=this.SymbolMarginBuyLimit(); res &=this.SymbolMarginBuyStopLimit(); res &=this.SymbolMarginShort(); res &=this.SymbolMarginSellStop(); res &=this.SymbolMarginSellLimit(); res &=this.SymbolMarginSellStopLimit(); #else this.InitMarginRates(); res=false; #endif return res; } //+------------------------------------------------------------------+
MQL5メソッドは、単に銘柄プロパティから割合データを読み取り、適切な構造変数に書き込むメソッドを呼び出します。すべてのメソッドを返す結果が合計され、呼び出し元プログラムに返されます。これらのメソッドについては、以下で説明します。MQL4の場合、すべての構造体フィールドは単純にゼロに設定されます。
以下は、証拠金率プロパティ構造体のフィールドを初期化するメソッドです。
//+------------------------------------------------------------------+ //| Initialize margin ratios | //+------------------------------------------------------------------+ void CSymbol::InitMarginRates(void) { this.m_margin_rate.Long.Initial=0; this.m_margin_rate.Long.Maintenance=0; this.m_margin_rate.BuyStop.Initial=0; this.m_margin_rate.BuyStop.Maintenance=0; this.m_margin_rate.BuyLimit.Initial=0; this.m_margin_rate.BuyLimit.Maintenance=0; this.m_margin_rate.BuyStopLimit.Initial=0; this.m_margin_rate.BuyStopLimit.Maintenance=0; this.m_margin_rate.Short.Initial=0; this.m_margin_rate.Short.Maintenance=0; this.m_margin_rate.SellStop.Initial=0; this.m_margin_rate.SellStop.Maintenance=0; this.m_margin_rate.SellLimit.Initial=0; this.m_margin_rate.SellLimit.Maintenance=0; this.m_margin_rate.SellStopLimit.Initial=0; this.m_margin_rate.SellStopLimit.Maintenance=0; } //+------------------------------------------------------------------+
m_margin_rate構造体のすべてのフィールドはここでリセットされます。
以下はサーバ上に銘柄が存在するかどうかのフラグを返すメソッドを呼び出す2番目の形式の実装です。
//+------------------------------------------------------------------+ //| Return the symbol existence flag | //+------------------------------------------------------------------+ long CSymbol::SymbolExists(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXIST) #else this.Exist() #endif); } //+------------------------------------------------------------------+ bool CSymbol::SymbolExists(const string name) const { return(#ifdef __MQL5__ (bool)::SymbolInfoInteger(name,SYMBOL_EXIST) #else this.Exist(name) #endif); } //+------------------------------------------------------------------+
ここで、MQL5に対してはSYMBOL_EXIST 銘柄プロパティが返されますが、MQL4に対しては Exist(const string name)メソッドを呼び出す2番目の形式を使用してサーバ上の銘柄の検索が実行されます。
以下は構造体内のすべての注文タイプの証拠金率を書き込むメソッドの実装です。
//+------------------------------------------------------------------+ //| Fill in the margin ratios for long positions | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginLong(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY,this.m_margin_rate.Long.Initial,this.m_margin_rate.Long.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for short positions | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginShort(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL,this.m_margin_rate.Short.Initial,this.m_margin_rate.Short.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyStop orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyStop(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_STOP,this.m_margin_rate.BuyStop.Initial,this.m_margin_rate.BuyStop.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_LIMIT,this.m_margin_rate.BuyLimit.Initial,this.m_margin_rate.BuyLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyStopLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyStopLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_STOP_LIMIT,this.m_margin_rate.BuyStopLimit.Initial,this.m_margin_rate.BuyStopLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellStop orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellStop(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_STOP,this.m_margin_rate.SellStop.Initial,this.m_margin_rate.SellStop.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_LIMIT,this.m_margin_rate.SellLimit.Initial,this.m_margin_rate.SellLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellStopLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellStopLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_STOP_LIMIT,this.m_margin_rate.SellStopLimit.Initial,this.m_margin_rate.SellStopLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+
ここでは、MQL5に対してはSymbolInfoMarginRate()関数が呼び出され、m_margin_rate構造体に格納された必要なプロパティが書き込まれ、関数使用の結果が返されます。MQL4に対しては、falseを返します。
[気配値表示]ウィンドウで銘柄の背景の説明を返すブロック内の銘柄プロパティの説明を返すメソッドを変更します。
property==SYMBOL_PROP_BACKGROUND_COLOR ? TextByLanguage("Цвет фона символа в Market Watch","Background color of symbol in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : #ifdef __MQL5__ (this.GetProperty(property)==CLR_DEFAULT || this.GetProperty(property)==CLR_NONE ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+::ColorToString((color)this.GetProperty(property),true)) #else TextByLanguage(": Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) :
以前は、色を白(clrWhite)と比較し、色の値が「白」の色の値を超える場合、色は設定されていないと見なされていました。この比較方法の欠点についてはすでに説明しました。したがって、色を「デフォルトの色」と比較するまたは「欠落している色」と比較して、[気配値表示]ウィンドウの銘柄に背景色が指定されていないことを定義します。
銘柄のGetPropertyDescription(ENUM_SYMBOL_PROP_DOUBLEプロパティ)実数プロパティの説明を返すメソッドにすべての証拠金率の説明の表示を追加します。
//--- Initial margin requirement of a Long position property==SYMBOL_PROP_MARGIN_LONG_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по длинным позициям","Coefficient of margin initial charging for long positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirement of a Short position property==SYMBOL_PROP_MARGIN_SHORT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по коротким позициям","Coefficient of margin initial charging for short positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirement of a Long position property==SYMBOL_PROP_MARGIN_LONG_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по длинным позициям","Coefficient of margin maintenance charging for long positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirement of a Short position property==SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по коротким позициям","Coefficient of margin maintenance charging for short positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirements of Long orders property==SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyStop ордерам","Coefficient of margin initial charging for BuyStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyLimit ордерам","Coefficient of margin initial charging for BuyLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyStopLimit ордерам","Coefficient of margin initial charging for BuyStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirements of Short orders property==SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellStop ордерам","Coefficient of margin initial charging for SellStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellLimit ордерам","Coefficient of margin initial charging for SellLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellStopLimit ордерам","Coefficient of margin initial charging for SellStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirements of Long orders property==SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyStop ордерам","Coefficient of margin maintenance charging for BuyStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyLimit ордерам","Coefficient of margin maintenance charging for BuyLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyStopLimit ордерам","Coefficient of margin maintenance charging for BuyStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirements of Short orders property==SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellStop ордерам","Coefficient of margin maintenance charging for SellStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellLimit ордерам","Coefficient of margin maintenance charging for SellLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellStopLimit ордерам","Coefficient of margin maintenance charging for SellStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //---
以下は、サーバ上の銘柄を名前で検索し、銘柄が存在するかどうかのフラグを返すメソッドを呼び出す2番目の形式の実装です。
//+-------------------------------------------------------------------------------+ //| Search for a symbol and return the flag indicating its presence on the server | //+-------------------------------------------------------------------------------+ bool CSymbol::Exist(void) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==this.m_symbol_name) return true; return false; } //+------------------------------------------------------------------+ bool CSymbol::Exist(const string name) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==name) return true; return false; } //+------------------------------------------------------------------+
「double」値の桁数を計算して返すメソッドを実装します。
//+------------------------------------------------------------------+ //| Return the number of decimal places in the 'double' value | //+------------------------------------------------------------------+ int CSymbol::GetDigits(const double value) const { string val_str=(string)value; int len=::StringLen(val_str); int n=len-::StringFind(val_str,".",0)-1; if(::StringSubstr(val_str,len-1,1)=="0") n--; return n; } //+------------------------------------------------------------------+
このメソッドについては前の記事で説明しました。ここでは、最小ロットとロットステップで複数の値を繰り返し計算する必要があるため、個別のメソッドで単純に実装されています。
1日の始まりからの相場セッションの開始時間と終了時間、および相場セッションの開始時刻と終了時刻を返すメソッドを実装します。
//+------------------------------------------------------------------+ //| Return the quote session start time | //| in seconds from the beginning of a day | //+------------------------------------------------------------------+ long CSymbol::SessionQuoteTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to) ? from : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the time in seconds since the day start | //| up to the end of a quote session | //+------------------------------------------------------------------+ long CSymbol::SessionQuoteTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to) ? to : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the start and end time of a required quote session | //+------------------------------------------------------------------+ bool CSymbol::GetSessionQuote(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to) { ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return ::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to); } //+------------------------------------------------------------------+
セッションインデックスと曜日は最初の2つのメソッドに渡されますが、3番目のメソッドはさらに、SymbolInfoSessionQuote()関数を使用して受信した、必要なセッションの開始と終了に関するデータを格納するdatetime型変数を受け取ります。
より便利なように、-1が曜日として選択されている場合、セッションデータは現在の曜日に取得されます。セッションインデックスはゼロから開始する必要があります。時間は、 day_of_weekパラメータで定義された日の始まりからの秒数として返されます。したがって、メソッドから受け取った秒数を1日の始まりの時間に加算することにより、実際に要求された時間をいつでも見つけることができます。
取引セッション時間を受け取るメソッドは同じ方法で実装されます。
//+------------------------------------------------------------------+ //| Return the trading session start time | //| in seconds from the beginning of a day | //+------------------------------------------------------------------+ long CSymbol::SessionTradeTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to) ? from : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the time in seconds since the day start | //| up to the end of a trading session | //+------------------------------------------------------------------+ long CSymbol::SessionTradeTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to) ? to : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the start and end time of a required trading session | //+------------------------------------------------------------------+ bool CSymbol::GetSessionTrade(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to) { ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return ::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to); } //+------------------------------------------------------------------+
これらのメソッドは、必要なデータを受信するためにSymbolInfoSessionTrade()関数が使用されることを除いて、上記のメソッドに似ています。
以下は、ENUM_DAY_OF_WEEK列挙値として現在の曜日を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the current day of the week | //+------------------------------------------------------------------+ ENUM_DAY_OF_WEEK CSymbol::CurrentDayOfWeek(void) const { MqlDateTime time={0}; ::TimeCurrent(time); return(ENUM_DAY_OF_WEEK)time.day_of_week; } //+------------------------------------------------------------------+
ここではすべてが簡単です。日付と時刻の構造体を宣言、TimeCurrent()関数にアクセスし、その2番目の呼び出し形式が関数に渡された日付と時刻の構造体に書き込み、最終的に書き込まれた構造体の曜日を返します。
以下は、指定したセッションの継続時間の秒数を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the number of seconds in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionSeconds(const ulong duration_sec) const { return int(duration_sec % 60); } //+------------------------------------------------------------------+
このメソッドはこの期間の秒数を受け取り分数で割った剰余を返します。
以下は、指定されたセッションの時間の分数を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the number of minutes in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionMinutes(const ulong duration_sec) const { return int((duration_sec-this.SessionSeconds(duration_sec)) % 3600)/60; } //+------------------------------------------------------------------+
このメソッドはこの期間の秒数を受け取り1分未満の秒数を切り捨てて計算された分数を返します。
以下は、指定されたセッションの時間の時間数を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the number of hours in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionHours(const ulong duration_sec) const { return int(duration_sec-this.SessionSeconds(duration_sec)-this.SessionMinutes(duration_sec))/3600; } //+------------------------------------------------------------------+
このメソッドはこの期間の秒数を受け取り、1分未満の秒数と1時間未満の分数を切り捨てて計算された分数を返します。
以下は、セッション期間の説明を「HH:MM:SS」形式で返すメソッドの実装です。
//+---------------------------------------------------------------------+ //| Return the description of a session duration in the hh:mm:ss format | //+---------------------------------------------------------------------+ string CSymbol::SessionDurationDescription(const ulong duration_sec) const { int sec=this.SessionSeconds(duration_sec); int min=this.SessionMinutes(duration_sec); int hour=this.SessionHours(duration_sec); return ::IntegerToString(hour,2,'0')+":"+::IntegerToString(min,2,'0')+":"+::IntegerToString(sec,2,'0'); } //+------------------------------------------------------------------+
ここでは、単に秒単位のセッション期間と秒単位、分単位、時間単位で計算されたセッション期間を取得し、IntegerToString()関数と時間、分、秒の2桁に等しい文字列サイズ(1桁の場合は0を前につける)を使用して、フォーマットされたメッセージをHours:Minutes:Seconds形式で表示します。
たとえば、「2時間」が受信された場合、「02」と表示されます。
銘柄オブジェクトのステータスをわずかに修正したため、銘柄オブジェクトステータスの説明を表示するメソッドを修正します。
//+------------------------------------------------------------------+ //| Return the status description | //+------------------------------------------------------------------+ string CSymbol::GetStatusDescription() const { return ( this.Status()==SYMBOL_STATUS_FX ? TextByLanguage("Форекс символ","Forex symbol") : this.Status()==SYMBOL_STATUS_FX_MAJOR ? TextByLanguage("Форекс символ-мажор","Forex major symbol") : this.Status()==SYMBOL_STATUS_FX_MINOR ? TextByLanguage("Форекс символ-минор","Forex minor symbol") : this.Status()==SYMBOL_STATUS_FX_EXOTIC ? TextByLanguage("Форекс символ-экзотик","Forex Exotic Symbol") : this.Status()==SYMBOL_STATUS_FX_RUB ? TextByLanguage("Форекс символ/рубль","Forex symbol RUB") : this.Status()==SYMBOL_STATUS_METAL ? TextByLanguage("Металл","Metal") : this.Status()==SYMBOL_STATUS_INDEX ? TextByLanguage("Индекс","Index") : this.Status()==SYMBOL_STATUS_INDICATIVE ? TextByLanguage("Индикатив","Indicative") : this.Status()==SYMBOL_STATUS_CRYPTO ? TextByLanguage("Криптовалютный символ","Crypto symbol") : this.Status()==SYMBOL_STATUS_COMMODITY ? TextByLanguage("Товарный символ","Commodity symbol") : this.Status()==SYMBOL_STATUS_EXCHANGE ? TextByLanguage("Биржевой символ","Exchange symbol") : this.Status()==SYMBOL_STATUS_FUTURES ? TextByLanguage("Фьючерс","Futures") : this.Status()==SYMBOL_STATUS_CFD ? TextByLanguage("Контракт на разницу","Contract For Difference") : this.Status()==SYMBOL_STATUS_STOCKS ? TextByLanguage("Ценная бумага","Stocks") : this.Status()==SYMBOL_STATUS_BONDS ? TextByLanguage("Облигация","Bonds") : this.Status()==SYMBOL_STATUS_OPTION ? TextByLanguage("Опцион","Option") : this.Status()==SYMBOL_STATUS_COLLATERAL ? TextByLanguage("Неторгуемый актив","Collateral") : this.Status()==SYMBOL_STATUS_CUSTOM ? TextByLanguage("Пользовательский символ","Custom symbol") : this.Status()==SYMBOL_STATUS_COMMON ? TextByLanguage("Символ общей группы","Common group symbol") : ::EnumToString((ENUM_SYMBOL_STATUS)this.Status()) ); } //+------------------------------------------------------------------+
すべての銘柄データを更新するメソッドで、すべての注文とポジションのタイプに対してMQL5で証拠金率の受信を追加します。
MQL4では使用されないため、クラスコンストラクタで初期化を開始した後も値はゼロのままです。
//+------------------------------------------------------------------+ //| Update all symbol data that can change | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); return; } #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; } //+------------------------------------------------------------------+
ここでMQL5では、MarginRates()証拠金率でデータを受信するメソッドを呼び出します。少なくとも1つの割合が受信されない場合(メソッドがfalseを返す)、クラスエラーコードを格納する変数にエラーコードを書き込み、メッセージなしでメソッドを終了します。
メソッドはタイマーで機能するため、エラーメッセージは操作ログには表示されません。データ受信にエラーがあった場合、操作ログは同じエラーに関する役に立たないメッセージですぐにいっぱいになってしまいます。このエラーコードは常にCEngineクラスで受け取ることができるので、受け取りと処理をこのクラスに任せましょう。
メソッドの最後で、取得したすべての割合データが適切な銘柄オブジェクトプロパティのフィールドに書き込まれます。
同じ理由で、相場データ更新メソッドから操作ログのエラーメッセージを表示する文字列を削除します。
//+------------------------------------------------------------------+ //| Update quote data by a symbol | //+------------------------------------------------------------------+ void CSymbol::RefreshRates(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); return; } //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); } //+------------------------------------------------------------------+
メソッドは次のようになります。
//+------------------------------------------------------------------+ //| Update quote data by a symbol | //+------------------------------------------------------------------+ void CSymbol::RefreshRates(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); return; } //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); } //+------------------------------------------------------------------+
これで、CSymbol銘柄抽象クラスの改善が完了しました。
クラスメソッドの最も重要または重要な変更については説明しましたが、小規模な、基本的にプロパティ記述メソッドでの単なるスペリングエラーと「セマンティック」エラーは説明していません。それらは添付ファイルでご覧になれます。
次に、銘柄の抽象基本クラスの子孫オブジェクトを作成し、それらをカテゴリで分割し、銘柄オブジェクトコレクションに配置する必要があります。
「銘柄」基本抽象オブジェクトの子孫オブジェクト
少し戻って、言及されている銘柄のカテゴリを見てみましょう。さらに、CSymbol基本クラスの対応する子孫クラスの名前を設定します。
- 外貨銘柄 — CSymbolFXクラス
- Major外貨銘柄 — CSymbolFXMajorクラス
- Minor外貨銘柄 — CSymbolFXMinorクラス
- Exotic外貨銘柄 — CSymbolFXExoticクラス
- 外貨銘柄/RUB — CSymbolFXRubクラス
- 金属 — CSymbolMetallクラス
- インデックス — CSymbolIndexクラス
- 指標 — CSymbolIndicativeクラス
- 暗号通貨銘柄 — CSymbolCryptoクラス
- 商品銘柄 — CSymbolCommodityクラス
- 取引所銘柄 — CSymbolExchangeクラス
- 先物 — CSymbolFuturesクラス
- CFD — CSymbolCFDクラス
- 株式 — CSymbolStocksクラス
- 債権 — CSymbolBondsクラス
- オプション — CSymbolOptionクラス
- 非取引資産 — CSymbolCollateralクラス
- カスタム銘柄 — CSymbolCustomクラス
- 一般カテゴリ — CSymbolCommonクラス
\MQL5\Include\DoEasy\Objects\Symbols\ライブラリフォルダで、新しいCSymbolFXクラスをSymbolFX.mqhファイルで作成します。基本クラスは銘柄のCSymbol抽象クラスとなります。
クラス使用に必要なすべてのメソッドを宣言します。
//+------------------------------------------------------------------+ //| SymbolFX.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 "Symbol.mqh" //+------------------------------------------------------------------+ //| Forex symbol | //+------------------------------------------------------------------+ class CSymbolFX : public CSymbol { public: //--- コンストラクタ CSymbolFX(const string name) : CSymbol(SYMBOL_STATUS_FX,name) {} //--- Supported integer properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property); //--- Supported real properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property); //--- Supported string properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property); //--- Display a short symbol description in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+
クラスコンストラクタは銘柄名を受け取り、クラスコンストラクタの初期化リストは、CSymbolFXクラスが作成されたときにそのクラスコンストラクタに銘柄名とともに「外国為替銘柄」カテゴリ(そのステータス)を基本クラスに送信するのに使用されます。
オブジェクトによって整数、実数、文字列のプロパティをサポートする仮想メソッドは基本クラスで宣言され、子孫クラスで実装されます。仮想PrintShort()メソッドも基本クラスで宣言されて子孫クラスで実装され、操作ログに簡単な銘柄データを表示します。
ほとんどすべての子孫クラスのメソッドは類似しており、子孫クラスを必要とせずに基本クラスに実装できます。ただし、この場合、銘柄グループごとにこれらのメソッドを変更できる柔軟性が失われます。そのため、子孫クラスを介してカテゴリごとに分割し、各子孫クラスを個別に変更できるようにしました。
以下は、銘柄オブジェクトによって整数プロパティをサポートするフラグを返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { if(property==SYMBOL_PROP_EXIST #ifdef __MQL4__ || property==SYMBOL_PROP_CUSTOM || property==SYMBOL_PROP_SESSION_DEALS || property==SYMBOL_PROP_SESSION_BUY_ORDERS || property==SYMBOL_PROP_SESSION_SELL_ORDERS || property==SYMBOL_PROP_VOLUME || property==SYMBOL_PROP_VOLUMEHIGH || property==SYMBOL_PROP_VOLUMELOW || property==SYMBOL_PROP_TICKS_BOOKDEPTH || property==SYMBOL_PROP_OPTION_MODE || property==SYMBOL_PROP_OPTION_RIGHT || property==SYMBOL_PROP_BACKGROUND_COLOR #endif ) return false; return true; } //+------------------------------------------------------------------+
メソッドに確認された整数プロパティが渡されます。渡されたプロパティが「銘柄の存在」の場合はfalseを返します。銘柄が作成された場合、それは存在し、そのプロパティは操作ログに表示される必要も、検索や並べ替えにも使用する必要もありません。他のすべての確認はMQL4に対してのみ行われます。MQL4のメソッドに意図的にサポートされていない銘柄プロパティが渡されると、Falseが返されます。
渡されたときに確認されて列挙されたプロパティの中に見つからなかったプロパティはサポートされていません。trueを返します。
以下は、銘柄オブジェクトによって実数プロパティをサポートするフラグを返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { if( #ifdef __MQL5__ (this.ChartMode()==SYMBOL_CHART_MODE_BID && ( property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW ) ) || (this.ChartMode()==SYMBOL_CHART_MODE_LAST && ( property==SYMBOL_PROP_BID || property==SYMBOL_PROP_BIDHIGH || property==SYMBOL_PROP_BIDLOW || property==SYMBOL_PROP_ASK || property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW ) ) //--- __MQL4__ #else property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW || property==SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT || property==SYMBOL_PROP_TRADE_TICK_VALUE_LOSS || property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW || property==SYMBOL_PROP_VOLUME_LIMIT || property==SYMBOL_PROP_MARGIN_LONG_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_LONG_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SHORT_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE || property==SYMBOL_PROP_SESSION_VOLUME || property==SYMBOL_PROP_SESSION_TURNOVER || property==SYMBOL_PROP_SESSION_INTEREST || property==SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME || property==SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME || property==SYMBOL_PROP_SESSION_OPEN || property==SYMBOL_PROP_SESSION_CLOSE || property==SYMBOL_PROP_SESSION_AW || property==SYMBOL_PROP_SESSION_PRICE_SETTLEMENT || property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN || property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX || property==SYMBOL_PROP_VOLUME_REAL || property==SYMBOL_PROP_VOLUMEHIGH_REAL || property==SYMBOL_PROP_VOLUMELOW_REAL || property==SYMBOL_PROP_OPTION_STRIKE || property==SYMBOL_PROP_TRADE_ACCRUED_INTEREST || property==SYMBOL_PROP_TRADE_FACE_VALUE || property==SYMBOL_PROP_TRADE_LIQUIDITY_RATE #endif ) return false; return true; } //+------------------------------------------------------------------+
ここでのロジックは、前のメソッドと同じですが、まず、取得したMQL5のプロパティを確認します。最後の取引価格プロパティの1つ(Last)である場合、チャートはBid価格に基づいています。これらのプロパティはすべてゼロに等しく、この場合はサポートされていません。
チャートがLast価格に基づいている場合、同じことがBid価格プロパティで行われます。すべてのBid価格プロパティはサポートされていません。MQL4の場合、前のメソッドとまったく同じように実行します。サポートされていない銘柄プロパティを意図的にメソッドに渡すとき、falseを返します。
以下は、銘柄オブジェクトによって文字列プロパティをサポートするフラグを返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_STRING property) { if( #ifdef __MQL5__ property==SYMBOL_PROP_FORMULA && !this.IsCustom() #else property==SYMBOL_PROP_BASIS || property==SYMBOL_PROP_BANK || property==SYMBOL_PROP_ISIN || property==SYMBOL_PROP_FORMULA || property==SYMBOL_PROP_PAGE #endif ) return false; return true; } //+------------------------------------------------------------------+
ここではすべてが似ています。MQL5でカスタム銘柄以外で「カスタム銘柄計算式」プロパティが渡された場合は、プロパティがサポートされていないのでfalseを返します。次に、 MQL4でサポートされていないことがわかっている銘柄プロパティで確認し、MQL4でサポートされていないプロパティが渡されたらfalseを返します。
以下は、操作ログに簡単な銘柄の説明を表示するメソッドです。
//+------------------------------------------------------------------+ //| Display a short symbol description in the journal | //+------------------------------------------------------------------+ void CSymbolFX::PrintShort(void) { ::Print(this.GetStatusDescription()+" "+this.Name()); } //+------------------------------------------------------------------+
このメソッドは、銘柄ステータスの文字列での説明と名前で構成される行を表示するだけです。
残りの子孫クラスは同じメソッドで構築され、同じ実装で同じメソッドを持ちます。
違いはカスタム銘柄クラスにあります。このような銘柄タイプはMQL4には存在しないため、すべての確認はMQL5にのみ適用されます。
//+------------------------------------------------------------------+ //| SymbolCustom.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 "Symbol.mqh" //+------------------------------------------------------------------+ //| Custom symbol | //+------------------------------------------------------------------+ class CSymbolCustom : public CSymbol { public: //--- コンストラクタ CSymbolCustom(const string name) : CSymbol(SYMBOL_STATUS_CUSTOM,name) {} //--- Supported integer properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property); //--- Supported real properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property); //--- Supported string properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property); //--- Display a short symbol description in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { if(property==SYMBOL_PROP_EXIST) return false; return true; } //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { if( (this.ChartMode()==SYMBOL_CHART_MODE_BID && ( property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW ) ) || (this.ChartMode()==SYMBOL_CHART_MODE_LAST && ( property==SYMBOL_PROP_BID || property==SYMBOL_PROP_BIDHIGH || property==SYMBOL_PROP_BIDLOW || property==SYMBOL_PROP_ASK || property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW ) ) ) return false; return true; } //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| その他の場合は「false」を返す | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_STRING property) { return true; } //+------------------------------------------------------------------+ //| Display a short symbol description in the journal | //+------------------------------------------------------------------+ void CSymbolCustom::PrintShort(void) { ::Print(this.GetStatusDescription()+" "+this.Name()); } //+------------------------------------------------------------------+
これで、CSymbol下位クラスの開発は終了です。
残りの子孫クラスの実装は、記事の最後と添付ファイルに記載されています。
銘柄コレクションを検索および並べ替える必要があるため、そのために必要なすべての関数を作成する必要があります。\MQL5\Include\DoEasy\Services\ライブラリフォルダにあるSelect.mqhファイルを開いて、以下を行います。
まず、銘柄の抽象クラスをインクルードします。
//+------------------------------------------------------------------+ //| Select.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\ArrayObj.mqh> #include "..\Objects\Orders\Order.mqh" #include "..\Objects\Events\Event.mqh" #include "..\Objects\Accounts\Account.mqh" #include "..\Objects\Symbols\Symbol.mqh" //+------------------------------------------------------------------+
クラスのpublicセクションで検索と並べ替えに必要なすべてのメソッドを宣言します。
//+------------------------------------------------------------------+ //| 基準を満たすオブジェクトを並び替えるクラス | //+------------------------------------------------------------------+ class CSelect { private: //--- 2つの値を比較するためのメソッド template<typename T> static bool CompareValues(T value1,T value2,ENUM_COMPARER_TYPE mode); public: //+------------------------------------------------------------------+ //| Methods of working with orders | //+------------------------------------------------------------------+ //--- 指定された基準を満たす(1)整数、(2)実数、(3)文字列プロパティのうちの1つを持つ注文のリストを返す static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the order index with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property); static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property); static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property); //--- Return the order index with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property); static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property); static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with events | //+------------------------------------------------------------------+ //--- Return the list of events with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the event index with the maximum value of the event's (1) integer, (2) real and (3) string properties static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property); static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property); static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property); //--- Return the event index with the minimum value of the event's (1) integer, (2) real and (3) string properties static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property); static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property); static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with accounts | //+------------------------------------------------------------------+ //--- Return the list of accounts with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the event index with the maximum value of the event's (1) integer, (2) real and (3) string properties static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property); static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property); static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property); //--- Return the event index with the minimum value of the event's (1) integer, (2) real and (3) string properties static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property); static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property); static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with symbols | //+------------------------------------------------------------------+ //--- Return the list of symbols with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the symbol index with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property); static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property); static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property); //--- Return the symbol index with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property); static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property); static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property); //--- }; //+------------------------------------------------------------------+
クラス本体の外側で実装しましょう。
//+------------------------------------------------------------------+ //| Methods of working with symbol lists | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Return the list of symbols with one integer | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); int total=list_source.Total(); for(int i=0; i<total; i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; long obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of symbols with one real | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; double obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of symbols with one string | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; string obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); long obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); double obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); string obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_INTEGER property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); long obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_DOUBLE property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total== 0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); double obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| リストでの注文のインデックスを返す | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_STRING property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); string obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+
コレクションクラスごとに同様のメソッドがあります。これらは、第3部でCSelectクラスを作成するときに考慮されているため、ここでは説明しません。
これで、銘柄コレクションクラスを作成する準備がすべて整いました。
プログラムから銘柄コレクションを使用するには4つのモードが使用できます。
- 1つの銘柄のみの使用
- 銘柄リストの使用
- [気配値表示]ウィンドウの使用
- サーバで使用可能な銘柄の完全なリストの使用
キャラクターコレクションクラスに何を扱うかが「わかる」ように、次のスキームを使用します。プログラム設定で銘柄を使用するためのメソッドの使用を設定します。これは、上記の4つの使用モードのいずれかです。
プログラムには、同じ原理に従ってライブラリ関数で満たされる文字列配列も必要です。
- 単一の銘柄を使用している場合、配列には現在の銘柄のみが含まれます
- 必要なコンマ区切りの銘柄が定義されたプログラム設定にもあるカスタム銘柄リストを使用している場合、配列には文字列の銘柄が格納されます。文字列に現在の銘柄が1つだけ設定されている場合、またはリストが空の場合、現在の銘柄が作業に使用されます
- [気配値表示]を使用している場合、銘柄名の代わりに[MARKET_WATCH]が唯一の配列セルに設定されます
- サーバ上の銘柄の完全なリストを使用している場合、銘柄名ではなく[ALL]が配列に設定されます
これはすべて自動的に行われます。ユーザは、銘柄コレクションで作業するために必要なモードの選択を調整し、設定で少なくとも1つの文字列配列または文字列配列と事前定義された銘柄の文字列を作成するだけです。
銘柄コレクションクラス
\MQL5\Include\DoEasy\Collections\ライブラリフォルダで、新しいCSymbolsCollectionクラスをSymbolsCollection.mqhファイルで作成します。
CObject標準ライブラリobjectクラスが基本クラスとなります。
必要なすべてのクラスファイルを新しく作成されたファイルに含めます。
//+------------------------------------------------------------------+ //| SymbolsCollection.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 "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| 過去の注文と取引のコレクション | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: public: //--- コンストラクタ CSymbolsCollection(); }; //+------------------------------------------------------------------+
ライブラリコレクションクラスの標準になっているクラスメンバ値とメソッドを追加します。
//+------------------------------------------------------------------+ //| SymbolsCollection.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 "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| 過去の注文と取引のコレクション | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: CListObj m_list_all_symbols; // The list of all symbol objects public: //--- 完全なコレクションリストを「そのまま」で返す CArrayObj *GetList(void) { return &this.m_list_all_symbols; } //--- 比較された基準を満たす選択された(1)整数、(2)実数、(3)文字列プロパティののリストを返す CArrayObj *GetList(ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } //--- コンストラクタ CSymbolsCollection(); }; //+------------------------------------------------------------------+
これらの変数とメソッドをは、以前のコレクションを作成するときにすべて考慮したので、ここで議論する必要はありません。
銘柄コレクションクラスを使用するための残りの変数とメソッドを追加します。
//+------------------------------------------------------------------+ //| SymbolsCollection.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 "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| 過去の注文と取引のコレクション | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: CListObj m_list_all_symbols; // The list of all symbol objects ENUM_SYMBOLS_MODE m_mode_list; // Mode of working with symbol lists int m_delta_symbol; // Difference in the number of symbols compared to the previous check int m_last_num_symbol; // Number of symbols in the Market Watch window during the previous check int m_global_error; // Global error code //--- Return the flag of a symbol object presence by its name in the list of all symbols bool IsPresentSymbolInList(const string symbol_name); //--- Create the symbol object and place it to the list bool CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name); //--- Return the type of a used symbol list (Market watch/Server) ENUM_SYMBOLS_MODE TypeSymbolsList(const string &symbol_used_array[]); //--- Define a symbol affiliation with a group by name and return it ENUM_SYMBOL_STATUS SymbolStatus(const string symbol_name) const; //--- Return a symbol affiliation with a category by custom criteria ENUM_SYMBOL_STATUS StatusByCustomPredefined(const string symbol_name) const; //--- Return a symbol affiliation with categories by margin calculation ENUM_SYMBOL_STATUS StatusByCalcMode(const string symbol_name) const; //--- Return a symbol affiliation with pre-defined (1) majors, (2) minors, (3) exotics, (4) RUB, //--- (5) indicatives, (6) metals, (7) commodities, (8) indices, (9) cryptocurrency, (10) options bool IsPredefinedFXMajor(const string name) const; bool IsPredefinedFXMinor(const string name) const; bool IsPredefinedFXExotic(const string name) const; bool IsPredefinedFXRUB(const string name) const; bool IsPredefinedIndicative(const string name) const; bool IsPredefinedMetall(const string name) const; bool IsPredefinedCommodity(const string name) const; bool IsPredefinedIndex(const string name) const; bool IsPredefinedCrypto(const string name) const; bool IsPredefinedOption(const string name) const; //--- Search for a symbol and return the flag indicating its presence on the server bool Exist(const string name) const; public: //--- 完全なコレクションリストを「そのまま」で返す CArrayObj *GetList(void) { return &this.m_list_all_symbols; } //--- 比較された基準を満たす選択された(1)整数、(2)実数、(3)文字列プロパティののリストを返す CArrayObj *GetList(ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } //--- Return the number of new symbols in the Market Watch window int NewSymbols(void) const { return this.m_delta_symbol; } //--- Return the mode of working with symbol lists ENUM_SYMBOLS_MODE ModeSymbolsList(void) const { return this.m_mode_list; } //--- コンストラクタ CSymbolsCollection(); //--- Set the list of used symbols bool SetUsedSymbol(const string &symbol_used_array[]); //--- Update (1) all, (2) quote data of the collection symbols void Refresh(void); void RefreshRates(void); }; //+------------------------------------------------------------------+
クラスは、現在の銘柄、指定された銘柄セット、[気配値表示]ウィンドウにある銘柄リスト、またはサーバ上のすべての銘柄の完全なリストを使用する銘柄クラスを知っている必要があります。m_mode_listクラスメンバ変数は、リストされている銘柄の使用モードのいずれかを保存します。
[気配値表示]の銘柄リストを使用する場合、m_list_all_symbols銘柄コレクションリストを時間内に再配置して銘柄を正確に使用し続けるために、このリストを常に追跡し(次の記事で実装)、最後の確認中には銘柄数を把握し、[気配値表示]リストから銘柄を追加/削除するときにはこの数値がどれだけ変化したかを知らなければなりません。前のコレクションと同様に、CEngineライブラリの基本クラスで表示および処理できるエラーコードを格納する新しいクラスメンバ変数を導入しました。
新しい銘柄オブジェクトを作成してコレクションに追加する場合、リストにそのような銘柄がないことを確認する必要があります。これはIsPresentSymbolInList()メソッドで行います。
CreateNewSymbol()メソッドを使用して、新しい銘柄を作成し、コレクションに追加します。
銘柄コレクションには4つの銘柄リストモードでの作業が配置されているため、TypeSymbolsList()メソッドを使用して、作業するモードを定義します。
新しい銘柄を作成する前に、最初にグループを定義および設定して、それを割り当てる(またはユーザーが割り当てるグループ)必要があります。SymbolStatus()メソッドは、銘柄グループ(そのステータス)を定義するために使用されます。
銘柄ステータスを定義する場合、まずStatusByCustomPredefined() メソッドを使用して、指定されたカスタム配列でその名前が検索されます。
メソッドが「一般」ステータスを返す場合、銘柄ステータスは、StatusByCalcMode()メソッドによる証拠金計算のタイプによって定義されます。
追加のメソッドを使用して、ユーザ配列による検索を実行し、銘柄が属するカスタムカテゴリを定義します。これらのメソッドは、銘柄がメジャー、マイナー、インデックス、その他のグループに属するかどうかを示すフラグを返します。
Exist()メソッドは、サーバ上で銘柄が存在するかどうかのフラグを返します。
NewSymbols()メソッドは、[気配値表示]ウィンドウで追加または削除された新しい銘柄の数を返し、ModeSymbolsList()メソッドは、4つのリスト(現在の銘柄、事前定義された銘柄セット、[気配値表示]リスト、サーバ上の銘柄の完全数)のいずれかで動作するモードを呼び出しプログラムに返します。
SetUsedSymbol()メソッドは、渡された配列内の銘柄のリストを含む銘柄配列または使用モードの説明を受け入れ、銘柄コレクションリストを作成します。
Refresh()メソッドは、変更可能なすべてのコレクション銘柄のすべてのデータを更新しますが、RefreshRates()メソッドは、すべてのコレクション銘柄の相場データのみを更新します。両方のメソッドは、CEngineライブラリのメインオブジェクトタイマーから呼び出されます。
この段階で銘柄コレクションクラスを使用するために必要なすべてのメソッドを定義したので、それらの構造を見てみましょう。
以下は、クラスコンストラクタの実装です。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CSymbolsCollection::CSymbolsCollection(void) : m_last_num_symbol(0),m_delta_symbol(0),m_mode_list(SYMBOLS_MODE_CURRENT) { this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_NAME); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Type(COLLECTION_SYMBOLS_ID); } //+------------------------------------------------------------------+
コンストラクタの初期化リストで、最後の確認中の銘柄数と現在の銘柄数と前の銘柄数の差を初期化し、銘柄リスト使用モードを「現在の銘柄を使用する」に設定します。
クラス本体で、名前による銘柄コレクションリストの並び替えを設定、リストをクリアして、「銘柄コレクションリスト」IDを割り当てます。
以下はすべてのコレクション銘柄のデータを更新するメソッドです。
//+------------------------------------------------------------------+ //| Update all collection symbol data | //+------------------------------------------------------------------+ void CSymbolsCollection::Refresh(void) { int total=this.m_list_all_symbols.Total(); if(total==0) return; for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.Refresh(); } } //+------------------------------------------------------------------+
すべてのコレクション銘柄の数によるループで、コレクションリストから次の銘柄を取得し、前の記事で検討したCSymbolクラスのRefresh()メソッドを使用してそのデータを更新します。
以下はすべてのコレクション銘柄の相場データを更新するメソッドです。
//+------------------------------------------------------------------+ //| Update quote data of the collection symbols | //+------------------------------------------------------------------+ void CSymbolsCollection::RefreshRates(void) { int total=this.m_list_all_symbols.Total(); if(total==0) return; for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.RefreshRates(); } } //+------------------------------------------------------------------+
すべてのコレクション銘柄の数によるループで、コレクションリストから次の銘柄を取得し、CSymbolクラスのRefresh()メソッドを使用してそのデータを更新します。
以下は、新しい銘柄オブジェクトを作成して銘柄コレクションリストに配置するメソッドです。
//+------------------------------------------------------------------+ //| Create a symbol object and place it to the list | //+------------------------------------------------------------------+ bool CSymbolsCollection::CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name) { if(this.IsPresentSymbolInList(name)) { return true; } if(#ifdef __MQL5__ !::SymbolInfoInteger(name,SYMBOL_EXIST) #else !this.Exist(name) #endif ) { string t1=TextByLanguage("Ошибка входных данных: нет символа ","Input error: no "); string t2=TextByLanguage(" на сервере"," symbol on the server"); ::Print(DFUN,t1,name,t2); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; return false; } CSymbol *symbol=NULL; switch(symbol_status) { case SYMBOL_STATUS_FX : symbol=new CSymbolFX(name); break; // Forex symbol case SYMBOL_STATUS_FX_MAJOR : symbol=new CSymbolFXMajor(name); break; // Major Forex symbol case SYMBOL_STATUS_FX_MINOR : symbol=new CSymbolFXMinor(name); break; // Minor Forex symbol case SYMBOL_STATUS_FX_EXOTIC : symbol=new CSymbolFXExotic(name); break; // Exotic Forex symbol case SYMBOL_STATUS_FX_RUB : symbol=new CSymbolFXRub(name); break; // Forex symbol/RUR case SYMBOL_STATUS_METAL : symbol=new CSymbolMetall(name); break; // Metal case SYMBOL_STATUS_INDEX : symbol=new CSymbolIndex(name); break; // Index case SYMBOL_STATUS_INDICATIVE : symbol=new CSymbolIndicative(name); break; // Indicative case SYMBOL_STATUS_CRYPTO : symbol=new CSymbolCrypto(name); break; // Cryptocurrency symbol case SYMBOL_STATUS_COMMODITY : symbol=new CSymbolCommodity(name); break; // Commodity case SYMBOL_STATUS_EXCHANGE : symbol=new CSymbolExchange(name); break; // Exchange symbol case SYMBOL_STATUS_FUTURES : symbol=new CSymbolFutures(name); break; // Futures case SYMBOL_STATUS_CFD : symbol=new CSymbolCFD(name); break; // CFD case SYMBOL_STATUS_STOCKS : symbol=new CSymbolStocks(name); break; // Stock case SYMBOL_STATUS_BONDS : symbol=new CSymbolBonds(name); break; // Bond case SYMBOL_STATUS_OPTION : symbol=new CSymbolOption(name); break; // Option case SYMBOL_STATUS_COLLATERAL : symbol=new CSymbolCollateral(name); break; // Non-tradable asset case SYMBOL_STATUS_CUSTOM : symbol=new CSymbolCustom(name); break; // Custom symbol default : symbol=new CSymbolCommon(name); break; // The rest } if(symbol==NULL) { ::Print(DFUN,TextByLanguage("Не удалось создать объект-символ ","Failed to create symbol object "),name); return false; } if(!this.m_list_all_symbols.Add(symbol)) { string t1=TextByLanguage("Не удалось добавить символ ","Failed to add "); string t2=TextByLanguage(" в список"," symbol to the list"); ::Print(DFUN,t1,name,t2); delete symbol; return false; } return true; } //+------------------------------------------------------------------+
このメソッドは銘柄のステータスと名前を渡します。そのような銘柄がすでに銘柄コレクションリストに存在する場合、エラーはありませんが銘柄が既に存在していて追加する必要がないので、静かにtrueを返します。 次に、名前で、銘柄がサーバ上に存在するかどうかを確認します。そのような銘柄がない場合、銘柄が見つからないというメッセージを表示して、 エラーコードに「未知の銘柄」値を割り当てて、falseを返します。
銘柄が存在する場合、メソッドに渡されたステータスに応じて新しい銘柄オブジェクトを作成します。銘柄オブジェクトを作成するには、渡されたステータスに対応する抽象銘柄の下位クラスを使用します。オブジェクト作成エラーの場合、適切なメッセージを表示してfalseを返します。
新しい銘柄オブジェクトが正常に作成された場合、それを銘柄コレクションリストに追加し、正常に追加できた場合は trueを返し、できなかった場合は、エラーメッセージを表示してfalseを返します。
以下は、コレクションリストに銘柄が存在するかどうかのフラグを返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the symbol object presence flag | //| by its name in the list of all symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPresentSymbolInList(const string symbol_name) { CArrayObj *list=dynamic_cast<CListObj*>(&this.m_list_all_symbols); list.Sort(SORT_BY_SYMBOL_NAME); list=CSelect::BySymbolProperty(list,SYMBOL_PROP_NAME,symbol_name,EQUAL); return(list==NULL || list.Total()==0 ? false : true); } //+------------------------------------------------------------------+
必要な銘柄の名前がメソッドに渡され 、リストは銘柄名と渡された名前で並び替えされます。リストが空でない場合、そのような名前の銘柄が見つかったのでtrueを返します。それ以外の場合、リストに銘柄が存在しないのでfalseを返します。
以下はコレクション銘柄のリストを設定するメソッドです。
//+------------------------------------------------------------------+ //| Set the list of used symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::SetUsedSymbol(const string &symbol_used_array[]) { this.m_mode_list=this.TypeSymbolsList(symbol_used_array); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_NAME); //--- Use only the current symbol if(this.m_mode_list==SYMBOLS_MODE_CURRENT) { string name=::Symbol(); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); return this.CreateNewSymbol(status,name); } else { bool res=true; //--- Use the pre-defined symbol list if(this.m_mode_list==SYMBOLS_MODE_DEFINES) { int total=::ArraySize(symbol_used_array); for(int i=0;i<total;i++) { string name=symbol_used_array[i]; ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } //--- Use the full list of the server symbols else if(this.m_mode_list==SYMBOLS_MODE_ALL) { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) { string name=::SymbolName(i,false); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } //--- Use the symbol list from the Market Watch window else if(this.m_mode_list==SYMBOLS_MODE_MARKET_WATCH) { int total=::SymbolsTotal(true); for(int i=0;i<total;i++) { string name=::SymbolName(i,true); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } } return false; } //+------------------------------------------------------------------+
このメソッドは、渡された銘柄配列の内容に応じて、銘柄コレクションリストを作成します。まず、銘柄リストを使用する方法を定義(1つの銘柄/銘柄のカスタムセット/[気配値表示]/完全なリスト)し、次にリストをクリア して名前で並び替えます。
現在の銘柄のみが使用される場合、
- 名前によって銘柄ステータスを定義して
- 新しい銘柄オブジェクトを作成し、それを銘柄コレクションリストに追加した結果を返します。
事前定義された銘柄リストが使用される場合、
- メソッドに渡された銘柄名配列により、ループ内の配列から銘柄名を取得します
- 名前によって銘柄ステータスを定義します
- 銘柄オブジェクトを作成して銘柄コレクションリストに追加した結果を、返された変数に追加します
- 銘柄の作成またはリストへの追加に失敗した場合は次の銘柄に移動します
- ループの完了時に、コレクション銘柄の作成結果が書き込まれた変数のステータスを返します
残りの2つのモードは、事前定義リストを使用するモードと同様に処理されます。 ただし、メソッドに渡される配列の代わりに、銘柄は [気配値表示]またはサーバ上の銘柄の完全なリストから取得されます。
以下は、銘柄リスト使用モードを返すメソッドの実装です。
//+------------------------------------------------------------------+ //|Return the type of a used symbol list (Market watch/Server) | //+------------------------------------------------------------------+ ENUM_SYMBOLS_MODE CSymbolsCollection::TypeSymbolsList(const string &symbol_used_array[]) { int total=::ArraySize(symbol_used_array); if(total<1) return SYMBOLS_MODE_CURRENT; string type=::StringSubstr(symbol_used_array[0],13); return ( type=="MARKET_WATCH" ? SYMBOLS_MODE_MARKET_WATCH : type=="ALL" ? SYMBOLS_MODE_ALL : (total==1 && symbol_used_array[0]==::Symbol() ? SYMBOLS_MODE_CURRENT : SYMBOLS_MODE_DEFINES) ); } //+------------------------------------------------------------------+
このメソッドは、銘柄名またはリストの使用モードの説明を含む配列を受け取ります。
空の配列が渡される場合、「現在の銘柄のみでの使用」モードを返します。
次に、ゼロセルから配列の内容を受け取り、
- 部分文字列のインデックス13から始まる場合、「MARKET_WATCH」エントリがあり、「[気配値表示]ウィンドウでの使用」モードを返します。
- 「ALL」文字列がある場合、「銘柄の完全なリストでの使用」モードを返します。
- その他の場合、
- 配列に単一のエントリが含まれており、それが現在の銘柄名を含む場合、「現在の銘柄のみでの使用」モードを返します。
- 可能な最後のオプションで、「定義済みリストでの使用」モードを返します。
以下は、名前によるグループとの銘柄所属を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Define a symbol affiliation with a group by name and return it | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::SymbolStatus(const string symbol_name) const { ENUM_SYMBOL_STATUS status=this.StatusByCustomPredefined(symbol_name); return(status==SYMBOL_STATUS_COMMON ? this.StatusByCalcMode(symbol_name) : status); } //+------------------------------------------------------------------+
メソッドに銘柄名が渡されます。次に、指定されたカスタムグループとの関係が確認されます。「一般グループ」ステータスが返された場合、「証拠金計算モード」銘柄プロパティでグループを検索します。その結果、取得したステータスを返します。 ちなみに、これには利益と証拠金計算モードに応じてグループの1つと見なされる場合と、銘柄の一般的なグループに残る場合とがあります。
その結果、銘柄はカスタムグループステータスになります。カスタムグループに存在しない場合は、証拠金計算方法 によるグループが割り当てられる場合があります。 そのグループ内で定義に失敗した場合、一般グループに残ります。
以下は、銘柄が特定のカスタムグループに属するかどうかのフラグを返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return a symbol affiliation with majors | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXMajor(const string name) const { int total=::ArraySize(DataSymbolsFXMajors); for(int i=0;i<total;i++) if(name==DataSymbolsFXMajors[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with minors | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXMinor(const string name) const { int total=::ArraySize(DataSymbolsFXMinors); for(int i=0;i<total;i++) if(name==DataSymbolsFXMinors[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with exotic symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXExotic(const string name) const { int total=::ArraySize(DataSymbolsFXExotics); for(int i=0;i<total;i++) if(name==DataSymbolsFXExotics[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with RUB symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXRUB(const string name) const { int total=::ArraySize(DataSymbolsFXRub); for(int i=0;i<total;i++) if(name==DataSymbolsFXRub[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with indicative symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedIndicative(const string name) const { int total=::ArraySize(DataSymbolsFXIndicatives); for(int i=0;i<total;i++) if(name==DataSymbolsFXIndicatives[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with metals | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedMetall(const string name) const { int total=::ArraySize(DataSymbolsMetalls); for(int i=0;i<total;i++) if(name==DataSymbolsMetalls[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with commodities | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedCommodity(const string name) const { int total=::ArraySize(DataSymbolsCommodities); for(int i=0;i<total;i++) if(name==DataSymbolsCommodities[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with indices | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedIndex(const string name) const { int total=::ArraySize(DataSymbolsIndexes); for(int i=0;i<total;i++) if(name==DataSymbolsIndexes[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with a cryptocurrency | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedCrypto(const string name) const { int total=::ArraySize(DataSymbolsCrypto); for(int i=0;i<total;i++) if(name==DataSymbolsCrypto[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with options | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedOption(const string name) const { int total=::ArraySize(DataSymbolsOptions); for(int i=0;i<total;i++) if(name==DataSymbolsOptions[i]) return true; return false; } //+------------------------------------------------------------------+
(確認されたカスタムグループの)メソッド名に応じて、名前がメソッドに渡された銘柄の検索は、そのグループに対応するカスタム配列で実行されます。配列でそのような銘柄が見つかった場合はtrueが返されます。さもなければfalseが返されます。
以下は、カスタムグループ内の存在によって銘柄ステータスを返すメソッドです。
//+------------------------------------------------------------------+ //| Return a category by custom criteria | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::StatusByCustomPredefined(const string symbol_name) const { return ( this.IsPredefinedFXMajor(symbol_name) ? SYMBOL_STATUS_FX_MAJOR : this.IsPredefinedFXMinor(symbol_name) ? SYMBOL_STATUS_FX_MINOR : this.IsPredefinedFXExotic(symbol_name) ? SYMBOL_STATUS_FX_EXOTIC : this.IsPredefinedFXRUB(symbol_name) ? SYMBOL_STATUS_FX_RUB : this.IsPredefinedOption(symbol_name) ? SYMBOL_STATUS_OPTION : this.IsPredefinedCommodity(symbol_name) ? SYMBOL_STATUS_COMMODITY : this.IsPredefinedCrypto(symbol_name) ? SYMBOL_STATUS_CRYPTO : this.IsPredefinedMetall(symbol_name) ? SYMBOL_STATUS_METAL : this.IsPredefinedIndex(symbol_name) ? SYMBOL_STATUS_INDEX : this.IsPredefinedIndicative(symbol_name) ? SYMBOL_STATUS_INDICATIVE : SYMBOL_STATUS_COMMON ); } //+------------------------------------------------------------------+
メソッドに銘柄名が渡され、上記のメソッドを使用して各カスタムグループに存在するかどうかが1つずつチェックされます 。いずれかのグループに銘柄が表示されるとすぐに、その銘柄が見つかったグループに対応するステータスが返されます。銘柄がどのグループにも見つからない場合、「一般的な銘柄グループ」ステータスが返されます。
以下は、証拠金計算方法による銘柄のグループへの所属を返すメソッドです。
//+------------------------------------------------------------------+ //|Return affiliation with a margin calculation category | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::StatusByCalcMode(const string symbol_name) const { ENUM_SYMBOL_CALC_MODE calc_mode=(ENUM_SYMBOL_CALC_MODE)::SymbolInfoInteger(symbol_name,SYMBOL_TRADE_CALC_MODE); return ( calc_mode==SYMBOL_CALC_MODE_EXCH_OPTIONS_MARGIN ? SYMBOL_STATUS_OPTION : calc_mode==SYMBOL_CALC_MODE_SERV_COLLATERAL ? SYMBOL_STATUS_COLLATERAL : calc_mode==SYMBOL_CALC_MODE_FUTURES ? SYMBOL_STATUS_FUTURES : calc_mode==SYMBOL_CALC_MODE_CFD || calc_mode==SYMBOL_CALC_MODE_CFDINDEX || calc_mode==SYMBOL_CALC_MODE_CFDLEVERAGE ? SYMBOL_STATUS_CFD : calc_mode==SYMBOL_CALC_MODE_FOREX || calc_mode==SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE ? SYMBOL_STATUS_FX : calc_mode==SYMBOL_CALC_MODE_EXCH_STOCKS || calc_mode==SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX ? SYMBOL_STATUS_STOCKS : calc_mode==SYMBOL_CALC_MODE_EXCH_BONDS || calc_mode==SYMBOL_CALC_MODE_EXCH_BONDS_MOEX ? SYMBOL_STATUS_BONDS : calc_mode==SYMBOL_CALC_MODE_EXCH_FUTURES || calc_mode==SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS ? SYMBOL_STATUS_FUTURES : SYMBOL_STATUS_COMMON ); } //+------------------------------------------------------------------+
このメソッドは銘柄名を受け取り、次に銘柄の証拠金計算方法を受け取り、取得した値に応じて銘柄のステータスを返します。計算方法が特定できなかった場合は、「一般的な銘柄グループ」ステータスを返します。
以下は、サーバ上で銘柄を探し、その存在のフラグを返すメソッドです。
//+---------------------------------------------------------------------------------+ //| Search for a symbol and return the flag indicating its presence on the server | //+---------------------------------------------------------------------------------+ bool CSymbolsCollection::Exist(const string name) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==name) return true; return false; } //+------------------------------------------------------------------+
これで銘柄コレクションクラスの準備ができました。起動できなければなりません。通常、起動と処理はCEngineクラスで実行されます。必要な変更を加えましょう。
CEngineクラスファイルに銘柄コレクションクラスファイルを含めて、銘柄コレクションオブジェクトおよび必要なメソッドを宣言します。
//+------------------------------------------------------------------+ //| Engine.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 "Services\TimerCounter.mqh" #include "Collections\HistoryCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\EventsCollection.mqh" #include "Collections\AccountsCollection.mqh" #include "Collections\SymbolsCollection.mqh" //+------------------------------------------------------------------+ //| ライブラリ基本クラス | //+------------------------------------------------------------------+ class CEngine : public CObject { private: CHistoryCollection m_history; // 過去の注文と取引のコレクション CMarketCollection m_market; // 注文と取引のコレクション CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CSymbolsCollection m_symbols; // Symbol collection CArrayObj m_list_counters; // タイマーカウンタのリスト int m_global_error; // Global error code 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; // Last account trading event ENUM_ACCOUNT_EVENT m_last_account_event; // Last event in the account properties //--- IDによるカウンタインデックスを返す int CounterIndex(const int id) const; //--- (1)初回実行フラグ、(2)取引イベントでのフラグの存在を返す bool IsFirstStart(void); //--- Work with (1) order, deal and position, (2) account events void TradeEventsControl(void); void AccountEventsControl(void); //--- (1) Working with a symbol collection and (2) symbol list events in the market watch window void SymbolEventsControl(void); void MarketWatchEventsControl(void); //--- 直近の(1)市場未決注文、(2)成行注文、(3)直近のポジション、(4)チケット別ポジションを返す COrder *GetLastMarketPending(void); COrder *GetLastMarketOrder(void); COrder *GetLastPosition(void); COrder *GetPosition(const ulong ticket); //--- Return the last (1) removed pending order, (2) historical market order, (3) historical order (market or pending one) by its ticket COrder *GetLastHistoryPending(void); COrder *GetLastHistoryOrder(void); COrder *GetHistoryOrder(const ulong ticket); //--- (1)すべてのポジション注文のリストからの最初および(2)直近の成行注文、(3)直近の取引を返す COrder *GetFirstOrderPosition(const ulong position_id); COrder *GetLastOrderPosition(const ulong 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(const ulong 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); //--- Return the list of used symbols CArrayObj *GetListAllUsedSymbols(void) { return this.m_symbols.GetList(); } //--- Return the list of order, deal and position events CArrayObj *GetListAllOrdersEvents(void) { return this.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 { return this.m_last_trade_event; } ENUM_ACCOUNT_EVENT LastAccountEvent(void) const { return this.m_last_account_event; } bool IsHedge(void) const { return this.m_is_hedge; } bool IsTester(void) const { return this.m_is_tester; } bool IsAccountsEvent(void) const { return this.m_accounts.IsAccountEvent(); } //--- Return an account event code int GetAccountEventsCode(void) const { return this.m_accounts.GetEventCode(); } //--- Return CEngine global error code int GetError(void) const { return this.m_global_error; } //--- タイマーカウンタを作成する void CreateCounter(const int id,const ulong frequency,const ulong pause); //--- タイマー void OnTimer(void); //--- Set the list of used symbols bool SetUsedSymbols(const string &array_symbols[]) { return this.m_symbols.SetUsedSymbol(array_symbols); } //--- コンストラクタ/デストラクタ CEngine(); ~CEngine(); }; //+------------------------------------------------------------------+
SymbolEventsControl()メソッドを使用してすべてのコレクション銘柄の相場データを更新し、MarketWatchEventsControl()メソッドを使用してすべてのコレクション銘柄の残りのデータを更新し、[気配値表示]ウィンドウでイベントを追跡します(次の記事の銘柄コレクションイベントクラスで考慮)。
GetListAllUsedSymbols()メソッドは、CSymbolsCollectionクラスのGetList()メソッドを使用して呼び出し元プログラムに銘柄コレクションの完全なリストを返します。
SetUsedSymbols()メソッドは、CSymbolsCollectionクラスの同じ名前のSetUsedSymbol()メソッドを呼び出します。このメソッドは、プログラムで使用されるすべての銘柄の銘柄オブジェクトをコレクションリストに書き込みます。
これらのメソッドの構造を考えてみましょう。
クラスコンストラクタで、1番目および2番目の銘柄コレクションタイマーのカウンターを作成します。1番目のタイマーではすべての相場データを更新し。 2番目のタイマーでは残りの銘柄データを更新して[気配値表示]ウィンドウイベントを管理します。
//+------------------------------------------------------------------+ //| CEngineコンストラクタ | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true),m_last_trade_event(TRADE_EVENT_NO_EVENT),m_last_account_event(ACCOUNT_EVENT_NO_EVENT),m_global_error(ERR_SUCCESS) { this.m_is_hedge=#ifdef __MQL4__ true #else bool(::AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) #endif; this.m_is_tester=::MQLInfoInteger(MQL_TESTER); this.m_list_counters.Sort(); this.m_list_counters.Clear(); this.CreateCounter(COLLECTION_ORD_COUNTER_ID,COLLECTION_ORD_COUNTER_STEP,COLLECTION_ORD_PAUSE); this.CreateCounter(COLLECTION_ACC_COUNTER_ID,COLLECTION_ACC_COUNTER_STEP,COLLECTION_ACC_PAUSE); this.CreateCounter(COLLECTION_SYM_COUNTER_ID1,COLLECTION_SYM_COUNTER_STEP1,COLLECTION_SYM_PAUSE1); this.CreateCounter(COLLECTION_SYM_COUNTER_ID2,COLLECTION_SYM_COUNTER_STEP2,COLLECTION_SYM_PAUSE2); ::ResetLastError(); #ifdef __MQL5__ if(!::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } //---__MQL4__ #else if(!this.IsTester() && !::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } #endif } //+------------------------------------------------------------------+
2つの銘柄コレクションタイマーを使用するための文字列をOnTimer()ハンドラクラスに追加します。
//+------------------------------------------------------------------+ //| CEngineタイマー | //+------------------------------------------------------------------+ void CEngine::OnTimer(void) { //--- 過去の注文と取引、および成行注文とポジションの収集のタイマー int index=this.CounterIndex(COLLECTION_ORD_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the order, deal and position collections events if(counter.IsTimeDone()) this.TradeEventsControl(); } //--- If this is a tester, work with collection events by tick else this.TradeEventsControl(); } } //--- Account collection timer index=this.CounterIndex(COLLECTION_ACC_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the account collection events if(counter.IsTimeDone()) this.AccountEventsControl(); } //--- If this is a tester, work with collection events by tick else this.AccountEventsControl(); } } //--- Timer 1 of the symbol collection (updating symbol quote data in the collection) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID1); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over, update quote data of all symbols in the collection if(counter.IsTimeDone()) this.SymbolEventsControl(); } //--- In case of a tester, update quote data of all collection symbols by tick else this.SymbolEventsControl(); } } //--- Timer 2 of the symbol collection (updating all data of all symbols in the collection and track symbol search events in the market watch window) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID2); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over if(counter.IsTimeDone()) { //--- update data of all symbols in the collection this.m_symbols.Refresh(); //--- When workign with the market watch list, check the market watch window events if(this.m_symbols.ModeSymbolsList()==SYMBOLS_MODE_MARKET_WATCH) this.MarketWatchEventsControl(); } } //--- In case of a tester, update data of all collection symbols by tick else this.m_symbols.Refresh(); } } } //+------------------------------------------------------------------+
ロジック全体は、コードのコメントで提供されており、ここで説明する意味はありません。
現在の実装では、銘柄コレクションを使用するメソッドは、CSymbolsCollectionクラスのRefreshRatesメソッドを使用して、すべてのコレクション銘柄の相場データを更新するだけです。
//+------------------------------------------------------------------+ //| Working with a symbol collection | //+------------------------------------------------------------------+ void CEngine::SymbolEventsControl(void) { this.m_symbols.RefreshRates(); } //+------------------------------------------------------------------+
現在の実装では、[気配値表示]ウィンドウイベントを使用するメソッドは、テスターから呼び出されたことを確認し、テスターで機能する場合は終了します( テスターで[気配値表示]イベントを追跡しても意味がありません)。
//+------------------------------------------------------------------+ //| Working with symbol list events in the market watch window | //+------------------------------------------------------------------+ void CEngine::MarketWatchEventsControl(void) { if(this.IsTester()) return; //--- Tracking Market Watch window events //--- } //+------------------------------------------------------------------+
銘柄コレクションイベントに関連するすべての作業は、次の記事で行います。
これらはすべて、CEngineクラスに必要な変更です。
銘柄の使用に必要なモードを銘柄コレクションクラスに渡す必要があるため、使用モードを定義し、CEngineライブラリのメインオブジェクトに渡す銘柄配列を正しく入力する関数が必要です。
\MQL5\Include\DoEasy\Services\からDELib.mqhサービス関数ファイルを開き、必要な関数を追加します。
//+------------------------------------------------------------------+ //| Prepare the symbol array for a symbol collection | //+------------------------------------------------------------------+ bool CreateUsedSymbolsArray(const ENUM_SYMBOLS_MODE mode_used_symbols,string defined_used_symbols,string &used_symbols_array[]) { //--- When working with the current symbol if(mode_used_symbols==SYMBOLS_MODE_CURRENT) { //--- Write the name of the current symbol to the only array cell ArrayResize(used_symbols_array,1); used_symbols_array[0]=Symbol(); return true; } //--- If working with a predefined symbol set (from the defined_used_symbols string) else if(mode_used_symbols==SYMBOLS_MODE_DEFINES) { //--- Set a comma as a separator string separator=","; //--- Replace erroneous separators with correct ones if(StringFind(defined_used_symbols,";")>WRONG_VALUE) StringReplace(defined_used_symbols,";",separator); if(StringFind(defined_used_symbols,":")>WRONG_VALUE) StringReplace(defined_used_symbols,":",separator); if(StringFind(defined_used_symbols,"|")>WRONG_VALUE) StringReplace(defined_used_symbols,"|",separator); if(StringFind(defined_used_symbols,"/")>WRONG_VALUE) StringReplace(defined_used_symbols,"/",separator); if(StringFind(defined_used_symbols,"\\")>WRONG_VALUE) StringReplace(defined_used_symbols,"\\",separator); if(StringFind(defined_used_symbols,"'")>WRONG_VALUE) StringReplace(defined_used_symbols,"'",separator); if(StringFind(defined_used_symbols,"-")>WRONG_VALUE) StringReplace(defined_used_symbols,"-",separator); if(StringFind(defined_used_symbols,"`")>WRONG_VALUE) StringReplace(defined_used_symbols,"`",separator); //--- Delete as long as there are spaces while(StringFind(defined_used_symbols," ")>WRONG_VALUE && !IsStopped()) StringReplace(defined_used_symbols," ",""); //--- As soon as there are double separators (after removing spaces between them), replace them with a separator while(StringFind(defined_used_symbols,separator+separator)>WRONG_VALUE && !IsStopped()) StringReplace(defined_used_symbols,separator+separator,separator); //--- If a single separator remains before the first symbol in the string, replace it with a space if(StringFind(defined_used_symbols,separator)==0) StringSetCharacter(defined_used_symbols,0,32); //--- If a single separator remains after the last symbol in the string, replace it with a space if(StringFind(defined_used_symbols,separator)==StringLen(defined_used_symbols)-1) StringSetCharacter(defined_used_symbols,StringLen(defined_used_symbols)-1,32); //--- Remove all redundant things to the left and right #ifdef __MQL5__ StringTrimLeft(defined_used_symbols); StringTrimRight(defined_used_symbols); //--- __MQL4__ #else defined_used_symbols=StringTrimLeft(defined_used_symbols); defined_used_symbols=StringTrimRight(defined_used_symbols); #endif //--- Prepare the array ArrayResize(used_symbols_array,0); ResetLastError(); //--- divide the string by separators (comma) and add all found substrings to the array int n=StringSplit(defined_used_symbols,StringGetCharacter(separator,0),used_symbols_array); //--- if nothing is found, display the appropriate message (working with the current symbol is selected automatically) if(n<1) { string err= (n==0 ? DFUN_ERR_LINE+TextByLanguage("Ошибка. Строка предопределённых символов пустая, будет использоваться ","Error. String of predefined symbols empty, symbol will be used: ")+Symbol() : DFUN_ERR_LINE+TextByLanguage("Не удалось подготовить массив используемых символов. Ошибка ","Failed to create array of used characters. Error ")+(string)GetLastError() ); Print(err); return false; } } //--- If working with the Market Watch window or the full list else { //--- Add the (mode_used_symbols) working mode to the only array cell ArrayResize(used_symbols_array,1); used_symbols_array[0]=EnumToString(mode_used_symbols); } return true; } //+------------------------------------------------------------------+
このメソッドは、銘柄コレクションを使用するモードを受け取ります。これは、プログラム設定で設定するか、厳密に定義されます(モード選択が不要な場合)、また、処理したい銘柄のカンマ区切りリスト(または空の文字列)と、銘柄リストを追加する配列または使用モード([気配値表示]とサーバ銘柄の完全なリストを使用する場合)も受け取ります。これは、銘柄を使用するライブラリモードを設定するためにCEngineクラスに送信されます。
リストおよび配列に向けられた関数のすべてのアクションは、リストで直接詳細に説明されています。それらを個別に検討しても意味がありません。
これで、銘柄コレクションクラスの開発は終了です。テストの準備ができました。
銘柄コレクションのテスト
コレクションをテストするには、\MQL4\Experts\TestDoEasy\Part10にある前の記事のテストEAを\MQL5\Experts\TestDoEasy\ にPart15\TestDoEasyPart15_1.mq5として保存します。
入力で、ライブラリの銘柄コレクションの使用モードの選択と、設定でこのモードが選択されている場合に使用するカスタム銘柄のリストを格納する文字列変数を追加します。
//--- 入力変数 input ulong InpMagic = 123; // Magic number input double InpLots = 0.1; // Lots input uint InpStopLoss = 50; // StopLoss in points input uint InpTakeProfit = 50; // TakeProfit in points input uint InpDistance = 50; // Pending orders distance (points) input uint InpDistanceSL = 50; // StopLimit orders distance (points) input uint InpSlippage = 0; // Slippage in points input double InpWithdrawal = 10; // Withdrawal funds (in tester) input uint InpButtShiftX = 40; // Buttons X shift input uint InpButtShiftY = 10; // Buttons Y shift input uint InpTrailingStop = 50; // Trailing Stop (points) input uint InpTrailingStep = 20; // Trailing Step (points) input uint InpTrailingStart = 0; // Trailing Start (points) input uint InpStopLossModify = 20; // StopLoss for modification (points) input uint InpTakeProfitModify = 60; // TakeProfit for modification (points) input ENUM_SYMBOLS_MODE InpModeUsedSymbols = SYMBOLS_MODE_CURRENT; // Mode of used symbols list input string InpUsedSymbols = "EURUSD,AUDUSD,EURAUD,EURCAD,EURGBP,EURJPY,EURUSD,GBPUSD,NZDUSD,USDCAD,USDJPY"; // List of used symbols (comma - separator) //--- グローバル変数
グローバル変数のリストで、カスタム銘柄リストを保存するための変数と、銘柄のリストをライブラリに渡すための文字列配列を追加します。
//--- グローバル変数 CEngine engine; #ifdef __MQL5__ CTrade trade; #endif SDataButt butt_data[TOTAL_BUTT]; string prefix; double lot; double withdrawal=(InpWithdrawal<0.1 ?0.1 : InpWithdrawal); ulong magic_number; uint stoploss; uint takeprofit; uint distance_pending; uint distance_stoplimit; uint slippage; bool trailing_on; double trailing_stop; double trailing_step; uint trailing_start; uint stoploss_to_modify; uint takeprofit_to_modify; string used_symbols; string array_used_symbols[]; //+------------------------------------------------------------------+
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; //--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray(InpModeUsedSymbols,used_symbols,array_used_symbols); //--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Check and remove remaining EA graphical objects
上記のSetUsedSymbols()関数は、銘柄コレクションクラスに送信される銘柄配列を作成します。選択したモードに応じて、配列は現在の銘柄、カスタム銘柄リスト、[気配値表示]ウィンドウまたはサーバ上の完全な銘柄リストを使用するモードの文字列の説明のいずれかを備えています。
OnInit()ハンドラの最後に、銘柄コレクションクラスによって作成された銘柄リストの高速チェック用のコードを追加します。
//--- 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 //--- Fast check of the symbol object collection CArrayObj *list=engine.GetListAllUsedSymbols(); CSymbol *symbol=NULL; if(list!=NULL) { int total=list.Total(); for(int i=0;i<total;i++) { symbol=list.At(i); if(symbol==NULL) continue; symbol.Refresh(); symbol.RefreshRates(); symbol.PrintShort(); if(InpModeUsedSymbols<SYMBOLS_MODE_MARKET_WATCH) symbol.Print(); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
ここでは、すべてのコレクション銘柄の完全なリストを取得します。取得したリストによるループで、そこから次の銘柄を取得し、すべてのデータを更新して、操作ログで銘柄の説明を印刷します。まず、簡潔なものが表示されます。次に、「[気配値表示]ウィンドウの使用」または「サーバ上の銘柄の完全なリストの使用」モードが選択されていない場合、操作ログで銘柄プロパティの完全な説明を表示します。
ターミナルウィンドウでEAを起動し、設定で[[気配値表示]ウィンドウの銘柄使用]モードを選択します。その結果、銘柄コレクションクラスによって作成されたすべてのコレクション銘柄の簡単な説明を含むリストが操作ログに表示されます。
2019.06.27 10:01:52.756 Stock ALNU 2019.06.27 10:01:52.756 Stock SU25075RMFS1 2019.06.27 10:01:52.756 Bond SU46022RMFS8 2019.06.27 10:01:52.756 Bond SU26214RMFS5 2019.06.27 10:01:52.756 Stock AESL 2019.06.27 10:01:52.756 Stock 123456.bin 2019.06.27 10:01:52.756 Stock ARMD 2019.06.27 10:01:52.757 Bond SU46018RMFS6 2019.06.27 10:01:52.757 Stock GAZP 2019.06.27 10:01:52.757 Metal XAUUSD 2019.06.27 10:01:52.757 Stock EURRUB_TOD 2019.06.27 10:01:52.757 Stock GBPRUB_TOM 2019.06.27 10:01:52.757 Futures Si-9.19 2019.06.27 10:01:52.757 Futures RTS-3.20 2019.06.27 10:01:52.758 Minor Forex symbol USDNOK 2019.06.27 10:01:52.758 Major Forex symbol USDJPY 2019.06.27 10:01:52.758 Major Forex symbol EURUSD 2019.06.27 10:01:52.758 Minor Forex symbol USDCZK 2019.06.27 10:01:52.758 Major Forex symbol USDCAD 2019.06.27 10:01:52.758 Minor Forex symbol USDZAR 2019.06.27 10:01:52.758 Minor Forex symbol USDSEK 2019.06.27 10:01:52.758 Major Forex symbol AUDUSD 2019.06.27 10:01:52.758 Minor Forex symbol USDDKK 2019.06.27 10:01:52.758 Major Forex symbol NZDUSD 2019.06.27 10:01:52.759 Minor Forex symbol USDPLN 2019.06.27 10:01:52.759 Major Forex symbol GBPUSD 2019.06.27 10:01:52.759 Forex symbol USDRUR 2019.06.27 10:01:52.759 Exotic Forex symbol USDMXN 2019.06.27 10:01:52.759 Forex symbol USDHUF 2019.06.27 10:01:52.759 Minor Forex symbol USDTRY 2019.06.27 10:01:52.759 Minor Forex symbol USDHKD 2019.06.27 10:01:52.760 Major Forex symbol USDCHF 2019.06.27 10:01:52.760 Minor Forex symbol USDSGD
次に、銘柄コレクション内の指定された値の検索を確認しましょう。
EAの名前を変更し、\MQL5\Experts\TestDoEasy\でPart15\TestDoEasyPart15_2.mq5として保存します。
OnInit()ハンドラのコレクション銘柄リストの高速チェックのコードを変更します。コレクション銘柄データの更新のみを残して、銘柄のリストを操作ログに移動し、ロングポジションとショートポジションの最大と最小のスワップ、およびコレクション銘柄の最大と最小のスプレッドを受け取るための文字列を追加します。取得したデータを操作ログに入力します。
//--- 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 //--- Fast check of the symbol object collection CArrayObj *list=engine.GetListAllUsedSymbols(); CSymbol *symbol=NULL; if(list!=NULL) { int total=list.Total(); for(int i=0;i<total;i++) { symbol=list.At(i); if(symbol==NULL) continue; symbol.Refresh(); symbol.RefreshRates(); } } //--- Get the minimum and maximum values //--- get the current account properties (we need the number of decimal places for the account currency) CAccount *account=engine.GetAccountCurrent(); if(account!=NULL) { int index_min=0, index_max=0, dgc=(int)account.CurrencyDigits(); //--- If working with the Market Watch window, leave only visible symbols in the list if(InpModeUsedSymbols==SYMBOLS_MODE_MARKET_WATCH) list=CSelect::BySymbolProperty(list,SYMBOL_PROP_VISIBLE,true,EQUAL); //--- min/max swap long index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SWAP_LONG); // symbol index in the collection list with the minimum swap long index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SWAP_LONG); // symbol index in the collection list with the maximum swap long if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum swap long for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapLong(),dgc)); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum swap long for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapLong(),dgc)); } //--- min/max swap short index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SWAP_SHORT); // symbol index in the collection list with the minimum swap short index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SWAP_SHORT); // symbol index in the collection list with the maximum swap short if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum swap short for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapShort(),dgc)); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum swap short for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapShort(),dgc)); } //--- min/max spread index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SPREAD); // symbol index in the collection list with the minimum spread index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SPREAD); // symbol index in the collection list with the maximum spread if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum symbol spread ",symbol.Name()," = ",symbol.Spread()); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum symbol spread ",symbol.Name()," = ",symbol.Spread()); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
EAをコンパイルしてターミナルチャートで起動します。設定でサーバ上の銘柄の完全なリストを使用する作業を選択します。サーバ上のすべての銘柄のコレクションリストを作成した後(時間がかかる)、最大および最小のロング/ショートスワップのデータと、銘柄コレクションリスト内のすべての銘柄の最大および最小スプレッドが操作ログに表示されます。
2019.06.27 10:36:28.885 Minimum long position swap for USDZAR = -192.9 2019.06.27 10:36:28.885 Maximum long position swap for USDMXN = 432.7 2019.06.27 10:36:28.886 Minimum short position swap for XAUUSD = -17.8 2019.06.27 10:36:28.886 Maximum short position swap for USDMXN = 200.0 2019.06.27 10:36:28.886 Minimum spread for SU52001RMFS3 = 0 2019.06.27 10:36:28.886 Maximum spread for GBPRUB_TOM = 3975
次の段階
次の記事では、銘柄コレクションイベントのクラスを開発します。
現在のバージョンのライブラリのすべてのファイルは、テスト用EAファイルと一緒に以下に添付されているので、テストするにはダウンロードしてください。
質問、コメント、提案はコメント欄にお願いします。
シリーズのこれまでの記事:
第1部: 概念、データ管理第2部: 過去の注文と取引のコレクション
第3部:注文と取引のコレクション、検索と並び替え
第4部: 取引イベント概念
第5部: 取引イベントのクラスとコレクション取引イベントのプログラムへの送信
第6部: ネッティング勘定イベント
第7部: StopLimit注文発動イベント、注文およびポジション変更イベントの機能の準備
第8部: 注文とポジションの変更イベント
第9部:MQL4との互換性 - データの準備
第10部:MQL4との互換性 - ポジションオープンイベントと指値注文発動イベント
第11部:MQL4との互換性 - ポジション決済イベント
第12部:口座オブジェクトクラスと口座オブジェクトコレクション
第13部:口座オブジェクトイベント>第14部銘柄オブジェクト
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/7041
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索