English Русский 中文 Español Deutsch Português
preview
チャート上で取引を視覚化する(第2回):データのグラフ表示

チャート上で取引を視覚化する(第2回):データのグラフ表示

MetaTrader 5トレーディングシステム | 2 12月 2024, 10:43
451 0
Aleksandr Seredin
Aleksandr Seredin

はじめに

この記事では、「チャート上で取引を視覚化する(第1回):分析期間の選択」稿で実装を開始したチャート上での取引の視覚化スクリプトを完成させます。ユーザーが選択した単一の取引のデータを選択するコードと、チャート上に必要なデータオブジェクトを描画するコードを記述し、対応するチャートの印刷画面としてファイルに保存します。このスクリプトを使用すると、取引グラフの形成に関連する技術的な作業や、遡及分析のために印刷画面に保存する作業にかかる時間を大幅に節約できます。 プロジェクトの組み立てに時間を費やしたくない場合は、マーケットでスクリプトの既製バージョンをダウンロードできます。


1つの取引のデータを選択する

特定の期間の取引データを選択する場合とは異なり、単一の取引データを選択する場合、履歴注文選択の実装は大幅に簡素化されます。主な違いは、定義済みの端末関数HistorySelect()の代わりにHistorySelectByPosition()メソッドを使用して履歴データを要求することです。メソッドパラメータは、MetaTrader 5端末([表示]>[ツールボックス]>[履歴]>[チケット列])で確認できるPOSITION_IDENTIFIERを受け取る必要があります。このPOSITION_IDENTIFIERの値は、スクリプト内で定義された入力用のグローバル変数inp_d_ticketを通じて渡されます。

その他のロジックに関しては、Select_one_dealケースの実装は、特定期間のデータ選択ロジックをほぼそのまま踏襲しています。ユーザーに表示される情報も同様であり、その完全なコード例が以下に示されています。

      //--- if one deal is needed
      case Select_one_deal:

         res = MessageBox("You have selected analysis of one deal. Continue?","",MB_OKCANCEL); // informed in the message

         if(res == IDCANCEL)                                            // if interrupted by user
           {
            printf("%s - %d -> Scrypt was stoped by user.",__FUNCTION__,__LINE__);  // informed in the journal
            return;                                                     // interrupted
           }

         MessageBox("Please press 'Ok' and wait for the next message until script will be done."); // informed in the message

         //--- select by one position
         if(HistorySelectByPosition(inp_d_ticket))                      // select position by id
           {
            int total = HistoryDealsTotal();                            // total deals

            if(total <= 0)                                              // if nothing found
              {
               printf("%s - %d -> Deal was not found.",__FUNCTION__,__LINE__); // notify
               MessageBox("Deal was not found with this tiket: "+IntegerToString(inp_d_ticket)+". Script is done."); // informed in the message
               return;
              }

            for(int i=0; i<total; i++)                                  // iterate through the number of deals
              {
               //--- try to get deals ticket
               if((ticket=HistoryDealGetTicket(i))>0)                   // took the deal number
                 {
                  //--- get deals properties
                  position_id = HistoryDealGetInteger(ticket,DEAL_POSITION_ID);     // took the main id
                  entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY);// entry or exit?

                  if(entry == DEAL_ENTRY_IN)                                        // if this is an entry
                    {
                     open = HistoryDealGetDouble(ticket,DEAL_PRICE);                // take open price
                     time_open  =(datetime)HistoryDealGetInteger(ticket,DEAL_TIME); // take open time
                     symbol=HistoryDealGetString(ticket,DEAL_SYMBOL);   	    // take symbol
                     stop_loss = HistoryDealGetDouble(ticket,DEAL_SL);  	    // take Stop Loss
                     take_profit = HistoryDealGetDouble(ticket,DEAL_TP);	    // take Take Profit
                     //---
                     magic = (int)HistoryDealGetInteger(ticket,DEAL_MAGIC);   	    // take Magic
                     comment=HistoryDealGetString(ticket,DEAL_COMMENT);       	    // take comment
                     externalID=HistoryDealGetString(ticket,DEAL_EXTERNAL_ID); 	    // take external id
                     volume = HistoryDealGetDouble(ticket,DEAL_VOLUME);             // take volume
                     commission = HistoryDealGetDouble(ticket,DEAL_COMMISSION);     // take commission value
                    }

                  if(entry == DEAL_ENTRY_OUT)                           	    // if this is an exit
                    {
                     close = HistoryDealGetDouble(ticket,DEAL_PRICE);               // take close price
                     time_close  =(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);// take close time
                     //---
                     reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(ticket,DEAL_REASON); // take reason
                     swap = HistoryDealGetDouble(ticket,DEAL_SWAP);     // take swap
                     profit = HistoryDealGetDouble(ticket,DEAL_PROFIT); // take profit
                     fee = HistoryDealGetDouble(ticket,DEAL_FEE);       // take fee
                    }


                  //--- enter data into the main storage
                  //--- check if there is such id
                  if(Find(PositionID,position_id)==-1)                         // if there is no such deal,
                    {
                     //--- change the dimensions of the arrays
                     ArrayResize(arr_time_open,ArraySize(arr_time_open)+1);    // open time
                     ArrayResize(arr_time_close,ArraySize(arr_time_close)+1);  // close time
                     ArrayResize(arr_symbol,ArraySize(arr_symbol)+1);          // symbols
                     ArrayResize(arr_stop_loss,ArraySize(arr_stop_loss)+1);    // stop levels
                     ArrayResize(arr_take_profit,ArraySize(arr_take_profit)+1);// profits
                     ArrayResize(arr_open,ArraySize(arr_open)+1);              // entries
                     ArrayResize(arr_close,ArraySize(arr_close)+1);            // exits
                     ArrayResize(PositionID,ArraySize(PositionID)+1);          // position id
                     //---
                     ArrayResize(arr_magic,ArraySize(arr_magic)+1);            // Magic
                     ArrayResize(arr_extermalID,ArraySize(arr_extermalID)+1);  // external id
                     ArrayResize(arr_comment,ArraySize(arr_comment)+1);        // comment
                     ArrayResize(arr_volume,ArraySize(arr_volume)+1);          // volume
                     ArrayResize(arr_commission,ArraySize(arr_commission)+1);  // commission
                     ArrayResize(arr_reason,ArraySize(arr_reason)+1);          // reason
                     ArrayResize(arr_swap,ArraySize(arr_swap)+1);              // swap
                     ArrayResize(arr_profit,ArraySize(arr_profit)+1);          // profit
                     ArrayResize(arr_fee,ArraySize(arr_fee)+1);                // fee


                     PositionID[ArraySize(arr_time_open)-1]=position_id;       // id



                     if(entry == DEAL_ENTRY_IN)                         	       // if this is an entry
                       {
                        arr_time_open[    ArraySize(arr_time_open)-1]   = time_open;   // deal time
                        arr_symbol[       ArraySize(arr_symbol)-1]      = symbol;      // instrument symbol
                        arr_stop_loss[    ArraySize(arr_stop_loss)-1]   = stop_loss;   // deal stop loss
                        arr_take_profit[  ArraySize(arr_take_profit)-1] = take_profit; // deal take profit
                        arr_open[         ArraySize(arr_open)-1]        = open;        // open price
                        //---
                        arr_magic[        ArraySize(arr_magic)-1]       = magic;       // Magic
                        arr_comment[      ArraySize(arr_comment)-1]     = comment;     // comment
                        arr_extermalID[   ArraySize(arr_extermalID)-1]  = externalID;  // external id
                        arr_volume[       ArraySize(arr_volume)-1]      = volume;      // volume
                        arr_commission[   ArraySize(arr_commission)-1]  = commission;  // commission
                       }

                     if(entry == DEAL_ENTRY_OUT)                        	       // if this is an exit
                       {
                        arr_time_close[   ArraySize(arr_time_close)-1]  = time_close;  // close time
                        arr_close[        ArraySize(arr_close)-1]       = close;       // close prices
                        //---
                        arr_reason[       ArraySize(arr_reason)-1]      = reason;      // reason
                        arr_swap[         ArraySize(arr_swap)-1]        = swap;        // swap
                        arr_profit[       ArraySize(arr_profit)-1]      = profit;      // profit
                        arr_fee[          ArraySize(arr_fee)-1]         = fee;         // fee
                       }
                    }
                  else
                    {
                     int index = Find(PositionID,position_id);          // if there was a record already,

                     if(entry == DEAL_ENTRY_IN)                         // if this was an entry
                       {
                        arr_time_open[index]   = time_open;             // deal time
                        arr_symbol[index]      = symbol;                // symbol
                        arr_stop_loss[index]   = stop_loss;             // deal stop loss
                        arr_take_profit[index] = take_profit;           // deal take profit
                        arr_open[index]        = open;                  // open price
                        //---
                        arr_magic[index]       = magic;                 // Magic
                        arr_comment[index]     = comment;               // comment
                        arr_extermalID[index]  = externalID;            // external id
                        arr_volume[index]      = volume;                // volume
                        arr_commission[index]  = commission;            // commission
                       }

                     if(entry == DEAL_ENTRY_OUT)                        // if this is an exit
                       {
                        arr_time_close[index]  = time_close;            // deal close time
                        arr_close[index]       = close;                 // deal close price
                        //---
                        arr_reason[index]      = reason;                // reason
                        arr_swap[index]        = swap;                  // swap
                        arr_profit[index]      = profit;                // profit
                        arr_fee[index]         = fee;                   // fee
                       }
                    }
                 }
              }
           }
         else
           {
            printf("%s - %d -> Error of selecting history deals: %d",__FUNCTION__,__LINE__,GetLastError());	// informed in the journal
            printf("%s - %d -> Deal was not found.",__FUNCTION__,__LINE__); 					// informed in the journal
            MessageBox("Deal was not found with this tiket: "+IntegerToString(inp_d_ticket)+". Script is done."); // informed in the message
            return;
           }
         break;

