English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
セマフォインディケーターを使った簡単なトレーディングシステム

セマフォインディケーターを使った簡単なトレーディングシステム

MetaTrader 5トレーディングシステム | 2 10月 2015, 16:06
1 567 0
Nikolay Kositsin
Nikolay Kositsin

はじめに

セマフォ、あるいはシグナルインディケーターはマーケットにエントリーするべきタイミングか、イグジットするべきタイミングかを示す簡単な発見器です。最新の足でエントリーシグナルが発生している場合、シンボルのチャート上にふさわしいラベルが出現します。このラベルは、取引を行うための条件として使われます。

そのようなインディケーターはたくさんありますが、そのインディケーターに基づくトレーディングシステムの本質は全く変わりません。ですから、もっともシンプルでユニバーサルな形でインプリメントするのが良いでしょう。そうすることで、得られた結果を似たようなインディケーターで使う時に、大きな変更を行う必要がなくなります。

図 1. ASCtrendセマフォシグナルインディケーター

図1. ASCtrendセマフォシグナルインディケーター

図 2. ASCtrendインディケーター取引を行うためのトレーディングシグナル

図 2. ASCtrendセマフォシグナルインディケーターを使用した取引を行うためのトレーディングシグナル


典型的なセマフォシグナルインディケーターのサンプル

現在、Code Baseにこのようなインディケーターがたくさんあります。この記事では、いくつかの有用なウエブページにのみリンクを張ります。

セマフォシグナルインディケーターの他に、セマフォトレンドインディケーターがあります。

図 3. Heiken_Ashi_Smoothedインディケーターを使ったトレードシグナル

図 3. セマフォトレンドインディケーター

図 4. Heiken Ashi Smoothed semaphoreトレンドインディケーター

図 4. Heiken Ashi Smoothed semaphoreトレンドインディケーター

これらのインディケーターを使うトレーディングシステムのトレーディングシグナルを得るためのコードは少し変わりますが Expert Advisorのコードはほとんど変わりません。


典型的なセマフォトレンドインディケーターのサンプル

これらのインディケーターを豊富に含むコードベース。この記事では、いくつかの有用なウエブページにリンクを張ります。


トレードシステムを開発するための基礎データ

  1. Expert Advisorの中にあって表示されるべき入力パラメータを持ったセマフォインディケーター;
  2. 追加の入力となるExpert Advisorトレーディングパラメータのリスト:
    • 取引に使用される入金された金融資産のシェア
    • ストップロスとテイクプロフィットのサイズ (0値の場合は未処理のオーダーは使用できません);
    • スリッページ(セットされた値と実際の約定価格との間の最大許容差);
    • トレーディングシグナルが受信される足のインデックス;
    • ロングとショートのポジションを開くための許可;
    • インディケーターシグナルに応じた、ロングポジションとショートポジションの強制クローズの許可

もちろん、汎用のトレーディング関数を使いトレードオーダーを出せればはるかに便利です。これらの関数はかなり複雑で実行コードをできるだけシンプルにするために、別々のライブラリファイルに入れておくべきです。


セマフォトレーディングシステムをインプリメントするExpert Advisorのコード

//+------------------------------------------------------------------+
//|                                                 Exp_ASCtrend.mq5 |
//|                             Copyright © 2011,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
#property version   "1.00"
//+----------------------------------------------+
//| Expert Advisor indicator input parameters    |
//+----------------------------------------------+
input double MM=-0.1;             // Share of a deposit in a deal, negative values - lot size
input int    StopLoss_=1000;      // Stop loss in points
input int    TakeProfit_=2000;    // Take profit in points
input int    Deviation_=10;       // Max. price deviation in points
input bool   BuyPosOpen=true;     // Permission to buy
input bool   SellPosOpen=true;    // Permission to sell
input bool   BuyPosClose=true;    // Permission to exit long positions
input bool   SellPosClose=true;   // Permission to exit short positions
//+----------------------------------------------+
//| ASCtrend indicator input parameters          |
//+----------------------------------------------+
input ENUM_TIMEFRAMES InpInd_Timeframe=PERIOD_H1; // ASCtrend indicator time frame
input int  RISK=4;                               // Risk level
input uint SignalBar=1;                          // Bar index for getting an entry signal
//+----------------------------------------------+

