MQL5 および MQL4 の選択およびナビゲーション ユーティリティ: チャートへのデータの追加

24 6月 2019, 16:02
Roman Klymenko
0
302

イントロダクション

これまでの記事でさまざまなことを行ってきました。(MQL5 および MQL4 の選択およびナビゲーション ユーティリティ: パターンの自動検索を追加し、検出されたシンボルを表示する方法MQL5 および MQL4 の選択およびナビゲーション ユーティリティ: "ホームワーク" タブを追加し、グラフィカル オブジェクトを保存する方法開発中のMQL5 および MQL4 のシンボル選択およびナビゲーション・ユーティリティーなどです。 しかし、まだ高品質のデイトレードには十分ではありません. この記事では、適切な相場参入/決済ポイントを見つけるための新しい機能を追加します。

各機能の項目については、別のセクションで説明します。 まず、目標を決定します。 例えば:次に、プロジェクトに同じ機能を実装する場合に備えて、関数またはコードを分析します。


今日のトレンドが昨日のトレンドと異なるシンボルを非表示にする

Input: 今日のトレンド !=機能のトレンドなら隠す
Area:並べ替え設定

多くのデイトレーダーは、今日のトレンドが昨日と同じである株式をトレードすることを勧めています。 シンプルに言えば、株価が昨日上昇した場合、今日は上昇するはずです。

次の関数を使用すると、このようなシンボルを並べ替えることができます。

/*
今日のトレンドが昨日のトレンドと等しくない場合は true を返す
symname - 使用済みシンボル名
*/
bool check_no_trend(string symname){
   MqlRates rates2[];
   ArraySetAsSeries(rates2, true);
   if(CopyRates(symname, PERIOD_D1, 0, 2, rates2)==2){
      if( rates2[0].close>rates2[0].open && rates2[1].close>rates2[1].open ){
         return false;
      }
      if( rates2[0].close<rates2[0].open && rates2[1].close<rates2[1].open ){
         return false;
      }
   }
   return true;
}


セッション開始の表示

Input:1 日の開始を表示する
Area:チャートの設定

トレードセッションの開始は、株式相場が開く時間(株式について話している場合)、例えば、米国の株式相場なら午後4時30分、ヨーロッパとロシアなら午前10:00です。 FXの場合は、真夜中をトレードセッションの開始時間とみなしましょう。

M5のような小さい時間枠では、現在のセッションの開始を定義するのが難しい場合があります。 よってシンボルの現在のトレード日が始まっている足を見ることができるように設定を追加します。

セッション開始を表示する関数:

/*
チャートに 1 日の開始を表示
currChart - チャートID
day - 日番号 (0 - 現在)
*/
void showNdays(long currChart, int day){
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   if(CopyRates(ChartSymbol(currChart), PERIOD_D1, day, 1, rates)>0){
      ObjectCreate(currChart, exprefix+"_Nday", OBJ_VLINE, 0, rates[0].time, 0);
      ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_RAY,true); 
      ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_Nday",OBJPROP_BACK,true); 
   }
}

チャート上では、これは垂直の赤い線のように見えます。

セッション開始の表示

同様の関数はMetaTraderに既に存在します。 さらに、直近のセッションの始まりだけでなく、各セッションの一般的な開始も確認できます。 これを行うには、チャートのプロパティの"期間区切りシンボル"ボックスをオンにします。 実際には、特定の時間枠では、この関数は冗長であり、チャートが乱雑になり、分析において不快になります。 サンプルです。

期間区切りシンボルの表示


昨日と前日の安値と高値を表示

Input:昨日の安値と高値を表示し、一昨日の安値と高値を表示します
Area:チャートの設定

デイトレードの場合、昨日と一昨日の高値と安値は、多くの場合、サポートとレジスタンスレベルとして使用します。 価格はしばしば下落し、昨日または前日の高値とリバウンドに当たります。 個人的な経験によると、70%の確率で、価格はそのような高値/安値をブレイクしません。

したがって、これらのレベルは無視されるべきではありません。

次の関数は、選択した日の安値と高値を表示するために使用します。