両方のオプションが説明され、プログラム実行中に必要なデータがすべてのストレージに入力されたので、このデータを端末チャートに表示できるようになります。


必要なチャートを表示する

チャートに取引を保存するには、まずプログラムレベルで必要な銘柄を含む新しいウィンドウを開き、取引全体が明確に表示されるように右側のインデントの個別のシフトを含む必要なデザイン設定をおこない、必要なフォルダに印刷画面を保存する定義済み関数を呼び出す必要があります。

まず、目的のチャートのウィンドウを開くために必要なローカル変数を宣言しましょう。bars変数には右側のチャートのオフセット値が保存され、chart_widthおよびchart_height変数には保存用の対応するサイズが保存され、新しいチャートが開かれると、そのハンドルがhandle変数に保存され、将来チャートにアクセスできるようになります。 

//--- data collected, moving on to printing
   int bars = -1;                                                       // number of bars in a shift
   int chart_width = -1;                                                // chart width
   int chart_height =-1;                                                // chart height
   long handle =-1;                                                     // chart handle

新しい銘柄ウィンドウを開く要求を開始する前に、履歴からこれらの銘柄の有効性を要求する必要があります。このチェックは、口座に「存在しない銘柄」を開くというエラーを回避するために絶対に必要です。ここで、「存在しない銘柄」が取引履歴に保存されている場合、つまりかつて存在していた場合、その銘柄がどこから来るのかを説明する必要があると思います。

まず第一に、これはブローカーの口座タイプに関連している可能性があります。現在、多くのブローカーは、トレーダーの取引戦略に応じて収益性と利便性を最大限に高めるため、複数の口座オプションを提供しています。一部の口座では取引に手数料が発生しますが、スプレッドが非常に低く設定されています。一方で、他の口座タイプではスプレッドが高い代わりに取引ごとの手数料がかからない仕組みになっています。このような条件の違いにより、中期的な取引をおこなうトレーダーは手数料が発生しない口座を選ぶことが一般的です。中期取引ではスプレッドの大きさがそれほど重要ではないためです。一方で、日中の短期取引を頻繁におこなうトレーダーは、スプレッドの急な変動による損失を避けるために、取引手数料が発生する口座を選ぶ傾向があります。通常、ブローカーはこれらの条件を「スタンダード」「ゴールド」「プラチナ」「ECN」などの口座タイプとして分類し、各口座タイプ専用の銘柄名を割り当てます。例えば、スタンダード口座でのEURUSDペアの場合、別の口座タイプではEURUSDb、EURUSDz、あるいはEURUSD_iなどと表記されることがあります(ブローカーによって異なります)。

