English Deutsch
preview
MQL5を使ったシンプルな多通貨エキスパートアドバイザーの作り方(第7回):オーサムオシレーターシグナルを持つジグザグ

MQL5を使ったシンプルな多通貨エキスパートアドバイザーの作り方(第7回):オーサムオシレーターシグナルを持つジグザグ

MetaTrader 5 | 22 5月 2024, 10:41
115 0
Roberto Jacobs
Roberto Jacobs

はじめに

多通貨EAは、1つの銘柄チャートから複数の銘柄ペアの注文をオープン、クローズ、管理できる自動売買です。
この記事では、30ペアを対象とし、オーサムオシレーターでフィルタされたジグザグ指標、またはオーサムオシレーターとの互いのシグナルをフィルタするジグザグ指標を使用したEA取引に焦点を当てます。

以前の記事で示したように、取引端末とストラテジーテスターの両方でMQL5のパワー、能力、機能を使えば、多通貨取引が可能です。
効率的かつ効果的な自動売買を求めるトレーダーのニーズに応えるために、信頼性の高いMQL5が提供するパワー、能力、設備に依存します。ここでの目標は、様々なアイデアや戦略を使用してシンプルな多通貨EAを作成することです。この記事では、ジグザグ指標を使用することに焦点を当て、オーサムオシレーターでフィルタするか、互いのシグナルをフィルタします。


計画と機能

1.通貨ペアの取引

この多通貨EAは、以下の銘柄またはペアで取引するように計画されています。

外国為替
EURUSD, GBPUSD, AUDUSD, NZDUSD, USDCAD, USDCHF, USDJPY, EURGBP, EURAUD, EURNZD, EURCAD, EURCHF, EURJPY, GBPAUD, GBPNZD、
GBPCAD、GBPCHF、GBPJPY、AUDNZD、AUDCAD、AUDCHF、AUDJPY、NZDCAD、NZDCHF、NZDJPY、CADCHF、CADJPY、CHFJPY =28ペア

追加のメタル2ペア:XAUUSD(金)とXAGUSD(銀)

合計30ペア


この記事で取り上げたEAをスムーズに動作させるために、接頭辞や接尾辞の付いた銘柄名を自動的に処理する機能を実装しました。
ただし、この機能はMT5のFXと金属の銘柄ペア名に対してのみ動作し、特殊な銘柄やインデックスに対しては動作しないことに注意が必要です。


1.1. その他の機能

1.1.1.単一通貨EA

この多通貨EAを単一通貨またはスタンドアロンEAとして使用することについてのお問い合わせがありました。
これに対処するため、この多通貨EAを単一通貨EAとして使用できる機能を追加しました。

[Select Trading Pairs Mode (Multi or Single)]オプションでは、2つの取引ペア条件(単一通貨または多通貨)を選択することができます。

1.Single Pair(単一通貨)
2.Multi Pairs(多通貨)

EA入力パラメータを下図のように設定します。

取引ペアオプション


Single Pairを選択した場合
SP(シングルペア)オプションでは、それが配置されているペアでのみ取引にEAを制限します。
例えば、EAがEURUSDペアに配置されている場合、EURUSDペアでのみ取引します。

Multi Pairsを選択した場合
Selected Pairs to Tradeオプショングループには、取引される10組のオプションが含まれています。
これらのペアの1つはTrader's Wishes Pairsと呼ばれ、トレーダーはEA入力プロパティに取引するペアを手動で入力する必要があります。 
ただし、入力したペア名がすでに30組のリストに登録されていることが重要です。

Trader's Wishes Pairsオプションは、EAが単一通貨のみを取引するように、またはスタンドアロンEAとして動作するように使用することができます。
EAは、提供された希望のペア名でのみ取引または動作します。これにより、単一のペアの取引や作業への集中的なアプローチが保証されます。

トレーダーがXAUUSDのペア名のみを入力した場合、EAはそのペアの取引のみをおこないます。
EAは、利用可能な30ペアの中でその位置に関係なく、XAUUSDペア上でのみ取引をおこないます。

EA入力パラメータの設定は、下図のように設定する必要があります。

stand-alone-twp


そこで今回は、単一通貨を取引する方法と、EAを使用してスタンドアロンEAとして活動する方法の2つを紹介します。

1.MP(マルチペア)オプションを選択し、Trader's Desired Pairsオプションを選択します。ただし、XAUUSDのようにペア名を1つだけ入力します。
このオプションでは、EAはTrader Wishes Pairsで指定されたペアの取引のみに制限され、他のペアでは取引しません。

2.[Select Trading Pairs Mode]で、SP(シングルペア)を選択します。
EAがEURUSDペアに適用されている場合、EURUSDペアで排他的に取引します。


1.1.2. 特定時間での取引

[Trade on Specific Time]グループでは、タイムゾーンで取引したいトレーダーのためのオプションが用意されています。
多分、多くのトレーダーは、タイムゾーンに従って取引したいので、取引するペアは、取引セッションの時間に対応することができます。よって、このEAでは、まだ取引セッション(タイムゾーン)のオプションを使用します。


2.シグナル指標

2.1.ジグザグ指標

ジグザグ指標は、不必要なノイズを排除した値動きを計測する方法です。この指標は、価格スイング(高値と安値)の間の距離を決定することによって動作し、その後、プルバックを計算します。プルバックが一定の予想額を超えた場合、値動きは完了したとみなされます。

よく知られているように、ジグザグは株式市場から為替取引に登場した最も古いテクニカル指標の1つで、市場の構造を視覚化することができます。
値動きを評価しようとするときは、軽微な値動きは自動的にフィルタされます。
ジグザグ指標を活用すれば、市場の構造をより明確に理解することができます。

ランダムな価格変動の影響を受けて値動きの状況が変動する場合、ジグザグ指標は、価格トレンドや価格トレンドの変化を特定するのに役立ちます。


テクニカルアナリストはジグザグ指標についてこう言います。

  • ランダムな価格変動の影響を軽減し、価格 トレンドや価格トレンドの変化を識別するために使用される
  • ノイズレベルを下げ、基本的なトレンドの上下を強調する
  • 強いトレンド相場で最も効果を発揮する

ジグザグ指標の制限
他のトレンドフォロー指標と同様に、売買シグナルは過去の値動きを見て決定されるため、将来の値動きを正確に予測できない可能性があります。例えば、ジグザグ線が生成されるまでに、トレンドの大部分がすでに発生している可能性があります。

トレーダーは、直近のジグザグ線が永久的なものではない可能性があることに注意すべきです。価格が方向転換すると、指標は新しい線を引き始めます。 
その線が指標の設定パーセンテージに達せずに証券の価格が方向転換した場合、その線は削除され、元のトレンド方向に延長されたジグザグ線に置き換わります。


ジグザグのパラメータ設定

ジグザグ指標には3つのパラメータがあります。

1. Depth(デフォルト値:12)
チャートの一連のバーのどのくらい後ろまで見るかを示します。
高さと低さを明確にするためには、十分なDepthを確保する必要があります。
これは、2本目の最大または最小の乖離がないバーの最小本数です(例:ローソク足xで最大があり、深さが12の場合、少なくともx+12本までは次の最大を描画できません)。

2. Deviation(デフォルト値:5)
トレンドラインを陽線から陰線に変化させるのに必要な価格変化の割合を示します。

3. Backstep(デフォルト値:3)
スイングの高値と安値の間の最小のバー数


ジグザグ指標の公式:

ZigZag (HL, %change=X, retrace=FALSE, LastExtreme=TRUE)

 もし%change>=Xなら、ジグザグにプロットします。 

ここで

HL = 高値-安値シリーズまたは終値シリーズ 

%change = 価格の最小値動き、単位はパーセント

Retrace = 変化は前の動きの綾戻しか、それとも頂点から谷までの絶対的な変化か

LastExtreme = 極端な価格が複数の期間にわたって同じである場合、極端な価格は最初の観測か最後の観測か 


私の観察では、ジグザグ指標には、少なくとも4つのシグナルアルゴリズムがあります。
そして、このEAでは、ジグザグ指標から4つのアルゴリズムシグナルを選択して試すことができるようにオプションを作成しました。


2.2. オーサムオシレーター(AO、Awesome Oscillator)

オーサムオシレーターは、市場のトレンドと勢いを識別するために使用するモメンタム指標です。有名なテクニカルアナリストであるビル・ウィリアムズによって開発され、そのシンプルさと信頼性からトレーダーの間で人気のツールとなっています。

オーサムオシレーターは、市場の勢いを示す指標で、最近の市場の動きを過去の市場の動きと比較します。
中央にゼロラインを使い、その両側の値動きを2つの異なる移動平均の比較に従ってプロットします。

オーサムオシレーターは、金融商品の中点価格(H+L)/2の5期間SMAから34期間単純移動平均(SMA)を引くことによって計算されます。

中点価格は一定期間の高値と安値の両方を考慮しているため、始値や終値よりも真の市場価格をより正確に表していると考えられています。
AOは陽線と陰線の間で変動し、陽線は強気トレンドを、陰線は弱気トレンドを示します。

34期間の単純移動平均(SMA)と5期間の単純移動平均(SMA)の値は、指標コードに恒久的に設定され、指標入力パラ メータのプロパティで変更することはできません。

オーサムオシレーター = 5期間SMA(中央値、5期間) - 34期間SMA(中央値、34期間)

ここで、中央値とは、(セッション期間の高値+セッション期間の安値)÷2です。


AO指標には、少なくとも3つのシグナルアルゴリズムがあります。
したがって、このEAでは、このAO指標から3つのアルゴリズムシグナルを選択して試すことができるようにオプションを作成しました。

このジグザグ指標は、オーサムオシレーターでフィルタされる、または互いのシグナルをフィルタします。

以下のシグナル図は、オプション番号2のジグザグシグナルとオプション番号2のAOシグナルです。

ZZ_AO_Indi_Signal_illustration

ZZ_AO_Indi_Signal_illustration_variation


3.取引と注文管理

この多通貨EAで取引を管理する方法はいくつかあります。

3.1.ストップロス注文

オプション:Use Order Stop Loss:Yes/No

  • Use Order Stop LossでNoを選択:すべての注文はストップロスなしで発注される

[Close Trade By Opposite Signal]がYesに設定されている場合、ストップロスなしで注文を開くことは安全です。しかし、[Close Trade By Opposite Signal]がNoに設定されている場合は、株式に対するリスクが非常に高くなります。そこで、エクイティと残高のパーセンテージを確認できる機能を追加しました。この場合、残高の持分割合が(100% - 取引ごとの持分リスク割合)より小さいと、EAは CheckLoss()関数(仮想ストップロスを実行する関数)を実行し、設定されたストップロス値より大きい損失を持つ注文をクローズします。
            //--
            if(use_sl==No && CheckVSLTP==Yes)
              {
                if(!mc.CheckEquityBalance())
                  if(mc.CloseAllLoss())
                    mc.Do_Alerts(symbol,"Close order due stop in loss to secure equity.");
              }
            //--

bool MCEA::CheckEquityBalance(void)
  {
//---
   bool isgood=false;
   if((mc_account.Equity()/mc_account.Balance()*100) > (100.00-Risk)) isgood=true;
   //--
   return(isgood);
//---
  } //-end CheckEquityBalance()
//---------//

bool MCEA::CheckLoss(const string symbol,ENUM_POSITION_TYPE intype,double slc=0.0)
   {
//---
     Pips(symbol);
     bool inloss=false;
     double lossval=slc==0.0 ? (SLval*0.5) : slc;
     double posloss  = mc_symbol.NormalizePrice(slc*pip);
     int ttlorder=PositionsTotal(); // number of open positions
     //--
     for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double price    = mc_position.PriceCurrent();
                  double pos_open = mc_position.PriceOpen();
                  double posloss  = mc_symbol.NormalizePrice(lossval*pip);
                  double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
                  //---
                  if(type==intype && pricegab>posloss) inloss=true;
                }
            }
       }
     //--
     return(inloss);
//----
   } //-end CheckLoss()
//---------//

bool MCEA::CloseAllLoss(void)
   {
//----
    ResetLastError();
    //--
    bool orclose=false;
    string isloss="due stop in loss.";
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int ttlorder=PositionsTotal(); // number of open positions
    //--
    for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         Pips(symbol);
         double posloss=mc_symbol.NormalizePrice(SLval*pip);
         orclose=false;
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double price    = mc_position.PriceCurrent();
                  double pos_open = mc_position.PriceOpen();
                  double posloss  = mc_symbol.NormalizePrice(SLval*pip);
                  double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
                  ulong  position_ticket = PositionGetTicket(i);
                  //---
                  if(type==POSITION_TYPE_BUY && pricegab>posloss)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close Buy %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
                    }
                  if(type==POSITION_TYPE_SELL && pricegab>posloss)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close Sell %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
                    }
                }
            }
       }
     //--
     return(orclose);
//----
   } //-end CloseAllLoss()
//---------//

  • Use Order Stop LossがYesの場合:再びオプションが与えられます。Use Automatic Calculation Stop Loss:Yes/No
  • Automatic Calculation Stop LossでYesを選択:ストップロスの計算はEAで自動的におこなわれる
  • Automatic Calculation Stop LossでNoを選択:トレーダーはストップロスの値をPipsで入力する必要がある
  • Use Order Stop LossがNoの場合:EAは、開かれた各注文について、シグナル状態がまだ良好で利益を得るために注文を維持できるか、または、シグナルが弱まり、利益を保存するために注文を閉じる必要がある状態か、または、シグナル状態の方向が逆になっているため、損失状態で注文を閉じる必要があるかを確認します。

注:特に弱いシグナルによる取引決済と利益の保存については、それをアクティブにするかどうかのオプションが与えられます。

