English Русский 中文 Español Deutsch Português
ユニバーサルな Expert Advisor のテンプレート

ユニバーサルな Expert Advisor のテンプレート

MetaTrader 4トレーディングシステム | 16 3月 2016, 06:53
1 129 0
Вадим Андреевич
Вадим Андреевич

はじめに

多くのトレーダーは自分の Expert Advisor を書くにあたり問題に出会います。まず何がくるのでしょうか?EA コード内にテイクプロフィット、ストップロス、トレーリングストップを設定する方法は?戦略の機能性を確認する方法は?本稿では、Expert Advisor を作成するための主要な関数について詳しく説明します。おそらくトレーリングコードが便利だと思う方もいらっしゃるでしょう。



Expert Advisor 変数

すべてのExpert Advisor にはどんな変数が必要なのでしょうか?テスターに bool タイプ変数で設定されたパラメータをすべて調査させるには、何をすべきでしょうか?第1に、一般的な EA コードを提供します。それはどんな通貨ペアにも有効で、スピードの速いものに対してはご自分の通貨タイプに応じてそれらを調整することをお薦めします。第2に、0-無効、1-有効(オプティマイザですべてのパラメータを確認したいためです。最終コードがほとんど最適化されないなら、このパラメータを変更するようお薦めします)。第3に、レベル(ストップ)の変数は整数で初期化され、コードでは必要に応じて小数数字に変更されます。現実には、異なる通貨をトレードしますが、ここではテンプレートです。第4に、ストップパラメータがゼロの場合、ストップは動作しません。



変数の定義

変数の定義を始めます。最適化しやすい外部変数からいきます。

extern double MaxLot;
extern double TakeProfit;
extern double TrailingStop;
extern double StopLoss;
extern double MinProfit;
extern double ProfitPoints;
extern int    Slippage=0;
extern int Condition1=1;
extern double LotSpliter=1.0;
extern int CloseByOtherSideCondition;

変数 MaxLot は、最大に使用されるロットを制限したい場合(ロットはサーバーでも制限されますが、これは後ほどお話しします)最大ロットを設定します。
TakeProfit、StopLoss、TrailingStop はゼロより大きい場合、コード内で作動します。
MinProfit と ProfitPoints は、ProfitPoints がゼロより大きい場合、原則に従って作動します。すなわち、価格が ProfitPoints に到達し、MinProfitまで戻っていきます。
ConditionX はエントリー条件を有効にします。
LotSpliter はロットのスプリッターです。それは有効なロットのほんの一部しか使用しません。たとえば、0.1 にはデポジット全体に対して有効なレートより10倍小さいロットしかありません。
CloseByOtherSideCondition は逆側の条件の出現時にオーダーをクローズします。

EA の記述と共にお話しする内部変数を設定します。

double Lot;
double PP=0;
double slu,sld,a,b;
double tp,sl;

初期化コード

ここでは Expert Advisor を起動しただけで計算され、後にコード内で使用されるものが何か確認します。

int init()
  {
   tp=TakeProfit;
   sl=StopLoss;
   return(0);
  }

ストップレベルが変更したときのためにこれら変数の値を取ります。また、常に同じボリュームでトレードを行うつもりであれば、ロットを計算し、超過値(ロット計算は本稿でのちに分析します)を表示します。EA 記述や著作権を持つ表示可能なコメントを作成することもできます。それは以下のように行います。

Comment("cloud trade \n v2.0.11");

"\n" -次の表示行『キャリッジ リターン』への移動を意味します。



フレームワーク コード

オーダーが一つもない場合のコードを見ます。

   if(OrdersTotal()==0)
   {   
      preinit();
      if(U()==1)
      {
         OrderBuy();
         return(0);
      }
      if(U()==2)
      {
         OrderSell();
         return(0);
      }
      return(0);
   }

これら関数の一部はのちに分析します。ここには原則があります。パラメータを初期化し、エントリー条件があるか確認し、条件によってエンターする、というものです。

オーダーが一つもない場合のコードを見ます。


      if(OrderType()==OP_BUY)
        {
         if((slu)>PP)
           {
            PP=slu;
           }
         if(((slu)>0.001) && (OrderStopLoss()<(b-TrailingStop))
          && (OrderOpenPrice()<(b-TrailingStop))
           && (OrderProfit()>MathAbs(OrderSwap())))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, b-TrailingStop, 0, 0, 0);
              }
           }
        }
      if(OrderType()==OP_SELL)
        {
         if((sld)>PP)
           {
            PP=sld;
           }
         if(((sld)>0.001) && (OrderStopLoss()>(a+TrailingStop))
          && (OrderOpenPrice()>(a+TrailingStop)))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, a+TrailingStop, 0, 0, 0);
              }
           }
        }
      if(ProfitPoints!=0)
        {
         if(OrderType()==OP_BUY && PP>=ProfitPoints && (slu)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && PP>=ProfitPoints && (sld)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }
      if(CloseByOtherSideCondition==1)
        {
         if(OrderType()==OP_BUY && U()==2)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && U()==1)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }

まずそれをのちに処理するためにオーダーを1件のみ選択します(このコードは本稿の別の部分で分析します)。それから、たとえば誤った方向でのトレーリングストップや利益の出ない新規価格などで、オーダーを変更しないために、価格に変数を割り当てます。最初にトレーリングストップの可能性があるかどうかオーダーを確認し、同時に次の関数-用法は先に述べた利益最低値、 用にデータを収集します。そして逆方向の条件が現れたらオーダーをクローズし、逆方向でオーダーをオープンする関数に行きます。



本稿で分析する関数