int TimeShiftSec;
//---- declaration of integer variables for the indicators handles
int InpInd_Handle;
//---- declaration of integer variables of the start of data calculation
int min_rates_total;
//+------------------------------------------------------------------+
//| Trading algorithms                                               | 
//+------------------------------------------------------------------+
#include <TradeAlgorithms.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---- getting ASCtrend indicator handle
   InpInd_Handle=iCustom(Symbol(),InpInd_Timeframe,"ASCtrend",RISK);
   if(InpInd_Handle==INVALID_HANDLE) Print(" Failed to get handle of ASCtrend indicator");

//---- initialization of a variable for storing a chart period in seconds  
   TimeShiftSec=PeriodSeconds(InpInd_Timeframe);

//---- initialization of variables of the start of data calculation
   min_rates_total=int(3+RISK*2+SignalBar);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
   GlobalVariableDel_(Symbol());
//----
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- checking the number of bars to be enough for calculation
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;
   
//---- uploading history for IsNewBar() and SeriesInfoInteger() functions normal operation  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaration of local variables
   double DnVelue[1],UpVelue[1];
//---- declaration of static variables
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| Searching for deals performing signals       |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- zeroing out trading signals
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copy newly appeared data into the arrays
      if(CopyBuffer(InpInd_Handle,1,SignalBar,1,UpVelue)<=0) {Recount=true; return;}
      if(CopyBuffer(InpInd_Handle,0,SignalBar,1,DnVelue)<=0) {Recount=true; return;}

      //---- getting buy signals
      if(UpVelue[0] && UpVelue[0]!=EMPTY_VALUE)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose) SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- getting sell signals
      if(DnVelue[0] && DnVelue[0]!=EMPTY_VALUE)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- searching for the last trading direction for getting positions closing signals
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester 
      if((BuyPosOpen && BuyPosClose || SellPosOpen && SellPosClose) && (!BUY_Close && !SELL_Close))
        {
         int Bars_=Bars(Symbol(),InpInd_Timeframe);

         for(int bar=int(SignalBar+1); bar<Bars_; bar++)
           {
            if(SellPosClose)
              {
               if(CopyBuffer(InpInd_Handle,1,bar,1,UpVelue)<=0) {Recount=true; return;}
               if(UpVelue[0]!=0 && UpVelue[0]!=EMPTY_VALUE)
                 {
                  SELL_Close=true;
                  break;
                 }
              }

            if(BuyPosClose)
              {
               if(CopyBuffer(InpInd_Handle,0,bar,1,DnVelue)<=0) {Recount=true; return;}
               if(DnVelue[0]!=0 && DnVelue[0]!=EMPTY_VALUE)
                 {
                  BUY_Close=true;
                  break;
                 }
              }
           }
        }
     }

//+----------------------------------------------+
//| Performing deals                             |
//+----------------------------------------------+
//---- Closing a long position
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Closing a short position   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Buying
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Selling
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }
//+------------------------------------------------------------------+

いくつかの細かな点は明確にする必要がありますが、このアイデアを実現するためのコードはとても簡単で明快です。

シグナルインディケーターとExpert Advisorで使用されるチャートの期間はExpert AdvisorのInpInd_Timeframe入力変数で固定されています。そのため、Expert Advisorが置かれたチャートの変化によりExpert Advisorのこのパラメータが変更されることはありません。

新しい足の出現を決定するためのIsNewBar()関数はTradeAlgorithms.mqhファイルに置かれたクラスとしてインプリメントされます。これにより、コードにあるこのような関数はいくつでもそれぞれに静的なCIsNewBar変数を設定することで簡単に使うことができます。

UpSignalTimeとDnSignalTime変数が時間の保存とトレーディング関数への転送に使われ、その後で前の取引の後に新たな取引を行うことが可能になります。今回のケースではこの機能は同じ足で同じ方向への複数の取引を防ぐために使います(取引を行うと、トレーディング関数が最新の足の終わりの時間を保管し、同じ方向への新しい取引を行いません)。

”ポジションを閉じるシグナルを得るために最後の取引の方向を検索する”というOnTick()関数内のブロックは、トレーディングシグナルのない足でポジションを閉じるためのシグナルを受け取るために必要です。Expert Advisorの通常の動作中にはその必要ありません。しかし、ネット接続の障害が起こると新しいトレーディングシグナルが失われてしまうことがあります。その後でそのマーケットに入るのはまったく良いアイデアではありませんが、開いたポジションを閉じるのは賢い選択でしょう。


他のセマフォシグナルインディケーターを使ったトレーディングシステム