また、Forex取引においては、通貨ペア以外の特定の商品が有効期限に応じて銘柄名を変更する場合もあります。ただし、本記事は通貨ペアに特化しているため、この点についてはここでは詳しく扱いません。

銘柄の有効性を確認する必要があるもう1つの重要な条件は、端末の気配値表示ウィンドウにおいて、必要な銘柄がサブスクリプションされていない場合です。たとえ銘柄名が口座で承認されていても、端末のコンテキストメニュー([表示]>[気配値表示])で選択されていない場合、呼び出し関数でエラーが発生し、チャートを開くことができません。

チェックを実装するには、以下のようにストレージ内の各ツールを反復処理するループを配置することから始めます。

   for(int i=0; i<ArraySize(arr_symbol); i++)                           // iterate through all deal symbols

コンテナに保存された銘柄の有効性を確認するには、定義済み端末関数SymbolSelect()を使用します。これに渡す最初のパラメータは、文字列形式の銘柄名です。これは、有効性を確認したい銘柄です。論理値「true」が2番目に来ます。2番目のパラメータとして「true」を渡すと、指定された銘柄が有効であるが気配値表示で選択されていない場合は、自動的に選択されることになります。完全なチェックロジックは次のようになります。

//--- check for symbol availability

   for(int i=0; i<ArraySize(arr_symbol); i++)                           // iterate through all deal symbols
     {
      if(!SymbolSelect(arr_symbol[i],true))                             // check if the symbol is in the book and add if not
        {
         printf("%s - %d -> Failed to add a symbol %s to the marketbook. Error: %d",
			__FUNCTION__,__LINE__,arr_symbol[i],GetLastError()); // informed in the journal
         MessageBox("Failed to add a symbol to the marketbook: "+arr_symbol[i]+
			". Please select 'show all' in the your market book and try again. Script is done."); // informed in the message
         return;                                                        // if failed, abort
        }
     }

したがって、銘柄の有効性チェックに合格しない場合は、ユーザーに適切な通知を送信してプログラムの実行を終了します。すべての有効性チェックに合格したら、必要な銘柄チャートを端末で直接開くことができます。

まず、MqlDateTimeデータ型のdeal_close_date補助変数を指定します。これにより、保存されたすべてのチャートを対応する期間フォルダに簡単に並べ替えることができます。ストレージ内のdatetimeデータ型をMqlDateTimeデータ型に明示的に縮小するには、以下に示すように、定義済みの端末関数TimeToStruct()を使用します。

      MqlDateTime deal_close_date;                                      // deal closure date in the structure
      TimeToStruct(arr_time_close[i],deal_close_date);                  // pass date to the structure

チャートは、main_graph、addition_graph、addition_graph_2、addition_graph_3変数内のユーザー定義データに従って描画されます。変数にPERIOD_CURRENT列挙値が含まれている場合、チャートは描画されません。変数に特定の値(たとえばPERIOD_D1)を入力すると、このチャートが描画されます。次の形式で入力されたすべての変数に対してこのチェックを実行します(メイン変数は例として以下に示されています)。

      //--- check the main one
      if(main_graph != PERIOD_CURRENT)                                  // if the main one selected

各チャートの描画は、必要な銘柄の新しいチャートを開くことから始まります。以下に示すように、必要な銘柄と時間枠をストレージから渡しながら、ChartOpen()定義済み端末関数を使用して銘柄チャートが開かれます。

         //--- open the required chart
         handle = ChartOpen(arr_symbol[i],main_graph);                  // open the necessary symbol chart

チャートが開いたら、上で説明したすべての標準ユーザー設定を適用します。これをおこなうには、ChartApplyTemplate()定義済み端末関数を使用します。これは非常に役立ち、自分でコードを記述する必要がなくなります。ChartApplyTemplate()関数のパラメータは、ChartOpen()関数の呼び出しから取得されたチャートハンドルと、取引時間枠に対してユーザーがdailyHistorytemp形式で指定したテンプレートの名前を取得します。テンプレートアプリケーション関数を呼び出すコードを以下に示します。

         ChartApplyTemplate(handle,main_template);                      // apply template

ここで、これまでMetaTrader 5端末でテンプレートを使用したことがない人のために、少し余談をしておきましょう。「見苦しい」テンプレートを使用すると、取引の保存された印刷画面が「不快」なもの、あるいは「役に立たないもの」になる可能性があります。独自のdailyHistorytempテンプレートを作成するには、次の手順に従います。

  • [ファイル]-[新規チャート]から任意の銘柄のチャートを開きます。
  • チャートが開いたら、F8キーを押してプロパティウィンドウ(例:「PropertiesGBPAUD,Daily」)を開きます。
  • プロパティウィンドウには[共通]、[表示]、[色]タブがあります。それぞれで、たとえば日次チャートなど、より使い慣れた設定を行い、[OK]をクリックします。詳細はチャート設定(公式端末ヘルプ)をご覧ください。
  • [OK]をクリックすると、プロパティウィンドウが閉じられ、チャートは必要な形式になります。
  • 次に、コンテキストメニューで、[チャート]>[テンプレート]>[テンプレートの保存]を選択します。テンプレート保存ウィンドウが表示され、テンプレート保存ウィンドウが表示されます。[ファイル名]にdailyHistorytemp.tplと入力し、[保存]をクリックします。
  • その後、..MQL5\Profiles\Templates端末フォルダにdailyHistorytemp.tplファイルが作成され、スクリプトで使用できるようになります。注目すべき主な点は、テンプレート名が「.tpl」拡張子なしでスクリプトに入力されることです。

さて、コードに戻りましょう。必要なテンプレートが適用されたら、チャートが目的の品質でロードされる時間を確保するために、コードの実行を少し遅らせる必要があります。そうしないと、必要な過去の価格データを端末に読み込むのに時間がかかるため、チャートが正しく表示されない可能性があります。たとえば、チャートをしばらく開いていない場合は、端末でチャートを正しく表示するには時間がかかります。以下に示すように、定義済み端末関数Sleep()を通じて時間遅延を通知します。

         Sleep(2000);                                                   // wait for the chart to load