コードを短くする関数を考察し、のちにブロック全体が呼び出しできるように、もっとも頻繁に使用される命令をブロックに組み込みます。その条件を設定し、確認します。

//+------------------------------------------------------------------+
//|  returns a signal to buy or to sell                              |
//+------------------------------------------------------------------+
int U()
  {
      if((U1()==2 && Condition1==1)
       || (U2()==2 && Condition2==1)){return(2);}
      if((U1()==1 && Condition1==1)
       || (U2()==1 && Condition2==1)){return(1);}
   return(0);
  }
//+------------------------------------------------------------------+
//|  returns a signal based on stochastic values                     |
//+------------------------------------------------------------------+
int U1()
  {
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)>=80)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)
           >=iStochastic(Symbol(),Period(),
              Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(2);
           }
        }
     }
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)<=20)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           >=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)
              <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(1);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| find trend direction using fractals                              |
//+------------------------------------------------------------------+
int U2()
  {
   double fu=0,fd=0;
   int f=0,shift=2;
   while(f<2)
     {
      if(iFractals(Symbol(),Period(),MODE_UPPER,shift)>0)
        {
         fu=fu+1;
         f=f+1;
        }
      if(iFractals(Symbol(),Period(),MODE_LOWER,shift)>0)
        {
         fd=fd+1;
         f=f+1;
        }
      shift=shift+1;
     }
   if(fu==2){return(2);}
   if(fd==2){return(1);}
   return(0);
  }

第1の関数は条件をチェックし、続く2つは条件を設定します。

ストップレベルを計算する関数を考察します。誤った設定になっていれば、この関数がロット値を定義します。

//+------------------------------------------------------------------+
//| preliminary initialization of variables                          |
//+------------------------------------------------------------------+
int preinit()
  {
   Lot=NormalizeDouble(MathFloor(LotSpliter*AccountBalance()*AccountLeverage()
      /Ask/MathPow(10,Digits+1)*10)/10,1);
   if(MaxLot>0 && Lot>MaxLot){Lot=MaxLot;}
   if(Lot>MarketInfo(Symbol(),MODE_MAXLOT)){Lot=MarketInfo(Symbol(),MODE_MAXLOT);}
   PP=0;
   StopLoss=sl;
   TakeProfit=tp;
   if(TakeProfit!=0 && TakeProfit<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      TakeProfit=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   if(StopLoss!=0 && StopLoss<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      StopLoss=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   return(0);
  }

ここで事前に設定したストップレベルに応じてオーダーをオープンする関数を設定します。

//+------------------------------------------------------------------+
//| returns true in case of a successful opening of Buy              |
//+------------------------------------------------------------------+
bool OrderBuy()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4),
        NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage, 0,
       NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask,
       Slippage, 0, 0, 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4), 0, 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }
//+------------------------------------------------------------------+
//|   returns true in case of a successful opening of Sell           |
//+------------------------------------------------------------------+
bool OrderSell()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }

次の関数は指定のチケット、ボリューム、価格でオーダーをクローズします。

//+-------------------------------------------------------------------------+
//|  returns true in case of a successful closing of an order with Ticket   |
//+-------------------------------------------------------------------------+
bool CloseOnlyOrder(int Ticket, double Lots ,double priceClose)
  {
   bool res=false;
   res=OrderClose(Ticket, Lots, priceClose, Slippage, 0);
   return(res);

のちに処理を行うポジション番号のオーダーを選択する関数を考察します。

//+--------------------------------------------------------------------------------+
//| returns true in case of a successful choosing of an order in the position pos  |
//+--------------------------------------------------------------------------------+
bool SelectOnlyOrder(int pos)
  {
   bool res=false;
   res=OrderSelect(pos,SELECT_BY_POS,MODE_TRADES);
   return(res);
  }
//+------------------------------------------------------------------+

コーディング推奨事項

第 1 に、真や偽の代わりに 0 や 1 にオプションを設定します。これは Expert Advisor のよりよい最適化に役立ちます。第 2 に、市場が条件とは反対の方向に変動するとき、潜在的損失を制限するためのストップロスをおろそかにしてはいけません。第 3 に、ストップロスを設定せずエキスパートを検証してはいけません。そうすれば、おそらくデポジットをすぐに失くしてしまうことになります。第 4 に、コードを簡単に理解するのに役立つ関数やブロックを使用します。



おわりに

Expert Advisor を作成することは簡単です。そしてそのタスクをさらに簡単にするために、添付ファイルには本稿で分析した Expert Advisor が入っています。ご活用ください。

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

添付されたファイル |
template.mq4 (8.07 KB)
『市場での勘』を養う手段としてのベットのモデル化 『市場での勘』を養う手段としてのベットのモデル化
本稿では、『市場での勘』の概念とそれを発展させる方法について詳しく説明します。ここに述べられる方法はシンプルなゲーム形式でのファイナンシャル ベッティングに基づいています。
楽になりエラーが少なくてすむように EA コードを短くする方法 楽になりエラーが少なくてすむように EA コードを短くする方法
本稿で述べられるシンプルなコンセプトにより、MQL4 で自動売買システムを作成する人が既存のトレーディングシステムをシンプルにすることができ、またコードが短くなることで新規にシステムを作成するのに必要な時間を削減することもできます。
快適なスキャルピング 快適なスキャルピング
本稿では快適なスキャルピングのためのツールを作成する方法を説明します。トレードをオープンするそのような方法はどんな取引にも適用可能なものです。
CSV ファイルを介した MetaTrader 4 と Matlab 間の連携 CSV ファイルを介した MetaTrader 4 と Matlab 間の連携
CSV ファイルを介した MetaTrader 4 と Matlab 間のデータ配列交換作成法の段階的手順。