さて、このコードを他のマフォシグナルインディケーターで使う必要が出てきたとき、次のアクションが実行されるはずです:

  1. 必要なExpert Advisorの新しい入力パラメータでこれまでのインディケーターのデータを置き換えます。
  2. OnInit() ブロックにあるインディケーターハンドルを取得するためのコードを変更します;
  3. インディケーターのコードの売買トレーディングシグナルを格納するためのインディケーターバッファのインデックスを決定し、それをOnTick()ブロックのCopyBuffer()関数呼び出しに正しく入力します。この場合は、0と1番目のインディケーターバッファが使用されます;
  4. Expert Advisor にあるデータ計算の開始ポイント変数(min_rates_total)の初期設定をインディケーターコードに対応して変更します;
  5. ”ポジションを閉じるシグナルを得るために最後の取引の方向を検索する”というOnTick()関数内のブロックをインディケーターコードに応じて変更します。


他のセマフォトレンドインディケーターを使ったトレーディングシステム

セマフォトレンドインディケーターを使ったこのトレーディングシステムの使用では、Expert AdvisorコードはOnTick()関数の取引シグナルを決めるためのブロックで少し変更があります。例えば、FiboCandlesインディケーターに基づくExpert Advisorのコードは次のようになります。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- checking the number of bars to be enough for calculation
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;
   
//---- uploading history for IsNewBar() and SeriesInfoInteger() functions  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaration of local variables
   double TrendVelue[2];
//---- declaration of static variables
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| Searching for deals performing signals       |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- zeroing out trading signals
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copy the newly obtained data into the arrays
      if(CopyBuffer(InpInd_Handle,4,SignalBar,2,TrendVelue)<=0) {Recount=true; return;}

      //---- getting buy signals
      if(TrendVelue[0]==1 && TrendVelue[1]==0)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose)SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- getting sell signals
      if(TrendVelue[0]==0 && TrendVelue[1]==1)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- searching for the last trading direction for getting positions closing signals
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester 
        {
         if(SellPosOpen && SellPosClose  &&  TrendVelue[1]==0) SELL_Close=true;
         if(BuyPosOpen  &&  BuyPosClose  &&  TrendVelue[1]==1) BUY_Close=true;
        }
     }

//+----------------------------------------------+
//| Performing deals                             |
//+----------------------------------------------+
//---- Closing a long position
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Closing a short position   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Buying
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Selling
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }

この場合、トレーディングシグナルは1つのカラーインディケーターバッファ(カラーインデックスを含む)からしかシグナルを受け取りません。このバッファのデータは2つの値しか持てません:0 - は上昇相場で1 - は下落相場です。ある足におけるトレンドの方向はインディケーターバッファのセルから直接受け取れるため、”ポジションを閉じるシグナルを得るために最後の取引の方向を検索する”ブロックは可能な限りシンプルになります。

”取引を実行する”ブロックでは、ポジションを閉じる関数がまず実行され、次にポジションを開く関数が実行されます。反対の場合には、1つの足ではポジションを閉じることしかできません。オープンプライスオンリー"モードでテストしている場合は同時に開くことはできません!そのため、トレードの結果にとって深刻な中断となります。


トレーディングシステムのテスト

トレーディングシステムのテストを行う前に、重要なことを1つ明確にする必要があります。SignalBar入力変数が0である場合、Expert Advisorは現在の足から取引実行シグナルを取得します。しかし現在の足のシグナルが、前の足のそのシグナルのトレンドに反する変化があった場合、信頼できません。最新の足のシグナルは出たり消えたりします、一方トレンドはそのようなシグナルに対してかなり長い間かけて動きます。このことは、あるExpert Advisorがすべてのティックに対して視覚化を有効にしてテストされ、SignalBar変数が0であるなら、簡単に見ることができます。ASCtrenインディケーター動作の視覚化が、こういった場合の事実を明確に表します。

ここでも、”ティック毎”モードだけがExpert Advisorの現在の足から受け取ったシグナルの最適化に適しています。過去の足からだけシグナルを受け取る場合は”オープンプライスオンリー”モードでも十分です。それにより、システムの質を落とすことなくトレーディングシステムの動作解析を大きく加速します。

ですから、このようなトレーディングシステムのテストや最適化のためには現在の足からのシグナルを使用しない方が良いのです。

それでは、EUR/USDについてデフォルトパラメータでExpert Advisorを1月1日から12月1日までテストしてみましょう:

図 5. EUR/USD 1時間足についてデフォルトパラメータでExp_ASCtrend Expert Advisorをテストした結果

図 5. EUR/USD 1時間足についてデフォルトパラメータでExp_ASCtrend Expert Advisorをテストした結果

ストラテジーテスターのExpert Advisorの設定を少し変更することで、既存の過去データとExpert Advisorのパラメータのベストな組み合わせを簡単に見つけることができます:

図 6. パラメータの最適化を行った後の改良パラメーターでEUR/USD 1時間足をExp_ASCtrend Expert Advisorでテストした結果

図 6. パラメータの最適化を行った後の改良パラメーターでEUR/USD 1時間足を Exp_ASCtrend Expert Advisorでテストした結果

トレーディングシステムの最適化プロセスにはいかなる特殊性もありません。このため、このプロセスを詳しく説明するためのリンクは1つしか貼りません:"MQL5: Guide to Testing and Optimizing of Expert Advisors in MQL5"(MQL5: Expert Advisorsのテストと最適化のためのガイド)。

もちろん、このような簡単なトレーディングシステムから巨大な利益を得られると期待するのは調子が良すぎるでしょう。しかし、この半自動のシステムを正しく使うスキルがあり、マーケットの変化に合わせて規則的に調節することができれば、良い結果を得ることが十分可能です。

例えばEUR/USDの12時間足には2011年の1月から5月まで上昇トレンドがありました。そして、それを初期の段階で把握するのは簡単なことでした:

図 7. EUR/USD 12時間足(2011年1月/5月)

図 7. EUR/USD 12時間足(2011年1月/5月)

Expert Advisorをこの期間にデフォルトの設定でテストしてみるのは興味深いでしょう。ポジションは買うだけにし、資金の5%のみを使うように設定しましょう(MM=0.05)。これがそのパラメータを使いExpert Advisorを1時間足でテストした結果です:

図 8. デフォルト値を設定したExp_ASCtrend Expert AdvisorをEUR/USD1時間足の2011年の1月/5月でテストした結果(買いポジションのみ、MM=0.05)

図 8. デフォルトのパラメータを持つ Exp_ASCtrend Expert Advisor EUR/USD1時間足に2011年の1月/5月で(買いポジションのみ、MM=0.05) テストした結果

もちろん、トレーダーに取引の方向を決める責任があります。しかし、覚えていてほしいのは、長いタイムフレームのチャートを使えば難しくはないということです。


他のインディケーターと一緒に使うトレーディングモジュールの変更

この記事はここで終わりにしても良いのですが、MetaEditorは既製のトレーディングモジュールを基にしたExpert Advisorsを生成することができるようになりました。ここで紹介されているすべてのものを考慮してこのようなモジュールを作成するプロセスは非常に複雑で別の勉強が必要です。ですので、提案したシステムに類似した既製のトレーディングモジュールについて説明します。そしてその後で、必要のないdetalizationを避ける特別なシグナルインディケーターに対応したこれらのモジュールの変更について詳しく説明します。

セマフォシグナルシステム(MySignals.zip) のトレーディングモジュールのコレクションをすでに持っていて、いずれか特定のインディケーターの類似モジュールを作成したいと仮定しましょう。それは典型的なセマフォシグナルインディケーターであるBykovTrendSignal.mq5インディケーターであるとしょう。まず、このコレクション(Indicators.zip)からこのインディケーターのもっとも正確なアナログを見つけましょう。この記事で最初に紹介したインディケーター(ASCtrend)が一番似ているように見えます。そこで、このインディケーターのトレーディングモジュールをモディフィケーションしてみましょう。

必要とされるコードでのその使用を考えてみましょう。インディケーター自身(BykovTrend)は入力パラメータのセットを持っています:

//+----------------------------------------------+
//| Indicator input parameters                   |
//+----------------------------------------------+
input int RISK=3;
input int SSP=9;
//+----------------------------------------------+

そして、取引を実行するためのシグナルを保管するインディケーターバッファのインデックスが必要です。今回は: 0 - 売りシグナル と 1 - 買いシグナルです。

これで、どのモジュールをモディフィケーションに使えば良いかが分かりました。\MQL5\Include\Expert\Signal\MySignals\フォルダに BykovTrendSignal.mqhをファイル名と一緒にコピーし、MetaEditorで開きます。使用されたコードには頻繁に目にする”ASCtrend ”(前のインディケーターの名前)という表現があります。新しいインディケーター - "BykovTrend"に置き換えましょう。そのためには、”Ctrl”と”H”キーを同時に押して必要な変更を行います:

インディケーター名をトレーディングモジュールコード内で置き換えます。

図 9. インディケーター名をトレーディングモジュールコード内で置き換えます。

次のステージはもっとも気をつかいます。トレーディングモジュールコード内のインディケーターインプットに関わるすべてのものを置き換えなければなりません。このプロセスは”MQL5 Wizard: How to create a module of trading signals”に書かれているものととても似ています。

まず、MQL5 ウィザード・トレーディングシグナルクラスのディスクリプションのコメントアウトブロックを変更します:

//+----------------------------------------------------------------------+
//| Description of the class                                             |
//| Title=The signals based on BykovTrend indicator                      |
//| Type=SignalAdvanced                                                  |
//| Name=BykovTrend                                                      |
//| Class=CBykovTrendSignal                                              |
//| Page=                                                                |
//| Parameter=BuyPosOpen,bool,true,Permission to buy                     |
//| Parameter=SellPosOpen,bool,true,Permission to sell                   |
//| Parameter=BuyPosClose,bool,true,Permission to exit a long position   |
//| Parameter=SellPosClose,bool,true,Permission to exit a short position |
//| Parameter=Ind_Timeframe,ENUM_TIMEFRAMES,PERIOD_H1,Timeframe          |
//| Parameter=RISK,int,4,Risk level                                      |
//| Parameter=SSP,int,9,SSP                                              |
//| Parameter=SignalBar,uint,1,Bar index for entry signal                |
//+----------------------------------------------------------------------+
//--- wizard description end
//+----------------------------------------------------------------------+
//| CBykovTrendSignal class.                                             |
//| Purpose: Class of generator of trade signals based on                |
//| BykovTrend indicator https://www.mql5.com/ru/code/497/.               |
//|             Is derived from the CExpertSignal class.                 |
//+----------------------------------------------------------------------+

両方のパラメータには同じRISK入力変数が含まれますので、そのままにしておきます。しかし、それぞれのデフォルト値は異なります。実際のところ、この違いは重要ではないのでそのままにしておきます。SSP変数に関するコメントラインが追加されました:

//| Parameter=SSP,int,9,SSP                                    |

そしてCodeBaseインディケーターへのリンクが置換されました:

//| Purpose: Class of generator of trade signals based on      |
//| BykovTrend values https://www.mql5.com/ru/code/497/.        |

これで、入力パラメータの変更に関することはすべてCBykovTrendSignalトレーディングシグナルクラスのディスクリプションに反映されました。変数の設定に新しいグローバルm_SSPクラス変数の宣言の行があります。

uint              m_SSP;              // SSP

新しいSSP()の設定パラメータのインストールメソッドの宣言の行があります:

void               SSP(uint value)                         { m_SSP=value;              } 

ここで作成したトレーディングシグナルモジュール内のRISK入力変数は、入力モジュールと等しいため、すべてのトレーディングモジュールブロック内での変更はありません。

では、CBykovTrendSignal::CBykovTrendSignal() クラスコンストラクタに渡しましょう。新しい変数の初期化はこのブロックに追加しなければなりません:

m_SSP=4;

新しい変数の正しさの確認はCBykovTrendSignal::ValidationSettings()パラメータの検証ブロックの設定で行われなければなりません:

if(m_SSP<=0)
     {
      printf(__FUNCTION__+": SSP must be above zero");
      return(false);
     }

BykovTrend インディケーター初期化ブロックにパスした後- BykovTrendSignal::InitBykovTrend()。新しいインディケーターは異なる数の入力変数を持ちます。ですので宣言された入力パラメータの次元もそれぞれ異なります:

//--- setting the indicator parameters
   MqlParam parameters[3];

今回は、インディケーターの文字列名には1次元、その入力パラメータには2次元必要です。

入力パラメータの新しいセルを初期化し、そこに格納する変数の型を示さなければいけません:

parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_SSP;

その変更の後に、このブロックのインディケーターの初期化の呼び出しの中の入力変数の数を3に変えます。

//--- object initialization   
   if(!m_indicator.Create(m_symbol.Name(),m_Ind_Timeframe,IND_CUSTOM,3,parameters))

インディケーターのインディケーターバッファの数は2のまま変わりません。ですので、インディケーターバッファのナンバー初期化の行は何も変更する必要はありません。