/*
指定した日の安値と高値をチャートに表示する
currChart - チャートのID
day - 表示された日インデックス
*/
void showHOBeforeDay(long currChart, int day=1){
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   
   color curColor=clrAquamarine;
   switch(day){
      case 2:
         curColor=clrOlive;
         break;
   }
   
   if(CopyRates(ChartSymbol(currChart), PERIOD_D1, day, 1, rates)>0){
      ObjectCreate(currChart, exprefix+"_beforeday_high_line"+(string) day, OBJ_HLINE, 0, 0, rates[0].high);
      ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_COLOR,curColor); 
      ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_beforeday_high_line"+(string) day,OBJPROP_BACK,true); 
      
      ObjectCreate(currChart, exprefix+"_beforeday_low_line"+(string) day, OBJ_HLINE, 0, 0, rates[0].low);
      ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_COLOR,curColor); 
      ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_beforeday_low_line"+(string) day,OBJPROP_BACK,true); 
   }
}

前日の安値と高値は明るい水平線で表示され、一昨日はグリーン線として表示されます。

昨日/一昨日の安値と高値を表示


最も近いラウンド価格を表示する

Input:最も近いのラウンド価格を表示する(period < 1 day)
Area:チャートの設定

ラウンド価格は、別の形の自然なサポート/レジスタンスレベルです。 .00または.50で終わるような価格です。 多くのトレーダーは、ラウンドレベルの近くにトレードのオーダーを置きます。

.25 と .75. レベルはラウンドと見なされることもありますが、信頼性が低いため、チャートを乱雑にしないように深追いしません。

ラウンド価格を照会するには、次の関数を使用します。

/*
現在の価格に最も近い 3 つのラウンド レベルを表示します。
currChart - チャートID
*/
void showRoundPrice(long currChart){
   string name=ChartSymbol(currChart);
   int tmpPrice;
   
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   if(CopyRates(name, PERIOD_D1, 0, 1, rates)==1){
      switch((int) SymbolInfoInteger(name, SYMBOL_DIGITS)){
         case 0:
            break;
         case 2:
         case 3:
         case 5:
            tmpPrice=(int) rates[0].close;

            ObjectCreate(currChart, exprefix+"_round_line_00_0", OBJ_HLINE, 0, 0, (double) tmpPrice-1 );
            ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_0",OBJPROP_BACK,true); 

            ObjectCreate(currChart, exprefix+"_round_line_05_0", OBJ_HLINE, 0, 0, (double) tmpPrice-0.5 );
            ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_0",OBJPROP_BACK,true); 
            
            ObjectCreate(currChart, exprefix+"_round_line_00_1", OBJ_HLINE, 0, 0, (double) tmpPrice );
            ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_1",OBJPROP_BACK,true); 

            ObjectCreate(currChart, exprefix+"_round_line_05_1", OBJ_HLINE, 0, 0, (double) tmpPrice+0.5 );
            ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_1",OBJPROP_BACK,true); 

            ObjectCreate(currChart, exprefix+"_round_line_00_2", OBJ_HLINE, 0, 0, (double) tmpPrice+1 );
            ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_00_2",OBJPROP_BACK,true); 

            ObjectCreate(currChart, exprefix+"_round_line_05_2", OBJ_HLINE, 0, 0, (double) tmpPrice+1.5 );
            ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_COLOR,clrCadetBlue); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_STYLE, STYLE_DASH); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_SELECTABLE,false); 
            ObjectSetInteger(currChart,exprefix+"_round_line_05_2",OBJPROP_BACK,true); 
            
            break;
      }
   }
}

チャート上では、ラウンドレベルが破線の水平線で表示されます。

最も近いラウンド価格を表示する


時間足の終わりを表示

Input parameter:表示時間クローズ(period < 1hour)
Area:チャートの設定

自然なサポート/レジスタンスレベルの主題から続けて、また、終了時刻レベルを言及することができます。 時間足の終値は、実際のトレードではなかなか気づきにくいですが、より小さな時間枠ではサポート/レジスタンスレベルであることあります。 いずれにしても、少なくとも過去 4 時間で、このパラメータを表示する関数を実装してみましょう。

チャート上の時間終了を強調表示する関数:

/*
チャート上の直近の 4 時間を閉じる表示
currChart - チャートID
*/
void showCloseHour(long currChart){
   MqlDateTime tmpTime;
   int tmpOffset=0;
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   if(CopyRates(ChartSymbol(currChart), PERIOD_M30, 0, 9, rates)>0){
      tmpOffset=0;
      TimeToStruct(rates[tmpOffset].time, tmpTime);
      if(tmpTime.min!=0){
         tmpOffset++;
      }
      ObjectCreate(currChart, exprefix+"_hour_0", OBJ_VLINE, 0, rates[tmpOffset].time, 0);
      ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_RAY,true); 
      ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_COLOR,clrYellow); 
      ObjectSetInteger(currChart,exprefix+"_hour_0",OBJPROP_BACK,true); 

      tmpOffset++;
      TimeToStruct(rates[tmpOffset].time, tmpTime);
      if(tmpTime.min!=0){
         tmpOffset++;
      }
      ObjectCreate(currChart, exprefix+"_hour_1", OBJ_VLINE, 0, rates[tmpOffset].time, 0);
      ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_RAY,true); 
      ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_COLOR,clrYellow); 
      ObjectSetInteger(currChart,exprefix+"_hour_1",OBJPROP_BACK,true); 

      tmpOffset++;
      TimeToStruct(rates[tmpOffset].time, tmpTime);
      if(tmpTime.min!=0){
         tmpOffset++;
      }
      ObjectCreate(currChart, exprefix+"_hour_2", OBJ_VLINE, 0, rates[tmpOffset].time, 0);
      ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_RAY,true); 
      ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_COLOR,clrYellow); 
      ObjectSetInteger(currChart,exprefix+"_hour_2",OBJPROP_BACK,true); 

      tmpOffset++;
      TimeToStruct(rates[tmpOffset].time, tmpTime);
      if(tmpTime.min!=0){
         tmpOffset++;
      }
      ObjectCreate(currChart, exprefix+"_hour_3", OBJ_VLINE, 0, rates[tmpOffset].time, 0);
      ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_RAY,true); 
      ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_COLOR,clrYellow); 
      ObjectSetInteger(currChart,exprefix+"_hour_3",OBJPROP_BACK,true); 
      
   }
}

チャート上では、過去 4 時間の終わりは垂直黄色の線で表示されます。

時間足の終わりを表示


年間の最大価格と最小価格を表示する

Input:年間の最大/最小価格を表示
Area:チャートの設定

年間の最大価格と最安値もトレーダーの間で人気があります。 チャートにも表示します。

次の関数は、1 年の中にある極端な価格を表示するために使用します。

/*
チャートに昨年の最大価格と最安値を表示します。
currChart - チャートID。
*/
void showMaxPrice(long currChart){
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   if(CopyRates(ChartSymbol(currChart), PERIOD_MN1, 0, 12, rates)==12){
      double maxPrice=0;
      double minPrice=0;
      
      
      for(int j=0; j<12; j++){
         if( maxPrice==0 || maxPrice<rates[j].high ){
            maxPrice=rates[j].high;
         }
         if( minPrice==0 || minPrice>rates[j].low ){
            minPrice=rates[j].low;
         }
      }
      
      ObjectCreate(currChart, exprefix+"_maxprice_line", OBJ_HLINE, 0, 0, maxPrice);
      ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_COLOR,clrMagenta); 
      ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_maxprice_line",OBJPROP_BACK,true); 

      ObjectCreate(currChart, exprefix+"_minprice_line", OBJ_HLINE, 0, 0, minPrice);
      ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_COLOR,clrMagenta); 
      ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_SELECTABLE,false); 
      ObjectSetInteger(currChart,exprefix+"_minprice_line",OBJPROP_BACK,true); 
      
      
   }
}

過去 12 か月間の最大価格と最小価格は、紫色の水平線で表示されます。

年間の最大/最小価格を表示する


チャートを開くときにスプレッドを表示する

Input:チャートを開くときにスプレッドを表示する
Area:チャートの設定

小さなストップロスを使用する場合、現在のシンボルスプレッドは、トレードに参入するための決定的な要因の一つです。 したがって、チャートを開く時に知ることが重要です。 では、チャートにデータを追加してみましょう。

チャートが開かれた瞬間にのみスプレッドを表示します。 これは、瞬間的に変更される可能性があります。 スプレッドレベルはリアルタイムでは表示されません。 シンボルの現在のスプレッド範囲を評価するためにのみ使用します。

次の短い関数は、スプレッドを返します。