ExpertActionTrade()関数の一部:

                //--
                if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes)
                  {
                    mc.CheckOpenPMx(symbol);
                    if(mc.profitb[x]>mc.minprofit && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell) 
                      {
                        mc.CloseBuyPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal.");
                      }
                    if(mc.profits[x]>mc.minprofit && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy)
                      {
                        mc.CloseSellPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal.");
                      }
                  }
                //--

シグナルが弱いために取引を終了し、利益を保存するコードは以下の通りです。

int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int AOdir=AOColorSignal(symbol);
    int ZZDir=ZigZagSignal(symbol);
    //--
    if(exis==down && (AOdir==rise||ZZDir==rise)) ret=rise;
    if(exis==rise && (AOdir==down||ZZDir==down)) ret=down;
    //--
    return(ret);
//---
  } //-end GetCloseInWeakSignal()
//---------//
  • アクティブ化されていない場合(No)、シグナルが弱まっても注文は維持されるか、利益を保存するために決済されない
  • アクティブ化されている場合(Yes)、ジグザグ指標とAO指標の条件は以下の通りです。

買い注文の決済: 
AO指標の色が緑から赤(デフォルトの色)に変わるか、ジグザグ指標が極端な高値位置に達して価格が方向転換すると、買い注文が決済されます。

売り注文の決済: 
AO指標の色が赤から緑(デフォルトの色)に変わるか、ジグザグ指標が極端な安値位置に達して価格が方向転換すると、売り注文が決済されます。

ストップロス注文を設定するコードは次のとおりです。

double MCEA::OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    slv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice-38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
           else slv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice+38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
           else slv=0.0;
         }
      }
    //---
    return(slv);
//---
  } //-end OrderSLSet()
//---------//


3.2.テイクプロフィット注文

オプション:Use Order Take Profit:Yes/No

  • Use Order Take ProfitでNoを選択:すべての注文はテイクプロフィットなしで発注される
  • Use Order Take ProfitがYesの場合:再びオプションが与えられます。Use Automatic Calculation Order Take Profit:Yes/Noオプションを指定することになります。
  • Automatic Calculation Order Take ProfitでYesを選択:テイクプロフィット注文の計算はEAで自動的におこなわれる
  • Automatic Calculation Order Take ProfitでNoを選択し:トレーダーは注文のテイクプロフィット値をPipsで入力する必要がある

テイクプロフィット注文を設定するコードは以下の通りです。

double MCEA::OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    tpv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice+50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
           else tpv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice-50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
           else tpv=0.0;
         }
      }
    //---
    return(tpv);
//---
  } //-end OrderTPSet()
//---------//


3.3.トレール注文

オプション:Use Trailing Stop Loss:Yes/No

  • [Use Trailing SL]オプションがNoの場合、EAはトレーリングストップロスやトレーリングテイクプロフィットをおこないません。
  • Use Trailing SLがYesの場合:トレーダーは3つのオプションから選択することができます。

1.価格によるトレーリング
トレーリングストップは、価格の動きと入力プロパティの値を使用してEAによって実行されます。

2.指標によるトレーリング
トレーリングストップは、VIDYA 指標を使用してEAによって実行されます。
私の研究と実験によると、VIDYA指標は、Parabolic SARや移動平均指標のいくつかのバリエーションと比較してわずかに優れており、トレーリングストップに理想的です。
VIDYA指標はParabolic SAR指標に比べて値動きに近く、AMA、DEMA、MA指標に比べて値動きからさらに離れています。
そこで今回は、VIDYA指標をベースにしたトレーリングストップ関数を使用することにしました。

3.前バーのHIGHまたはLOWでのトレーリングストップ
買い注文の場合、トレーリングストップポジションは直前のバーの安値(LOW[1])に置かれます。
売り注文の場合、トレーリングストップポジションは前のバーの高値(HIGH[1])に置かれます。

トレーリングストップ価格関数:

double MCEA::TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type)
  {
//---
    int br=2;
    double pval=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    //--
    switch(TS_type)
      {
        case byprice:
          {
            RefreshTick(xsymb);
            if(ptype==POSITION_TYPE_BUY)  pval=mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip);
            if(ptype==POSITION_TYPE_SELL) pval=mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip);
            break;
          }
        case byindi:
          {
            double VIDyAv[];
            ArrayResize(VIDyAv,br,br);
            ArraySetAsSeries(VIDyAv,true);
            CopyBuffer(hVIDyAv[x],0,0,br,VIDyAv);
            RefreshPrice(xsymb,TFt,br);
            //--
            if(ptype==POSITION_TYPE_BUY  && (VIDyAv[0]<mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip)))
               pval=VIDyAv[0];
            if(ptype==POSITION_TYPE_SELL && (VIDyAv[0]>mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip)))
               pval=VIDyAv[0];
            break;
          }
        case byHiLo:
          {
            UpdatePrice(xsymb,TFt,2);
            //--
            if(ptype==POSITION_TYPE_BUY  && (HIGH[0]>HIGH[1]))
               pval=LOW[1];
            if(ptype==POSITION_TYPE_SELL && (LOW[0]<LOW[1]))
               pval=HIGH[1];
            break;
          }
      }
    //--
    return(pval);
//---
  } //-end TSPrice()
//---------//


bool MCEA::ModifyOrdersSL(const string symbx,int TS_type)
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   int TRSP=TS_type;
   bool modist=false;
   int x=PairsIdxArray(symbx);
   Pips(symbx);
   //--
   int total=PositionsTotal();
   //--        
   for(int i=total-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       if(symbol==symbx && mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               RefreshTick(symbol);
               double price = mc_position.PriceCurrent();
               double vtrsb = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
               double pos_open   = mc_position.PriceOpen();
               double pos_stop   = mc_position.StopLoss();
               double pos_tp     = mc_position.TakeProfit();
               double pos_profit = mc_position.Profit();
               double pos_swap   = mc_position.Swap();
               double pos_comm   = mc_position.Commission();
               double netp=pos_profit+pos_swap+pos_comm;
               double modstart=mc_symbol.NormalizePrice(pos_open+TSmin*pip);
               double modminsl=mc_symbol.NormalizePrice(vtrsb+((TSmin-1.0)*pip));
               double modbuysl=vtrsb;
               bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop));
               //--
               if(modbuy && netp>minprofit)
                 {
                   modist=mc_trade.PositionModify(symbol,modbuysl,pos_tp);
                 }  
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               RefreshTick(symbol);
               double price = mc_position.PriceCurrent();
               double vtrss = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
               double pos_open   = mc_position.PriceOpen();
               double pos_stop   = mc_position.StopLoss();
               double pos_tp     = mc_position.TakeProfit();
               double pos_profit = mc_position.Profit();
               double pos_swap   = mc_position.Swap();
               double pos_comm   = mc_position.Commission();
               double netp=pos_profit+pos_swap+pos_comm;
               double modstart=mc_symbol.NormalizePrice(pos_open-TSmin*pip);
               double modminsl=mc_symbol.NormalizePrice(vtrss-((TSmin+1.0)*pip));
               double modselsl=vtrss;
               bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); 
               //--
               if(modsel && netp>minprofit)
                 {
                   modist=mc_trade.PositionModify(symbol,modselsl,pos_tp);
                 }  
             }
         }
     }
    //--
    return(modist);
//---
  } //-end ModifyOrdersSL()
//---------//


3.4.トレーリングテイクプロフィット

オプション:Use Trailing Take Profit:Yes/No

  • Use Trailing TPオプションがNoの場合、EAはトレーリングTPをおこないません。
  • Use Trailing TPオプションがYesの場合、トレーリング利益値をPipsで入力します(デフォルト値25pips)。EAは変数値TPmin(トレーリング利益最小値)に基づいてトレーリングTPを実行します。

bool MCEA::ModifyOrdersTP(const string symbx)
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   bool modist=false;
   int x=PairsIdxArray(symbx);
   Pips(symbx);
   //--
   int total=PositionsTotal();
   //--        
   for(int i=total-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       if(symbol==symbx && mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_tp   = mc_position.TakeProfit();
               double modbuytp = pos_tp==0.0 ? mc_symbol.NormalizePrice(pos_open+TPmin*pip) : pos_tp;
               double modpostp = mc_symbol.NormalizePrice(price+TPmin*pip);
               bool modtpb = (price>pos_open && modbuytp-price<TPmin*pip && pos_tp<modpostp);
               //--
               if(modtpb)
                 {
                   modist=mc_trade.PositionModify(symbol,pos_stop,modpostp);
                 }  
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_tp   = mc_position.TakeProfit();
               double modseltp = pos_tp==0.0 ? mc_symbol.NormalizePrice(pos_open-TPmin*pip) : pos_tp;
               double modpostp = mc_symbol.NormalizePrice(price-TPmin*pip);
               bool modtps = (price<pos_open && price-modseltp<TPmin*pip && pos_tp>modpostp);
               //--
               if(modtps)
                 {
                   modist=mc_trade.PositionModify(symbol,pos_stop,modpostp);
                 }  
             }
         }
     }
    //--
    return(modist);
//---
  } //-end ModifyOrdersTP()
//---------//


3.5.反対シグナルで取引を終了する

オプション:Close Trade By Opposite Signal:Yes/No

  • Close Trade By Opposite SignalがYesの場合:

売り注文が以前に発注され、その後指標のシグナルが反転した場合、売り注文は決済され、EAは買い注文を出します。その逆も同様です。
ExpertActionTrade()関数の一部:
if(Close_by_Opps==Yes && mc.xos[x]>0) mc.CloseSellPositions(symbol);
bool MCEA::CloseSellPositions(const string symbol)
  {
    //---
    ResetLastError();
    bool sellclose=false;
    int total=PositionsTotal(); // number of open positions
    ENUM_POSITION_TYPE closetype = POSITION_TYPE_SELL;
    ENUM_ORDER_TYPE     type_req = ORDER_TYPE_BUY;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int x=PairsIdxArray(symbol);
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        if(mc_position.SelectByIndex(i))
          {
            //--- Parameters of the order
            string position_Symbol   = PositionGetSymbol(i);
            ulong  position_ticket   = PositionGetTicket(i);
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            //--- if the MagicNumber matches
            if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
              { 
                //--
                if(type==closetype)
                  {
                    RefreshTick(position_Symbol);
                    sellclose=mc_trade.PositionClose(position_Symbol,slip);
                    //--- output information about the closure
                    PrintFormat("Close Sell #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                  }
              }
          }
      }
   //---
   return(sellclose);
//----
   } //-end CloseSellPositions()
//---------//

ExpertActionTrade()関数の一部:

if(Close_by_Opps==Yes && mc.xob[x]>0) mc.CloseBuyPositions(symbol);

bool MCEA::CloseBuyPositions(const string symbol)
   {
 //---
    //--
    ResetLastError();
    bool buyclose=false;
    int total=PositionsTotal(); // number of open positions
    ENUM_POSITION_TYPE closetype = POSITION_TYPE_BUY;
    ENUM_ORDER_TYPE     type_req = ORDER_TYPE_SELL;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int x=PairsIdxArray(symbol);
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        if(mc_position.SelectByIndex(i))
          {
            //--- Parameters of the order
            string position_Symbol   = PositionGetSymbol(i);
            ulong  position_ticket   = PositionGetTicket(i);
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            //--- if the MagicNumber matches
            if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
              { 
                //--
                if(type==closetype)
                  {
                    RefreshTick(position_Symbol);
                    buyclose=mc_trade.PositionClose(position_Symbol,slip);
                    //--- output information about the closure
                    PrintFormat("Close Buy #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                  }
              }
          }
      }
   //---
   return(buyclose);
//----
   } //-end CloseBuyPositions()
//---------//


Close Trade By Opposite SignalがNoの場合、問題が発生します。

1.注文は各ペアの取引合計の2倍となります。

2.1つのペアには損失状態の注文もあれば、利益状態の注文もあります。

3.損失と利益のバランスが悪いため、エクイティは損なわれます。

この問題を克服するために、SLとTPの注文条件を検出する関数をいくつか作りました。

ExpertActionTrade()関数の一部:

            //--
            mc.CheckOpenPMx(symbol);
            if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1))
              {
                if(mc.CheckProfitLoss(symbol))
                   mc.Do_Alerts(symbol,"Close order due stop in loss.");
              }
            //--

bool MCEA::CheckProfitLoss(const string symbol)
   {
//----
     ResetLastError();
     //--
     bool closeinloss=false;
     string isloss="due stop in loss.";
     //--
     int xx=PairsIdxArray(symbol);
     //--
     bool BuyProfitSellLoss=(xob[xx]>0 && CheckProfit(symbol,POSITION_TYPE_BUY)) && (xos[xx]>0 && CheckLoss(symbol,POSITION_TYPE_SELL,0.0));
     bool SellProfitBuyLoss=(xos[xx]>0 && CheckProfit(symbol,POSITION_TYPE_SELL)) && (xob[xx]>0 && CheckLoss(symbol,POSITION_TYPE_BUY,0.0));
     //--
     if(BuyProfitSellLoss && !SellProfitBuyLoss)
       {
         if(CloseSellPositions(symbol))
           {
             PrintFormat("Close Sell %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
             closeinloss=true;
           }
       }
     if(SellProfitBuyLoss && !BuyProfitSellLoss)
       {
         if(CloseBuyPositions(symbol))
           {
             PrintFormat("Close Buy %s %s %s",symbol,EnumToString(POSITION_TYPE_SELL),isloss);
             closeinloss=true;
           }
       }
     //--
     return(closeinloss);
//----
   } //-end CheckProfitLoss()
//---------//


CheckProfitLoss()関数は他の2つの関数を呼び出し、
買いの利益と売りの損失、または買いの損失と売りの利益の条件について1組の注文を比較します。

  • 買いの利益と売りの損失があれば、売り注文は決済されます。
  • 買いの損失と売りの利益があれば、買い注文は決済されます。

bool MCEA::CheckProfit(const string symbol,ENUM_POSITION_TYPE intype)
   {
//---
     Pips(symbol);
     double posprofit=mc_symbol.NormalizePrice((TPval*0.5)*pip);
     bool inprofit=false;
     //--
     int ttlorder=PositionsTotal(); // number of open positions
     //--
     for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double price     = mc_position.PriceCurrent();
                  double pos_open  = mc_position.PriceOpen();
                  double posprofit = mc_symbol.NormalizePrice((TPval*0.5)*pip);
                  double pricegab  = mc_symbol.NormalizePrice(fabs(price-pos_open));
                  //---
                  if(type==intype && posprofit<pricegab) inprofit=true;
                }
            }
       }
     //--
     return(inprofit);
