
テクニカル分析のツールとしてのMTF指標
概論
私たちのほとんどは、現在の市場の状況を分析するプロセスはチャートの上位期間の見直しから始まるという意見を持ちます。これは、取引をする予定に進むまで起こります。この分析は成功した取引とビジネスへの専門的なアプローチのための条件の一つです。通常これのために同じツールのセットを使用すれば、私達は複数のウィンドウを開けるかまたはグラフの期間を切り替えます。そして、一次分析のプロセスが完了します。
次に何をしたらよいでしょうか?古いTFで何が起こっているのかを知らないままにしておくか、それともウィンドウとピリオドの間を「ジャンプ」し続けるか?H1以上の時間枠で作業する場合は、慎重に評価する時間があります。そしてそれがM1-M15である場合となると?しかし、私たちはこの情報を必要としており、時にはそれが不可欠です。他のタブのどこか、次のキーを押した後ではありません。これは、「Wolfe Waves」や「Elder Three Screens」など、さまざまなTFの同時評価に基づくMTF戦略に特に当てはまります。
このように行動することを余儀なくされているトレーダーは強い精神的および視覚的な緊張状態にあります。小さいTFで取引をする場合、古い期間の有益なシグナルを簡単に逃してしまいます。これらすべての事態は、結果的に、早急な決定の採用、取引の早期終了、または市場の逆転の瞬間の喪失につながります。そのような過ちの結果はよく知られています。このような状況では、私達は私達の経験または情報をいかに早く得るかに頼ることしかできません。
しかし、この問題に対する解決策があります。それは与えられた1つのまたはいくつかの取引商品のために異なるTFから情報を受け取り、それをスクリーン上に包括的に表示し、それによって市場が迅速に評価されることを可能にするインジケーターです。基本的な情報に加えて、市場動向の実際の状態を表示し、取引活動を推薦します。
アルゴリズムの特徴
従来のものとの主な違いは、すべての時間間隔または取引商品からの一般情報の処理とそれに続く現在の情報への転送です。マルチフレームインディケータは任意のタイプ(オシレーター、トレンド、ボリュームなど)またはそれらの組み合わせになります。それらは、設定で指定された時間間隔を考慮に入れて、それらの基本的なアルゴリズムに従って計算され、情報を送信します。
MTFバージョンでは、データを使用する時間間隔またはシンボルのリストを指定するための追加のパラメーター(またはパラメーターのグループ)を除いて、従来のMTFバージョンと比較して特別な設定は必要ありません。結果は、メインチャートウィンドウまたは個別に出力することができ、また、ツールタイプに基づいてグループを組み合わせてシグナルとして表示することもできます。
マルチタイムフレーム指標の分類
これらの指標はすべての標準クラスで表示されますが、それらのほとんどは複雑なタイプ、つまり計算とグラフィック要素の組み合わせです。
1. 情報クラス:これらのインジケーターはデータや追加情報を表示します。典型的な例はMultiTimeFrameインジケーターです。これは、各期間のローソクの終了時間、選択した通貨ペアの見積もりと入札、ローソクの状態(UP、DOWN、DOJI)、および数量を表示します。インディケータスクリーンは役に立つ情報でいっぱいですが、それは取引で使うのが難しく、参考のみにとどまります。
図
1. 情報インジケーター
このグループには、取引決定を下すために使用できる独立したツールもあります。複数の標準インジケーターの分析結果を表示するため、これらインジケーターをチャートにインストール(自動的に計算を実行し)するため、取引の推奨事項を生成する必要がなくなります。
図2. 情報インジケータシグナル
図3.情報インジケータシグナル
2. グラフィックインジケータは、同じツールのグラフィックを異なる時間枠で表示します。これは、3つの異なる時間枠からの標準エンベロープMA(13)です。
図4.グラフィックインジケーター
もう1つのタイプのグラフィック構成は、計算期間が異なるチャートのグループです。このアプローチは純粋な数学に基づいています。つまり、M5の確率指標(5.3.3)には、M15から(15.3.9)、M30から(30.3.18)のパラメータがあります。
図5. 計算期間が異なるグラフィックインジケーター
上記のバージョンは、何らかの予約を入れてMTFクラスを参照することができます。この方法は常に可能というわけではありませんが、この解決方法の欠点が非常に深刻であり、使用するのは適切ではありません。この方法の適用とその利点と欠点について詳しく説明します。
別のグループは、いわゆるシグナルインジケーターで構成されています。作業領域内のグラフィック構造が多すぎになることを避けるために、インジケーターはトレンドの方向や他のパラメータを反映するシグナル線またはグラフィックブロックを形成します。標準のMTF_Coralインディケータと上記のMTFソリューションはこのようになります。
図6. シグナルインジケーター
別のグループを「ウィンドウ内のウィンドウ」と呼び、メインのチャートウィンドウに異なる時間枠または指標のチャートを表示することができます。
図7. 「ウィンドウ内ウィンドウ」インジケーター
図7.1. 「ウィンドウ内ウィンドウ」インジケーター
All_Woodies CCIソリューションのもう1つの例。
図7.1. 「ウィンドウ内ウィンドウ」タイプインジケータAll_Woodies CCI
別のグループには、MTFのボラティリティ指標が含まれています。これらはMTF Candlesを含みます。
図8. ボラティリティインジケーターMTF Candles
実施方法
MTFインジケーターの主な種類を検討しました。ここで、線形実装の主な方法を示す簡単な例を見てみましょう。また各ソリューションの具体的な機能についても分析します。
多期間インジケーターMAインディケータを考えて、次のタスクを解決してみましょう。計算期間を変えてインディケータバージョンを作成し、3つの異なる時間枠を表示します。主なパラメータと変数を設定しましょう。
//---- indicator settings #property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 3 #property indicator_type1 DRAW_LINE #property indicator_type2 DRAW_LINE #property indicator_type3 DRAW_LINE #property indicator_color1 Blue #property indicator_color2 Red #property indicator_color3 Lime #property indicator_width1 1 #property indicator_width2 1 #property indicator_width3 1 //---- input parameters input ENUM_TIMEFRAMES tf1 = 1; // Time Frame (1) input ENUM_TIMEFRAMES tf2 = 5; // Time Frame (2) input ENUM_TIMEFRAMES tf3 = 15; // Time Frame (3) input int maPeriod = 13; // MA period input int Shift = 0; // Shift input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // Moving average method input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied price //---- indicator buffers double ExtBuf1[]; double ExtBuf2[]; double ExtBuf3[]; //---- handles for moving averages int ExtHandle1; int ExtHandle2; int ExtHandle3; //--- bars minimum for calculation int ExtBarsMinimum; //--- int period1=0; int period2=0; int period3=0;
配列データを実装するときの条件は、それが関連付けられている時間枠が、変数で指定された時間枠以下であることです。
void OnInit() { int timeframe; //---- indicator buffers mapping SetIndexBuffer(0,ExtBuf1,INDICATOR_DATA); SetIndexBuffer(1,ExtBuf2,INDICATOR_DATA); SetIndexBuffer(2,ExtBuf3,INDICATOR_DATA); //--- timeframe =_Period; //--- if(tf1>=timeframe) { period1=maPeriod*(int)MathFloor(tf1/timeframe); PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,period1-1); //sets first bar from what index will be drawn PlotIndexSetInteger(0,PLOT_SHIFT,Shift); //line shifts when drawing PlotIndexSetString(0,PLOT_LABEL,"MA("+string(period1)+")"); //name for DataWindow ExtHandle1=iMA(NULL,0,period1,0,InpMAMethod,InpAppliedPrice); //get MA's handles } //---- if(tf2>=timeframe) { period2=maPeriod*(int)MathFloor(tf2/timeframe); PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,period2-1); //sets first bar from what index will be drawn PlotIndexSetInteger(1,PLOT_SHIFT,Shift); //line shifts when drawing PlotIndexSetString(1,PLOT_LABEL,"MA("+string(period2)+")"); //name for DataWindow ExtHandle2=iMA(NULL,0,period2,0,InpMAMethod,InpAppliedPrice); //get MA's handles } //---- if(tf3>=timeframe) { period3=maPeriod*(int)MathFloor(tf3/timeframe); PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,period3-1); //sets first bar from what index will be drawn PlotIndexSetInteger(2,PLOT_SHIFT,Shift); //line shifts when drawing PlotIndexSetString(2,PLOT_LABEL,"MA("+string(period3)+")"); //name for DataWindow ExtHandle3=iMA(NULL,0,period3,0,InpMAMethod,InpAppliedPrice); //get MA's handles } //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- bars minimum for calculation int per=MathMax(period3,MathMax(period1,period2)); ExtBarsMinimum=per+Shift; //--- initialization done }
メインサイクルは初期化と計算をチェックします。
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- check for rates total if(rates_total<ExtBarsMinimum) return(0); // not enough bars for calculation //--- not all data may be calculated int calculated=BarsCalculated(ExtHandle1); if(calculated<rates_total&&period1!=0) { Print("Not all data of ExtHandle1 is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } calculated=BarsCalculated(ExtHandle2); if(calculated<rates_total&&period2!=0) { Print("Not all data of ExtHandle2 is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } calculated=BarsCalculated(ExtHandle3); if(calculated<rates_total&&period3!=0) { Print("Not all data of ExtHandle3 is calculated (",calculated,"bars ). Error",GetLastError()); return(0); } //--- we can copy not all data int to_copy; if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total; else { to_copy=rates_total-prev_calculated; if(prev_calculated>0) to_copy++; } //---- get ma buffers if(IsStopped()) return(0); //Checking for stop flag if(period1!=0) if(CopyBuffer(ExtHandle1,0,0,to_copy,ExtBuf1)<=0) { Print("getting ExtHandle1 is failed! Error",GetLastError()); return(0); } if(IsStopped()) return(0); //Checking for stop flag if(period2!=0) if(CopyBuffer(ExtHandle2,0,0,to_copy,ExtBuf2)<=0) { Print("getting ExtHandle2 is failed! Error",GetLastError()); return(0); } if(IsStopped()) return(0); //Checking for stop flag if(period3!=0) if(CopyBuffer(ExtHandle3,0,0,to_copy,ExtBuf3)<=0) { Print("getting ExtHandle3 is failed! Error",GetLastError()); return(0); } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
結果を見てみましょう。
図9. MTFインディケータの実装
計算期間の増加を使用して、異なる指標で同じ指標を使用する例を検討しました。わずかな変更で、各行に個別の期間を設定する可能性を与えながら使用できます。この方法は非効率的に見えるかもしれません。期間を計算し、複数の指標を同時に適用することは非常に簡単です。ただし、場合によっては、この方法がすべての欠点にもかかわらず最適な方法です。そのうちの1つは、1つのウィンドウで2つ(3つ)の正規化されていないオシレーターを同時に観測する必要があることです。振幅範囲に起因して、これらのオシレーターは中心線に対してずれているため、この解釈は困難になります。この方法は上記の欠点を解消します。
マルチタイムフレームインジケーター
MQL5はよく知られているiClose()、iHigh()、iLow()、iOpen()、iTime()、iVolume()を使用しませんが、CopyTime()、CopyClose()、CopyHigh()、CopyLow()を提供します。 CopyOpen()、CopyTime()、CopyVolume()、およびiCustom、iMA、iCCI、iMACDなどの関数、およびその他の関数は、CopyBuffer()によって実装されています。およびその他の関数は、CopyBuffer()によって実装されています。 それぞれには長所と短所があり、私たちの例では、MQL5だけに触れます。私たちの測定基準では、M1からMN1までの完全なタイムラインリスト、すなわち26バージョンが必要です。さらに、複数の記号やツールを使用する必要がある場合、この数は何度も増えます。ほとんどの場合、履歴全体をコピーする必要はありません。ほとんどの情報指標では、バーの数は2本に制限されています。したがって、コードが長くなり過ぎないようにするには、これらのコマンドを別々の関数として記述し、それらを繰り返し呼び出すことをお勧めします。
時系列関数CopyClose()の場合、この関数は次のとおりです。
//+------------------------------------------------------------------+ double _iClose(string symbol,int tf,int index) { if(index < 0) return(-1); double buf[]; ENUM_TIMEFRAMES timeframe=TFMigrate(tf); if(CopyClose(symbol,timeframe, index, 1, buf)>0) return(buf[0]); else return(-1); } //+------------------------------------------------------------------+
WPRを呼び出す方法。
//+------------------------------------------------------------------+ double _iWPR(string symbol, int tf, int period, int shift) { ENUM_TIMEFRAMES timeframe=TFMigrate(tf); int handle=iWPR(symbol,timeframe,period); if(handle<0) { Print("iWPRオブジェクトが作成されていません:エラー",GetLastError()); return(-1); } else return(_CopyBuffer(handle,shift)); } //+------------------------------------------------------------------+ double _CopyBuffer(int handle,int shift) { double buf[]; if(CopyBuffer(handle,0,shift,1,buf)>0) return(buf[0]); return(EMPTY_VALUE); } //+------------------------------------------------------------------+
複数の行がある場合、CopyBuffer関数は次のように書くことができます。
//+------------------------------------------------------------------+ double _CopyBuffer(int handle,int index,int shift) { double buf[]; switch(index) { case 0: if(CopyBuffer(handle,0,shift,1,buf)>0) return(buf[0]); break; case 1: if(CopyBuffer(handle,1,shift,1,buf)>0) return(buf[0]); break; case 2: if(CopyBuffer(handle,2,shift,1,buf)>0) return(buf[0]); break; case 3: if(CopyBuffer(handle,3,shift,1,buf)>0) return(buf[0]); break; case 4: if(CopyBuffer(handle,4,shift,1,buf)>0) return(buf[0]); break; default: break; } return(EMPTY_VALUE); } //+------------------------------------------------------------------+
そして_iWPR関数はこの行を取ります
return(_CopyBuffer(handle,shift)
に変更します
return(_CopyBuffer(handle,0,shift)
どちらの場合もTFMigrate()は次のようになります。
//+------------------------------------------------------------------+ ENUM_TIMEFRAMES TFMigrate(int tf) { switch(tf) { case 0: return(PERIOD_CURRENT); case 1: return(PERIOD_M1); case 5: return(PERIOD_M5); case 15: return(PERIOD_M15); case 30: return(PERIOD_M30); case 60: return(PERIOD_H1); case 240: return(PERIOD_H4); case 1440: return(PERIOD_D1); case 10080: return(PERIOD_W1); case 43200: return(PERIOD_MN1); case 2: return(PERIOD_M2); case 3: return(PERIOD_M3); case 4: return(PERIOD_M4); case 6: return(PERIOD_M6); case 10: return(PERIOD_M10); case 12: return(PERIOD_M12); case 20: return(PERIOD_M20); case 16385: return(PERIOD_H1); case 16386: return(PERIOD_H2); case 16387: return(PERIOD_H3); case 16388: return(PERIOD_H4); case 16390: return(PERIOD_H6); case 16392: return(PERIOD_H8); case 16396: return(PERIOD_H12); case 16408: return(PERIOD_D1); case 32769: return(PERIOD_W1); case 49153: return(PERIOD_MN1); default: return(PERIOD_CURRENT); } } //+------------------------------------------------------------------+
すでに説明したように、この計算タイプには限られた数の要素(バー)が必要です。しかし時々それは全体の履歴を計算することが賢明です。ここでは注意が必要です。時間枠が短いほど、時間枠が大きいほど履歴列が多くなることを忘れないでください。このようなツールを作成するときには、この事実を考慮に入れる必要があります。最も簡単な方法は、最小小節数を決定し、その値を計算に使用することです。より困難な方法は、各時間枠について別々にこの値を決定することです。多くの場合(特に情報インジケーターの場合)、データは列が閉じているときにのみ必要であるため、各時分割で下位の時間枠で古いデータを再計算する必要はありません。これを開発時に提供すると、コードの複雑さが大幅に軽減されます。
情報指標(図1、図2、図3)の開発は、従来の指標の開発と変わらないので、すぐに私が考える最も興味深いカテゴリであるグラフィカル指標のカテゴリに入りましょう。情報指標は現在の市況と使用されているシンボルに関するデータのみを必要とし、グラフィック指標はグラフィックに対する追加要件を持っています。M5の期間は5つのM1列からなり、M15は3つのM5列からなります。すなわち、M5上に線が形成されると、3つの列の間にM15から始まる線が引かれます。行の位置は固定されておらず、М15のローソクが閉じるまで変更することができます。したがって、ローソクを形成する時間を組み合わせる必要があります。これを達成するためにMAの例を使用しましょう。
//---- indicator settings #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_type1 DRAW_LINE #property indicator_color1 Blue #property indicator_width1 1 //---- input parameters input ENUM_TIMEFRAMES tf = 5; // Time Frame input int maPeriod = 13; // MA period input int Shift = 0; // Shift input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // Moving average method input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied price input int Bars_Calculated = 500; //---- indicator buffers double ExtMA[]; //---- handles for moving averages int MA_Handle; //--- bars minimum for calculation int ExtBarsMinimum; ENUM_TIMEFRAMES _tf; int pf; //--- Moving Average値は、インデックス内に保持されます int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { _tf=tf; ENUM_TIMEFRAMES timeframe; int draw_shift=Shift;// PLOT_SHIFTの初期値 int draw_begin=maPeriod;// PLOT_DRAW_BEGINの初期値 //--- timeframe=_Period; if(_tf<=timeframe)_tf=timeframe;// 時間枠が以下である場合現在値に等しく、PERIOD_CURRENTを設定 pf=(int)MathFloor(_tf/timeframe);// PLOT_DRAW_BEGIN、PLOT_SHIFTおよび計算バーの数の係数を計算します draw_begin=maPeriod*pf;// PLOT_DRAW_BEGINを計算します draw_shift=Shift*pf;// PLOT_SHIFTを計算します //---- indicator buffers mapping SetIndexBuffer(0,ExtMA,INDICATOR_DATA); //--- PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,draw_begin-pf); //sets first bar from what index will be drawn PlotIndexSetInteger(0,PLOT_SHIFT,draw_shift); //line shifts when drawing PlotIndexSetString(0,PLOT_LABEL,"MA("+string(tf)+" "+string(maPeriod)+")");//name for DataWindow //--- MA_Handle=iMA(NULL,_tf,maPeriod,0,InpMAMethod,InpAppliedPrice); //get MA's handles if(MA_Handle==INVALID_HANDLE) { Print("getting MA Handle is failed! Error",GetLastError()); return(INIT_FAILED); } //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- bars minimum for calculation ExtBarsMinimum=draw_begin+draw_shift;// 計算に必要な最小バー数を計算する //--- initialization done return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- check for rates total if(rates_total<ExtBarsMinimum) return(0); // not enough bars for calculation int limit; //--- 時系列インデックスを配列要素に適用する ArraySetAsSeries(time,true); ArraySetAsSeries(ExtMA,true); //--- detect start position //--- 開始位置を検出 // --- およびバーの再計算サイクルのlimitの開始番号 if(prev_calculated>rates_total || prev_calculated<=0|| calculated!=bars_calculated)// 指標計算の最初の開始をチェックします { limit=rates_total-ExtBarsMinimum-1; // すべてのバーを計算するための開始番号 } else { limit=(rates_total-prev_calculated)+pf+1; // 新しいバーを計算するための開始番号 } if(Bars_Calculated!=0) limit=MathMin(Bars_Calculated,limit);
バーインデックス(iBarShift())で検索するのではなく、時間ごとに値を直接コピーします。
//--- main cycle for(int i=limit;i>=0 && !IsStopped();i--) { ExtMA[i]=_CopyBuffer(MA_Handle,time[i]); } //--- bars_calculated=calculated; ここで上記の関数を使用してください。 //+--------- CopyBuffer MA Handle ----------------------------------+ double _CopyBuffer(int handle,datetime start_time) { double buf[]; if(CopyBuffer(handle,0,start_time,1,buf)>0) return(buf[0]); return(EMPTY_VALUE); } //+-------------------- END -----------------------------------------+
私達の結果はこのようになります。
図10. MTF指標ライン
この方法はすべての種類の線形指標に使用できます。主な欠点は上のスクリーンショットからわかります。MAの場合、このような振る舞いは問題ではなく、サポートや抵抗レベルの明確な定義を可能にするので、役に立つこともあります。しかし、私たちがパターンを使うオシレータにとって、この振る舞いはそのようなパターンの認識とレンダリングを妨げることがあります。さらに、線の外観が認識を超えて変化するので、この解決策は、WPR、CCIおよび同様の指標には受け入れられません。
この問題を解決するには、重み係数を考慮して最後のバーを計算する必要があります。両方のソリューションを使用できるようにする「Interpolate」グローバル変数を追加しましょう。
input bool Interpolate = true; //--- main cycle for(int i=limit;i>=0 && !IsStopped();i--) { int n; datetime t=time[i]; ExtMA[i]=_CopyBuffer(MA_Handle,t); if(!Interpolate) continue; //--- datetime times= _iTime(t); for(n = 1; i+n<rates_total && time[i+n]>= times; n++) continue; double factor=1.0/n; for(int k=1; k<n; k++) ExtMA[i+k]=k*factor*ExtMA[i+n]+(1.0-k*factor)*ExtMA[i]; } //---
このバリエーションでは、現在のチャートに、_iTime関数を追加する必要があります。この関数は、開始時間に基づいてバー番号を決定します。
//+------------------------------------------------------------------+ datetime _iTime(datetime start_time) { if(start_time < 0) return(-1); datetime Arr[]; if(CopyTime(NULL,_tf, start_time, 1, Arr)>0) return(Arr[0]); else return(-1); } //+------------------------------------------------------------------+
これは今では普通の行のように見えます。
図11. MTFインジケーターライン_iTime
このような複雑で、リソースを集約したようなシステムの開発は不適切に見えるかもしれませんが、それらには長所があり、さらには不可欠になることさえあります。従来の平均化(MA、アリゲーターなど)が使用されている場合、計算期間の増加はMTFバージョンと比較していくらかの遅延を引き起こすかもしれません。これは、期待値が小さい期間に特に顕著です。
図12. MTF指標MAにおける遅延
図13. MTFインディケータ確率の遅れ
MAやアリゲーターのような単純な指標では、これはそれほど重要ではないかもしれません。しかし、MACD、AOなど、複数のMAから構成される複雑なシステムの場合、これは非常に重要になります。さらに、AOまたはACの平均期間を変更することはできません。滑らかでない線(WPR、CCIなど)を持つインジケーターの場合、計算期間が少し長くなっても非常にノイズが多いため、満足のいく結果が得られません。
図14 WRP MTFインディケーター
図15 CCI MTFインディケーター
図14〜図15は、この関数がアルゴリズムに提供されていないとき、それらが平滑化のために首尾よく使用できることを明確に示しています。
その直接の機能に加えて、このタイプはまたMetaTrader 5ストラテジーテスターの視覚テストパターンの欠如を補うことができます。取引のMTF EA取引を作成するとき、またはこの戦略の有効性を分析するとき、画面上の異なる時間枠でインディケータの位置を同時に観察することはできません。テスト後、使用されたサイクル数に応じて、一連のタブが表示されます。Anatoli Kazharskiの記事『MQL5 Cookbook:フレームワークに基づく「エルダーのトリプルフィルター」戦略』の例を見てみましょう。この戦略の考え方は、最初の期間が、毎週、毎日、または4時間など、最大の期間であるということです。主な傾向を特定するために使用されます。第2期間と第1期間の間には、1つまたは2つのレベルの違いがあります。これは修正を判断するために使用されます。3番目の期間は別のレベルであり、これは最良のエントリポイントを決定するために使用されます。
最初のフィルタでは、通常はM30-W1を使用してMACD(12、26、1)とEMAを13の周期で実行します。2番目のフィルタМ5-D1では、Stochastic Oscillator(5、3、3)が実行され、3番目のフィルタは、M1からH4まで使用され、主なトレンド方向のストップロス次数を設定します。
図16. エルダーのトリプルスクリーン
記事の著者はこの方法を使用することを主張しませんでしたが、テスト中およびテスト後に「トリプルフィルタ」の概念を保持しました。
図17. エルダーのトリプルスクリーンの戦略テスト
このオプションでは、エキスパートアドバイザの動作(戦略)を正しく分析する方法がありません。
私たちのツールを使って、より古典的な戦略版に近い私達のエキスパートアドバイザーのバージョンを作りましょう。上記のシグナルに基づいたエキスパートアドバイザーの作成は、従来のエキスパートアドバイザーと非常によく似ています。これがメインコードです。
#define EXPERT_MAGIC 1234502 //--- #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\AccountInfo.mqh> #include <Trade\OrderInfo.mqh> //+------------------------------------------------------------------+ enum compTF { A, //m1-m5-m15 B, //m5-m15-h1 C, //m15-h1-h4 E //h1-h4-d1 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ input string s0="//--- input parameters Lots+Trailing ---//"; input double InpLots =0.1; // Lots input int InpTakeProfit =150; // Take Profit (in pips) input int InpStopLoss =60; // StopLoss (in pips) input int InpLevel_S =20; // Level Signal input compTF InpTFreg =2; input string s1="//--- input parameters MA ---//"; input int Signal_MA_PeriodMA =21; // Period of averaging input string s2="//--- input parameters MACD ---//"; input int Signal_MACD_PeriodFast =12; // Period of fast EMA input int Signal_MACD_PeriodSlow =26; // Period of slow EMA input string s3="//--- input parameters Stochastic ---//"; input int Signal_Stoch_PeriodK =5; // K-period input int Signal_Stoch_PeriodD =3; // D-period input string s4="//--- input parameters Trailing ---//"; //--- inputs for trailing input int InpTrailingStop =25; // Trailing Stop Level (in pips) input int InpOffset =5; // Distance from the price (in pips) //--- int ExtTimeOut=10; // 取引操作間の秒数 int barsCalculated=3; datetime t=0; datetime time[]; //+------------------------------------------------------------------+ //| AC Sample expert class | //+------------------------------------------------------------------+ class CSampleExpert { protected: double m_adjusted_point; // 3または5文字の値 CTrade m_trade; // 取引オブジェクト CSymbolInfo m_symbol; // シンボル情報 CPositionInfo m_position; // 取引ポジション CAccountInfo m_account; // アカウント情報 COrderInfo m_order; // オーダー情報 //--- indicators ENUM_TIMEFRAMES mas_tf[3]; // timeframesの配列 int handle_MACD; // MACD indicator handle int handle_MA; // MA indicator handle int handle_Stochastic; // Stochastic indicator handle //--- indicator buffers double macd_buff[]; // MACD indicator main buffer double ma_buff[]; // MA indicator main buffer double stoch_buff[]; // Stochastic indicator main buffer //--- double close[]; double open[]; double low[]; double high[]; //--- 処理の為のインジケーターデータ double macd_ind_0; double macd_ind_1; double ma_ind; double stoch_ind_0; double stoch_ind_1; int level_stoch; //--- 処理の為のtrailing stopデータ double m_traling_stop; double m_take_profit; double m_stop_losse; public: CSampleExpert(void); ~CSampleExpert(void); bool Init(void); void Deinit(void); bool Processing(void); protected: bool InitCheckParameters(const int digits_adjust); bool Copy(void); // bool InitIndicators(void); bool LongModified(void); bool ShortModified(void); bool LongOpened(void); // Long条件を確認します bool ShortOpened(void); // Short条件を確認します bool OpenSellStop(void); // SELLSTOPオーダーを設定します bool OpenBuyStop(void); // BUYSTOPオーダーを設定します bool OrderModifySellStop(void); // SELLSTOPオーダーを設定します bool OrderModifyBuyStop(void); // BUYSTOPオーダーを設定します bool DellSellStop(void); // SELLSTOPオーダーを削除します bool DellBuyStop(void); // BUYSTOPオーダーを削除します }; //--- global expert CSampleExpert ExtExpert; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSampleExpert::CSampleExpert(void) : m_adjusted_point(0), handle_MACD(INVALID_HANDLE), handle_Stochastic(INVALID_HANDLE), handle_MA(INVALID_HANDLE), macd_ind_0(0), macd_ind_1(0), stoch_ind_0(0), stoch_ind_1(0), ma_ind(0), m_traling_stop(0), m_take_profit(0) { ArraySetAsSeries(macd_buff,true); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSampleExpert::~CSampleExpert(void) { } //+------------------------------------------------------------------+ //| 入力パラメータの初期化と検証 | //+------------------------------------------------------------------+ bool CSampleExpert::Init(void) { //--- 一般情報を初期化します m_symbol.Name(Symbol()); // symbol m_trade.SetExpertMagicNumber(EXPERT_MAGIC); // magic m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(Symbol()); //--- tuning for 3 or 5 digits int digits_adjust=1; if(m_symbol.Digits()==3 || m_symbol.Digits()==5) digits_adjust=10; m_adjusted_point=m_symbol.Point()*digits_adjust; //--- 取引のデフォルト偏差を設定します m_traling_stop =InpTrailingStop*m_adjusted_point; m_take_profit =InpTakeProfit*m_adjusted_point; m_stop_losse =InpStopLoss*m_adjusted_point; //--- set default deviation for trading in adjusted points m_trade.SetDeviationInPoints(3*digits_adjust); //--- int x=InpTFreg; switch(x) { case 0: {mas_tf[0]=PERIOD_M1;mas_tf[1]=PERIOD_M5;mas_tf[2]=PERIOD_M15;} break; case 1: {mas_tf[0]=PERIOD_M5;mas_tf[1]=PERIOD_M15;mas_tf[2]=PERIOD_H1;} break; case 2: {mas_tf[0]=PERIOD_M15;mas_tf[1]=PERIOD_H1;mas_tf[2]=PERIOD_H4;} break; case 3: {mas_tf[0]=PERIOD_H1;mas_tf[1]=PERIOD_H4;mas_tf[2]=PERIOD_D1;} break; } //--- if(!InitCheckParameters(digits_adjust)) return(false); if(!InitIndicators()) return(false); //--- 結果 return(true); } //+------------------------------------------------------------------+ //| 入力パラメータの確認 | //+------------------------------------------------------------------+ bool CSampleExpert::InitCheckParameters(const int digits_adjust) { //--- 初期データの確認をします if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel()) { printf("Take Profitは%dよりも大きい必要があります",m_symbol.StopsLevel()); return(false); } if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel()) { printf("Trailing Stopは%dよりも大きい必要があります",m_symbol.StopsLevel()); return(false); } //--- 正しいロット数を確認します if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax()) { printf("Lotsは%fから%fまでの範囲にある必要があります",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10) { printf("金額が%fロットのステップと一致していません",m_symbol.LotsStep()); return(false); } //--- warning if(InpTakeProfit<=InpTrailingStop) printf("Warning: Trailing StopはTake Profitよりも小さい必要があります"); //--- 結果 return(true); } //+------------------------------------------------------------------+ //| インジケーターの初期化 | //+------------------------------------------------------------------+ bool CSampleExpert::InitIndicators(void) { //--- MACDインジケーターを作成します if(handle_MACD==INVALID_HANDLE) { //--- handle_MACD=iCustom(NULL,0,"MTF\\Oscillators\\MTF_MACD",mas_tf[2],Signal_MACD_PeriodFast,Signal_MACD_PeriodSlow); //--- if(handle_MACD==INVALID_HANDLE) { printf("MACDインジケーター作成中にエラーが発生しました"); return(false); } } //--- MAインジケーターの作成をします if(handle_MA==INVALID_HANDLE) { //--- handle_MA=iCustom(NULL,0,"MTF\\Trend\\MA_MultiTF",mas_tf[2],Signal_MA_PeriodMA,0,MODE_EMA,PRICE_CLOSE); //--- if(handle_MA==INVALID_HANDLE) { printf("MAインジケーターの作成時にエラーが発生しました"); return(false); } } //--- Stochasticインジケーターを作成します if(handle_Stochastic==INVALID_HANDLE) { //--- handle_Stochastic=iCustom(NULL,0,"MTF\\Oscillators\\MTF_Stochastic",mas_tf[1],Signal_Stoch_PeriodK,Signal_Stoch_PeriodD); //--- if(handle_Stochastic==INVALID_HANDLE) { printf("Stochasticインジケーターの作成中にエラーが発生しました"); return(false); } } //--- 結果 return(true); } //+------------------------------------------------------------------+ //| ロングポジションを変更します | //+------------------------------------------------------------------+ bool CSampleExpert::LongModified(void) { bool res=false; //--- トレーリングストップを確認します if(InpTrailingStop>0) { if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop) { double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()<sl || m_position.StopLoss()==0.0) { //--- ポジションを変更します if(m_trade.PositionModify(Symbol(),sl,tp)) printf("Long position by %s to be modified",Symbol()); else { printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Modify parameters : SL=%f,TP=%f",sl,tp); } //--- 変更があったため、エキスパートアドバイザを終了する必要があります res=true; } } } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| ショートポジションを変更します | //+------------------------------------------------------------------+ bool CSampleExpert::ShortModified(void) { bool res=false; //--- トレーリングストップを確認します if(InpTrailingStop>0) { if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop)) { double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0) { //--- ポジションを変更します if(m_trade.PositionModify(Symbol(),sl,tp)) printf("Short position by %s to be modified",Symbol()); else { printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Modify parameters : SL=%f,TP=%f",sl,tp); } //--- 変更があったため、エキスパートアドバイザを終了する必要があります res=true; } } } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| ロングポジションを開く条件を確認してください | //+------------------------------------------------------------------+ bool CSampleExpert::LongOpened(void) { bool res=false; level_stoch=InpLevel_S; //--- ロングポジション(BUY)の可能性を確認します if(stoch_ind_1<level_stoch && stoch_ind_0>level_stoch && macd_ind_1>macd_ind_0 && ma_ind<close[1] && ma_ind<open[1])//&& ma_ind<close[1] && ma_ind<open[1] { //--- エキスパートアドバイザを終了 res=true; } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| Buy Stopポジション開きます | //+------------------------------------------------------------------+ bool CSampleExpert::OpenBuyStop(void) { bool res=false; double tp=0,sl=0; //--- if(LongOpened()) { res=true; //-- リクエストの宣言と初期化及び結果 MqlTradeRequest request={0}; MqlTradeResult result={0}; //--- 未決済オーダーの設定パラメータ request.action =TRADE_ACTION_PENDING; // 取引操作タイプ request.symbol =Symbol(); // シンボル request.deviation=5; // 価格からの許容偏差 request.volume =InpLots; // ロットあたりの量 request.magic =EXPERT_MAGIC; // MagicNumberのオーダー double offset=InpOffset; // 現在の価格からポイントを2倍して注文する double price; // 注文トリガーの価格 double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT); // ポイントサイズ int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // 小数桁数(桁数) //--- 取引タイプ request.type=ORDER_TYPE_BUY_STOP; // オーダータイプ price=high[1]+offset*m_adjusted_point; // 開始価格 request.price=NormalizeDouble(price,digits); // 正規化された開始価格 tp=price+m_take_profit; sl=price-m_stop_losse; request.sl =NormalizeDouble(sl,_Digits); // 新しいストップロス値を構造体 request.tp =NormalizeDouble(tp,_Digits); // 新しいTake Profit値を構造体に追加する //--- リクエストの送信 if(!OrderSend(request,result)) {res=false;printf("OrderSend error %d",GetLastError());} // リクエストを送信できなかった場合、エラーコードを出力する //--- 操作情報 printf("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); //--- エキスパートアドバイザを終了 } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| ショートポジションの開始条件を確認します | //+------------------------------------------------------------------+ bool CSampleExpert::ShortOpened(void) { bool res=false; level_stoch=100-InpLevel_S; //--- ショートポジション(SELL)の可能性をチェックする if(stoch_ind_1>level_stoch && stoch_ind_0<level_stoch && macd_ind_1<macd_ind_0 && ma_ind>close[1] && ma_ind>open[1]) { //--- エキスパートアドバイザを終了 res=true; } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| Sell Stopポジションを開く | //+------------------------------------------------------------------+ bool CSampleExpert::OpenSellStop(void) { bool res=false; double tp=0,sl=0; //--- if(ShortOpened()) { res=true; //-- リクエストの宣言と初期化及び結果 MqlTradeRequest request={0}; MqlTradeResult result={0}; //--- 未決済オーダーの設定パラメータ request.action =TRADE_ACTION_PENDING; // 取引操作タイプ request.symbol =Symbol(); // シンボル request.deviation=5; // 価格からの許容偏差 request.volume=InpLots; // ロットあたりの量 request.magic=EXPERT_MAGIC; // MagicNumberのオーダー int offset=InpOffset; // 現在の価格からポイントを2倍して注文する double price; // 注文トリガーの価格 int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // 小数桁数(桁数) request.type=ORDER_TYPE_SELL_STOP; // オーダータイプ price=low[1]-offset*m_adjusted_point; // 開始価格 request.price=NormalizeDouble(price,digits); // 正規化された開始価格 tp=price-m_take_profit; sl=price+m_stop_losse; request.sl =NormalizeDouble(sl,_Digits); // 新しいストップロス値を構造体 request.tp =NormalizeDouble(tp,_Digits); // 新しいTake Profit値を構造体に追加する //--- リクエストの送信 if(!OrderSend(request,result)) {res=false;printf("OrderSend error %d",GetLastError());} // リクエストを送信できなかった場合、エラーコードを出力する //--- 操作情報 printf("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); //--- エキスパートアドバイザを終了 } //--- 結果 return(res); } //+------------------------------------------------------------------+ //| メインの関数はもしポジションがある場合はtrueを返します | //| 処理します | //+------------------------------------------------------------------+ bool CSampleExpert::Processing(void) { // MqlDateTime dt; //--- 更新速度 if(!m_symbol.RefreshRates()) return(false); //--- 更新インジケーター if(BarsCalculated(handle_Stochastic)<barsCalculated) return(false); if(CopyBuffer(handle_Stochastic,0,0,barsCalculated,stoch_buff)!=barsCalculated) return(false); //--- if(BarsCalculated(handle_MACD)<barsCalculated) return(false); if(CopyBuffer(handle_MACD,0,0,barsCalculated,macd_buff)!=barsCalculated) return(false); //--- if(BarsCalculated(handle_MA)<barsCalculated) return(false); if(CopyBuffer(handle_MA,0,0,barsCalculated,ma_buff)!=barsCalculated) return(false); //--- if(!Copy())return(false); //--- コーディングとアクセスのスピードアップのために //--- データは内部変数内に配置されます macd_ind_0 = macd_buff[1]; macd_ind_1 = macd_buff[0]; ma_ind = ma_buff[1]; stoch_ind_0 = stoch_buff[1]; stoch_ind_1 = stoch_buff[0]; //--- 正しく終了することが大切です ... //--- 始めにポジションがあるか確認し、それを選択してください bool bord=false,sord=false; ulong ticket; //+---------オープンポジションがあり、トレーリングストップが有効になっている-----------+ if(m_position.Select(Symbol()) && PositionsTotal()>0 && m_traling_stop!=0) { if(m_position.PositionType()==POSITION_TYPE_BUY) { bord=true; //--- ロングポジションを変更する if(LongModified()) return(true); } else { sord=true; //---ショートポジションを変更する if(ShortModified()) return(true); } } //+----- STOPオーダーを使用した取引------------------------------------+ // このサイクルでは、確立された全ての未決済注文を繰り返します for(int i=0;i<OrdersTotal();i++) { // 各注文を選択してチケットを取得します ticket=OrderGetTicket(i); // Buy Stopオーダーを受け付けます if(m_order.OrderType()==ORDER_TYPE_BUY_STOP) { // Buy Stop注文があることを示すフラグを設定 bord=true; //--- 正しく市場に参入、必要に応じて順序を移動させることが重要です if(bord)OrderModifyBuyStop(); // BUYSTOPオーダーを変更します } // Sell Stop注文を処理します if(m_order.OrderType()==ORDER_TYPE_SELL_STOP) { // Sell Stop注文があることを示すフラグを設定 sord=true; //--- 正しく市場に参入、必要に応じて順序を移動させることが重要です if(sord)OrderModifySellStop(); // SELLSTOPオーダーを変更します } } //--- 注文がない場合 ------------------------------------+ if(!sord)if(OpenSellStop()){sord=true;return(true);} if(!bord)if(OpenBuyStop()){bord=true;return(true);} //--- ポジションを処理せずに終了します return(false); } //+------------------------------------------------------------------+ //| 先に設置されたSell Stop注文のパラメータを変更する | //+------------------------------------------------------------------+ bool CSampleExpert::OrderModifySellStop(void) { bool res=true; ulong ticket; double tp=0,sl=0; double offset=InpOffset; // 現在の価格からポイントを2倍して注文する double price; // 注文トリガーの価格 int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // 小数桁数(桁数) // リクエストの宣言と初期化及び結果 MqlTradeRequest request={0}; MqlTradeResult result={0}; int total=OrdersTotal(); // 設定された未決済注文の数 //--- 設定された全ての未決済注文の数 for(int i=total-1; i>=0; i--) { // 各注文を選択してチケットを取得します ticket=OrderGetTicket(i); // Sell Stop注文を処理します if(m_order.OrderType()==ORDER_TYPE_SELL_STOP) { ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumberオーダー //--- もしMagicNumberが一致した場合 if(magic==EXPERT_MAGIC) { price=low[1]-offset*m_adjusted_point; // 開始価格 if(price>m_order.PriceOpen()) // 条件を確認 if(low[1]>low[2]) // 条件を確認 { request.action=TRADE_ACTION_MODIFY; // 取引操作タイプ request.order = OrderGetTicket(i); // オーダーチケット request.symbol =Symbol(); // シンボル request.deviation=InpOffset; // 価格からの許容偏差 price=low[1]-offset*m_adjusted_point; // 開始価格 request.price=NormalizeDouble(price,digits); // 正規化された開始価格 tp=price-m_take_profit; sl=price+m_stop_losse; request.sl =NormalizeDouble(sl,_Digits); // 新しいストップロス値を構造体 request.tp =NormalizeDouble(tp,_Digits); // 新しいTake Profit値を構造体に追加する //--- リクエストの送信 if(!OrderSend(request,result)) { // Sell Stop注文があることを示すフラグを設定 res=true; printf("OrderSend error %d",GetLastError()); } // リクエストを送信できなかった場合、エラーコードを出力する //--- 操作情報 printf("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); } } } } return(res); } //+------------------------------------------------------------------+ //|先に設置されたSell Stop注文のパラメータを変更する | //+------------------------------------------------------------------+ bool CSampleExpert::OrderModifyBuyStop(void) { bool res=true; ulong ticket; double tp=0,sl=0; double offset=InpOffset; // 現在の価格からポイントを2倍して注文する double price; // 注文トリガーの価格 int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); // 小数桁数(桁数) //-- リクエストの宣言と初期化及び結果 MqlTradeRequest request={0}; MqlTradeResult result={0}; int total=OrdersTotal(); // 設定された未決済注文の数 //--- 設定された全ての未決済注文の数 for(int i=total-1; i>=0; i--) { // 各注文を選択してチケットを取得します ticket=OrderGetTicket(i); // Buy Stopオーダーを受け付けます if(m_order.OrderType()==ORDER_TYPE_BUY_STOP) { ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumberオーダー //--- もしMagicNumberが一致した場合 if(magic==EXPERT_MAGIC) { price=high[1]+offset*m_adjusted_point; // 開始価格 if(price<m_order.PriceOpen()) // 条件を確認 { request.action=TRADE_ACTION_MODIFY; // 取引操作タイプ request.symbol =Symbol(); // シンボル request.action=TRADE_ACTION_MODIFY; // 取引操作タイプ request.order = OrderGetTicket(i); // オーダーチケット request.symbol =Symbol(); // シンボル request.deviation=InpOffset; // 価格からの許容偏差 //--- テイクプロフィットとストップロスオーダー価格の設定 request.price=NormalizeDouble(price,digits); // 正規化された開始価格 tp=price+m_take_profit; sl=price-m_stop_losse; request.sl =NormalizeDouble(sl,_Digits); // 新しいストップロス値を構造体 request.tp =NormalizeDouble(tp,_Digits); // 新しいTake Profit値を構造体に追加する //--- リクエストの送信 if(!OrderSend(request,result)) { // Sell Stop注文が削除されていないことを示すフラグを設定 res=true; printf("OrderSend error %d",GetLastError()); } // リクエストを送信できなかった場合、エラーコードを出力する //--- 操作情報 printf("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); } } } } return(res); } //+------------------------------------------------------------------+ //| エキスパートアドバイザの初期化機能 | //+------------------------------------------------------------------+ int OnInit(void) { //--- 必要なすべてのオブジェクトを作成します if(!ExtExpert.Init()) return(INIT_FAILED); //--- ok return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| ティック処理関数 | //+------------------------------------------------------------------+ void OnTick(void) { static datetime limit_time=0; // 最終取引処理時間+タイムアウト //--- タイムアウトの場合処理を行わない if(TimeCurrent()>=limit_time) { //--- データをチェックする if(Bars(Symbol(),Period())>barsCalculated) { //--- タイムアウトの制限時間を秒単位で変更する if(ExtExpert.Processing()) limit_time=TimeCurrent()+ExtTimeOut; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CSampleExpert::Copy(void) { //--- コピーする数 int copied=3; //--- ArrayResize(high,copied); ArrayResize(low,copied); ArrayResize(close,copied); ArrayResize(open,copied); //+------ 配列インデックスの方向を設定します ---------------------+ ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(close,true); ArraySetAsSeries(open,true); //--- バーの価格をコピーする if(CopyHigh(NULL,mas_tf[0],0,copied,high)<0) {printf("No copied High",GetLastError());return(false);} //--- if(CopyLow(NULL,mas_tf[0],0,copied,low)<0) {printf("No copied Low",GetLastError());return(false);} //--- if(CopyClose(NULL,mas_tf[2],0,copied,close)<0) {printf("No copied Close",GetLastError());return(false);} //--- if(CopyOpen(NULL,mas_tf[2],0,copied,open)<0) {printf("No copied Open",GetLastError());return(false);} //--- return(true); } //+------------------------------------------------------------------+
このようなツールを使用すると、異なる見方ができます。
図18. 実装したMTFツールを使用したエキスパートアドバイザのテスト
まとめ
MQL5ソフトウェアモジュールの作者はこのようなアルゴリズムを作成する直接的な可能性を提供していませんが、これらの測定基準は非常に役に立ちます。場合によっては、さまざまな時間枠で同時に市場状態分析を実行し、ストラテジーテスタの効率を向上させ、滑らかさを向上させることができます。与えられたコード例には欠点があるかもしれないので、MQL5プログラミング言語を使用してMTF指標のアイデアをさらに開発する機会がたくさんあると思います。
添付ファイル
名前 | タイプ | パス |
---|---|---|
MA_MultiPeriod | Trend | MQL5\Indicators\MA_MultiPeriod.mq5 |
MA_MultiTF | Trend | MQL5\Indicators\MTF\Trend\MA_MultiTF.mq5 |
MTF_BB | Trend | MQL5\Indicators\MTF\Trend\MTF_BB.mq5 |
MTF_Envelopes | Trend | MQL5\Indicators\MTF\Trend\MTF_Envelopes.mq5 |
MTF_ParabolicSAR | Trend | MQL5\Indicators\MTF\Trend\MTF_ParabolicSAR.mq5 |
MTF_StdDev | Trend | MQL5\Indicators\MTF\Trend\MTF_StdDev.mq5 |
MTF_CCI | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_CCI.mq5 |
MTF_Force_Index | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_Force_Index.mq5 |
MTF_MACD | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_MACD.mq5 |
MTF_Momentum | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_Momentum.mq5 |
MTF_RSI | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_RSI.mq5 |
MTF_RVI | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_RVI.mq5 |
MTF_Stochastic | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_Stochastic.mq5 |
MTF_WPR | Oscillators | MQL5\Indicators\MTF\Oscillators\MTF_WPR.mq5 |
Triple Screen Trading System 1.0 | Expert |
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/2837





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索