/*
指定したシンボルの現在のスプレッドを持つ文字列を返します。
symname - シンボル名
*/
string getmespread_symbol(string symname){
   double curSpread=SymbolInfoDouble(symname, SYMBOL_ASK)-SymbolInfoDouble(symname, SYMBOL_BID);
   return "Spread: "+(string) DoubleToString(curSpread, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+" ("+DoubleToString(curSpread/SymbolInfoDouble(symname, SYMBOL_POINT), 0)+" p)";
}

このスプレッドは、他の追加データの中で開いているチャートへのコメントで表示されます。

スプレッドを表示する

名前の付いているテンプレートをチャートに適用する

Input:名前の付いているテンプレートをチャートに適用
Area:チャートの設定

MetaTraderでは、テンプレートを使用することにより、前の設定、EA、およびいろいろ数値設定したパラメータのインジケータをすばやく適用することができます。

ただし、"すばやく" は少し緩い概念です。 チャートにテンプレートを適用するには、チャートのコンテキスト メニューで[テンプレート]/"テンプレート名"を選択します。 しかし、インジケータ(例えば移動平均)が意思決定を行う際に使用していて、しかも1日あたり数百のツールを操作している場合はどうでしょうか。 ひとつひとつそれぞれをクリックする必要があるでしょうか。

各チャートにセットしたインジケータのテンプレートを自動的に適用する方がはるかに簡単です。 では、この関数を実装してみましょう。

チャートにテンプレートを適用するには、MQL5 と MQL4 の両方で動作するChartApplyTemplateコマンドを使用します。

      ChartApplyTemplate(curChartID[ArraySize(curChartID)-1], allApplyTemplate+".tpl");


ゲルチクのATRを表示する

Input:ゲルチクのATRを表示する
Area:チャートの設定

ATR は、一定期間内の平均日次シンボルの移動であり、シンボルの移動範囲を決定する際に重要なパラメータです。 これはさまざまな目的に使用します。

例えば、デイトレードの際にエントリーする価値があるかどうかを判断するのに役立ちます。 100ポイントの値動きをつかみ取りたい場合、もしシンボルの1日の平均移動範囲が50ポイントだったら、利益を取れる可能性は小さく、エントリーしない方が賢明です。

また、シンボルが既に日のATRの80%以上を片方にオーバーしている場合、同じ方向にトレードを行うのは意味がなく、逆方向にのみエントリーするべきだと考えられています。

ゲルチクのATRは、異常な足だけが考慮されるという観点から、従来のATRとは異なります。 異常な足は、平均的な足よりも2倍大きいか0.3より小さいものです。

ATR は通常、5日間または 3 日間で計算されます。

次の関数は、Gerchik の ATR を表示します。

/*
指定したシンボルの Gerchik の ATR を含む文字列を返します。
symname - シンボル名
*/
string getmeatr_symbol(string symname){
   string msg="";
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   double atr=0;
   double pre_atr=0;
   int curDigits=(int) SymbolInfoInteger(symname, SYMBOL_DIGITS);
   string currencyS=SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT);
   int count=0;
   int copied=CopyRates(symname, PERIOD_D1, 0, 8, rates);
   if(copied>1){
      for(int j=1; j<copied; j++){
         pre_atr+=rates[j].high-rates[j].low;
      }
      pre_atr/=(copied-1);
   }
   if(pre_atr>0){
      for(int j=1; j<copied; j++){
         if( rates[j].high-rates[j].low > pre_atr*2 ) continue;
         if( rates[j].high-rates[j].low < pre_atr*0.3 ) continue;
               
         if( ++count > 5 ){
            break;
         }
               
         atr+=rates[j].high-rates[j].low;
      }
      if( count > 5 ){
         count=5;
      }
      atr= NormalizeDouble(atr/count, curDigits );
   }
   if(atr>0){
      StringAdd(msg, "ATR: "+(string) DoubleToString(atr, curDigits)+" "+currencyS+", today: "+DoubleToString(rates[0].high-rates[0].low, curDigits)+" "+currencyS+" ("+(string) (int) (((rates[0].high-rates[0].low)/atr)*100) +"%)");
   }
   
   return msg;
}

このユーティリティは、前のセクションで説明したスプレッドのように、ATR をチャートコメントに表示します。 ATR は前のスクリーンショットで見ることができます。


ガイドシンボルの方向の表示

Input:#Nの方向を表示する
Area:追加データの表示

すでにこの記事で述べたことから判断すると、デイトレードは、心に留めておくべきことがたくさんあるので、複雑な試みです。 結局のところ、これがすべてではありません。

多くのトレーダーは、エントリーする前に、いわゆるガイドシンボルの現在の方向を見ることをお勧めします。