遅延としては、純粋に実践から得た2000ミリ秒または2秒の値を使用します。これにより、チャートがロードする時間が保証され、大量の取引でスクリプトの実行に長時間かかることがなくなります。この値を自分でカスタマイズするには、スクリプト設定にこの値を個別に入力して、機器やインターネット接続のパフォーマンスに応じてプロセスを高速化または低速化することができます。実践が示すように、ほとんどの場合、2秒で十分です。

ここでは、履歴を分析しており、チャートを常に右にシフトするための新しいティックは必要ないため、チャートを最新のバー値にスクロールするのを無効にする必要があります。これは、以下に示すように、ChartSetInteger()定義済み関数を使用して、必要なチャートのCHART_AUTOSCROLLプロパティをfalseに設定することで実行できます。

         ChartSetInteger(handle,CHART_AUTOSCROLL,false);                // disable auto scroll

自動スクロールが無効になったので、まず、該当する取引を終了した期間の履歴に向かってチャートをシフトするために、左側の対応する時間枠のチャート上のバーの数を数える必要があります。最初から最後までの取引全体を印刷画面に表示したいので、銘柄、チャートの時間枠、取引終了時間をパラメータとして渡し、iBarShift()定義済み端末関数を介して値を取得できます。exactパラメータでは、履歴が非常に深い場合に備えてfalseを渡します。ただし、この場合の実装ではそれほど重要ではありません。パラメータを含む完全なメソッド呼び出しを以下に示します。

         bars = iBarShift(arr_symbol[i],main_graph,arr_time_close[i],false); // get the shift for the deal time

必要なチャートシフトがわかれば、履歴の中で必要な取引を捉える期間を正確に表示できます。以下に示すように、ChartNavigate()定義済み端末変数に次のパラメータを渡すことで、チャートを必要な距離だけ目的の方向にシフトできます。

         ChartNavigate(handle,CHART_CURRENT_POS,-bars+bars_from_right_main); // shifted the chart with a custom margin

チャートをシフトするために、チャートハンドル、ENUM_CHART_POSITION列挙のCHART_CURRENT_POSの現在のポジション値、および、ポジションを終了した後の価格変動の可能性を評価するためにユーザーが入力したオフセットを含むbars変数で以前に取得した取引へのシフトを渡しました。

説明したチャート変換の後、念のためChartRedraw()メソッドを呼び出し、チャートに追加のデータを描画して履歴取引を分析します。

ポジションの開始と終了、およびストップロスとテイクプロフィットのレベルを示すカスタム情報パネル要素と線を描画するには、対応するpaintDeal()およびpaintPanel()カスタム関数を使用します。端末チャートを操作するための標準的な動作パターンに基づいて、paintDeal()が取引の開始価格と終了価格、およびテイクプロフィットストップロスの線を描画するのを定義します。一方、paintPanel()メソッドには、画面の隅に完全な取引情報を含むテーブルが含まれます。

メソッドの詳細な定義については、次のセクションで説明します。ここでは、メソッドがこのコードセグメントで呼び出されることを単に示します。これは、これらの2つの要素グループを描画するために必ずしもこの記事で示した実装を使用する必要はないという観点からも行われます。希望する署名を維持しながら、自分で再定義することができます。本記事で紹介したメソッドの実装は、コードに書き込んだ時点でのグラフィックスの美しさと情報量の最適な比率の例です。ここでの主な目的は、メインコード内でのメソッド呼び出しの位置を維持することです。

         //--- draw the deal
         paintDeal(handle,PositionID[i],arr_stop_loss[i],arr_take_profit[i],arr_open[i],arr_close[i],arr_time_open[i],arr_time_close[i]);

         //--- draw the information panel
         paintPanel(handle,PositionID[i],arr_stop_loss[i],arr_take_profit[i],arr_open[i],
                    arr_close[i],arr_time_open[i],arr_time_close[i],arr_magic[i],arr_comment[i],
                    arr_extermalID[i],arr_volume[i],arr_commission[i],arr_reason[i],arr_swap[i],
                    arr_profit[i],arr_fee[i],arr_symbol[i],(int)SymbolInfoInteger(arr_symbol[i],SYMBOL_DIGITS));

メソッドによってチャート上に取引ラインと情報パネルが描画されたら、現在のチャートで発生したすべての内容の印刷画面を保存する実装に進むことができます。これをおこなうには、以下に示すように、再定義されたChartSetInteger()端末関数を使用して、開いているチャートからこのデータを要求することによって、印刷画面の幅と高さの将来の寸法を最初に決定します。

         //--- get data by screen size
         chart_width = (int) ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS);   // look at the chart width
         chart_height = (int) ChartGetInteger(handle,CHART_HEIGHT_IN_PIXELS); // look at the chart height

チャートを表示するための対応するパラメータとして、幅CHART_WIDTH_IN_PIXELSと高さCHART_HEIGHT_IN_PIXELSにそれぞれhttps://www.mql5.com/ja/docs/constants/chartconstants/enum_chart_property#enum_chart_property_integer列挙値を渡しました。

サイズデータを受け取ったら、標準の端末フォルダに取引の印刷画面チャートを保存するためのパスを作成する必要があります。EAがすべてのファイルを1つのフォルダに配置するのを防ぎ、代わりにユーザーの利便性のためにファイルを並べ替えるために、次の文字列のファイル名を通じてこのプロセスを自動化します。

         string name_main_screen = brok_name+"/"+
                                   IntegerToString(account_num)+"/"+
                                   IntegerToString(deal_close_date.year)+"-"+IntegerToString(deal_close_date.mon)+
				   "-"+IntegerToString(deal_close_date.day)+"/"+
                                   IntegerToString(PositionID[i])+"/"+
                                   EnumToString(main_graph)+IntegerToString(PositionID[i])+".png"; // assign the name

グラフィカルに言えば、標準ディレクトリ内のフォルダにファイルを分類する構造は、図1のようになります。

図1:取引ごとに保存された印刷画面のフォルダアドレスの構造

図1:取引ごとに保存された印刷画面のフォルダアドレスの構造