//----
   } //-end CheckProfit()
//---------//

bool MCEA::CheckLoss(const string symbol,ENUM_POSITION_TYPE intype,double slc=0.0)
   {
//---
     Pips(symbol);
     bool inloss=false;
     double lossval=slc==0.0 ? (SLval*0.5) : slc;
     double posloss  = mc_symbol.NormalizePrice(slc*pip);
     int ttlorder=PositionsTotal(); // number of open positions
     //--
     for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double price    = mc_position.PriceCurrent();
                  double pos_open = mc_position.PriceOpen();
                  double posloss  = mc_symbol.NormalizePrice(lossval*pip);
                  double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
                  //---
                  if(type==intype && pricegab>posloss) inloss=true;
                }
            }
       }
     //--
     return(inloss);
//----
   } //-end CheckLoss()
//---------//


4. 手動注文管理

この多通貨EAでは、EAの作業を監視するトレーダーに効率性と有効性を提供するために、いくつかの手動クリックボタンを追加します。

4.1.Set SL / TP All Orders: 
このボタンは、トレーダーがパラメータセットUse Order Stop Loss (No)やUse Order Take Profit (No)を入力しているが、すべての注文でストップロスまたはテイクプロフィットを使用したい場合に便利です。 [Set SL / TP All Orders]ボタンをクリックすると、すべての注文が変更され、ストップロスやテイクプロフィットが適用されます。

4.2.Close All Orders:
すべての注文を決済したい場合、[Close All Orders]ボタンを1回クリックするだけで、すべての未決済注文が決済されます。

4.3.Close All Orders Profit:
すでに利益が出ている注文をすべて決済したい場合、[Close All Orders Profit]ボタンを1回クリックするだけで、すでに利益が出ているすべての未決済注文を決済することができます。


5.注文管理とチャート銘柄

1つのチャート銘柄から30ペアを取引する多通貨EAの場合、トレーダーがワンクリックでチャートの時間枠や銘柄を変更し、EAが注文を出すまたは決済する際の指標シグナルの精度を確認できるように、すべての銘柄にボタンパネルを提供することは非常に有用かつ簡単です。


MQL5プログラムでの実装計画

1.プログラムヘッダーと入力プロパティ

ヘッダーファイルMQL5をインクルードします。

//+------------------------------------------------------------------+
//|                             Include                              |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
//--
CTrade              mc_trade;
CSymbolInfo         mc_symbol;
CPositionInfo       mc_position; 
CAccountInfo        mc_account;
//---


以下は、使用するタイムゾーンの列挙です。

//--
enum tm_zone
 {
   Cus_Session,        // Trading on Custom Session
   New_Zealand,        // Trading on New Zealand Session
   Australia,          // Trading on Autralia Sydney Session
   Asia_Tokyo,         // Trading on Asia Tokyo Session
   Europe_London,      // Trading on Europe London Session
   US_New_York         // Trading on US New York Session
 };
//--


以下は、選択できる時間の列挙です。

//--
enum swhour
  {
    hr_00=0,   // 00:00
    hr_01=1,   // 01:00
    hr_02=2,   // 02:00
    hr_03=3,   // 03:00
    hr_04=4,   // 04:00
    hr_05=5,   // 05:00
    hr_06=6,   // 06:00
    hr_07=7,   // 07:00
    hr_08=8,   // 08:00
    hr_09=9,   // 09:00
    hr_10=10,  // 10:00
    hr_11=11,  // 11:00
    hr_12=12,  // 12:00
    hr_13=13,  // 13:00
    hr_14=14,  // 14:00
    hr_15=15,  // 15:00
    hr_16=16,  // 16:00
    hr_17=17,  // 17:00
    hr_18=18,  // 18:00
    hr_19=19,  // 19:00
    hr_20=20,  // 20:00
    hr_21=21,  // 21:00
    hr_22=22,  // 22:00
    hr_23=23   // 23:00
  };
//--


以下は、選択できる分の列挙です。

//--
enum inmnt
  {
    mn_00=0,   // Minute 0
    mn_05=5,   // Minute 5
    mn_10=10,  // Minute 10
    mn_15=15,  // Minute 15
    mn_20=20,  // Minute 20
    mn_25=25,  // Minute 25
    mn_30=30,  // Minute 30
    mn_35=35,  // Minute 35
    mn_40=40,  // Minute 40
    mn_45=45,  // Minute 45
    mn_50=50,  // Minute 50
    mn_55=55   // Minute 55
  };
//--


次は、取引に選択するオプションペアを10組を選択するための列挙です。

//--
enum PairsTrade
 {
   All30,  // All Forex 30 Pairs
   TrdWi,  // Trader Wishes Pairs 
   Usds,   // Forex USD Pairs
   Eurs,   // Forex EUR Pairs
   Gbps,   // Forex GBP Pairs
   Auds,   // Forex AUD Pairs
   Nzds,   // Forex NZD Pairs
   Cads,   // Forex CDD Pairs
   Chfs,   // Forex CHF Pairs
   Jpys    // Forex JPY Pairs
 };   
//--


YN列挙は、EA入力プロパティのYesまたはNoのオプションに使用されます。

//--
enum YN
  {
   No,
   Yes
  };
//--


以下は、使用する資金管理ロットサイズの列挙です。

//--
enum mmt
  {
   FixedLot,   // Fixed Lot Size
   DynamLot    // Dynamic Lot Size
  };
//--


以下は、シグナル指標の計算に使用する時間枠を選択するための列挙です。

//--
enum TFUSE
  {
   TFM5,     // 00_PERIOD_M5
   TFM15,    // 01_PERIOD_M15
   TFM30,    // 02_PERIOD_M30
   TFH1,     // 03_PERIOD_H1
   TFH2,     // 04_PERIOD_H2
   TFH3,     // 05_PERIOD_H3
   TFH4,     // 06_PERIOD_H4
   TFH6,     // 07_PERIOD_H6
   TFH8,     // 08_PERIOD_H8
   TFH12,    // 09_PERIOD_H12
   TFD1      // 10_PERIOD_D1
  };
//--

TFUSE列挙体では、EAによる時間枠計算の使用をTF-M5からTF-D1までに制限しています。


以下は、トレーリングストップの計算で使用するタイプを選択するための列挙です。

//--
enum TrType
  {
    byprice, // Trailing Stop by Price
    byindi,  // Trailing Stop by Indicator
    byHiLo   // Trailing Stop in HIGH or LOW bar
  };
//--


以下は、EAが取引する取引の種類、単一通貨または複数通貨を選択するための列挙です。

//--
enum MS
 {
   SP, // Single Pair
   MP  // Multi Pairs
 };
//--


ジグザグ指標からシグナルアルゴリズムを選択するための列挙

//--
enum SignalZZ
 {
   SZZ1,  // ZigZagSignal 1
   SZZ2,  // ZigZagSignal 2
   SZZ3,  // ZigZagSignal 3
   SZZ4   // ZigZagSignal 4
 };
//--


AO指標からシグナルアルゴリズムを選択するための列挙

//--
enum SignalAO
 {
   SAO1,  // AOSignal 1
   SAO2,  // AOSignal 2
   SAO3   // AOSignal 3
 };
//--


EA入力プロパティ

//---
input group               "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE               tfinuse = TFH4;             // Select Expert TimeFrame, default PERIOD_H4
//---
input group               "=== ZigZag Indicator Input Properties ===";  // ZigZag Indicator Input Properties
input int                 zzDepth = 12;               // Input ZigZag Depth, default 12
input int                 zzDevia = 5;                // Input ZigZag Deviation, default 5
input int                 zzBackS = 3;                // Input ZigZag Back Step, default 3
input SignalZZ              sigzz = SZZ2;             // Select ZigZag Signal to Use
input SignalAO              sigao = SAO2;             // Select AO Signal to Use
//---
input group               "=== Selected Pairs to Trade ===";  // Selected Pairs to trading
input MS                trademode = MP;              // Select Trading Pairs Mode (Multi or Single)
input PairsTrade         usepairs = All30;           // Select Pairs to Use
input string         traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
//--
input group               "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
input mmt                  mmlot = DynamLot;         // Money Management Type
input double                Risk = 10.0;             // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
input double                Lots = 0.01;             // Input Manual Lot Size FixedLot
//--Trade on Specific Time
input group               "=== Trade on Specific Time ==="; // Trade on Specific Time
input YN           trd_time_zone = Yes;              // Select If You Like to Trade on Specific Time Zone
input tm_zone            session = Cus_Session;      // Select Trading Time Zone
input swhour            stsescuh = hr_00;            // Time Hour to Start Trading Custom Session (0-23)
input inmnt             stsescum = mn_15;            // Time Minute to Start Trading Custom Session (0-55)
input swhour            clsescuh = hr_23;            // Time Hour to Stop Trading Custom Session (0-23)
input inmnt             clsescum = mn_55;            // Time Minute to Stop Trading Custom Session (0-55)
//--Day Trading On/Off
input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group               "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN                  use_sl = No;               // Use Order Stop Loss (Yes) or (No)
input YN                  autosl = Yes;              // Use Automatic Calculation Stop Loss (Yes) or (No)
input double               SLval = 30.0;             // If Not Use Automatic SL - Input SL value in Pips
input YN                  use_tp = Yes;              // Use Order Take Profit (Yes) or (No)
input YN                  autotp = Yes;              // Use Automatic Calculation Take Profit (Yes) or (No)
input double               TPval = 60.0;             // If Not Use Automatic TP - Input TP value in Pips
input YN              TrailingSL = Yes;              // Use Trailing Stop Loss (Yes) or (No)
input TrType               trlby = byHiLo;           // Select Trailing Stop Type
input double               TSval = 10.0;             // If Use Trailing Stop by Price Input value in Pips
input double               TSmin = 5.0;              // Minimum Pips to start Trailing Stop
input YN              TrailingTP = Yes;              // Use Trailing Take Profit (Yes) or (No)
input double               TPmin = 25.0;             // Input Trailing Profit Value in Pips
input YN           Close_by_Opps = Yes;              // Close Trade By Opposite Signal (Yes) or (No)
input YN               SaveOnRev = Yes;              // Close Trade and Save profit due to weak signal (Yes) or (No)
input YN              CheckVSLTP = Yes;              // Check Virtual SL/TP & Close Loss Trade (Yes) or (No)
//--Others Expert Advisor Parameter
input group               "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN                  alerts = Yes;              // Display Alerts / Messages (Yes) or (No)
input YN           UseEmailAlert = No;               // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;               // Send Notification (Yes) or (No)
input YN      trade_info_display = Yes;              // Select Display Trading Info on Chart (Yes) or (No)
input ulong              magicEA = 20240218;         // Expert ID (Magic Number)
//---

注:Expert ID(マジックナンバー)の入力プロパティが空白のままの場合、EAは手動で開かれた注文を管理できます。


Global Strategy EA Parameters EA入力プロパティグループで、トレーダーは指標シグナル計算のEA時間枠をデフォルトのPERIOD_H4で選択するように指示されます。

EAのSelect Pairs to Tradeプロパティグループで、トレーダーは提供されている10のオプションから取引するペアを選択する必要があります。デフォルトでは、すべての外国為替30ペアが設定されています。

取引されるペアを設定するには、HandlingSymbolArrays()関数を呼び出します。HandlingSymbolArrays()関数で、取引されるすべてのペアを処理します。

