
領域法
目次
- 概論
- 1. RSIインディケータの指数の一般的な評価方法
- 2. 領域法
- 3. インディケータ RSIAreaIndicator_v1
- 3.1. インディケータのドラフトを作成する
- 3.2. インディケータの『ヘッダー』を作成する
- 3.3. インディケータのOnInit()関数の編集
- 3.4. インディケータの補助関数の作成
- 3.5. インディケータの主要動作コードの作成
- 4. エキスパートアドバイザ RSIAreaExpertバージョン1.00
- 4.1. エキスパートアドバイザの『ヘッダー』の編集
- 4.2. RSIAreaFunc補助関数
- 4.3. CopyBuffer関数の動作コードの検証
- 4.4. 補助関数の編集の続き
- 4.5. エキスパートアドバイザのOnTick()関数
- 5. 様々な期間と銘柄でのエキスパートアドバイザRSIAreaExpertバージョン1.00のテスト
- まとめ
- リファレンス
概論
記事の最後にある添付ファイルからインディケータとエキスパートアドバイザを正しくインストールするには、 "Indicators.zip"と"Experts.zip"アーカイブを<data catalog>\MQL5\で解凍する必要があります。
面積法についての一番初めの記事は2004年[1]に公開されました。この方法はRSIインディケータのデータへの特殊な外観が面白いです。ここでは最後の交差時から50より上(下)のラインを描くオシレーターの領域を評価するものです。2004年から市場は激しく変化し、MQL5言語が開発されました。つまり、MQL5言語や今日の市場で戦略をテストする時が到来したのです。
1. RSIインディケータの指数の一般的な評価方法
RSIインディケータのシグナルに基づく取引の一般的なメソッドは、商品の買われすぎ/売られすぎの指標を評価し、インディケータと価格の指標のあいだの分岐の検索、インディケータによる買われすぎ/売られすぎの領域の発生後の反転です。このように、RSIオシレーターのテクニカル分析には、最低でも4つのシグナルが使用されるため、これが意思決定システムを複雑にしています。
また私達は、RSIインディケータは非常に長い時間買われすぎ(70のラインより上)/売られすぎ(30のラインより下)の領域に留まることはなく、必ず戻ってきて、50の中心線と交差することを知っています。
図1. RSIオシレーターは常に買われすぎ/売られすぎの領域から戻ってくる
図1で分かるように、オシレーターが買われすぎ/売られすぎ領域にあった総合時間は、他の時間と比べるととても短いことが分かります。また、買われすぎ/売られすぎ領域に入った後、RSIは50の中心線と交差します。RSIオシレーターが必ず戻ってきて、50のラインと交差するという認識と、RSIオシレーターの指標のテクニカル分析を簡素化する必然性が、領域法開発のベースとなりました。
2. 領域法
領域法は、RSIオシレーターの指標を1つの指標(50のラインより上/下のオシレーターによって形成された領域)で評価します。この数値こそが買われすぎ/売られすぎの度合いを定義します。
図2. 面積法 - 領域が50のラインより上か下かを評価する方法
ポジションを保有するシグナルは、この場合には、RSIインディケータの最後に交差した時からの50ラインより上/下の領域の値です。
- 50のラインより上に長い間RSIがある場合、特定の領域値を超えた後に(領域値が300になる)、売りポジションが保有されます。
図3. 売りポジションの保有シグナルは、領域が300となってから
-
また、50のラインより下にRSIが長い間ある場合、特定の領域値を超えた後、買いポジションが保有されます。
ポジション決済のシグナルは、RSIオシレーターが、ローカル最大/最小値の形成を伴う50のラインとの交差と、そこからの4%の後退です。
- 例えば、50ラインよりも上に長い間あって、売りポジションを保有しているとします。そして、インディケータ値が減少していき、40のラインまで到達し、その後、インディケータの値は増加し始めます(つまり、ローカル最大値が形成されます)。インディケータ値が44のラインまで到達した場合、これがポジション決済のシグナルとなります。
図4. 売りポジションの決済シグナル ー ローカル最小値とそれに続く4%の後退の形成後
- 同様のロジックがインディケータが長い間50ラインより下にある場合に発生し、ただこの場合には私達はローカル最大値の形成を待ちます。
50ラインより上/下の領域を可視化するのに、RSIAreaIndicatorが役に立ちます。
3. インディケータ RSIAreaIndicator_v1
RSIAreaIndicatorは、RSIをベースに作られています。主な違いは、RSIAreaIndicatorは2つのバッファを持っていることです。1つ目のバッファはDRAW_HISTOGRAMの構築スタイルを持ち、2つ目のバッファはDRAW_LINEの構築スタイルを持っています。バッファ値は式によって得られます。
RSIAreaIndicator version 1.00の外観
図5. RSIAreaIndicator _v1
貴方が作成したカスタムインディケータを別のフォルダに配置することをお勧めします。私の場合、こういったフォルダには"MyInd"という名前をつけています。インディケータの作成を始めるには、まずそのドラフトをMQL5 Wizardのヘルプを使ったMetaEditorで作成する必要があります。インディケータのドラフト作成の最初のステップこのビデオに集約しました。
次のステップはインディケータの説明書きを加えることです。こうすることで、いつでも『共通』タブのインディケータのプロパティで見ることができるようになります。見やすくする為、記事に追加したコードは色で強調表示されています。
#property version "1.00" #property description "The indicator displays area RSI over/under line 50" #property indicator_separate_window
先ほども述べたように、RSIAreaIndicatorには2つのインディケータバッファがあります。その他に、もう1つの補助が必要になります。したがって、インディケータには全部で3つのバッファが使用されることになります。インディケータの『ヘッダー』のコードの編集を始めましょう。
#property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 2 #property indicator_type1 DRAW_HISTOGRAM #property indicator_type2 DRAW_LINE #property indicator_color1 clrGray #property indicator_color2 clrGray //--- input parameters input int ExtRSIPeriod=13;
ここで、インディケータと補助バッファの値が格納される3つの配列を宣言する必要があります。
//--- input parameters input int ExtRSIPeriod=13; //---- buffers double ExtMapBuffer1[]; double ExtMapBuffer2[]; double ExtMapBuffer3[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
次に、私達のRSIAreaIndicatorはRSI標準インディケータをベースに計算されるため、インディケータ値を取得する必要があり、Relative Strength Indexハンドラが格納される変数が必要になります。
double ExtMapBuffer3[]; //--- variable for storing the handle of the iRSI indicator int handle; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
そして最後に、3つの変数の『ヘッダー』で宣言します。name 変数には、インディケータが起動するシンボルの名前が、short_name変数にはインディケータの略名が、そしてbars_calculated変数には、RSIインディケータで計算されたバーの数が格納されます。
int handle; //--- variable for storing string name=Symbol(); //--- name of the indicator on a chart string short_name; //--- we will keep the number of values in the Relative Strength Index indicator int bars_calculated=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function |
インディケータの『ヘッダー』は記入したので、これでOnInit()関数の編集へと移ることができます。
インディケータを作成するということは、私達のインディケータバッファを前に宣言したdouble型の動的配列と繋げる必要があるということです。
int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ExtMapBuffer1,INDICATOR_DATA); SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA); SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS); //--- return(INIT_SUCCEEDED);
それから、バッファと配列を繋げた後すぐに、時系列での配列要素の目録作成を設定します(ArraySetAsSeriesを参考にすることをお勧めします)。配列の右端の要素はインデックス『0』となります。
SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA); SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS); ArraySetAsSeries(ExtMapBuffer1,true); ArraySetAsSeries(ExtMapBuffer2,true); ArraySetAsSeries(ExtMapBuffer3,true); //--- return(INIT_SUCCEEDED);
ここで、表示精度を設定します。インディケータは小数点以下2桁を表示します。
ArraySetAsSeries(ExtMapBuffer3,true); //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,2); //--- return(INIT_SUCCEEDED);
あとはOnInit()関数でRSIndexのハンドルを取得し、short_name変数を埋め、私達のインディケータに略名をつけます。
ArraySetAsSeries(ExtMapBuffer2,true); ArraySetAsSeries(ExtMapBuffer3,true); //--- set accuracy IndicatorSetInteger(INDICATOR_DIGITS,2); handle=iRSI(name,0,ExtRSIPeriod,PRICE_CLOSE); //--- if the handle is not created if(handle==INVALID_HANDLE) { //--- notify about failure and output error code PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d", name, EnumToString(PERIOD_CURRENT), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- show the symbol/timeframe the RSI Area Indicator is calculated for short_name=StringFormat("RSIArea(%d)",ExtRSIPeriod); IndicatorSetString(INDICATOR_SHORTNAME,short_name); //--- normal initialization of the indicator return(INIT_SUCCEEDED);
これでインディケータの『ヘッダー』とOnInit()関数を埋めました。編集したコードは、記事の最後で参照することができます。インディケータは"RSIAreaIndicatorStep2.mq5"という名前で保存されています。
RSIAreaIndicatorの動作には、OnCalculate()関数への各エントリでRSIインディケータのデータを取得する必要があります。コード読み取りの容易性を確保することとプログラムの機能を分けることは同じように重要です。その為、RSI値を取得する補助コードと、RSIAreaIndicatorバッファのうちの1つへのこれらの数値のコピーは、個別のFillArrayFromBuffer()関数に入れました。これをOnCalculate()の後に配置します。数値はCopyBuffer関数を使ってコピーされます。
//--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Filling indicator buffers from the iRSI indicator | //+------------------------------------------------------------------+ bool FillArrayFromBuffer(double &rsi_buffer[], // indicator buffer of Relative Strength Index values int ind_handle, // handle of the iRSI indicator int amount // number of copied values ) { //--- reset error code ResetLastError(); //--- fill a part of the iRSIBuffer array with values from the indicator buffer that has 0 index if(CopyBuffer(ind_handle,0,0,amount,rsi_buffer)<0) { //--- output error code if copying fails PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } //--- all in order return(true); } //+------------------------------------------------------------------+
RSIAreaIndicatorの主要な動作コード(またはロジック)はOnCalculate()関数に配置しました。ここでは主要変数values_to_copyを宣言します。続いて、values_to_copy変数が、RSIインディケータからコピーする必要がある数値の数を保存します。
const int &spread[]) { //--- number of values copied from the iRSI indicator int values_to_copy; //--- determine the number of values calculated in the indicator int calculated=BarsCalculated(handle); if(calculated<=0) { PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError()); return(0); } //--- return value of prev_calculated for next call return(rates_total); }
values_to_copy値の計算:
PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError()); return(0); } //--- if it is the first calculation of the indicator or if the number of values in the iRSI indicator changed //---calculate if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1) { //--- if the iRSIBuffer array is greater than the number of values in the iRSI indicator for symbol/period, then we don't copy everything //--- otherwise, we copy less than the size of indicator buffers if(calculated>rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { //--- it means that the indicator is calculated not for the first time, but since the last call of OnCalculate() //--- not more than one bar is added for calculation values_to_copy=(rates_total-prev_calculated)+1; } //--- return value of prev_calculated for next call return(rates_total);
何故values_to_copy変数はこのように計算されるのでしょうか?MQL5のインディケータでは、OnCalculate()関数に引き渡される配列要素(time[]、open[]、high[]、low[]、close[]、tick_volume[]、volume[]、spread[])は、配列の始めから最後まで索引付けされています。チャート上ではこのようになります。
図6. 配列が時系列でない場合の要素の索引付け
つまり、時系列ではない配列では、一番右の要素は最大インデックスを持つことになります。これは数学的な計算の際に考慮する必要があります。
values_to_copy変数の値が計算されたら、FillArrayFromBuffer()補助関数を呼び出し、ExtMapBuffer1[]とExtMapBuffer2[]のインディケータバッファを数値で埋めます。
//--- for calculation not more than one bar is added values_to_copy=(rates_total-prev_calculated)+1; } //--- fill the array with values of the iRSI indicator //--- not ready if(!FillArrayFromBuffer(ExtMapBuffer3,handle,values_to_copy)) return(0); //--- for(int i=0;i<values_to_copy;i++) { ExtMapBuffer1[i]=ExtMapBuffer2[i]=ExtMapBuffer3[i]-50.0; } //--- memorize the number of values in the Relative Strength Index indicator bars_calculated=calculated; //--- return value of prev_calculated for next call return(rates_total);
RSIAreaIndicator version 1.00の出来上がりです。これは記事の最後でダウンロードすることができます(RSIAreaIndicatorv1.mq5)。これで領域法に基づいて取引を行うRSIAreaEA version 1.00エキスパートアドバイザの作成に取り掛かることができます。
4. エキスパートアドバイザ RSIAreaExpert version 1.00
インディケータの時と同じように、作成したエキスパートアドバイザは別個のフォルダに配置することをお勧めします。私の場合、エキスパートアドバイザ用のフォルダ名は"MyExp"としています。インディケータの時と同様に、RSIAreaExpert_v1のドラフトを作成します。重要:ステップでは全てのチェックを外す必要があります。
図7. エキスパートアドバイザの作成時の設定
出来上がったエキスパートアドバイザのドラフトは記事の最後で参照することができます(RSIAreaExpert_v1_Step1.mq5)。
エキスパートアドバイザの説明書きを追加します。これはエキスパートアドバイザの『共通』タブで見ることができるようになります。
#property version "1.00" #property description "EA trades on \"Method areas\"" //+------------------------------------------------------------------+ //| Expert initialization function |
説明書きはすぐには書きたくないものですが、最終的にはこれが貴方に大いに役立つものになるでしょう。
エキスパートアドバイザは標準ライブラリを使用し、取引操作実行の為のCTradeクラスを使用します。この為にはCTradeクラスを接続し、my_trade変数を宣言する必要があります。
#property description "EA trades on \"Method areas\"" #include <Trade\Trade.mqh> //--- global variables CTrade my_trade; //+------------------------------------------------------------------+ //| Expert initialization function |
また、3つの変数を追加します(Relative Strength Indexインディケータのハンドルを保存するもの、算出された現在の領域を保存するもの、そして補助変数)。
//--- global variables CTrade my_trade; int handle; // variable for storing the handle of the iRSI indicator double RSIArea; // the calculated area double RSIOpen; // the auxiliary variable //+------------------------------------------------------------------+ //| Expert initialization function |
そして、エキスパートアドバイザの『ヘッダー』の編集の最後のステップは、入力パラメータの追加です。
double RSIOpen; // the auxiliary variable //--- input parametres input int ExtRSIPeriod=13; // period of RSI input int AreaCondition=300; // area input ENUM_TIMEFRAMES period=PERIOD_M15; //+------------------------------------------------------------------+ //| Expert initialization function |
period変数はストラテジーテスターでのテストを快適にする為に導入されていて、こうすることでテスト期間の様々な範囲を設定することができるようになります。
図8. period変数で幅広い期間でエキスパートアドバイザをテストできるようになる
エキスパートアドバイザの『ヘッダー』は埋めたので、次はOnInit()関数です。OnInit()では、現在のシンボル(Symbol())と設定した期間(period)でのインディケータのハンドルの取得という1つの操作のみ行います。
int OnInit() { //--- handle=iRSI(Symbol(),period,ExtRSIPeriod,PRICE_CLOSE); //--- if the handle is not created if(handle==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(period), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); }
エキスパートアドバイザの編集プロセスでのこれらの全ての変更はRSIAreaExpert_v1_Step2.mq5ファイルで見ることができます。
領域を特定するRSIAreaFunc()関数は、いくつかの機能ユニットから構成されています。機能を順を追って追加していきましょう。第一ブロック(説明はコードの後):
void OnTick() { //--- } //+------------------------------------------------------------------+ //| Area calculation | //+------------------------------------------------------------------+ double RSIAreaFunc(int &RSIAreaShift,int BeginShift) { int shift,limit; double rsivalue,result; //--- get current RSI limit=Bars(Symbol(),period)-ExtRSIPeriod; if(limit>100) limit=100; double arr_rsi[]; ArrayResize(arr_rsi,limit); ArraySetAsSeries(arr_rsi,true); if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } return(result); }
limit変数は、いくつのiRSIインディケータの数値をarr_rsi[]配列にCopyBufferを使ってコピーするかを担っています。limit変数を『100』で制限します。つまり、常にiRSIインディケータの最後の100の数値をコピーするということです。エキスパートアドバイザの編集のこれらの変更はRSIAreaExpert_v1_Step3.mq5ファイルで見ることができます。
もしCopyBuffer関数の動作やどんな数値がインデックス『0』に含まれるのか、あまり良くわからない場合は、検証済の簡単なコードを書くこともできます。OnTick()関数にRSIAreaFunc()補助関数の呼び出しを記述します。
void OnTick() { //--- static int RSIAreaShift=0; RSIAreaFunc(RSIAreaShift,0); } //+------------------------------------------------------------------+ //| Area calculation | //+------------------------------------------------------------------+ double RSIAreaFunc(int &RSIAreaShift,int BeginShift)
RSIAreaFunc()関数の最初のブロックの最後に、arr_rsi[]配列要素の最初と最後の数値というコメントを書き加えます。
if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } //--- Comment("arr_rsi[",limit-1,"]=",DoubleToString(arr_rsi[limit-1],2), "; arr_rsi[0]=",DoubleToString(arr_rsi[0],2)); return(result); }
これは検証済コードで RSIAreaExpert_v1_Step3_check.mq ファイルにのみ入れられており、これは主要エキスパートアドバイザにはありません。チェックの為に次のことを行います。
- (以前に行っていない場合)RSIAreaExpert_v1_Step3_check.mq5エキスパートアドバイザのファイルをコンパイルする。
- 任意の商品の新規チャートを開き、時間軸をM15に変更する(デフォルトでは入力パラメータのperiod変数はPERIOD_M15となっている為)。
- RSIインディケータをチャートに入れる(メニュー『挿入』→『インディケータ』→『オシレーター』→『期間』13およびCloseを『適用する』という設定をした『Relative Strength Index』)。
- チャートにRSIAreaExpert_v1_Step3_check.mq5エキスパートアドバイザをつける。
チャート上ではarr_rsi配列のインデックス『0』の要素値が、一番初めのバーでRSIインディケータの値と一致していることがすぐにわかります。
図9. CopyBuffer関数の動作チェック
RSIAreaFunc()関数の次のブロック:
if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return(0); } result=arr_rsi[0]-50.0; // values from the bar that has 0 index for(shift=BeginShift+1;shift<limit;shift++) { rsivalue=arr_rsi[shift]-50; if((result>0 && rsivalue<-3) || (result<0 && rsivalue>3)) { RSIAreaShift=shift; break; } result+=rsivalue; } return(result); }
まずresult変数に一番右のバーのマイナス50のRSIインディケータの値が割り当てられます。それからarr_rsi配列でループが続きます(インデックス『1』の要素から、インデックスlimit-1の要素まで)。このサイクルでは『ゼロラインとの交差はあったか』という条件がチェックされます。交差があった場合、バーのインデックス(右から左へ計算)はRSIAreaShift変数に格納されます。
RSIAreaFunc()補助関数の編集が終了しました。次はOnTick()主要取引関数の番です。OnTick()に次のコードを追加します。
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- static int RSIAreaShift=0; int shift; double RSICurrent,RSILocalMin,RSILocalMax,value; double arr_rsi[1],rsi; MqlTick last_tick; //--- if(CopyBuffer(handle,0,0,1,arr_rsi)==-1) { Print("CopyBuffer from iRSI failed, no data"); return; } rsi=arr_rsi[0]; //--- if(!SymbolInfoTick(Symbol(),last_tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); //--- }
既にお馴染みのCopyBuffer関数を使って、一番右のバーのRSIインディケータの1つの値を取得し、この数値をrsi-変数値に代入します。次に、コード内ではこの変数を数回参照します。それから現在のシンボルの現在価格を取得し、last_tick変数でこれらの価格を格納します。
コードの次のブロックは現在の商品に保有ポジションがある場合に処理されます。
if(!SymbolInfoTick(Symbol(),last_tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); //--- check the conditions for opening a position if(!PositionSelect(Symbol())) { RSIArea=RSIAreaFunc(RSIAreaShift,0); //--- check for a chance to take a long position if(RSIArea<-AreaCondition) { my_trade.Buy(1.0,NULL,last_tick.ask,0.0,0.0,NULL); RSIOpen=rsi; return; } //---check for a chance to take a short position if(RSIArea>AreaCondition) { my_trade.Sell(1.0,NULL,last_tick.bid,0.0,0.0,NULL); RSIOpen=rsi; return; } RSIAreaShift=0; } //--- } //+------------------------------------------------------------------+ //| Area calculation |
コード内ではポジション保有の条件がチェックされます(現在算出された領域(RSIArea変数) が、入力パラメータ (AreaCondition)より少ない/多い場合、買い/売りポジションが保有されます。
次にRSICurrent変数にrsi変数値が割り当てられ(ここには一番右のバーのRSIインディケータ値が保存されます)、OnTick()関数からの条件の発生がチェックされます。
- 50のラインより上(RSIOpen>50)でポジションを保有する場合、現在私達は50のラインより上(RSICurrent>50)にいるということです。
- 50のラインより下(RSIOpen<50)でポジションを保有する場合、現在私達は50のラインより下(RSICurrent<50)にいるということです。
RSIAreaShift=0; } RSICurrent=rsi; if(RSIOpen>50 && RSICurrent>50) return; if(RSIOpen<50 && RSICurrent<50) return; RSILocalMin = RSICurrent; RSILocalMax = RSICurrent; //--- } //+------------------------------------------------------------------+ //| Area calculation |
コードの次のブロックは、ローカル最大/最小値を検出し、RSILocalMinとRSILocalMax変数にこれらの数値を代入します。
RSILocalMin = RSICurrent; RSILocalMax = RSICurrent; //--- search local minimum/maximum if(RSIAreaShift>1) { double arr_rsi_1[]; ArrayResize(arr_rsi_1,RSIAreaShift); ArraySetAsSeries(arr_rsi_1,true); if(CopyBuffer(handle,0,0,RSIAreaShift,arr_rsi_1)==-1) { Print("CopyBuffer from iRSI failed, no data"); return; } for(shift=1; shift<RSIAreaShift; shift++) { value=arr_rsi_1[shift]; if(value<RSILocalMin && RSIArea>0) RSILocalMin=value; if(value>RSILocalMax && RSIArea<0) RSILocalMax=value; } } //--- } //+------------------------------------------------------------------+ //| Area calculation |
そして、最後にコードの最後のブロックです。
if(value>RSILocalMax && RSIArea<0) RSILocalMax=value; } } //--- check for rollback if(PositionSelect(Symbol())) { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { //--- сheck if it is time for closing if(RSILocalMax>=RSICurrent+4 && RSILocalMax>50) my_trade.PositionClose(Symbol(),20); } if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) { //--- check, can it is time already be closing? if(RSILocalMin<=RSICurrent-4 && RSILocalMin<50) my_trade.PositionClose(Symbol(),20); } } //--- return; } //+------------------------------------------------------------------+ //| Area calculation |
ここでは(保有ポジションがある場合)ルールに沿ったポジション決済の条件をチェックします。
RSIオシレーターの、ローカル最大/最小値の形成を伴う50のラインとの交差と、そこからの4%の後退です。
例えば、50ラインよりも上に長い間あって、売りポジションを保有しているとします。そして、インディケータ値が減少していき、40のラインまで到達し、その後、インディケータの値は増加し始めます(つまり、ローカル最大値が形成されます)。ポジション決済のシグナルは、インディケータ値が44のラインに到達した時です。
これでRSIAreaExpert_v1 エキスパートアドバイザの作成は終了です。RSIAreaExpert_v1.mq5ファイルはこの記事の最後でダウンロードすることができます。
5. 様々な期間と銘柄でのエキスパートアドバイザRSIAreaExpertバージョン1.00のテスト
RSIAreaExpertエキスパートアドバイザのテストは、初めにH1[1]のチャート期間で行われましたが、2004年からは市場は激しく変化しより不安定になった為、領域法のパフォーマンス性のチェックに、M10からH6までの幅広い期間でテストが行われることになりました。またテストの為の領域の範囲が100から800まで大幅に広げられました。テスト期間は、2015年1月5日から2016年1月5日です。
AUDCADのRSIAreaExpert version 1のテスト結果は以下のようになりました。
図10. RSIAreaExpert version 1のテスト結果。AUDCAD。領域間隔100-800。期間M10-H6。
H2の期間で、結果の良い密度が分かります。更にH3を計算に入れることができます。ここで、下の図を見て、RSIAreaExpert version 1エキスパートアドバイザのテスト時に1年間においてAUDCADでいくつの取引が行われたかを評価しましょう。
図11. RSIAreaExpert version 1のテスト結果。AUDCAD。領域間隔100-800。期間M10-H6。
H2とH3での一年間の取引数は50の範囲内で変動しています。これは少しで、誤差は多いです。その為、AUDCADでは領域法のメソッドの戦略は上手く機能しないと結論づけることができます。
AUDUSDのシンボルでのRSIAreaExpert version 1のテスト結果:
図12. RSIAreaExpert version 1のテスト結果。AUDUSD。領域間隔100-800。期間M10-H6。
AUDUSDでの戦略の利益性を考えるなら、H2とH3での取引を検証することができます。これらの期間ではAreaConditionパラメータは、250から400の範囲内で変動しています。H2とH3の期間での取引の論拠を確認する為に、これらの期間での1年間の取引量を検証する必要があります。
図13. RSIAreaExpert version 1のテスト結果。AUDUSD。領域間隔100-800。期間M10-H6。
お分かりのように、あまりにも少ないです。つまり、AUDUSDでは領域法のメソッドはお勧めできないということです。
EURUSDでのRSIAreaExpert version 1のテスト結果
図14. RSIAreaExpertのテスト結果。領域間隔100-800。期間M10-H6。
図4で分かるように、M10に対しては400から550まで、M12に対しては300から400まで、M15に対しては300から400までの領域の、利益の結果の良い密度を確認できます。一年間における取引量は少ない為、もっと大きい期間は検証しません(図5参照)。
図5ではEURUSDの為の利益と取引数の依存関係のチャートが表示されています。
図15. RSIAreaExpertのテスト結果。領域間隔100-800。期間M10-H6。
(H1からH6までの)大きな期間での取引数はごくわずかで、これらの期間で領域法を使う正当性に疑問がわきます。M10、M12、M15の期間では、取引数は領域法の利益性を確かめるのに十分なものです。確かにEURUSDは領域法での取引に合っています。
GBPUSDでのRSIAreaExpert version 1のテスト結果
図16. RSIAreaExpert version 1のテスト結果。GBPUSD。領域間隔100-800。期間M10-H6。
GBPUSDではM20の期間で肯定的な利益の良い密度となります。AreaConditionパラメータは300から500まで変化します。
図17. RSIAreaExpert version 1のテスト結果。GBPUSD。領域間隔100-800。期間M10-H6。
GBPUSDでのM20の期間における1年間の取引量は140から250までです。これは確かに素晴らしい数字ではありませんが、注意に値するものです。言い換えれば、領域法によるGBPUSDでの取引は、全ての人に適しているとは言えないということです。
USDCADでのRSIAreaExpert version 1のテスト結果:
図18. RSIAreaExpert version 1のテスト結果。USDCAD。領域間隔100-800。期間M10-H6。
USDCADでは、肯定的な利益性の良い密度が確認されるので、M30だけ検証します。また、AreaConditionパラメータは、280から550の範囲で変化しています。
図19. RSIAreaExpert version 1のテスト結果。USDCAD。領域間隔100-800。期間M10-H6。
M30の時間軸におけるこの通貨ペアでの1年間の取引量は、90から200までの範囲で変化しています。これはそんなに多いものではないので、USDCADの為に領域法を使用することはお勧めできません。
USDJPYでのRSIAreaExpert version 1のテスト結果:
図20. RSIAreaExpert version 1のテスト結果。USDJPY。領域間隔100-800。期間M10-H6。
USDJPYでは2つの期間(M10とM30)が割り当てられています。M10の期間ではAreaConditionパラメータは320から650の間にあり、M30の期間では550から600の間にあります。
図21. RSIAreaExpert version 1のテスト結果。USDJPY。領域間隔100-800。期間M10-H6。
USDJPYでのM10の期間における領域法による1年間の取引量は150から200の間、またM30も期間における取引量は50から150でした。したがって、ここでは取引の推奨は非常に曖昧であることが分かります。
まとめ
領域法は取引に使用するにはまだ早いことがわかりました。しかし、市場の現在の条件では、システムは[1]以前は主な利益を示したもののH1の期間では損失を示すようになりました。現代の市場では最も利益的で効率的なものは、M10、M12、M15の期間におけるEURUSDでの領域法による取引でした。この通貨ペアとこれらの時間軸でのテストは、1年間の十分な取引量を示しました。
リファレンス
- I.V.モロゾフ、R.R.ファトフリン、FOREX:単純なものから複雑なものまで。『MetaTrader』クライアントターミナルの新しい機能。2004年、『テレトレード』社、448p。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/2249





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