ご覧のとおり、チャートファイルはブローカー名、口座番号、実行年、月、日で並べ替えられるため、ユーザーは1つの一般的なリストでファイル名を探すことなく、目的の取引を簡単に見つけることができます。異なる時間枠は、端末の対応するポジション番号のフォルダに配置されます。

ChartScreenShot()定義済み端末関数を呼び出して情報を直接保存し、必要なチャートのハンドル、チャートのサイズに対応する先ほど取得した印刷画面のサイズ、およびフォルダアドレスの構造全体を含むファイルの名前を、図1および以下のコードに示すようにパラメータとして渡します。

         ChartScreenShot(handle,name_main_screen,chart_width,chart_height,ALIGN_LEFT);             // make a screenshot

階層で指定されたフォルダが標準の端末フォルダに存在しない場合は、ユーザーの介入なしに端末によって自動的に作成されます。

ファイルを保存した後、特にダウンロードに口座の過去の取引が多数含まれている場合は、端末のビューが乱雑にならないようにチャートを閉じることができます。不要なものを閉じないように、必要なチャートのハンドルを渡すChartClose()定義済み端末関数を使用してチャートを閉じます。関数呼び出しを以下に示します。

         ChartClose(handle);                                            // closed the chart

ユーザーが入力で指定したすべての時間枠に対して同様にこの操作を繰り返します。ここで、スクリプトを完成させるために、メインプログラムコードの外部でpaintDeal()メソッドとpaintPanel()メソッドの動作を定義する必要があります。


チャート上にデータオブジェクトを描画する

印刷画面のチャートに情報を便利に配置するには、ユーザーが必要とするデータがどのように描画されるかを決定する2つのメソッドを再定義するだけで済みます。

まず、paintDeal()メソッドの説明から始めましょう。その目的は、始値と終値、ストップロス、および利益確定ポジションの位置に関連付けられたポジションのグラフィックを描画することです。これをおこなうには、メインコード本体の外側で次のシグネチャを使用してメソッドの説明を宣言します。

void paintDeal(long handlE,
               ulong tickeT,
               double stop_losS,
               double take_profiT,
               double opeN,
               double closE,
               datetime timE,
               datetime time_closE)

メソッドパラメータでは、次handlelE(描画するチャートのハンドル)、ticketT(取引チケット)、stop_losS(存在する場合はストップロスの価格)、take_profiT(存在する場合はテイクプロフィットの価格)、opeN(始値)、closE(終値)、timeE(取引開始時刻)、time_closE(取引終了時刻)の値が指定されます。

まず、重複しない一意の名前に対応するオブジェクトの名前から描画を始めましょう。したがって、名前では、このオブジェクトが「name_sl_」の形式でストップに対応する機能を実装します。名前を一意にするために、以下に示すように、取引のチケット番号も追加します。

   string name_sl = "name_sl_"+IntegerToString(tickeT);                    // assign the name

ここで、チャート上の履歴ポジションによってストップロスレベルを描画するObjectCreate()定義済み端末関数を使用して、グラフィックオブジェクト自体を作成できます。渡されるパラメータは、チャートのハンドルとname_sl変数からの一意の名前です。OBJ_ARROW_LEFT_PRICE値をオブジェクト型として指定します。これは、以下に示すように、ENUM_OBJECT列挙からの左の価格ラベル、実際の価格値、およびラベルがチャートに配置された時刻を意味します。

   ObjectCreate(handlE,name_sl,OBJ_ARROW_LEFT_PRICE,0,timE,stop_losS);     // create the left label object

オブジェクトが作成されたので、OBJPROP_COLORフィールドとOBJPROP_TIMEFRAMESフィールドの値を設定しましょう。ストップロスは通常赤色で表示されるため、OBJPROP_COLORをclrRedに設定し、OBJPROP_TIMEFRAMESをOBJ_ALL_PERIODSに設定してすべての時間枠で表示します。ただし、この実装では2番目の条件は重要ではありません。一般的に、ストップロス描画ブロックは次のようになります。

//--- draw stop loss
   string name_sl = "name_sl_"+IntegerToString(tickeT);                    // assign the name
   ObjectCreate(handlE,name_sl,OBJ_ARROW_LEFT_PRICE,0,timE,stop_losS);     // create the left label object
   ObjectSetInteger(handlE,name_sl,OBJPROP_COLOR,clrRed);                  // add color
   ObjectSetInteger(handlE,name_sl,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);    // set visibility
   ChartRedraw(handlE);                                                    // redraw

各ブロックを描画した後、ChartRedraw()メソッドを呼び出します。

テイクプロフィットブロックの描画は、以下の例外を除いてストップロスの描画と似ています。まず、一意のオブジェクト名に「name_tp_」と取引チケットを追加し、受け取った利益の従来の指定に対応する緑色のパレットから、clrLawnGreen色を介して色を設定します。それ以外の点では、ロジックはストップロスブロックに似ており、ここで完全に紹介されています。

//--- draw take profit
   string name_tp = "name_tp_"+IntegerToString(tickeT);                    // assign the name
   ObjectCreate(handlE,name_tp,OBJ_ARROW_LEFT_PRICE,0,timE,take_profiT);   // create the left label object
   ObjectSetInteger(handlE,name_tp,OBJPROP_COLOR,clrLawnGreen);            // add color
   ObjectSetInteger(handlE,name_tp,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);    // set visibility
   ChartRedraw(handlE);                                                    // redraw

左の価格ラベルを介してエントリ価格を描画する実装に移りましょう。前のブロックとの違いは、まず第一に、オブジェクトの一意の名前にあります。先頭に「name_open_」を追加します。もう1つの違いはclrWhiteSmokeの線の色です。この色はグラフ上で目立ちすぎませんが、それ以外はすべて同じです。

//--- draw entry price
   string name_open = "name_open_"+IntegerToString(tickeT);                // assign the name
   ObjectCreate(handlE,name_open,OBJ_ARROW_LEFT_PRICE,0,timE,opeN);        // create the left label object
   ObjectSetInteger(handlE,name_open,OBJPROP_COLOR,clrWhiteSmoke);         // add color
   ObjectSetInteger(handlE,name_open,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);  // set visibility
   ChartRedraw(handlE);                                                    // redraw