void MCEA::HandlingSymbolArrays(void)
  {
//---
    string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",
                    "EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
                    "GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
                    "NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; // 30 pairs
    string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; // USD pairs
    string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; // EUR pairs
    string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; // GBP pairs
    string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; // AUD pairs
    string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; // NZD pairs
    string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; // CAD pairs
    string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; // CHF pairs
    string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; // JPY pairs
    //--
    sall=ArraySize(All30);
    arusd=ArraySize(USDs);
    areur=ArraySize(EURs);
    aretc=ArraySize(JPYs);
    ArrayResize(VSym,sall,sall);
    ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
    //--
    if(usepairs==TrdWi && StringFind(traderwishes,"eg.",0)<0)
      {
        string to_split=traderwishes; // A string to split into substrings pairs name
        string sep=",";               // A separator as a character 
        ushort u_sep;                 // The code of the separator character 
        //--- Get the separator code 
        u_sep=StringGetCharacter(sep,0);
        //--- Split the string to substrings 
        int p=StringSplit(to_split,u_sep,SPC); 
        if(p>0)
          {
            for(int i=0; i<p; i++) StringToUpper(SPC[i]);
            //--
            for(int i=0; i<p; i++)
              {
                if(ValidatePairs(SPC[i])<0) ArrayRemove(SPC,i,1);
              }
          }
        arspc=ArraySize(SPC);
      }
    //--
    SetSymbolNamePS();      // With this function we will detect whether the Symbol Name has a prefix and/or suffix
    //--
    if(inpre>0 || insuf>0)
      {
        if(usepairs==TrdWi && arspc>0)
          {
            for(int t=0; t<arspc; t++)
              {
                SPC[t]=pre+SPC[t]+suf;
              }
          }
        //--
        for(int t=0; t<sall; t++)
          {
            All30[t]=pre+All30[t]+suf;
          }
        for(int t=0; t<arusd; t++)
          {
            USDs[t]=pre+USDs[t]+suf;
          }
        for(int t=0; t<areur; t++)
          {
            EURs[t]=pre+EURs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            GBPs[t]=pre+GBPs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            AUDs[t]=pre+AUDs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            NZDs[t]=pre+NZDs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            CADs[t]=pre+CADs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            CHFs[t]=pre+CHFs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            JPYs[t]=pre+JPYs[t]+suf;
          }
      }
    //--
    ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
    ArrayResize(AS30,sall,sall);
    ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
    for(int x=0; x<sall; x++) {SymbolSelect(AS30[x],true);}
    if(ValidatePairs(Symbol())>=0) symbfix=true;
    if(!symbfix) 
      {
        Alert("Expert Advisors will not trade on pairs "+Symbol());
        Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
        ExpertRemove();
      }
    //--
    switch(usepairs)
      {
        case 0: // All Forex & Metal 30 Pairs
          {
            ArrayResize(DIRI,sall,sall);
            arrsymbx=sall;
            ArraySymbolResize();
            ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
            pairs="Multi Currency "+string(sall)+" Pairs";
            //--
            break;
          }
        case 1: // Trader wishes pairs
          {
            ArrayResize(DIRI,arspc,arspc);
            arrsymbx=arspc;
            ArraySymbolResize();
            ArrayCopy(DIRI,SPC,0,0,WHOLE_ARRAY);
            pairs="("+string(arspc)+") Trader Wishes Pairs";
            //--
            break;
          }
        case 2: // USD pairs
          {
            ArrayResize(DIRI,arusd,arusd);
            arrsymbx=arusd;
            ArraySymbolResize();
            ArrayCopy(DIRI,USDs,0,0,WHOLE_ARRAY);
            pairs="("+string(arusd)+") Multi Currency USD Pairs";
            //--
            break;
          }
        case 3: // EUR pairs
          {
            ArrayResize(DIRI,areur,areur);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,EURs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex EUR Pairs";
            //--
            break;
          }
        case 4: // GBP pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,GBPs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex GBP Pairs";
            //--
            break;
          }
        case 5: // AUD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,AUDs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex AUD Pairs";
            //--
            break;
          }
        case 6: // NZD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,NZDs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex NZD Pairs";
            //--
            break;
          }
        case 7: // CAD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,CADs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex CAD Pairs";
            //--
            break;
          }
        case 8: // CHF pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,CHFs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex CHF Pairs";
            //--
            break;
          }
        case 9: // JPY pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,JPYs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex JPY Pairs";
            //--
            break;
          }
      }
    //--
    return;
//---
  } //-end HandlingSymbolArrays()
//---------//


HandlingSymbolArrays()関数内でSetSymbolNamePS()関数を呼び出します。SetSymbolNamePS()を使えば、プレフィックスやサフィックスを含む銘柄名を扱えるようになります。

void MCEA::SetSymbolNamePS(void)
  {
//---
   int sym_Lenpre=0;
   int sym_Lensuf=0;
   string sym_pre="";
   string sym_suf="";
   SymbolSelect(Symbol(),true);
   string insymbol=Symbol();
   int inlen=StringLen(insymbol);
   int toseek=-1;
   string dep="";
   string bel="";
   string sym_use ="";
   int pairx=-1;
   string xcur[]={"EUR","GBP","AUD","NZD","USD","CAD","CHF"}; // 7 major currency
   int xcar=ArraySize(xcur);
   //--
   for(int x=0; x<xcar; x++)
     {
       toseek=StringFind(insymbol,xcur[x],0);
       if(toseek>=0)
         {
           pairx=x;
           break;
         }
     }
   if(pairx>=0)
     {
       int awl=toseek-3 <0 ? 0 : toseek-3;
       int sd=StringFind(insymbol,"SD",0);
       if(toseek==0 && sd<4)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
       if(toseek>0)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
         {
           dep=StringSubstr(insymbol,awl,3);
           bel=StringSubstr(insymbol,awl+3,3);
           sym_use=dep+bel;
         }
     }
   //--
   string sym_nmx=sym_use;
   int lensx=StringLen(sym_nmx);
   //--
   if(inlen>lensx && lensx==6)
     {
       sym_Lenpre=StringFind(insymbol,sym_nmx,0);
       sym_Lensuf=inlen-lensx-sym_Lenpre;
       //--
       if(sym_Lenpre>0)
         {
           sym_pre=StringSubstr(insymbol,0,sym_Lenpre);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_pre,xcur[i],0)>=0) sym_pre="";
         }
       if(sym_Lensuf>0)
         {
           sym_suf=StringSubstr(insymbol,sym_Lenpre+lensx,sym_Lensuf);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_suf,xcur[i],0)>=0) sym_suf="";
         }
     }
   //--
   pre=sym_pre;
   suf=sym_suf;
   inpre=StringLen(pre);
   insuf=StringLen(suf);
   posCur1=inpre;
   posCur2=posCur1+3;
   //--
   return;
//---
  } //-end SetSymbolNamePS()
//---------//

注:EAがペアを検証します。  ペア名に入力ミス(タイプミス)があったりペア検証に失敗したりした場合、EAには警告が表示され、EAはチャートから削除されます。


EA入力プロパティのTrade on Specific Timeグループで、トレーダーはTrade on Specific Time ZoneでYes/Noを選択します。

Trade on Specific Time ZoneオプションがNoに指定されている場合、EAはMT5の00:15から23:59まで取引します。

Yesの場合は、列挙オプションを選択します。

  • カスタムセッションでの取引
  • ニュージーランドセッションでの取引
  • オーストラリアシドニーセッションでの取引
  • アジア東京セッションでの取引
  • ヨーロッパロンドンセッションでの取引
  • アメリカニューヨークセッションでの取引

デフォルトでは、Trading on Specific Time ZonesはYesに設定され、Trading on Custom Sessionsに設定されています。

カスタムセッションでの取引:
このセッションで、トレーダーは取引を開始する時間または時間と分、取引を停止する時間と分を設定しなければなりません。これは、EAが開始から終了までの指定された期間のみ活動をおこなうことを意味します。

一方、ニュージーランド取引セッションからニューヨーク米国取引セッションでは、取引開始から取引終了までの時間がEAによって計算されます。


2.EA操作クラス

EAのワークフローを構築し設定するために、多通貨EAに必要なすべての変数、オブジェクト、関数を宣言するクラスを作成しました。

//+------------------------------------------------------------------+
//| Class for working Expert Advisor                                 |
//+------------------------------------------------------------------+
class MCEA
  {
//---
    private:
    //---- 
    int              x_year;       // Year 
    int              x_mon;        // Month 
    int              x_day;        // Day of the month 
    int              x_hour;       // Hour in a day 
    int              x_min;        // Minutes 
    int              x_sec;        // Seconds
    //--
    int              oBm,
                     oSm,
                     ldig;
    //--- Variables used in prefix and suffix symbols
    int              posCur1,
                     posCur2;
    int              inpre,
                     insuf;
    bool             symbfix;
    string           pre,suf;
    string           prefix,suffix;       
    //--- Variables are used in Trading Time Zone
    int              ishour,
                     onhour;
    int              tftrlst,
                     tfcinws;
    datetime         rem,
                     znop,
                     zncl,
                     zntm;
    datetime         SesCuOp,
                     SesCuCl,
                     Ses01Op,
                     Ses01Cl,
                     Ses02Op,
                     Ses02Cl,
                     Ses03Op,
                     Ses03Cl,
                     Ses04Op,
                     Ses04Cl,
                     Ses05Op,
                     Ses05Cl,
                     SesNoOp,
                     SesNoCl;
    //--
    string           tz_ses,
                     tz_opn,
                     tz_cls;
    //--
    string           tmopcu,
                     tmclcu,
                     tmop01,
                     tmcl01,
                     tmop02,
                     tmcl02,
                     tmop03,
                     tmcl03,
                     tmop04,
                     tmcl04,
                     tmop05,
                     tmcl05,
                     tmopno,
                     tmclno;      
    //----------------------
    //--
    double           LotPS;
    double           point;
    double           slv,
                     tpv,
                     pip,
                     xpip;
    double           SARstep,
                     SARmaxi;
    double           floatprofit,
                     fixclprofit;
    //--
    string           pairs,
                     hariini,
                     daytrade,
                     trade_mode;
    //--
    double           OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
    datetime         TIME[];
    datetime         closetime;
    //--
    //------------
     
    //------------
    void             SetSymbolNamePS(void);
    void             HandlingSymbolArrays(void);
    void             Set_Time_Zone(void);
    void             Time_Zone(void);
    bool             Trade_session(void);
    string           PosTimeZone(void);
    int              ThisTime(const int reqmode);
    int              ReqTime(datetime reqtime,const int reqmode);
    //--
    int              DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf);
    int              GetIndiSignals(const string symbol);
    int              ZigZagSignal(const string symbol);
    int              AOSignal(const string symbol);
    int              AOColorSignal(const string symbol);
    int              PARSAR05(const string symbol);
    int              PARSAR15(const string symbol);
    int              LotDig(const string symbol);
    //--
    double           MLots(const string symbx);
    double           NonZeroDiv(double val1,double val2);
    double           OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type);
    //--
    string           ReqDate(int d,int h,int m);
    string           TF2Str(ENUM_TIMEFRAMES period);
    string           timehr(int hr,int mn);
    string           TradingDay(void);
    string           AccountMode();
    string           GetCommentForOrder(void)             { return(expname); }
    //------------

    public:
    //---
    
    //-- ZigZag_AO_MCEA Config --
    string           DIRI[],
                     AS30[],
                     VSym[];
    string           SPC[];
    string           USD[];
    string           EUR[];
    string           GBP[];
    string           AUD[];
    string           NZD[];
    string           CAD[];
    string           CHF[];
    string           JPY[];             
    //--                 
    string           expname;
    string           indiname1;
    //--
    //--- Indicators Handle
    int              hZigZag[],
                     hAO[];
    int              hVIDyAv[];
    int              hPar05[],
                     hPar15[];
    //---
    int              ALO,
                     dgts,
                     arrsar,
                     arrsymbx;
    int              sall,
                     arusd,
                     areur,
                     aretc,
                     arspc,
                     arper;
    ulong            slip;        
    //--
    double           profitb[],
                     profits[];
    double           minprofit;
    //--
    int              Buy,
                     Sell;
    int              ccur,
                     psec,
                     xtto,
                     checktml;
    int              OpOr[],xob[],xos[];         
    //--
    int              year,  // Year 
                     mon,   // Month 
                     day,   // Day 
                     hour,  // Hour 
                     min,   // Minutes 
                     sec,   // Seconds 
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
    //--
    ENUM_TIMEFRAMES  TFt,
                     TFT05,
                     TFT15;
    //--
    bool             PanelExtra;
    //------------
                     MCEA(void);
                     ~MCEA(void);            
    //------------
    //--
    virtual void     ZigZag_AO_MCEA_Config(void);
    virtual void     ExpertActionTrade(void);
    //--
    void             ArraySymbolResize(void);
    void             CurrentSymbolSet(const string symbol);
    void             Pips(const string symbol);
    void             TradeInfo(void);
    void             Do_Alerts(const string symbx,string msgText);
    void             CheckOpenPMx(const string symbx);
    void             SetSLTPOrders(void);
    void             CloseAllOrders(void);
    void             CheckClose(const string symbx);
    void             TodayOrders(void);
    void             UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf);
    void             UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf,int bars);
    void             RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars);
    //--
    bool             CheckEquityBalance(void);
    bool             RefreshTick(const string symbx);  
    bool             TradingToday(void);
    bool             OpenBuy(const string symbol);
    bool             OpenSell(const string symbol);
    bool             ModifyOrderSLTP(double mStop,double ordtp);
    bool             ModifyOrdersSL(const string symbx,int TS_type);
    bool             ModifyOrdersTP(const string symbx);
    bool             CloseAllProfit(void);
    bool             CloseAllLoss(void);
    bool             ManualCloseAllProfit(void);
    bool             CheckProfitLoss(const string symbol);
    bool             CloseBuyPositions(const string symbol);
    bool             CloseSellPositions(const string symbol);
    bool             CheckProfit(const string symbol,ENUM_POSITION_TYPE intype);
    bool             CheckLoss(const string symbol,ENUM_POSITION_TYPE intype,double slc=0.0);
    //--
    int              PairsIdxArray(const string symbol);
    int              ValidatePairs(const string symbol);
    int              GetOpenPosition(const string symbol);
    int              GetCloseInWeakSignal(const string symbol,int exis);
    //--
    string           getUninitReasonText(int reasonCode);
    //--
    //------------
//---
  }; //-end class MCEA
//---------//
 
MCEA mc;

//---------//

多通貨EAのワークフロープロセスで、OnInit()から最初に呼び出される最も重要な関数はZigZag_AO_MCEA_Config()です。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   mc.ZigZag_AO_MCEA_Config();
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()
//---------//


ZigZag_AO_MCEA_Config()関数は、使用するすべての銘柄、すべての時間枠、すべてのハンドル指標、びEAワークフローのインクルードファイルヘッダーのいくつかの重要な機能を設定します。

ZigZag_AO_MCEA_Config()関数は、EAワークフローで使用されるすべての指標の時間枠の処理方法と指標ハンドルの作成方法を説明し、実装します。