たとえば、米国株式相場でトレードする場合は、次のステップに従う必要があります。

  • 米国の主要指数、少なくともダウ・ジョーンズまたはSP500です。;
  • 残りの国のインデックスは中国、ヨーロッパ、日本です。;
  • 様々な市場セグメントのリーディングカンパニー:銀行セクターのJPモルガン、テクノロジーのアップル、エネルギーのエクソンモービル、IBM、その他です。

また、石油、金、米ドルの相場を追跡することができます。

すべてのガイドシンボルが一方向に移動する場合に最適です。 お察しのように、片方のシンボルのみトレードすることが賢明です。

異なるブローカーは同じツールの異なる名前を持つ可能性があるため、監視するツールをプログラムで指定することは不可能です。 しかし、文字列型の受信パラメータを追加して、ユーザーがブローカーによって名前が付けられたシンボルのティッカーを設定できるようにすることができます。 このユーティリティには、7 つのパラメータがあります。

次の関数は、指定したシンボルの方向を返します。

/*
指定したシンボルで価格移動方向の文字列を返します。
symname - シンボル名
show - シンボル名ラベルを文字列に表示する場合
*/
string getmeinfo_symbol(string symname, bool show=true){
   MqlRates rates2[];
   ArraySetAsSeries(rates2, true);
   string msg="";

   if(CopyRates(symname, PERIOD_D1, 0, 1, rates2)>0){
      if(show){
         StringAdd(msg, (string) symname+": ");
      }
      StringAdd(msg, "D1 ");
      if( rates2[0].close > rates2[0].open ){
         StringAdd(msg, "+"+DoubleToString(((rates2[0].close-rates2[0].open)/rates2[0].close)*100, 2) +"% (+"+DoubleToString(rates2[0].close-rates2[0].open, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")");
      }else{
         if( rates2[0].close < rates2[0].open ){
            StringAdd(msg, "-"+DoubleToString(((rates2[0].open-rates2[0].close)/rates2[0].close)*100, 2) +"% (-"+DoubleToString(rates2[0].open-rates2[0].close, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")");
         }else{
            StringAdd(msg, "0%");
         }
      }
   }
   if(CopyRates(symname, PERIOD_H1, 0, 1, rates2)>0){
      StringAdd(msg, ", H1 ");
      if( rates2[0].close > rates2[0].open ){
         StringAdd(msg, "+"+DoubleToString(((rates2[0].close-rates2[0].open)/rates2[0].close)*100, 2)+"% (+"+DoubleToString(rates2[0].close-rates2[0].open, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")");
      }else{
         if( rates2[0].close < rates2[0].open ){
            StringAdd(msg, "-"+DoubleToString(((rates2[0].open-rates2[0].close)/rates2[0].close)*100, 2)+"% (-"+DoubleToString(rates2[0].open-rates2[0].close, (int) SymbolInfoInteger(symname, SYMBOL_DIGITS))+" "+SymbolInfoString(symname, SYMBOL_CURRENCY_PROFIT)+")");
         }else{
            StringAdd(msg, "0%");
         }
      }
   }
   
   return msg;
}

方向は、ユーティリティが起動されたチャートコメントに表示されます。 これは、次のようになります。

ガイドシンボルの方向の表示

誘導シンボルの移動方向は自動的には更新されませんのでご注意ください。 データを更新するには、他のタブに切り替えるか、Rキーを押します。 ただし、新しいインプットで簡略化することもできます。


ユーティリティ タブの自動更新

Input:開いているタブを設定した秒数ごとに更新する
Area:追加データの表示

現在開いているタブの内容を(R キーを押すだけでなく)自動的に更新する場合は、更新が行われた秒数を設定するだけです。 0を超える値は、指定した秒数が経過した後にタブを更新するようになります。 これは、タブが N 秒ごとに厳密に更新されることを意味するものではありません。 代わりに、タブが N に加えてさらに 1 ~ 2 秒で更新されることを意味します。

この関数を実装するコードはOnTimer関数内で、シンプルです。

   //指定した秒数後にタブの内容を更新する
   if( autoUpdateAfter>0 && TimeCurrent()-lastUpd >= autoUpdateAfter ){
      start_symbols();
      lastUpd=TimeCurrent();
   }

ユーティリティー操作の開始時に、OnInit関数の現在の時刻で直近のUpd変数値を初期化しました。

株式に関する財務データの表示

Input:会社情報の表示
Area:外部データ

株式を売買する前に会社のファンダメンタルズの指標に従う場合は、異なるウェブサイトを閲覧しないように、パラメータをMetaTraderウィンドウに直接表示する必要があります。

その関数を実装してみましょう。 これをするために、ユーティリティを使用してチャートが開かれるとすぐに、ターミナルのエキスパートタブにパラメータが表示されます。

もちろん、金融指標自体はどこからともなく引き出すことはできません。 最初は、直接EAに「ハードコーディング」したかったのですが、メモリエラーが原因で計画の妨げになりました。 したがって、すべての財務指標は、この記事に添付されているファインダーフォルダに個別に格納されます。 この関数を機能させるには、アーカイブをダウンロードして解凍し、 ファインダーフォルダをターミナルのファイルディレクトリに配置します。

Filesディレクトリを見つけるには、MetaTraderの[ファイル]メニューを開き、[データフォルダを開く]をクリックします。 新しく開いたエクスプローラ ウィンドウで、MQL4またはMQL5フォルダに移動します。

財務指標は、この記事を執筆した時点で、今後数ヶ月間分あります。 後でデータが必要な場合は、個人的にメッセージを書いてください。

しかし、データ出力関数に戻りましょう。 この関数は、会社のティッカー、つまり #プレフィックス、およびブローカーによって追加された .us および .eu サフィックスから冗長な要素を削除します。 ブローカーがティッカーに何か他のものを追加する場合は、ユーティリティコードに独自のフィルタを追加して、過剰な文字を削除します。

finderフォルダに必要なティッカーデータが見つからない場合、検索は会社名で実行されます。

void printTicker(string ticker, string name){
   bool isYes=false;
   int filehandle;
   
   //ティッカーからサフィックスとプレフィックスを削除する
   //小文字に変換する
   StringToLower(ticker);
   StringReplace(ticker, "#", "");
   StringReplace(ticker, ".us", "");
   StringReplace(ticker, ".eu", "");
   
   //会社名を小文字に変換する
   StringToLower(name);
   
   ResetLastError(); 
   //「ファインダー」フォルダに会社のデータがある場合、
   if( FileIsExist("finder\\"+ticker+".dat") ){
      isYes=true;
      filehandle=FileOpen("finder\\"+ticker+".dat",FILE_READ|FILE_TXT); 
      if(filehandle!=INVALID_HANDLE){ 
         int str_size; 
         string str; 
         Print("----------------");
         while(!FileIsEnding(filehandle)){ 
            str_size=FileReadInteger(filehandle,INT_VALUE); 
            str=FileReadString(filehandle,str_size); 
            Print(str);
         }
         FileClose(filehandle); 
      }
   }else if( FileIsExist("finder\\"+name+".dat") ){
      isYes=true;
      filehandle=FileOpen("finder\\"+name+".dat",FILE_READ|FILE_TXT); 
      if(filehandle!=INVALID_HANDLE){ 
         int str_size; 
         string str; 
         Print("----------------");
         while(!FileIsEnding(filehandle)){ 
            str_size=FileReadInteger(filehandle,INT_VALUE); 
            str=FileReadString(filehandle,str_size); 
            Print(str);
        }
         FileClose(filehandle); 
      }
   }
   
   //それ以外の場合は、データが見つからないことを出力します。
   if(!isYes){
      Print("No symbol data");
   }
}

その結果、ユーティリティを使用してチャートを開くと、[エキスパート] タブに会社情報が表示されます。 おおよそ次のようになります。

会社の財務情報


日の利益を表示する

Input:日の利益を表示する
Area:追加データの表示

最後に、1日に受け取った損益の額である日のトレード活動をストップするパラメータを追加し、収益性と損失を生み出すトレードの総数(チャートに表示) 上記のシーケンス)です。

以下に示すgetmetoday_profit()カスタム関数を使用して、MQL4 の現在の利益を取得します。 MQL5の場合、この関数は不十分です。

MQL5では、まずクローズポジションのデータを更新する必要があるかどうかを確認します。 これを行うには、グローバルに宣言されたneedHistory変数を使用します。 OnInit()標準関数では、この変数は 'true' の値を取得します。 したがって、 getmetoday_profit()関数の最初の起動時に、トレードに関するデータがヒストリーからアップロードされます。 その後、needHistory変数の値は 'false' です。

次に、標準の MQL5 OnTrade()関数を使用して、オープンポジションの 1 つがクローズされるたびにトレードヒストリーを再度アップロードします。

その結果、次のコードが得られます。

#ifdef __MQL5__ 
   void OnTrade(){
      if(orders_total==PositionsTotal()){
         return;
      }
      if(orders_total>PositionsTotal()){
         needHistory=true;
      }
      orders_total=(ushort) PositionsTotal();
   }
#endif 
/*
日の損益を含む文字列を返します。
*/
string getmetoday_profit(){
   string msg="";
   double curProfit=0;
   int tradeAll=0;
   int tradeMinus=0;
   int tradePlus=0;
   
   MqlDateTime curD;
   TimeCurrent(curD);
   curD.hour=0;
   curD.min=0;
   curD.sec=0;
   
   #ifdef __MQL5__ 
      if( needHistory ){
         HistorySelect(StructToTime(curD),TimeCurrent()); 
      }
      uint totalHistory=HistoryDealsTotal();
      double currHistory=0;
      ulong ticket_history;
      for(uint j=0;j<totalHistory;j++){
         if((ticket_history=HistoryDealGetTicket(j))>0 ){
            double profitHistory=HistoryDealGetDouble(ticket_history,DEAL_PROFIT);
            profitHistory+=HistoryDealGetDouble(ticket_history,DEAL_COMMISSION);
            profitHistory+=HistoryDealGetDouble(ticket_history,DEAL_SWAP);
            if(profitHistory!=0){
               currHistory+=profitHistory;
            }
         }
      }
         
   #else 
      int cntMyPos=OrdersHistoryTotal();
      if(cntMyPos>0){
         for(int ti=cntMyPos-1; ti>=0; ti--){
            if(OrderSelect(ti,SELECT_BY_POS,MODE_HISTORY)==false) continue;
            
            if( OrderCloseTime()<StructToTime(curD) ){ continue; }
            
            double tmpProfit=OrderProfit();
            tmpProfit+=OrderSwap();
            tmpProfit+=OrderCommission();
            
            tradeAll++;
            if(tmpProfit>0){
               tradePlus++;
            }else if(tmpProfit<0){
               tradeMinus++;
            }
            curProfit+=tmpProfit;
         }
      }
   #endif 
   
   if(tradeAll>0){
      StringAdd(msg, "Today: "+DoubleToString(curProfit, 2)+" "+AccountInfoString(ACCOUNT_CURRENCY)+" ("+(string) tradeAll+";+"+(string) tradePlus+";-"+(string) tradeMinus+")");
   }
   
   return msg;
}

この利益は、ユーティリティが起動されたチャートにも表示されます。 これは次のようになります。

日の利益を表示する

その日の利益は自動的に再計算されないことに注意してください。 現在の利益データを更新するには、別のタブを開くか、Rキーを押します。


結論

この記事は、おそらくこのシリーズの最後の記事です。 結果のユーティリティが役立つことを願っています。

しかし、機能性について何か欠けている場合は、そのことについて個人的にメッセージをください。 新しい記事を書くために十分な機能が欠落している場合に備えて、ユーティリティを改善し続けます。

最後に、この一連の記事で実装した機能を要約し、確認しましょう。

このユーティリティを起動すると、条件を満たすツールの一覧にアクセスできます。 リストの上には、All,LONG,SHORT,Rangeのタブのボタンだけでなく、自動ソートタブが表示されます。 All[すべて]タブはデフォルトで開きます。

起動されたユーティリティを使用したチャート

このチャートのコメントでは、更新で始まるラインを見ることができます。 このラインには、直近のタブコンテンツ更新の日時があります。 Rキーを押して、現在のタブを手動で更新します。 また、ユーティリティ設定で、現在開いているタブコンテンツの更新周期性 (秒単位) を指定できます。

ユーティリティの設定といえば... 設定を考慮すると、ユーティリティの関数を理解する方がはるかに楽になります。

All[すべて] タブに表示されるシンボルの一覧は、フィルタ設定グループによって異なります。

フィルタ設定グループ

ユーティリティによって表示されるシンボル ボタンをクリックすると、追加のデータを含む適切なシンボル チャートが開きます。

ユーティリティを使用して開かれたシンボル チャート

チャート上で最初に目に入るのはナビゲーションボタンです。 ユーティリティでソートされたシンボルから別のシンボルに移動できます。 また、ボタンを使用すると、"ホームワーク" タブ (LONG, SHORT, Range) シンボルを追加したり、そこからシンボルを削除したりできます。

また、チャートコメントには様々なシンボルデータがあります。 また、様々な水平線があります。

紫色の線は、年の高値/安値を示します。

赤いのはカスタムレベルを表します。 このユーティリティは、シンボル用に描画されたすべてのカスタムレベルを保存および復元できます。

既に述べたように、緑色の線は、おとといの始値/終値を表します。 スクリーンショットの最後のラインは、前日の始値/終値を意味します。

[チャート設定]グループは、シンボル チャートに表示する線とデータを定義します。

チャート設定グループ

時間枠とチャート表示スケールもカスタマイズ可能です。 これは、All[すべて]タブ、"ホームワーク" タブ、および一部の自動並べ替えタブに対して個別に行われます。

All[すべて]タブの時間枠は、追加データグループで設定されます。

その他のデータ グループ設定

D1は、All[すべて] タブのすべてのシンボルボタンにデフォルトで使用します。 M15に変更してみましょう:

M15の期間のシンボルチャート

これより、ラインは1日未満の期間にのみ表示されるので、ユーティリティが表示できるチャート上の複数のラインを確認できます。

赤い垂直線は、現在のセッションが開始する足を示し、シンボルが今日上昇または下降しているかどうかを視覚的に判断しやすくします。

破線の水平線は、小数点以下2桁のクオートの場合は .00 または .50 で終わり、小数点以下4桁と5桁のクオートの場合は 0.x1000/0.xx500 で終わるラウンドレベルを示します (ここでは同様)。

しかし、この設定に戻りましょう。 自動並べ替えタブには、独自の設定もあります。 グローバルグループは、追加タブグループに配置されます。 また、一部のタブの設定を持つ別々のグループがあります。

タブの自動並べ替え設定

設定の直近のグループは、新しいウィンドウ外部データでチャートを開きます。

新しいウィンドウと外部データ設定グループでチャートを開く

新しいウィンドウでチャートを開くの設定は、新しいウィンドウをクリックしたときに開いたチャートの期間とスケールに影響します。

ユーティリティの機能の詳細については、このシリーズの前の記事にあります。


MetaQuotes Software Corp.によりロシア語から翻訳された
元の記事: https://www.mql5.com/ru/articles/5614

添付されたファイル |
finder.zip (8456.89 KB)
_finder.ex5 (354.46 KB)
_finder.mq5 (258.68 KB)
_finder.ex4 (230.82 KB)
_finder.mq4 (258.68 KB)
HTMLとCSVレポートに基づいて多通貨トレードヒストリーを可視化する方法 HTMLとCSVレポートに基づいて多通貨トレードヒストリーを可視化する方法

このテーマのイントロダクションをしてから、MetaTrader5は多通貨テストオプションを提供するようになりました。 この可能性は、多くの場合、トレーダーにとって有用です。 しかし、この機能は完璧ではありません。 この記事では、HTML および CSV トレードヒストリーレポートに基づいてチャート上にグラフィカル オブジェクトを描画するためのプログラムを紹介します。 多通貨トレードは、動的切り替えコマンドを使用して、複数のサブウィンドウだけでなく、1つのウィンドウで並行して分析することができます。

f()10分でできるMQL5 のためのDLL (パート II): Visual Studio 2017で作成 f()10分でできるMQL5 のためのDLL (パート II): Visual Studio 2017で作成

元の基本となる記事との関連性は失われていませんが、このトピックに興味がある場合は、まず最初の記事を読んでください。 しかし、前回の記事から時間が経過しているので、現在の Visual Studio 2017 には、更新されたインターフェイスがあります。 また、MetaTrader5プラットフォームにも新しい機能が追加されました。 この記事では、DLLのプロジェクト開発、およびセットアップと MetaTrader5 ツールとのやり取りについて説明します。

ウェブからの債券利回りデータのスクレイピング ウェブからの債券利回りデータのスクレイピング

EAのパフォーマンスを向上させるために、金利データの収集を自動化します。

MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第3部)成行注文と取引のコレクション、検索と並び替え MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第3部)成行注文と取引のコレクション、検索と並び替え

最初の部分では、MetaTrader 5とMetaTrader 4プラットフォーム用のプログラムの開発を単純化するための大規模なクロスプラットフォームライブラリの作成を始めました。さらに、履歴の注文と取引の収集を実装しました。次のステップは、コレクションリスト内の注文、取引、ポジションの便利な選択と並び替えのためのクラスを作成することです。Engineという基本ライブラリオブジェクトを実装し、成行注文とポジションのコレクションをライブラリに追加します。