取引の開始価格ラベルと終了価格ラベルを結ぶ線は同じ色で表示されます。線の種類が異なります。ObjectCreate()メソッドパラメータでオブジェクトを作成するときに、トレンドラインを作成するために、ENUM_OBJECT列挙のOBJ_TREND値を3番目のパラメータとして渡します。チャート上にトレンドラインを正しく配置するには、2つのポイントの位置に関する追加のパラメータを指定する必要があります。各ポイントには、価格と時間という2つの属性があります。これをおこなうには、以下に示すように、始値と終値(opeNとclosE)を、終値と始値(timeEとtime_closE変数)とともに後続のパラメータに渡します。

//--- deal line
   string name_deal = "name_deal_"+IntegerToString(tickeT);                // assign the name
   ObjectCreate(handlE,name_deal,OBJ_TREND,0,timE,opeN,time_closE,closE);  // create the left label object
   ObjectSetInteger(handlE,name_deal,OBJPROP_COLOR,clrWhiteSmoke);         // add color
   ObjectSetInteger(handlE,name_deal,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);  // set visibility
   ChartRedraw(handlE);                                                    // redraw

チャート上に取引を完全に表示するには、取引を終了するための価格ラベルを描画する必要があります。これを実現するために、適切な価格ラベルを使用して、情報がより視覚的に見やすい形で印刷画面に表示されるようにします。正しいラベルを描画するには、ObjectCreate()メソッドは3番目のパラメータとしてOBJ_ARROW_RIGHT_PRICE値(ENUM_OBJECT列挙からの正しい価格ラベルを意味する)を受け取る必要があります。残りの描画では価格と時間だけが必要で、以下に示すように対応するtime_closE、closE変数を介して渡します。

//--- draw exit price
   string name_close = "name_close"+IntegerToString(tickeT);                // assign the name
   ObjectCreate(handlE,name_close,OBJ_ARROW_RIGHT_PRICE,0,time_closE,closE);// create the left label object
   ObjectSetInteger(handlE,name_close,OBJPROP_COLOR,clrWhiteSmoke);         // add color
   ObjectSetInteger(handlE,name_close,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);  // set visibility
   ChartRedraw(handlE);                                                     // redraw

これで、ポジションのエントリラインとエグジットラインを描画するためのカスタムpaintDeal()メソッドの説明は完了です。ここで、paintPanel()メソッドで完全な取引情報のパネルを描画する方法の説明に進みます。

パネルを描画する方法を説明するには、OBJ_LABELタイプのテキストラベル、ENUM_OBJECT列挙、およびユーザーグラフィカルインターフェイスを作成および設計するためのOBJ_RECTANGLE_LABELオブジェクトなど、テキストラベルの描画を担当するより複雑なメソッド構造が必要になります。テキストラベルを作成するためのLabelCreate()と長方形のラベルを作成するためのRectLabelCreate()という対応するカスタムメソッドを宣言しましょう。まず補助メソッドの説明から始め、次に補助メソッドを使用するメインのpaintPanel()メソッドの説明に移ります。

一般に、スクリプトメソッドの構造は図2のようになります。

図2:グラフィックスを描画するためのカスタムメソッドの構造

図2:グラフィックスを描画するためのカスタムメソッドの構造


次のシグネチャをパラメータとしてLabelCreate()メソッドを宣言します。

bool LabelCreate(const long              chart_ID=0,               // chart ID
                 const string            name="Label",             // label name
                 const int               sub_window=0,             // subwindow number
                 const long              x=0,                      // X coordinate
                 const long              y=0,                      // Y coordinate
                 const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // chart corner for anchoring
                 const string            text="Label",             // text
                 const string            font="Arial",             // font
                 const int               font_size=10,             // font size
                 const color             clr=clrRed,               // color
                 const double            angle=0.0,                // text angle
                 const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type
                 const bool              back=false,               // in the background
                 const bool              selection=false,          // select to move
                 const bool              hidden=true,              // hidden in the list of objects
                 const long              z_order=0)                // priority for clicking with a mouse

chart_IDパラメータは、オブジェクトを描画する必要があるチャートのハンドルを受け取ります。「name」は一意のオブジェクト名であり、sub_windowパラメータの値が0の場合は、オブジェクトをメインチャートウィンドウに描画することを意味します。オブジェクトの左上隅の座標は、それぞれXパラメータとYパラメータを介して渡されます。対応する値を「corner」パラメータに渡すことで、オブジェクトのコーナーとチャートのバインディングを標準の左コーナーから変更できますが、ここではデフォルト値のANCHOR_LEFT_UPPERのままにします。表示する情報の文字列値をtextパラメータに渡します。フォントの種類やサイズ、色、角度などの表示タイプは、対応する「font」、「font_size」、「clr」、「angle」パラメータで渡されます。また、「selection」および「hidden」パラメータを使用して、オブジェクトをユーザーのオブジェクトリスト内で非表示にし、マウスで選択できないようにします。z_orderパラメータは、マウスクリックの優先順位を決定します。

メソッドの説明を始める前に、まずエラー変数をリセットして、定義済み端末関数ResetLastError()を通じて将来オブジェクトを作成する結果を正しく制御できるようにします。OBJ_LABEL型のオブジェクト作成結果は、以下に示すように、ObjectCreate()関数を呼び出すときにif'論理演算子によって処理されます。オブジェクトが作成されない場合は、EAログでそのことをユーザーに通知し、通常どおりreturnステートメントを介してメソッドの実行を中断します。

//--- reset the error value
   ResetLastError();
//--- create a text label
   if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0))
     {
      Print(__FUNCTION__,
            ": failed to create the text label! Error code = ",GetLastError());
      return(false);
     }

オブジェクトが正常に作成された場合は、ObjectSetInteger()ObjectSetString()、およびObjectSetDouble()の定義済み端末関数を使用してオブジェクトのプロパティフィールドを初期化し、必要な外観を実現します。ObjectSetInteger()関数を使用して、対応する座標、オブジェクトアンカー角度、フォントサイズ、オブジェクトアンカーメソッド、色、表示モード、およびユーザーに対するオブジェクトの可視性に関連するプロパティの値を設定します。ObjectSetDouble()関数を使用してフォント角度の値を設定し、ObjectSetString()関数を使用して渡されたテキストの内容と表示するフォントタイプを定義します。メソッド本体の完全な実装を以下に示します。