//+------------------------------------------------------------------+
//| Expert Configuration                                             |
//+------------------------------------------------------------------+
void MCEA::ZigZag_AO_MCEA_Config(void) 
  {
//---
    //--
    HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
    //--
    TFT05=PERIOD_M5;
    TFT15=PERIOD_M15;
    ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
    int arTFs=ArraySize(TFs);
    //--
    for(int x=0; x<arTFs; x++) if(tfinuse==x) TFt=TFs[x]; // TF for calculation signal
    //--
    //-- Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hZigZag[x] = iCustom(DIRI[x],TFt,indiname1,zzDepth,zzDevia,zzBackS);   //-- Handle for the ZigZag indicator
        hAO[x]     = iAO(DIRI[x],TFt);                                         //-- Handle for the Awesome_Oscillator indicator
        hVIDyAv[x] = iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED);                //-- Handle for the VIDYA indicator for Trailing Stop
        hPar05[x]  = iSAR(DIRI[x],TFT05,SARstep,SARmaxi);                      //-- Handle for the iSAR indicator for M5 Timeframe
        hPar15[x]  = iSAR(DIRI[x],TFT15,SARstep,SARmaxi);                      //-- Handle for the iSAR indicator for M15 Timeframe
        //--
      }
    //--
    TesterHideIndicators(true);
    minprofit=NormalizeDouble(TSmin/100.0,2);
    //--
    ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
    if(Close_by_Opps==No) 
      {
        if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2;
        else 
        ALO=(int)(mc_account.LimitOrders()/2);
      }
    //--
    LotPS=(double)ALO;
    //--
    mc_trade.SetExpertMagicNumber(magicEA);
    mc_trade.SetDeviationInPoints(slip);
    mc_trade.SetMarginMode();
    Set_Time_Zone();
    //--
    return;
//---
  } //-end ZigZag_AO_MCEA_Config()
//---------//


3.EAティック関数とワークフロー

EAのティック関数(OnTick()関数)の中で、多通貨EAのもっとも重要な関数の1つであるExpertActionTrade()を呼び出します。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
//---
    mc.ExpertActionTrade();
    //--
    return;
//---
  } //-end OnTick()
//---------//


EAが取引に使用されるすべてのプロセスは、この機能に含まれています。

これは、ExpertActionTrade()関数が、新規注文、決済注文、トレーリングストップまたはトレーリングプロフィット、およびその他の追加アクティビティに始まり、すべてのアクティビティを実行し、自動売買を管理することを意味します。

void MCEA::ExpertActionTrade(void)
  {
//---
    //--Check Trading Terminal
    ResetLastError();
    //--
    if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==0) //-- Check whether MT5 Algorithmic trading is Allow or Prohibit
      {
        mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting.");
        mc.checktml=1;  //-- Variable checktml is given a value of 1, so that the alert is only done once.
        return;
      }
    //--
    if(!DisplayManualButton("M","C","R")) DisplayManualButton(); //-- Show the expert manual button panel
    //--
    if(trade_info_display==Yes) mc.TradeInfo(); //-- Displayed Trading Info on Chart
    //---
    //--
    int mcsec=mc.ThisTime(mc.sec); 
    //--
    if(fmod((double)mcsec,5.0)==0) mc.ccur=mcsec;
    //--
    if(mc.ccur!=mc.psec)
      {
        string symbol;
        //-- Here we start with the rotation of the name of all symbol or pairs to be traded
        for(int x=0; x<mc.arrsymbx && !IsStopped(); x++) 
          {
            //--
            switch(trademode)
              {
                case SP:
                  {
                    if(mc.DIRI[x]!=Symbol()) continue;
                    symbol=Symbol();
                    mc.pairs=mc.pairs+" ("+symbol+")";
                    break;
                  }
                case MP:
                  {
                    if(mc.DIRI[x]==Symbol()) symbol=Symbol();
                    else symbol=mc.DIRI[x];
                    break;
                  }
              }
            //--
            mc.CurrentSymbolSet(symbol);
            //--
            if(mc.TradingToday() && mc.Trade_session())
              {
                //--
                mc.OpOr[x]=mc.GetOpenPosition(symbol); //-- Get trading signals to open positions
                //--                                   //-- and store in the variable OpOr[x]
                if(mc.OpOr[x]==mc.Buy) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Buy" (value=1)
                  {
                    //--
                    mc.CheckOpenPMx(symbol);
                    //--
                    if(Close_by_Opps==Yes && mc.xos[x]>0) mc.CloseSellPositions(symbol);
                    //--
                    if(mc.xob[x]==0 && mc.xtto<mc.ALO) mc.OpenBuy(symbol);
                    else
                    if(mc.xtto>=mc.ALO)
                      {
                        //--
                        mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                            "\n the limit = "+string(mc.ALO)+" Orders ");
                        //--
                        mc.CheckOpenPMx(symbol);
                        //--
                        if(mc.xos[x]>0 && mc.profits[x]<-1.02 && mc.xob[x]==0) {mc.CloseSellPositions(symbol); mc.OpenBuy(symbol);}
                        else
                          mc.CloseAllProfit();
                        //--
                        if(mc.xos[x]>0 && use_sl==No && CheckVSLTP==Yes)
                          {
                            if(mc.CheckLoss(symbol,POSITION_TYPE_SELL,SLval)) 
                              if(mc.CloseSellPositions(symbol))
                                mc.Do_Alerts(symbol,"Check Profit Trade and Close order due stop in loss.");
                          }
                      }
                  }
                if(mc.OpOr[x]==mc.Sell) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Sell" (value=-1)
                  {
                    //--
                    mc.CheckOpenPMx(symbol);
                    //--
                    if(Close_by_Opps==Yes && mc.xob[x]>0) mc.CloseBuyPositions(symbol);
                    //--
                    if(mc.xos[x]==0 && mc.xtto<mc.ALO) mc.OpenSell(symbol);
                    else
                    if(mc.xtto>=mc.ALO)
                      {
                        //--
                        mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                            "\n the limit = "+string(mc.ALO)+" Orders ");
                        //--
                        mc.CheckOpenPMx(symbol);
                        //--
                        if(mc.xob[x]>0 && mc.profitb[x]<-1.02 && mc.xos[x]==0) {mc.CloseBuyPositions(symbol); mc.OpenSell(symbol);}
                        else
                          mc.CloseAllProfit();
                        //--
                        if(mc.xob[x]>0 && use_sl==No && CheckVSLTP==Yes)
                          {
                            if(mc.CheckLoss(symbol,POSITION_TYPE_BUY,SLval)) 
                              if(mc.CloseBuyPositions(symbol))
                                mc.Do_Alerts(symbol,"Check Profit Trade and Close order due stop in loss.");
                          }
                      }
                  }
              }
            //--
            mc.CheckOpenPMx(symbol);
            //--
            if(mc.xtto>0)
              {
                //--
                if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes)
                  {
                    mc.CheckOpenPMx(symbol);
                    if(mc.profitb[x]>mc.minprofit && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell) 
                      {
                        mc.CloseBuyPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal.");
                      }
                    if(mc.profits[x]>mc.minprofit && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy)
                      {
                        mc.CloseSellPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal.");
                      }
                  }
                //--
                if(TrailingSL==Yes) mc.ModifyOrdersSL(symbol,trlby); //-- Use Trailing Stop Loss (Yes)
                if(TrailingTP==Yes) mc.ModifyOrdersTP(symbol);       //-- Use Trailing Take Profit (Yes)
              }
            //--
            mc.CheckOpenPMx(symbol);
            if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1))
              {
                if(mc.CheckProfitLoss(symbol))
                   mc.Do_Alerts(symbol,"Close order due stop in loss.");
              }
            //--
            if(use_sl==No && CheckVSLTP==Yes)
              {
                if(!mc.CheckEquityBalance())
                  if(mc.CloseAllLoss())
                    mc.Do_Alerts(symbol,"Close order due stop in loss to secure equity.");
              }
            //--
            mc.CheckClose(symbol);
          }
        //--
        mc.psec=mc.ccur;
      }
    //--
    return;
//---
  } //-end ExpertActionTrade()
//---------//


一方、Day Trading On/Offプロパティグループは、トレーダーが日曜日から土曜日までの特定の日に取引をおこなうことを可能にします。トレーダーはYesまたはNoのオプションを使用して、特定の日にEAの取引を有効または無効にすることができます。

//--Day Trading On/Off
input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)

Day Trading On/Offの執行は以下の通りです。

bool MCEA::TradingToday(void)
  {
//---
    bool tradetoday=false;
    int trdday=ThisTime(dow);
    hariini="No";
    //--
    int ttd[];
    ArrayResize(ttd,7);
    ttd[0]=ttd0;
    ttd[1]=ttd1;
    ttd[2]=ttd2;
    ttd[3]=ttd3;
    ttd[4]=ttd4;
    ttd[5]=ttd5;
    ttd[6]=ttd6;
    //--
    if(ttd[trdday]==Yes) {tradetoday=true; hariini="Yes";}
   //--
   return(tradetoday);
//---
  } //-end TradingToday()
//---------//

メモ:DayTradingOn/Off条件は、チャートの取引情報に表示されます。

TradingDay()関数によって実行されます。

string MCEA::TradingDay(void)
  {
//---
   int trdday=ThisTime(dow);
   switch(trdday)
     {
        case 0: daytrade="Sunday";    break;
        case 1: daytrade="Monday";    break;
        case 2: daytrade="Tuesday";   break;
        case 3: daytrade="Wednesday"; break;
        case 4: daytrade="Thursday";  break;
        case 5: daytrade="Friday";    break;
        case 6: daytrade="Saturday";  break;
     }
   return(daytrade);
//---
  } //-end TradingDay()  
//---------//

トレーダーは、EAの「TradeatSpecificTime」プロパティグループで、時間帯別に取引するオプションがあります。

メモ:上記で説明したように、ニュージーランドセッションでの取引から米国ニューヨークセッションでの取引の場合、取引開始から取引終了までの時間はEAが計算します。 
そのため、EAEntryプロパティでは、トレーダーはカスタムセッションの取引開始時刻と終了時刻を設定するだけでよくなります。


ExpertActionTrade()関数が拡張され、タイムゾーン取引専用のブール値Trade_session()関数が呼び出されるようになりました。

Trade_session()がtrueの場合、EAの作業プロセスは終了するまで続行されますが、falseの場合、EAは[Close Trade and Save Profit due to Weak Signal if it is(Yes)]および[Trailing Stop if it is(Yes)]タスクのみを実行します。

bool MCEA::Trade_session(void)
  {
//---
   bool trd_ses=false;
   ishour=ThisTime(hour);
   if(ishour!=onhour) Set_Time_Zone();
   datetime tcurr=TimeCurrent(); // Server Time
   //--
   switch(session)
     {
       case Cus_Session:
         {
           if(tcurr>=SesCuOp && tcurr<=SesCuCl) trd_ses=true;
           break;
         }
       case New_Zealand:
         {
           if(tcurr>=Ses01Op && tcurr<=Ses01Cl) trd_ses=true;
           break;
         }
       case Australia:
         {
           if(tcurr>=Ses02Op && tcurr<=Ses02Cl) trd_ses=true;
           break;
         }
       case Asia_Tokyo:
         {
           if(tcurr>=Ses03Op && tcurr<=Ses03Cl) trd_ses=true;
           break;
         }
       case Europe_London:
         {
           if(tcurr>=Ses04Op && tcurr<=Ses04Cl) trd_ses=true;
           break;
         }
       case US_New_York:
         {
           if(tcurr>=Ses05Op && tcurr<=Ses05Cl) trd_ses=true;
           break;
         }
     }
   //--
   if(trd_time_zone==No) 
     {
      if(tcurr>=SesNoOp && tcurr<=SesNoCl) trd_ses=true;
     }
   //--
   onhour=ishour;
   //--
   return(trd_ses);
//---  
  } //-end Trade_session()
//---------//


まずExpertActionTrade()関数がTrade_session()関数を呼び出し、次にTrade_session()関数がSet_Time_Zone()関数を呼び出し、最後にSet_Time_Zone()関数がTime_Zone()関数を呼び出します。