//--- number of buffers
   if(!m_indicator.NumBuffers(2))  return(false);

ASCtrendとBykovTrendインディケーターはそれぞれ2つのバッファを持ちます。バッファの関数はそっくりです。売りシグナルの保管に0バッファは使われ、インデックス1のバッファは買いシグナルの保管のために使われます。ですからCBykovTrendSignal::LongCondition() やCBykovTrendSignal::ShortCondition()トレーディングシグナル を送るための関数のブロックは何も変更する必要がありません。そしてトレーディングシグナルモジュールのモディフィケーションは完了したと考えてよいでしょう。

しかし、一般的に、すべてのセマフォインディケーターは異なっているため、異なるセマフォインディケーターのブロックもそれぞれ大きく異なることがあります。MySignals.zipトレーディングモジュールアーカイブとIndicators.zipアーカイブには様々なインディケーターを作成するために十分なサンプルが含まれています。いくつか詳しく見てみれば、置換プロセスとそのためのコードについてよく分かると思います。

次に、トレーディングシグナルモジュールのInd_Timeframe入力変数を見てみたいと思います。この変数を使うと、インディケーターのためにタイムフレームをダウンロードすることができます。しかし、作られたExpert Advisorは割り当てられたタイムフレームで動作します。つまり、Ind_Timeframe入力変数のタイムフレームはモジュールに通常の動作をさせるためにExpert Advisorの動作するチャートの期間を超えてはいけないということです。

最後に、 トレーディングシグナルモジュールの作成のもう1つの特殊性を紹介しましょう。カスタムエニュメレーションはベーシックインディケーターのコードに、モジュール入力変数の型としてインプリメントされることがあります。例えば、Smooth_MethodのカスタムエニュメレーションはCandles_SmoothedインディケーターのMA_SMethod変数の型として使用されます:

//+-----------------------------------+
//|  Declaration of enumerations      |
//+-----------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  }; */
//+----------------------------------------------+
//| Indicator input parameters                   |
//+----------------------------------------------+
input Smooth_Method MA_SMethod=MODE_LWMA; // Smoothing method
input int MA_Length=30;                   // Smoothing depth                    
input int MA_Phase=100;                   // Smoothing parameter
                                          // for JJMA varying within the range -100 ... +100,
                                          // for VIDIA it is a CMO period, for AMA it is a slow average period
//+----------------------------------------------+

このような場合、その種類の変数とそれに関連するトレーディングシグナル(Candles_SmoothedSignal.mqh) 内のすべての要素は int型かuint型の変数に変換されなければなりません。また、カスタムエニュメレーションからExpert Advisor入力変数と必要な入力変数の型の置換 (ExpM_Candles_Smoothed Expert Advisor) までの逆の手順は完成したEAで生成されたコード内の入力変数を使用しやすいように実行されなければなりません。

//+------------------------------------------------------------------+
//|  Declaration of enumerations                                     |
//+------------------------------------------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  };
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string          Expert_Title         ="Candles_Smoothed"; // Document name
ulong                 Expert_MagicNumber   =29976;              // 
bool                  Expert_EveryTick     =false;              // 
//--- inputs for main signal
input int             Signal_ThresholdOpen =40;                 // Signal threshold value to open [0...100]
input int             Signal_ThresholdClose=20;                 // Signal threshold value to close [0...100]
input double          Signal_PriceLevel    =0.0;                // Price level to execute a deal
input double          Signal_StopLevel     =50.0;               // Stop Loss level (in points)
input double          Signal_TakeLevel     =50.0;               // Take Profit level (in points)
input int             Signal_Expiration    =1;                  // Expiration of pending orders (in bars)
input bool            Signal__BuyPosOpen   =true;               // Candles_Smoothed() Permission to buy
input bool            Signal__SellPosOpen  =true;               // Candles_Smoothed() Permission to sell
input bool            Signal__BuyPosClose  =true;               // Candles_Smoothed() Permission to exit a long position
input bool            Signal__SellPosClose =true;               // Candles_Smoothed() Permission to exit a short position
input ENUM_TIMEFRAMES Signal__Ind_Timeframe=PERIOD_H1;            // Candles_Smoothed() Timeframe
input Smooth_Method   Signal__MA_SMethod   =4;                  // Candles_Smoothed() Smoothing method (1 - 10)
input uint            Signal__MA_Length    =30;                 // Candles_Smoothed() Smoothing depth
input uint            Signal__MA_Phase     =100;                // Candles_Smoothed() Smoothing parameter
input uint            Signal__SignalBar    =1;                  // Candles_Smoothed() Bar index for the entry signal
input double          Signal__Weight       =1.0;                // Candles_Smoothed() Weight [0...1.0]
//--- inputs for money
input double          Money_FixLot_Percent =10.0;               // Percent
input double          Money_FixLot_Lots    =0.1;                // Fixed volume