//--- reset the error value
   ResetLastError();
//--- create a text label
   if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0))
     {
      Print(__FUNCTION__,
            ": failed to create the text label! Error code = ",GetLastError());
      return(false);
     }
//--- set label coordinates
   ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- set the chart's corner, relative to which point coordinates are defined
   ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- set the text
   ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set the text font
   ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- set font size
   ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- set the text angle
   ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set anchor type
   ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set the color
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the label by mouse
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click on the chart
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
   return(true);

オブジェクト作成パラメータとして次のシグネチャを持つRectLabelCreate()メソッドを宣言します。

bool RectLabelCreate(const long             chart_ID=0,               // chart ID
                     const string           name="RectLabel",         // label name
                     const int              sub_window=0,             // subwindow number
                     const int              x=19,                     // X coordinate
                     const int              y=19,                     // Y coordinate
                     const int              width=150,                // width
                     const int              height=20,                // height
                     const color            back_clr=C'236,233,216',  // background color
                     const ENUM_BORDER_TYPE border=BORDER_SUNKEN,     // border type
                     const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // chart corner for anchoring
                     const color            clr=clrRed,               // flat border color (Flat)
                     const ENUM_LINE_STYLE  style=STYLE_SOLID,        // flat border style
                     const int              line_width=1,             // flat border width
                     const bool             back=true,                // 'true' in the background
                     const bool             selection=false,          // select to move
                     const bool             hidden=true,              // hidden in the list of objects
                     const long             z_order=0)                // priority for clicking with a mouse

RectLabelCreate()メソッドのパラメータは、前のメソッドオブジェクトのデータを表示するための背景として機能する長方形のラベル境界の追加設定を除いて、以前に宣言したLabelCreate()メソッドのパラメータと非常に似ています。オブジェクトの境界線を構成するための追加パラメータは、border(ENUM_BORDER_TYPE列挙体で定義される境界線タイプで、デフォルト値はBORDER_SUNKEN)、style(ENUM_LINE_STYLE列挙体で定義される境界線スタイルで、デフォルト値はSTYLE_SOLID)、line_width(境界線の線幅(整数値))です。

メソッド本体の定義は前のものと似ており、同様に、以下に示すように、オブジェクトの作成と、対応する定義済み端末メソッドによるそのプロパティの定義という2つのグローバルセクションで構成されます。

//--- reset the error value
   ResetLastError();                                                    // reset error
//--- create a rectangle label
   if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0))   // create object
     {
      //--- set label coordinates
      ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);              // assign x coordinate
      ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);              // assign y coordinate
      //--- set label size
      ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);              // width
      ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);             // height
      //--- set the background color
      ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);         // background color
      //--- set border type
      ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border);       // border type
      //--- set the chart corner, relative to which point coordinates are defined
      ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);            // anchor corner
      //--- set flat border color (in Flat mode)
      ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);                // frame
      //--- set flat border line style
      ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);              // style
      //--- set flat border width
      ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width);         // width
      //--- display in the foreground (false) or background (true)
      ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);                // default is background
      //--- enable (true) or disable (false) the mode of moving the label by mouse
      ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);     // is it possible to select
      ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);       //
      //--- hide (true) or display (false) graphical object name in the object list
      ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);            // is it visible in the list
      //--- set the priority for receiving the event of a mouse click on the chart
      ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);           // no events
      //--- successful execution
     }
   return(true);

すべての補助メソッドについて説明したので、パネル全体を描画するメインメソッドの本体であるpaintPanel()を定義しましょう。入力には、以下に示すように、ユーザーに完全な取引情報を表示するために必要なフィールドが含まれます。

void paintPanel(long handlE,                 
                ulong tickeT,                
                double stop_losS,            
                double take_profiT,          
                double opeN,                 
                double closE,                
                datetime timE,               
                datetime time_closE,         
                int magiC,                   
                string commenT,              
                string externalIDD,          
                double volumE,               
                double commissioN,           
                ENUM_DEAL_REASON reasoN,     
                double swaP,                 
                double profiT,               
                double feE,                  
                string symboL,               
                int digitS                   
               )

前のメソッドと同様に、最初のパラメータはチャートのハンドルを定義します。このハンドル上に、情報パネルに関連付けられたすべてのオブジェクトが作成されます。他のすべてのパラメータは、履歴取引オブジェクトのフィールドを繰り返します。

以下に示すように、パネルのサイズを格納する変数と、表示される情報の名前と以前に取得した値で列を固定するための座標を定義することにより、取引データパネルを描画するためのメソッドの実装を開始します。

int height=20, max_height =0, max_width = 0;	// column height and max values for indent
int x_column[2] = {10, 130};			// columns X coordinates
int y_column[17];				// Y coordinates

height変数には、各行が均等に描画されるように各列の高さとして静的な値20が格納され、max_height値とmax_width値には、均等に描画されるように各列の最大値が保存されます。X軸とY軸に沿った必要な座標は、それぞれx_column[]配列とy_column[]配列に格納されます。

ここで、ヘッダー列と値列を表示するための行の値を格納する2つの配列を宣言する必要があります。次のコードに示すように、文字列型のデータ配列を介してヘッダー列を宣言します。

   string column_1[17] =
     {
      "Symbol",
      "Position ID",
      "External ID",
      "Magic",
      "Comment",
      "Reason",
      "Open",
      "Close",
      "Time open",
      "Time close",
      "Stop loss",
      "Take profit",
      "Volume",
      "Commission",
      "Swap",
      "Profit",
      "Fee"
     };

パネルは変更されず、データは常に同じ順序で表示されるため、すべての配列値は静的に宣言および初期化されます。これは、さまざまな取引に関する情報を閲覧することに慣れるという点で便利なはずです。値が含まれていないデータやゼロに等しいデータをパネルから除外できる機能を実装することは可能ですが、情報をすばやく検索するときには視覚的に不便です。毎回列の値を確認するよりも、よく知られた表示パターンで情報を検索する方がまだ馴染みがあります。