void MCEA::Set_Time_Zone(void)
  {
//---
    //-- Server Time==TimeCurrent()
    datetime TTS=TimeTradeServer();
    datetime GMT=TimeGMT();
    //--
    MqlDateTime svrtm,gmttm; 
    TimeToStruct(TTS,svrtm); 
    TimeToStruct(GMT,gmttm); 
    int svrhr=svrtm.hour;  // Server time hour
    int gmthr=gmttm.hour;  // GMT time hour
    int difhr=svrhr-gmthr; // Time difference Server time to GMT time
    //--
    int NZSGMT=12;  // New Zealand Session GMT/UTC+12
    int AUSGMT=10;  // Australia Sydney Session GMT/UTC+10
    int TOKGMT=9;   // Asia Tokyo Session GMT/UTC+9
    int EURGMT=0;   // Europe London Session GMT/UTC 0
    int USNGMT=-5;  // US New York Session GMT/UTC-5
    //--
    int NZSStm=8;   // New Zealand Session time start: 08:00 Local Time
    int NZSCtm=17;  // New Zealand Session time close: 17:00 Local Time 
    int AUSStm=7;   // Australia Sydney Session time start: 07:00 Local Time 
    int AUSCtm=17;  // Australia Sydney Session time close: 17:00 Local Time  
    int TOKStm=9;   // Asia Tokyo Session time start: 09:00 Local Time 
    int TOKCtm=18;  // Asia Tokyo Session time close: 18:00 Local Time  
    int EURStm=9;   // Europe London Session time start: 09:00 Local Time 
    int EURCtm=19;  // Europe London Session time close: 19:00 Local Time  
    int USNStm=8;   // US New York Session time start: 08:00 Local Time 
    int USNCtm=17;  // US New York Session time close: 17:00 Local Time  
    //--
    int nzo = (NZSStm+difhr-NZSGMT)<0 ? 24+(NZSStm+difhr-NZSGMT) : (NZSStm+difhr-NZSGMT);
    int nzc = (NZSCtm+difhr-NZSGMT)<0 ? 24+(NZSCtm+difhr-NZSGMT) : (NZSCtm+difhr-NZSGMT);
    //--
    int auo = (AUSStm+difhr-AUSGMT)<0 ? 24+(AUSStm+difhr-AUSGMT) : (AUSStm+difhr-AUSGMT);
    int auc = (AUSCtm+difhr-AUSGMT)<0 ? 24+(AUSCtm+difhr-AUSGMT) : (AUSCtm+difhr-AUSGMT);
    //--
    int tko = (TOKStm+difhr-TOKGMT)<0 ? 24+(TOKStm+difhr-TOKGMT) : (TOKStm+difhr-TOKGMT);
    int tkc = (TOKCtm+difhr-TOKGMT)<0 ? 24+(TOKCtm+difhr-TOKGMT) : (TOKCtm+difhr-TOKGMT);
    //--
    int euo = (EURStm+difhr-EURGMT)<0 ? 24+(EURStm+difhr-EURGMT) : (EURStm+difhr-EURGMT);
    int euc = (EURCtm+difhr-EURGMT)<0 ? 24+(EURCtm+difhr-EURGMT) : (EURCtm+difhr-EURGMT);
    //--
    int uso = (USNStm+difhr-USNGMT)<0 ? 24+(USNStm+difhr-USNGMT) : (USNStm+difhr-USNGMT);
    int usc = (USNCtm+difhr-USNGMT)<0 ? 24+(USNCtm+difhr-USNGMT) : (USNCtm+difhr-USNGMT);
    if(usc==0||usc==24) usc=23;
    //--
    //---Trading on Custom Session
    int _days00=ThisTime(day);
    int _days10=ThisTime(day);
    if(stsescuh>clsescuh) _days10=ThisTime(day)+1;
    tmopcu=ReqDate(_days00,stsescuh,stsescum); 
    tmclcu=ReqDate(_days10,clsescuh,clsescum); 
    //--
    //--Trading on New Zealand Session GMT/UTC+12
    int _days01=ThisTime(hour)<nzc ? ThisTime(day)-1 : ThisTime(day);
    int _days11=ThisTime(hour)<nzc ? ThisTime(day) : ThisTime(day)+1;
    tmop01=ReqDate(_days01,nzo,0);    // start: 08:00 Local Time == 20:00 GMT/UTC
    tmcl01=ReqDate(_days11,nzc-1,59); // close: 17:00 Local Time == 05:00 GMT/UTC
    //--
    //--Trading on Australia Sydney Session GMT/UTC+10
    int _days02=ThisTime(hour)<auc ? ThisTime(day)-1 : ThisTime(day);
    int _days12=ThisTime(hour)<auc ? ThisTime(day) : ThisTime(day)+1;
    tmop02=ReqDate(_days02,auo,0);    // start: 07:00 Local Time == 21:00 GMT/UTC
    tmcl02=ReqDate(_days12,auc-1,59); // close: 17:00 Local Time == 07:00 GMT/UTC
    //--
    //--Trading on Asia Tokyo Session GMT/UTC+9
    int _days03=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    int _days13=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    tmop03=ReqDate(_days03,tko,0);    // start: 09:00 Local Time == 00:00 GMT/UTC
    tmcl03=ReqDate(_days13,tkc-1,59); // close: 18:00 Local Time == 09:00 GMT/UTC
    //--
    //--Trading on Europe London Session GMT/UTC 00:00
    int _days04=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    int _days14=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    tmop04=ReqDate(_days04,euo,0);     // start: 09:00 Local Time == 09:00 GMT/UTC
    tmcl04=ReqDate(_days14,euc-1,59);  // close: 19:00 Local Time == 19:00 GMT/UTC
    //--
    //--Trading on US New York Session GMT/UTC-5
    int _days05=ThisTime(hour)<usc  ? ThisTime(day) : ThisTime(day)+1;
    int _days15=ThisTime(hour)<=usc ? ThisTime(day) : ThisTime(day)+1;
    tmop05=ReqDate(_days05,uso,0);  // start: 08:00 Local Time == 13:00 GMT/UTC
    tmcl05=ReqDate(_days15,usc,59); // close: 17:00 Local Time == 22:00 GMT/UTC
    //--
    //--Not Use Trading Time Zone
    if(trd_time_zone==No)
      {
        tmopno=ReqDate(ThisTime(day),0,15); 
        tmclno=ReqDate(ThisTime(day),23,59);
      }
    //--
    Time_Zone();
    //--
    return;
//---
  } //-end Set_Time_Zone()
//---------//
void MCEA::Time_Zone(void)
  {
//---
   //--
   tz_ses="";
   //--
   switch(session)
     {
       case Cus_Session:
         {
           SesCuOp=StringToTime(tmopcu);
           SesCuCl=StringToTime(tmclcu);
           zntm=SesCuOp;
           znop=SesCuOp;
           zncl=SesCuCl;
           tz_ses="Custom_Session";
           tz_opn=timehr(stsescuh,stsescum);
           tz_cls=timehr(clsescuh,clsescum);
           break;
         }
       case New_Zealand:
         {
           Ses01Op=StringToTime(tmop01);
           Ses01Cl=StringToTime(tmcl01);
           zntm=Ses01Op;
           znop=Ses01Op;
           zncl=Ses01Cl;
           tz_ses="New_Zealand/Oceania";
           tz_opn=timehr(ReqTime(Ses01Op,hour),ReqTime(Ses01Op,min));
           tz_cls=timehr(ReqTime(Ses01Cl,hour),ReqTime(Ses01Cl,min));
           break;
         }
       case Australia:
         {
           Ses02Op=StringToTime(tmop02);
           Ses02Cl=StringToTime(tmcl02);
           zntm=Ses02Op;
           znop=Ses02Op;
           zncl=Ses02Cl;
           tz_ses="Australia Sydney";
           tz_opn=timehr(ReqTime(Ses02Op,hour),ReqTime(Ses02Op,min));
           tz_cls=timehr(ReqTime(Ses02Cl,hour),ReqTime(Ses02Cl,min));
           break;
         }
       case Asia_Tokyo:
         {
           Ses03Op=StringToTime(tmop03);
           Ses03Cl=StringToTime(tmcl03);
           zntm=Ses03Op;
           znop=Ses03Op;
           zncl=Ses03Cl;
           tz_ses="Asia/Tokyo";
           tz_opn=timehr(ReqTime(Ses03Op,hour),ReqTime(Ses03Op,min));
           tz_cls=timehr(ReqTime(Ses03Cl,hour),ReqTime(Ses03Cl,min));
           break;
         }
       case Europe_London:
         {
           Ses04Op=StringToTime(tmop04);
           Ses04Cl=StringToTime(tmcl04);
           zntm=Ses04Op;
           znop=Ses04Op;
           zncl=Ses04Cl;
           tz_ses="Europe/London";
           tz_opn=timehr(ReqTime(Ses04Op,hour),ReqTime(Ses04Op,min));
           tz_cls=timehr(ReqTime(Ses04Cl,hour),ReqTime(Ses04Cl,min));
           break;
         }
       case US_New_York:
         {
           Ses05Op=StringToTime(tmop05);
           Ses05Cl=StringToTime(tmcl05);
           zntm=Ses05Op;
           znop=Ses05Op;
           zncl=Ses05Cl;
           tz_ses="US/New_York";
           tz_opn=timehr(ReqTime(Ses05Op,hour),ReqTime(Ses05Op,min));
           tz_cls=timehr(ReqTime(Ses05Cl,hour),ReqTime(Ses05Cl,min));
           break;
         }
     }
   //--
   if(trd_time_zone==No)
     {
       SesNoOp=StringToTime(tmopno);
       SesNoCl=StringToTime(tmclno);
       zntm=SesNoOp;
       znop=SesNoOp;
       zncl=SesNoCl;
       tz_ses="Not Use Time Zone";
       tz_opn=timehr(ReqTime(SesNoOp,hour),ReqTime(SesNoOp,min));
       tz_cls=timehr(ReqTime(SesNoCl,hour),ReqTime(SesNoCl,min));
     }
   //--
   return;
//---
  } //-end Time_Zone()
//---------//


4.未決済ポジションの取引シグナルの取得

ポジションを建てるシグナルを得るために、ExpertActionTrade()関数はGetOpenPosition()関数を呼び出します。

int MCEA::GetOpenPosition(const string symbol) // Signal Open Position 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int ZZAOSignal=GetIndiSignals(symbol);
    int dirmove=DirectionMove(symbol,TFt);
    int psar15=PARSAR15(symbol);
    //--
    if(ZZAOSignal==rise && dirmove==rise && psar15==rise) ret=rise;
    if(ZZAOSignal==down && dirmove==down && psar15==down) ret=down;
    //--
    return(ret);
//---
  } //-end GetOpenPosition()
//---------//

そして、GetOpenPosition()関数は3つの関数を呼び出します。

  1. GetIndiSignals(symbol)
  2. DirectionMove(symbol,TFt)
  3. PARSAR15(symbol)

4.1.GetIndiSignals(symbol)関数は2つの関数を呼び出します。

  1. ZigZagSignal(symbol)
  2. AOSignal(symbol)

4.1.1.ジグザグシグナル

ZigZagSignal()関数の内部で使用して呼び出す関数はPairsIdxArray()だけです。

int xx=PairsIdxArray(symbol)
int MCEA::PairsIdxArray(const string symbol)
  {
//---
    int pidx=-1;
    //--
    for(int x=0; x<arrsymbx; x++)
      {
        if(DIRI[x]==symbol)
          {
            pidx=x;
            break;
          }
      } 
    //--
    return(pidx);
//---
  } //-end PairsIdxArray()
//---------//


PairsIdxArray()関数は、要求された銘柄の名前とその指標のハンドルを取得するために使用されます。
次に、対応する指標ハンドルが呼び出され、その時間枠からジグザグ指標のバッファ値を取得します。

    //-- Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hZigZag[x] = iCustom(DIRI[x],TFt,indiname1,zzDepth,zzDevia,zzBackS);   //-- Handle for the ZigZag indicator
        hAO[x]     = iAO(DIRI[x],TFt);                                         //-- Handle for the Awesome_Oscillator indicator
        hVIDyAv[x] = iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED);                //-- Handle for the VIDYA indicator for Trailing Stop
        hPar05[x]  = iSAR(DIRI[x],TFT05,SARstep,SARmaxi);                      //-- Handle for the iSAR indicator for M5 Timeframe
        hPar15[x]  = iSAR(DIRI[x],TFT15,SARstep,SARmaxi);                      //-- Handle for the iSAR indicator for M15 Timeframe
        //--
      }
    //--


そこで、ジグザグ指標のバッファ値を取得するために、ジグザグ指標のハンドルから各バッファをコピーします。

ジグザグバッファ(バッファ0)をジグザグ指標ハンドルからコピー先配列にコピーします。

CopyBuffer(hZigZag[x],0,0,barcalc,ZZBuffer);

それとは別に、UpdatePrice()関数を呼び出して高値と安値を取得し、ジグザグバッファのHighとLowのポジションを取得します。

void MCEA::UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf)
  {
//---
    //--
    ArrayFree(OPEN);
    ArrayFree(HIGH);
    ArrayFree(LOW);
    ArrayFree(CLOSE);
    ArrayFree(TIME);
    //--
    ArrayResize(OPEN,arper,arper);
    ArrayResize(HIGH,arper,arper);
    ArrayResize(LOW,arper,arper);
    ArrayResize(CLOSE,arper,arper);
    ArrayResize(TIME,arper,arper);
    //--
    ArraySetAsSeries(OPEN,true);
    ArraySetAsSeries(HIGH,true);
    ArraySetAsSeries(LOW,true);
    ArraySetAsSeries(CLOSE,true);
    ArraySetAsSeries(TIME,true);
    //--
    ArrayInitialize(OPEN,0.0);
    ArrayInitialize(HIGH,0.0);
    ArrayInitialize(LOW,0.0);
    ArrayInitialize(CLOSE,0.0);
    ArrayInitialize(TIME,0);    
    //--
    RefreshPrice(symbol,xtf,arper);
    //--
    int co=CopyOpen(symbol,xtf,0,arper,OPEN);
    int ch=CopyHigh(symbol,xtf,0,arper,HIGH);
    int cl=CopyLow(symbol,xtf,0,arper,LOW);
    int cc=CopyClose(symbol,xtf,0,arper,CLOSE);
    int ct=CopyTime(symbol,xtf,0,arper,TIME);
   //--
   return;
//---
  } //-end UpdatePrice()
//---------//

そして、ジグザグHighとジグザグLowのバーポジションを得るために、反復をおこない、価格のHighと価格のLowと比較します。

    //--
    for(int i=barcalc-1; i>=0; i--)
      {
        if(ZZBuffer[i]==HIGH[i]) ZH=i;
        if(ZZBuffer[i]==LOW[i])  ZL=i;
      }
    //--

ジグザグのHigh (ZH)とジグザグのLow (ZL)のバーポジションを取得した後は、プロパティ入力で選択したシグナルジグザグ指標オプションに依存します。

完全なZigZagSignal()関数は以下の通りです。