今回はSignal__MA_SMethod入力変数によって行われました。

2つのコードバージョン (ASCtrendSignal.mqh and BykovTrendSignal.mqh)をエディターで両方開き(左右に並べて)それぞれのバージョンを注意深く比較すれば、コードの変更スピードをかなり加速することができます。


まとめ

この記事に添付されたExperts.zipアーカイブには、Expert Advisorの開発の初心者の方が、書かれたコードの機能の理解や、とても人気のある既製のインディケーターを使うことができるようになるための、豊富なセマフォトレーディングシステムに基づいたExpert Advisorが入っています。

添付されたすべてのExpert Advisorは、自身のトレーディングシステムの基礎としてトレーディングストラテジーのジェネレーターを使いたい人たちのために、追加のトレーディングモジュールとして提供されています。これらのモジュールはMySignals.zipに入っていて、それに基づいたトレーディングシステムはExpertsez.zipに入っています。Expert Advisorsで使われるインディケーターはIndicators.zipに入っています。解凍するためのパスは次の通りです:

  • Experts.zip: "\MQL5\Experts\";
  • Expertsez.zip: "\MQL5\Experts\";
  • MySignals.zip: "\MQL5\Include\Expert\Signal\MySignals\";
  • Indicators.zip: "\MQL5\Indicators\";
  • SmoothAlgorithms.mqh: "\Include\";
  • TradeAlgorithms.mqh: "\Include\".

MetaEditorを再起動し、ナビゲータウインドウを開き、MQL5ラベルを右クリックしてポップアップメニューの”コンパイル”をクリックします。

SmoothAlgorithms.mqhファイルがIndicators.zipのいくつかのインディケーターのコンパイルには必要で、Experts.zipのすべてのExpert AdvisorのコンパイルにはTradeAlgorithms.mqhファイルが必要です。

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

添付されたファイル |
expertsez.zip (31.51 KB)
mysignals.zip (44.08 KB)
indicators.zip (39.15 KB)
experts.zip (34.67 KB)
6つのステップでトレーディング自動装置を作りましょう! 6つのステップでトレーディング自動装置を作りましょう!
もしどのようにトレード用クラス群がどのように組まれているかをご存知でなく、「オブジェクト指向プログラミング」という単語に恐怖を感じるようであれば、この記事はあなたにとって最適かもしれません。実際、売買シグナルのためのモジュールの作成のために詳しい内容を知る必要はありません。ただ、いくつかの簡単なルールに従ってください。作業は全てMQL5のウィザードに従って進められ、すぐに使用できる取引用自動システムを作ることができます!
マルチタイムフレームとマルチ通貨パネルの作成 マルチタイムフレームとマルチ通貨パネルの作成
この記事では、オブジェクト指向プログラミングを使うMetaTrader 5のマルチタイムフレームとマルチ通貨パネルの作成の仕方を解説します。主な目的は、パネルのコードを変更することなく、価格や価格の変化、インディケーターの値や売買条件のカスタマイズなど 多くの異なった種類のデータを表示することのできる汎用パネルの作成です。
メタトレーダー5 - 想像以上の製品です! メタトレーダー5 - 想像以上の製品です!
メタトレーダー5クライアントターミナルは1から開発され、もちろん旧バージョンをはるかに超える製品となっています。この新しいトレーディングプラットフォームは、どの金融市場においても無限の取引機会を提供します。また、常により使いやすい機能・利便性を提供するため拡張し続けています。そのため、メタトレーダー5の利便性を全て挙げることは難しいものとなっています。一つの記事において簡潔に全てを説明することを試みましたが、簡潔に収めることができず大変驚きました。
オブジェクト指向プログラミング オブジェクト指向プログラミング
オブジェクト指向プログラミングに関する多相性やカプセル化などについて理解する必要はありません。これらの機能を使うだけで良いのです。この記事ではオブジェクト指向プログラミングの基本を例を使って具体的に見ていきます。