同じデータシーケンスで、上記の配列で宣言された列の値がすでに含まれている2番目の配列を宣言します。配列の宣言は次のように記述します。

   string column_2[17] =
     {
      symboL,
      IntegerToString(tickeT),
      externalIDD,
      IntegerToString(magiC),
      commenT,
      EnumToString(reasoN),
      DoubleToString(opeN,digitS),
      DoubleToString(closE,digitS),
      TimeToString(timE),
      TimeToString(time_closE),
      DoubleToString(stop_losS,digitS),
      DoubleToString(take_profiT,digitS),
      DoubleToString(volumE,2),
      DoubleToString(commissioN,2),
      DoubleToString(swaP,2),
      DoubleToString(profiT,2),
      DoubleToString(feE,2)
     };

配列はメソッドレベルでローカルに宣言され、対応する定義済み端末関数を使用して、メソッドパラメータから直接フィールドが同時に初期化されます。

必要なデータを含むコンテナを宣言したので、各セル座標のアンカー値を計算して、各セルの最大値を検索する必要があります。これは次のコードで実装できます。

   int count_rows = 1;
   for(int i=0; i<ArraySize(y_column); i++)
     {
      y_column[i] = height * count_rows;
      max_height = y_column[i];
      count_rows++;

      int width_curr = StringLen(column_2[i]);

      if(width_curr>max_width)
        {
         max_width = width_curr;
        }
     }

   max_width = max_width*10;
   max_width += x_column[1];
   max_width += x_column[0];

ここでは、行数をループし、各行に固定のY高さ値を掛けて、各オブジェクトのアンカー座標を見つけます。また、各値を最大幅の値と比較し、X座標を取得します。

すべての値とその座標を取得したら、以前に宣言したカスタムLabelCreate()メソッドを使用して情報の描画を開始できます。このメソッドは、以下に示すように、表示する行数に応じて周期的に呼び出されます。

   color back_Color = clrWhiteSmoke;
   color font_Color = clrBlueViolet;

   for(int i=0; i<ArraySize(column_1); i++)
     {
      //--- draw 1
      string name_1 = column_1[i]+"_1_"+IntegerToString(tickeT);            
      LabelCreate(handlE,name_1,0,x_column[0],y_column[i],CORNER_LEFT_UPPER,column_1[i],"Arial",10,font_Color,0,ANCHOR_LEFT_UPPER,false);
      //--- draw 2
      string name_2 = column_1[i]+"_2_"+IntegerToString(tickeT);            
      LabelCreate(handlE,name_2,0,x_column[1],y_column[i],CORNER_LEFT_UPPER,column_2[i],"Arial",10,font_Color,0,ANCHOR_LEFT_UPPER,false);
     }

メソッドの最後では、以下に示すように、以前に宣言および説明したカスタムメソッドRectLabelCreate()を使用してこれらの値に背景を描画し、表示されるチャートを更新するだけです。

//--- draw the background
   RectLabelCreate(handlE,"RectLabel",0,1,height,max_width,max_height,back_Color);                   

   ChartRedraw(handlE);                                                 

これですべてのメソッドの説明は完了です。プロジェクトは組み立てて使用できる状態です。

その結果、スクリプトを使用した後のチャートファイルは図3のようになります。

図3:取引データを表示したスクリプト操作の結果

図3:取引データを表示したスクリプト操作の結果

ご覧のとおり、取引に関するすべての情報が1つのチャートに一般化された形式で表示されるため、ユーザーが実行する取引操作の分析と評価がより便利になります。スクリプトはそのようなファイルを適切なフォルダに配置するため、ユーザーはいつでも口座履歴内の取引操作に関する必要な情報を検索することができます。


結論

この記事では、チャート上の取引を自動的に視覚化するスクリプトを作成するプロセスを完了しました。このソリューションを活用することで、エントリポイントを選定する際に起こり得るエラーを修正し、取引精度を大幅に向上させるだけでなく、適切な銘柄や価格変動の予測地点を選ぶことで、戦略全体の数学的期待値を高めることができます。さらに、このスクリプトを使用することで、チャートファイルの準備にかかる時間を大幅に短縮でき、その時間を分析や新しい取引アイデアの発掘に充てることが可能です。重要な点として、市場は常に変化しているため、安定した運用を維持するには、市場の動向を絶えず監視し、必要に応じて適応することが不可欠です。このツールは、そのプロセスをサポートします。読者の成功を祈っています。コメント欄にフィードバックをお寄せください。


MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/14961

添付されたファイル |
DealsPrintScreen.mq5 (104.52 KB)
初心者からエキスパートへ:MQL5での共同デバッグ 初心者からエキスパートへ:MQL5での共同デバッグ
問題解決は、MQL5でのプログラミングのような複雑なスキルを習得するための簡潔なルーチンを確立することができます。このアプローチでは、問題解決に集中しながら、同時にスキルアップを図ることができます。問題に取り組めば取り組むほど、高度な専門知識が脳に伝達されます。個人的には、デバッグはプログラミングをマスターするための最も効果的な方法だと思っています。今日は、コードクリーニングのプロセスを紹介し、乱雑なプログラムをクリーンで機能的なものに変えるための最善のテクニックについて解説します。この記事を読んで、貴重な洞察を発見してください。
リプレイシステムの開発(第53回):物事は複雑になる(V) リプレイシステムの開発(第53回):物事は複雑になる(V)
今回は、あまり理解されていない重要なトピックを取り上げます。「カスタムイベント」です。これは危険です。これらの要素の長所と短所を解説します。このトピックは、MQL5やその他の言語でプロのプログラマーになりたい人にとって重要な鍵となります。ここではMQL5とMetaTrader 5に焦点を当てます。
ニューラルネットワークが簡単に(第93回):周波数領域と時間領域における適応予測(最終回) ニューラルネットワークが簡単に(第93回):周波数領域と時間領域における適応予測(最終回)
本稿では、時系列予測において2つのブロック(周波数と時間)の結果を適応的に組み合わせるATFNetモデルのアプローチの実装を継続します。
リプレイシステムの開発(第52回):物事は複雑になる(IV) リプレイシステムの開発(第52回):物事は複雑になる(IV)
この記事では、信頼性と安定性のある操作を確保するために、マウスポインタを変更してコントロール指標との対話を有効にします。