int MCEA::ZigZagSignal(const string symbol) // ZigZag Signal for Open Position
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int ZH=-1,
        ZL=-1;
    int barcalc=100;
    bool ZZrise=false;
    bool ZZdown=false;
    //--
    double ZZBuffer[];
    ArrayResize(ZZBuffer,barcalc,barcalc);
    ArraySetAsSeries(ZZBuffer,true);
    //--  
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt);
    //--    
    CopyBuffer(hZigZag[x],0,0,barcalc,ZZBuffer);
    //--
    for(int i=barcalc-1; i>=0; i--)
      {
        if(ZZBuffer[i]==HIGH[i]) ZH=i;
        if(ZZBuffer[i]==LOW[i])  ZL=i;
      }
    //--
    switch(sigzz)
      {
        case SZZ1:
          {
            ZZrise=((ZH==0 && HIGH[0]>HIGH[1])||(ZL<ZH && ZL>1));
            ZZdown=((ZL==0 && LOW[0]<LOW[1])||(ZH<ZL && ZH>1));
            //--
            break;
          }
        case SZZ2:
          {
            ZZrise=(ZL<ZH && ZL>1);
            ZZdown=(ZH<ZL && ZH>1);
            //--
            break;
          }
        case SZZ3:
          {
            ZZrise=((ZH==0 && HIGH[0]>HIGH[1])||(ZL<ZH && ZL>0));
            ZZdown=((ZL==0 && LOW[0]<LOW[1])||(ZH<ZL && ZH>0));
            //--
            break;
          }
        case SZZ4:
          {
            ZZrise=(ZL<ZH && ZL>0);
            ZZdown=(ZH<ZL && ZH>0);
            //--
            break;
          }
      };
    //--
    if(ZZrise) ret=rise;
    if(ZZdown) ret=down;
    //--
    return(ret);
//---
  } //-end ZigZagSignal()
//---------//


4.1.2.AOシグナル

ZigZagSignal()関数と同様に、AOSignal()関数でもPairsIdxArray()関数を使用して、AO指標からバッファ値を取得する必要があります。

AO指標のバッファ値を取得するために、AO指標のハンドルから各バッファをコピーします。

AOバッファ(バッファ0)をAO指標ハンドルからコピー先配列にコピーします。

CopyBuffer(hAO[x],0,0,barcalc,AOValue);

そしてそれは、プロパティ入力で選択されたシグナルAO指標のオプションに依存します。

それとは別に、AO指標からのシグナルを完成させるために、AO指標の色を使用して、バッファ値からのシグナルを確認します。

そのために、AOColorSignal()という関数名で、AO指標のカラー値を取得する関数を作成しました。

この関数では、AO指標からバッファ1(指標カラーインデックスバッファ)をコピーします。

CopyBuffer(hAO[x],1,0,barcalc,AOColor);
int MCEA::AOColorSignal(const string symbol)
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int barcalc=9;
    //--
    double AOColor[];
    ArrayResize(AOColor,barcalc,barcalc);
    ArraySetAsSeries(AOColor,true);
    //--
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt,barcalc);
    //--
    CopyBuffer(hAO[x],1,0,barcalc,AOColor);
    //--
    bool AORise=((AOColor[1]==1.0 && AOColor[0]==0.0)||(AOColor[1]==0.0 && AOColor[0]==0.0));
    bool AODown=((AOColor[1]==0.0 && AOColor[0]==1.0)||(AOColor[1]==1.0 && AOColor[0]==1.0));
    //--
    if(AORise) ret=rise;
    if(AODown) ret=down;
    //--
    return(ret);
//---
  } //-end AOColorSignal()
//---------//

完全なAOSignal()関数は以下の通りです。

int MCEA::AOSignal(const string symbol)
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int barcalc=9;
    bool AORValue=false;
    bool AODValue=false;
    //--
    double AOValue[];
    ArrayResize(AOValue,barcalc,barcalc);
    ArraySetAsSeries(AOValue,true);
    //--
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt,barcalc);
    //--
    CopyBuffer(hAO[x],0,0,barcalc,AOValue);
    //--
    switch(sigao)
      {
        case SAO1:
          {
            AORValue=(AOValue[2]<=0.0 && AOValue[1]>0.0 && AOValue[0]>AOValue[1])||(AOValue[1]>AOValue[2] && AOValue[0]>AOValue[1]);
            AODValue=(AOValue[2]>=0.0 && AOValue[1]<0.0 && AOValue[0]<AOValue[1])||(AOValue[1]<AOValue[2] && AOValue[0]<AOValue[1]);
            //--
            break;
          }
        case SAO2:
          {
            AORValue=(AOValue[1]<=0.0 && AOValue[0]>0.0)||(AOValue[0]>0.0 && AOValue[0]>AOValue[1]);
            AODValue=(AOValue[1]>=0.0 && AOValue[0]<0.0)||(AOValue[0]<0.0 && AOValue[0]<AOValue[1]);
            //--
            break;
          }
        case SAO3:
          {
            AORValue=(AOValue[1]<=0.0 && AOValue[0]>0.0)||(AOValue[0]>AOValue[1]);
            AODValue=(AOValue[1]>=0.0 && AOValue[0]<0.0)||(AOValue[0]<AOValue[1]);
            //--
            break;
          }
      };
    //--
    bool AORise=(AOColorSignal(symbol)==rise);
    bool AODown=(AOColorSignal(symbol)==down);
    //--
    if(AORValue && AORise) ret=rise;
    if(AODValue && AODown) ret=down;
    //--
    return(ret);
//---
  } //-end AOSignal()
//---------//


GetIndiSignals()関数は、ZigZagSignal()関数とAOSignal()関数の戻り値を合計します。

int MCEA::GetIndiSignals(const string symbol) // Get Signal for Open Position 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int sigrise=2;
    int sigdown=-2;
    //--
    int ZZSignal=ZigZagSignal(symbol);
    int AwSignal=AOSignal(symbol);
    //Print(symbol+" = ZZ="+string(ZZSignal)+" AO="+string(AwSignal)+" Signal="+string(ZZSignal+AwSignal));
    //--
    if(ZZSignal+AwSignal==sigrise) ret=rise;
    if(ZZSignal+AwSignal==sigdown) ret=down;
    //--
    return(ret);
//---
  } //-end GetIndiSignals()
//---------//        


上気したように、GetIndiSignals()関数は、ZigZagSignal()関数とAOSignal()関数の戻り値を合計します。

  • 結果が「2」なら買いシグナル
  • 結果が「-2」なら売りシグナル

4.2.DirectionMove関数

DirectionMove()関数は、始値の上(上昇)または始値の下(下)に関係なく、現在の足の終値位置を取得するのに役立ちます。

int MCEA::DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf) // Bar Price Direction 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    Pips(symbol);
    double difud=mc_symbol.NormalizePrice(1.5*pip);
    UpdatePrice(symbol,stf,2);
    //--
    if(CLOSE[0]>OPEN[0]+difud) ret=rise;
    if(CLOSE[0]<OPEN[0]-difud) ret=down;
    //--
    return(ret);
//---
  } //-end DirectionMove()
//---------//


4.3.PARSAR15()関数

PARSAR15()関数は、M15時間枠上で、ジグザグ指標およびAO指標とPSAR/iSAR (Parabolic Stop and Reverseシステム指標)の動きを合わせるのに便利です。

int MCEA::PARSAR15(const string symbol) // formula Parabolic SAR M15
  {
//---
   int ret=0;
   int rise=1,
       down=-1;
   int br=2;
//--
   double PSAR[];
   ArrayResize(PSAR,br,br);
   ArraySetAsSeries(PSAR,true);
   int xx=PairsIdxArray(symbol);
   CopyBuffer(hPar15[xx],0,0,br,PSAR);
   //--
   UpdatePrice(symbol,TFT15,br);
   //--
   if(PSAR[0]<LOW[0])
      ret=rise;
   if(PSAR[0]>HIGH[0])
      ret=down;
//--
   return(ret);
//---
  } //-end PARSAR15()
//---------//


3つのメインシグナル関数といくつかのサポート関数を実行した後、GetOpenPosition()関数が値を提供します。

  • 値=0:シグナル不明
  • 値=1:買い注文のシグナル
  • 値=-1:売り注文のシグナル

GetOpenPosition()関数が値1を返すと、EAはOpenBuy()関数を呼び出して買い注文を出します。

bool MCEA::OpenBuy(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool buyopen      = false;
    string ldComm     = GetCommentForOrder()+"_Buy";
    double ldLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Bid());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Ask());
    //--
    if(RefreshTick(symbol))
       buyopen=mc_trade.Buy(ldLot,symbol,mc_symbol.Ask(),SL,TP,ldComm);
    //--
    int error=GetLastError();
    if(buyopen||error==0)
      {
        string bsopen="Open BUY Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open BUY order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(buyopen);
    //--
//---
  } //-end OpenBuy
//---------//


一方、GetOpenPosition()関数が-1を返した場合、EAはOpenSell()関数を呼び出して売り注文を出します。

bool MCEA::OpenSell(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool selopen      = false;
    string sdComm     = GetCommentForOrder()+"_Sell";
    double sdLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Ask());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Bid());
    //--
    if(RefreshTick(symbol))
       selopen=mc_trade.Sell(sdLot,symbol,mc_symbol.Bid(),SL,TP,sdComm);
    //--
    int error=GetLastError();
    if(selopen||error==0)
      {
        string bsopen="Open SELL Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open SELL order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(selopen);
    //--
//---
  } //-end OpenSell
//---------//


5.ChartEvent関数

多通貨EAを効果的かつ効率的に使用するためには、注文の管理、チャートの時間枠や銘柄の変更において、1つ以上の手動ボタンを作成する必要があると考えられます。

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
   ResetLastError();
   //--
   ENUM_TIMEFRAMES CCS=mc.TFt;
   //--
   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       int lensymbol=StringLen(Symbol());
       int lensparam=StringLen(sparam);
       //--
       //--- if "Set SL All Orders" button is click
       if(sparam=="Set SL/TP All Orders") 
         { 
           mc.SetSLTPOrders();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Set SL/TP All Orders");
           //--- unpress the button 
           ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "Close All Order" button is click
       if(sparam=="Close All Order") 
         { 
           mc.CloseAllOrders();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Orders");
           //--- unpress the button 
           ObjectSetInteger(0,"Close All Order",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Close All Order",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "Close All Profit" button is click
       if(sparam=="Close All Profit") 
         { 
           mc.ManualCloseAllProfit();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Profit");
           //--- unpress the button 
           ObjectSetInteger(0,"Close All Profit",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Close All Profit",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "X" button is click
       if(sparam=="X") 
         { 
           ObjectsDeleteAll(0,0,OBJ_BUTTON);
           ObjectsDeleteAll(0,0,OBJ_LABEL);
           ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
           //--- unpress the button 
           ObjectSetInteger(0,"X",OBJPROP_STATE,false);
           ObjectSetInteger(0,"X",OBJPROP_ZORDER,0);
           //--
           DeleteButtonX();
           mc.PanelExtra=false;
           DisplayManualButton();
         }
       //--- if "M" button is click
       if(sparam=="M") 
         { 
           //--- unpress the button 
           ObjectSetInteger(0,"M",OBJPROP_STATE,false);
           ObjectSetInteger(0,"M",OBJPROP_ZORDER,0);
           mc.PanelExtra=true;
           CreateManualPanel();
         }
       //--- if "C" button is click
       if(sparam=="C") 
         { 
           //--- unpress the button 
           ObjectSetInteger(0,"C",OBJPROP_STATE,false);
           ObjectSetInteger(0,"C",OBJPROP_ZORDER,0);
           mc.PanelExtra=true;
           CreateSymbolPanel();
         }
       //--- if "R" button is click
       if(sparam=="R") 
         { 
           Alert("-- "+mc.expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
           ExpertRemove();
           //--- unpress the button 
           ObjectSetInteger(0,"R",OBJPROP_STATE,false);
           ObjectSetInteger(0,"R",OBJPROP_ZORDER,0);
           if(!ChartSetSymbolPeriod(0,Symbol(),Period()))
             ChartSetSymbolPeriod(0,Symbol(),Period());
           DeletePanelButton();
           ChartRedraw(0);
         }
       //--- if Symbol button is click
       if(lensparam==lensymbol)
         {
           int sx=mc.ValidatePairs(sparam);
           ChangeChartSymbol(mc.AS30[sx],CCS);
           mc.PanelExtra=false;
         }
       //--
     }
    //--
    return;
//---
  } //-end OnChartEvent()
//---------//

その他のEAパラメータグループの入力プロパティで、トレーダーは取引情報をチャートに表示するかどうか(Yes/No)を選択できます。

このオプションが選択されている場合(Yes)、TradeInfo()関数を呼び出すことによって、EAが接続されているチャートに取引情報が表示されます。

また、TradeInfo()関数の一部に、取引時間帯の条件に応じた時刻を記述する関数を追加しました。

string MCEA::PosTimeZone(void)
  {
//---
    string tzpos="";
    //--
    if(ReqTime(zntm,day)>ThisTime(day))
     {
       tzpos=tz_opn+ " Next day to " +tz_cls + " Next day";
     }
    else
    if(TimeCurrent()<znop)
      {
        if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)==ReqTime(zncl,day))
          tzpos=tz_opn+" to " +tz_cls+ " Today";
        //else
        if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
          tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
      }
    else
    if(TimeCurrent()>=znop && TimeCurrent()<zncl)
      {
        if(ThisTime(day)<ReqTime(zncl,day))
          tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
        else
        if(ThisTime(day)==ReqTime(zncl,day))
          tzpos=tz_opn+" to " +tz_cls+ " Today";
      }
    else
    if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
      {
        tzpos=tz_opn+" Today to " +tz_cls+ " Next day";
      }
    //--
    return(tzpos);
//----
  } //-end PosTimeZone()
//---------//
void MCEA::TradeInfo(void) // function: write comments on the chart
  {
//----
   Pips(Symbol());
   double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip;
   rem=zntm-TimeCurrent();
   string postime=PosTimeZone();
   string eawait=" - Waiting for active time..!";
   //--
   string comm="";
   TodayOrders();
   //--
   comm="\n     :: Server Date Time : "+string(ThisTime(year))+"."+string(ThisTime(mon))+"."+string(ThisTime(day))+ "   "+TimeToString(TimeCurrent(),TIME_SECONDS)+
        "\n     ------------------------------------------------------------"+
        "\n      :: Broker               :  "+ TerminalInfoString(TERMINAL_COMPANY)+
        "\n      :: Expert Name      :  "+ expname+
        "\n      :: Acc. Name         :  "+ mc_account.Name()+
        "\n      :: Acc. Number      :  "+ (string)mc_account.Login()+
        "\n      :: Acc. TradeMode :  "+ AccountMode()+
        "\n      :: Acc. Leverage    :  1 : "+ (string)mc_account.Leverage()+
        "\n      :: Acc. Equity       :  "+ DoubleToString(mc_account.Equity(),2)+
        "\n      :: Margin Mode     :  "+ (string)mc_account.MarginModeDescription()+
        "\n      :: Magic Number   :  "+ string(magicEA)+
        "\n      :: Trade on TF      :  "+ EnumToString(TFt)+
        "\n      :: Today Trading   :  "+ TradingDay()+" : "+hariini+
        "\n      :: Trading Session :  "+ tz_ses+
        "\n      :: Trading Time    :  "+ postime;
        if(TimeCurrent()<zntm)
          {
            comm=comm+
            "\n      :: Time Remaining :  "+(string)ReqTime(rem,hour)+":"+(string)ReqTime(rem,min)+":"+(string)ReqTime(rem,sec) + eawait;
          }
        comm=comm+
        "\n     ------------------------------------------------------------"+
        "\n      :: Trading Pairs     :  "+pairs+
        "\n      :: BUY Market      :  "+string(oBm)+
        "\n      :: SELL Market     :  "+string(oSm)+
        "\n      :: Total Order       :  "+string(oBm+oSm)+
        "\n      :: Order Profit      :  "+DoubleToString(floatprofit,2)+
        "\n      :: Fixed Profit       :  "+DoubleToString(fixclprofit,2)+
        "\n      :: Float Money     :  "+DoubleToString(floatprofit,2)+
        "\n      :: Nett Profit        :  "+DoubleToString(floatprofit+fixclprofit,2);
   //--
   Comment(comm);
   ChartRedraw(0);
   return;
//----
  } //-end TradeInfo()  
//---------//


多通貨EA ZigZag_AO_MCEAのインターフェイスは下図のようになっています。

ZZ_AO_MCEA_Look


ご覧のように、ZigZag_AO_MCEAというEA名の下に「M」、「C」、「R」というボタンがあります。

[M]ボタンがクリックされると、以下のように手動クリックボタンパネルが表示されます。

Expert_manual_button_01

手動クリックボタンパネルが表示されている場合、トレーダーは注文を手動で管理できます。

5.1.Set SL/TP All Orders

上記で説明したように、トレーダーがUse Order Stop Loss(No)やUse Order Take Profit(No)というパラメータを入力し、全ての注文にストップロスまたはテイクプロフィットを使用したい場合、[Set SL / TP All Orders]ボタンをシングルクリックすると、全ての注文が修正され、ストップロスまたはテイクプロフィットが適用されます。

void MCEA::SetSLTPOrders(void) 
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   double modbuysl=0;
   double modselsl=0;
   double modbuytp=0;
   double modseltp=0;
   string position_symbol;
   int totalorder=PositionsTotal();
   //--    
   for(int i=totalorder-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       position_symbol=symbol;
       if(mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modbuysl=SetOrderSL(symbol,opstype,pos_open);
               if(price<modbuysl) modbuysl=mc_symbol.NormalizePrice(price-slip*pip);
               modbuytp=SetOrderTP(symbol,opstype,pos_open);
               if(price>modbuytp) modbuytp=mc_symbol.NormalizePrice(price+slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modbuysl,modbuytp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modselsl=SetOrderSL(symbol,opstype,pos_open);
               if(price>modselsl) modselsl=mc_symbol.NormalizePrice(price+slip*pip);
               modseltp=SetOrderTP(symbol,opstype,pos_open);
               if(price<modseltp) modseltp=mc_symbol.NormalizePrice(price-slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modselsl,modseltp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
         }
     }
    //--
    return;
//---
  } //-end SetSLTPOrders
//---------//


5.2.Close All Orders

すべての注文を決済したい場合、[Close All Orders]ボタンを1回クリックするだけで、すべての未決済注文が決済されます。

void MCEA::CloseAllOrders(void) //-- function: close all order
   {
//----
    ResetLastError();
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int total=PositionsTotal(); // number of open positions
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        //--- if the MagicNumber matches
        if(mc_position.Magic()==magicEA)
          { 
            //--
            string position_Symbol   = PositionGetSymbol(i);  // symbol of the position
            ulong  position_ticket   = PositionGetTicket(i);  // ticket of the the opposite position
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            RefreshTick(position_Symbol);
            bool closepos = mc_trade.PositionClose(position_Symbol,slip);
            //--- output information about the closure
            PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
            //---
          }
      }
   //---
   return;
//----
   } //-end CloseAllOrders()
//---------//


5.3.Close All Profits

トレーダーがすでに利益が出ている注文をすべて決済したい場合、[Close All Profits]ボタンを1回クリックするだけで、すでに利益が出ているすべての未決済注文を決済することができます。

bool MCEA::ManualCloseAllProfit(void)
   {
//----
    ResetLastError();
    //--
    bool orclose=false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int ttlorder=PositionsTotal(); // number of open positions
    //--
    for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         orclose=false;
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  ulong  position_ticket = PositionGetTicket(i);
                  //---
                  if(type==POSITION_TYPE_BUY && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    }
                  if(type==POSITION_TYPE_SELL && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    }
                }
            }
       }
     //--
     return(orclose);
//----
   } //-end ManualCloseAllProfit()
//---------//


さらに、[C]ボタンをクリックすると、30の銘柄名またはペアが表示されたパネルボタンが表示され、ペア名または銘柄名のいずれかをクリックできます。 
ペア名または銘柄のいずれかがクリックされると、チャート銘柄は即座にクリックされた名前の銘柄に置き換わります。

Expert_manual_button_02

void CreateSymbolPanel()
  {
//---    
    //--
    ResetLastError();
    DeletePanelButton();
    int sydis=83;
    int tsatu=int(mc.sall/2);
    //--
    CreateButtonTemplate(0,"Template",180,367,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,187,45,true);
    CreateButtonTemplate(0,"TempCCS",167,25,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBlue,clrWhite,CORNER_RIGHT_UPPER,181,50,true);
    CreateButtonClick(0,"X",14,14,"Arial Black",10,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,22,48,true,"Close Symbol Panel");
    //--
    string chsym="Change SYMBOL";
    int cspos=int(181/2)+int(StringLen(chsym)/2);
    CreateButtontLable(0,"CCS","Bodoni MT Black",chsym,11,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,cspos,62,true,"Change Chart Symbol");
    //--
    for(int i=0; i<tsatu; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,180,sydis+(i*22),true,"Change to "+mc.AS30[i]);
    //--
    for(int i=tsatu; i<mc.sall; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,94,sydis+((i-tsatu)*22),true,"Change to "+mc.AS30[i]);
    //--
    ChartRedraw(0);
    //--
    return;
//---
   } //-end CreateSymbolPanel()
//---------//

この場合、銘柄名のいずれかがクリックされると、OnChartEvent()関数からChangeChartSymbol()関数が呼び出されます。
   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       int lensymbol=StringLen(Symbol());
       int lensparam=StringLen(sparam);

       //--- if Symbol button is click
       if(lensparam==lensymbol)
         {
           int sx=mc.ValidatePairs(sparam);
           ChangeChartSymbol(mc.AS30[sx],CCS);
           mc.PanelExtra=false;
         }
       //--
     }
void ChangeChartSymbol(string c_symbol,ENUM_TIMEFRAMES cstf)
  {
//---
   //--- unpress the button 
   ObjectSetInteger(0,c_symbol,OBJPROP_STATE,false);
   ObjectSetInteger(0,c_symbol,OBJPROP_ZORDER,0);
   ObjectsDeleteAll(0,0,OBJ_BUTTON);
   ObjectsDeleteAll(0,0,OBJ_LABEL);
   ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
   //--
   ChartSetSymbolPeriod(0,c_symbol,cstf);
   //--
   ChartRedraw(0);
   //--
   return;
//---
  } //-end ChangeChartSymbol()
//---------//


[R]ボタンをクリックすると、多通貨EA ZigZag_AO_MCEAがチャートから削除されるため、EAを手動で切断する必要がありません。

   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       //--
       //--- if "R" button is click
       if(sparam=="R") 
         { 
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Expert Advisor will be Remove from the chart.");
           ExpertRemove();
           //--- unpress the button 
           ObjectSetInteger(0,"R",OBJPROP_STATE,false);
           ObjectSetInteger(0,"R",OBJPROP_ZORDER,0);
           if(!ChartSetSymbolPeriod(0,Symbol(),Period()))
             ChartSetSymbolPeriod(0,Symbol(),Period());
           DeletePanelButton();
           ChartRedraw(0);
         }
       //---
     }


ストラテジーテスター

MetaTrader 5ストラテジーテスターの利点は、複数の銘柄で取引する戦略をテストしたり、利用可能なすべての銘柄と利用可能なすべての時間枠で自動売買をテストできることです。

そこで、MetaTrader 5ストラテジーテスタープラットフォーム上で、ZigZag_AO_MCEAMulti-Currency EAをテストします。

テストでは、ZigZag_AO_MCEAを2023.10.01から2024.02.17のカスタム期間でXAUUSDペアとH4時間枠に配置しました。

ZZ_AO_ST_input

 そして結果は以下の図の通りです。

ZZ_AO_ST_result


ZZ_AO_ST_result_graph_01

ZZ_AO_ST_result_graph_02

ZZ_AO_ST_result_graph_03

ZZ_AO_ST_result_graph_04


結論

ジグザグ指標からのシグナルをオーサムオシレーターでフィルタしたり、MQL5を使用してFX取引用に互いのシグナルをフィルタして、多通貨EAを作成しました。結論は以下の通りです。

  1. MQL5で多通貨EAを作成するのは非常に簡単で、単一通貨EAを作成するのと大差ないことがわかりました。多通貨EAは単一通貨EAとしても使用できます。
  2. 多通貨EAを作成すると、取引のために多くのチャート銘柄を開く必要がないため、トレーダーの効率と有効性が向上します。
  3. 適切な取引戦略を適用することで、単一通貨のEAを使用するよりも利益の確率が高まります。あるペアの損失が他のペアの利益によってカバーされるためです。
  4. このZigZag_AO_MCEA多通貨EAは、学習とアイデア創出のための単なるサンプルです。ストラテジーテスターのテスト結果はまだ良くありません。したがって、異なる時間枠や異なる指標期間の計算、選択された異なるシグナルで実験やテストをおこなうことで、より良い戦略やより収益性の高い結果を得ることが可能です。
  5. 私の意見では、このAO指標付きジグザグ戦略は、時間枠、ジグザグ指標パラメータ入力の微分値、そしてジグザグ指標とAO指標の他のアルゴリズムシグナルを追加するなど、様々な異なる実験でさらに研究されるべきだと思います。
  6. 私のストラテジーテスターでの実験結果によると、H1以下の時間枠では結果は良くなく、H1以上の時間枠でのみ、未決済の取引が少なく良い結果が出ています。比べて、短い時間枠ではあ多くの未決済の負け取引発生します。

この記事とMQL5多通貨EAプログラムが、トレーダーの皆さんの学習とアイデアの開発に役立つことを願っています。

ご精読ありがとうございました。


MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/14329

添付されたファイル |
ZigZag_AO_MCEA.mq5 (123.74 KB)
知っておくべきMQL5ウィザードのテクニック(第13回):ExpertSignalクラスのためのDBSCAN 知っておくべきMQL5ウィザードのテクニック(第13回):ExpertSignalクラスのためのDBSCAN
DBSCAN (Density-Based Spatial Clustering of Applications with Noise)は、データをグループ化する教師なし形式であり、入力パラメータをほとんど必要としません。入力パラメータは2つだけであり、K平均法などの他のアプローチと比較すると利点が得られます。ウィザードで組み立てたEAを使用してテストし、最終的に取引するために、これがどのように建設的であり得るかを掘り下げます。
不一致問題(Disagreement Problem):AIにおける複雑性の説明可能性を深く掘り下げる 不一致問題(Disagreement Problem):AIにおける複雑性の説明可能性を深く掘り下げる
説明可能性という波乱の海を航海しながら、人工知能(AI)の謎の核心に飛び込みましょう。モデルがその内部構造を隠す領域において、私たちの探求は、機械学習の回廊にこだまする「不一致問題」を明らかにします。
Pythonを使用したEA用ディープラーニングONNXモデルの季節性フィルタと期間 Pythonを使用したEA用ディープラーニングONNXモデルの季節性フィルタと期間
Pythonでディープラーニングのモデルを作成する際、季節性から恩恵を受けることはできるのでしょうか。ONNXモデルのデータをフィルタすることでより良い結果が得られるのでしょうか。どの期間を使用するべきでしょうか。この記事では、これらすべてを取り上げます。
MQL5の高度な変数とデータ型 MQL5の高度な変数とデータ型
変数とデータ型は、MQL5プログラミングだけでなく、どのプログラミング言語でも非常に重要なトピックです。MQL5の変数とデータ型は、単純なものと高度なものに分類できます。単純なものについては前回の記事ですでに述べたので、今回は高度なものを特定し、それについて学ぶことにします。