MQL5を使ったシンプルな多通貨エキスパートアドバイザーの作り方(第4回):三角移動平均 — 指標シグナル
はじめに
この記事における多通貨EAの定義は、1つの銘柄チャートからのみ複数の銘柄ペアの取引(注文を出す、注文を決済する、注文を管理するなど)ができるEAまたは自動売買ロボットです。この記事では、EAは30ペアを取引します。
今回は、多時間枠または単一時間枠の「三角移動平均」という1つの指標のみを使用します。三角移動平均は著者Mladen RakicによるMT5のカスタム指標です。私は著者からその指標を多通貨EA TriangularMA_MTF_MCEAのシグナルとして使用する許可を受けています。
Rakic氏に敬意を表し、感謝します。
そのため、この記事では、効率的で効果的な自動売買ロボットを求めるトレーダーの本質的なニーズを満たすことを目的とし、信頼性の高いMQL5が提供する長所、能力、機能に頼ることで、指標シグナルを使用するシンプルな多通貨EAを作成します。三角移動平均指標です。
注:多通貨EA TriangularMA_MTF_MCEAの作成は、トレーダーの提案とリクエストによっておこなわれました。
計画と機能
1.通貨ペアの取引
この多通貨EAは、以下の銘柄またはペアで取引するように計画されています。
28ペア: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
メタル2ペア:XAUUSD(金)とXAGUSD(銀)
合計30ペア
前回の記事では、プレフィックスやサフィックスを持つ特別なペア名を持つブローカー上のペアについて、自動関数を使用してプレフィックスやサフィックスを持つペア名を検出しました。
今回は、ペア名のプレフィックスとペア名のサフィックスに特別な入力プロパティを追加することで、それを簡単にします。
次に、簡単な関数を使用して、プレフィックスおよび/またはサフィックスのペア名と、登録されている30個のペア名を組み合わせて処理します。そのため、そのような特殊な銘柄名を持つブローカーからEAがMetaTrader5で使用された場合、すべてがスムーズに実行されます。
プレフィックスとサフィックスを持つ銘柄名を検出する関数の弱点は、この関数がMT5の外国為替および金属銘柄のペアまたは名前に対してのみ機能し、特殊な銘柄やインデックスに対しては機能しないことです。
それとは別に、この方法のもう1つの弱点は、トレーダーがペアのプレフィックスおよび/またはサフィックスの名前にタイプミス(入力の大文字と小文字は区別されるなど)をした場合です。
前回の記事と同様に、このEAでも、現時点で取引されるペアのオプションを10個追加しました。
取引される10のオプションペアの1つは「トレーダーウィッシュペア」で、取引されるペアはトレーダーがEA入力プロパティに手動で入力する必要があります。ただし、入力したペアの名前がすでに30ペアのリストに含まれている必要があることを常に覚えておく必要があります。
前回の記事と同様に、このバージョンのEAでは、取引セッション(タイムゾーン)のオプションも追加したため、取引されるペアは取引セッションの時間に対応する可能性があります。
2.シグナル指標
三角移動平均指標の説明の中で、著者は次のように述べています。
「使用法:
色の変化をシグナルとして使用できます...」
デフォルトでは、三角移動平均指標の色は次のとおりです。
- 0-DarkGray=未知のシグナル
- 1-DeepPink=売りシグナル
- 2-MediumSeaGreen=買いシグナル
このバージョンのEAでは、三角移動平均指標シグナルの計算に時間枠を使用するための2つのオプションを作成しました。
1.多時間枠に基づくシグナル計算
多時間枠計算システムでは、トレーダーは列挙リストから目的の時間枠シリーズを選択する必要があります。
選択した時間枠シリーズの範囲はM5からD1(11時間枠)です。
また、トレーダーは時間枠シリーズを選択し、開始を選択します(例:M15)と終了(例:H4)を選択します。
この場合、EAは、時間枠M15から時間枠H4までの三角移動平均指標シグナルを計算します。
多時間枠での三角移動平均シグナルの計算は次のとおりです。
- 買いシグナル:選択したすべての時間枠で指標の色がMediumSeaGreenの場合
- 売りシグナル:選択したすべての時間枠で指標がDeepPinkの場合
2.単一時間枠に基づくシグナル計算
単一時間枠シグナル計算システムでは、トレーダーはM5時間枠からD1時間枠までの11時間枠から1つの時間枠を選択する必要があります。
EAは、選択された時間枠から三角移動平均指標シグナルを計算します。
一方、単一時間枠での三角移動平均シグナルの計算は次のようになります。
- 前の2つのバーがDeepPink、前の1つのバーがMediumSeaGreen、現在のバーがMediumSeaGreenの場合、買いシグナル
- 前の2つのバーがMediumSeaGreen、前の1つのバーがDeepPink、現在のバーがDeepPinkの場合、売りシグナル
買いまたは売りシグナルの三角移動平均指標の図を図1と図2に示します。
3.取引と注文の管理
この多通貨EAの取引管理には、いくつかのオプションが与えられています。
1.ストップロス注文
- オプション:UseOrderStopLoss:Yes/No
UseOrderStopLossでNoを選択すると、すべての注文はストップロスなしで発注されます。
オプションUse Order Stop LossがYesの場合:
再びオプションが与えられます。Use Automatic Calculation Stop LossでYes/Noを指定することになります。
Use Automatic Calculation Stop LossがYesの場合、ストップロスの計算はEAによって自動的に実行されます。
Use Automatic Calculation Stop LossでNoを選択すると、トレーダーはストップロスの値をPipsで入力する必要があります。
オプションUse Order Stop LossがNoの場合:
EAは開かれた各注文について、シグナル状態がまだ良好であるかどうかを確認し、注文します。
利益を維持できるか、シグナルが弱まり、保存するには注文を閉じる必要がある状態が維持される可能性があります。
利益またはシグナル状態の方向が逆転したため、損失状態で注文を決済する必要があります。
注:
特に弱いシグナルによる取引決済と利益の保存については、それをアクティブにするかどうかのオプションが与えられます。
アクティブ化されていない場合(No)、シグナルが弱まっても注文は維持されるか、利益を保存するために決済されません。
2.テイクプロフィット注文
- オプション:UseOrderTakeProfit:Yes/No
UseOrderTakeProfitでNoを選択した場合、すべての注文はテイクプロフィットなしで発注されます。
オプションUse Order Take ProfitがYesの場合:
再びオプションが与えられます。Use Automatic Calculation Order Take Profit:Yes/Noオプションを指定することになります。
Use Automatic Calculation Order Take ProfitでYesを選択すると、テイクプロフィット注文の計算はEAで自動的におこなわれます。
Use Automatic Calculation Order Take ProfitでNoを選択した場合、トレーダーは注文のテイクプロフィット値をPipsで入力する必要があります。
3.トレーリングストップとトレーリングテイクプロフィット
- オプション:Use Trailing SL/TP:Yes/No
Use Trailing SL/TPがNoの場合、EAはトレーリングストップロスおよびトレーリングテイクプロフィットをおこないません。
オプションUse Trailing SL/TPがYesの場合:
再びオプションが与えられます。Use Automatic Trailing:Yes/Noを指定することになります。
オプションUse Automatic TrailingがYesの場合、EAは以下を使用してトレーリングストップを実行します。
EAによって自動的に選択される時間枠上の三角移動平均バッファ0(指標データ)
変数値TPmin(最小トレーリング利益値)に基づいてトレーリング利益を得ることによる
Use Automatic TrailingでNoを選択すると、EAによってトレーリングストップが入力プロパティの値を使用して実行されます。
注:EAはトレーリングストップと同時にトレーリングテイクプロフィットを実行します。
以下は、トレーリングストップ価格関数です。
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 0: { 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 1: { double TriMAID[]; //-- ArrayResize(TriMAID,br,br); ArraySetAsSeries(TriMAID,true); CopyBuffer(hTriMAt[x],0,0,br,TriMAID); // Copy buffer 0 from the hTriMAt indicator handle //-- RefreshTick(xsymb); if(ptype==POSITION_TYPE_BUY && (mc_symbol.Bid()>mc_symbol.NormalizePrice(TriMAID[0]+TSval*pip))) pval=TriMAID[0]; if(ptype==POSITION_TYPE_SELL && (mc_symbol.Ask()<mc_symbol.NormalizePrice(TriMAID[0]-TSval*pip))) pval=TriMAID[0]; break; } } //-- return(pval); //--- } //-end TSPrice() //---------//
SL/TP機能を変更します。
bool MCEA::ModifySLTP(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_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*pip); double modbuysl=vtrsb; double modbuytp=mc_symbol.NormalizePrice(price+TPmin*pip); bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop)); //-- if(modbuy && netp>0.05) { modist=mc_trade.PositionModify(symbol,modbuysl,modbuytp); } } 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_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*pip); double modselsl=vtrss; double modseltp=mc_symbol.NormalizePrice(price-TPmin*pip); bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); //-- if(modsel && netp>0.05) { modist=mc_trade.PositionModify(symbol,modselsl,modseltp); } } } } //-- return(modist); //--- } //-end ModifySLTP() //---------//
4.手動注文管理
この多通貨EAの効率をサポートするために、いくつかの手動クリックボタンが追加されます。
1.Set SL / TP All Orders
トレーダー入力パラメータが、Use Order Stop Loss:Noおよび/またはUse Order Take Profit:Noに設定されているが
すべての注文でストップロスまたはテイクプロフィットを使用する場合、
[Set SL / TP All Orders]ボタンを1回クリックするだけで済みます。すべての注文が変更され、ストップロスやテイクプロフィットが適用されます。
2.Close All Orders
すべての注文を決済したい場合、[Close All Orders]ボタンを1回クリックするだけで、すべての未決注文が決済されます。3.Close All Orders Profit
すでに利益を上げている注文をすべて決済したい場合、
[Close All Orders Profit]ボタンを1回クリックするだけで、すでに利益が出ているすべての未処理の注文が決済されます。
5.注文管理とチャート銘柄
1つのチャート銘柄から30ペアを取引する多通貨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 }; //--
取引するオプションペアを選択するための列挙
//-- 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 TFMTF { TFM5, // PERIOD_M5 TFM15, // PERIOD_M15 TFM30, // PERIOD_M30 TFH1, // PERIOD_H1 TFH2, // PERIOD_H2 TFH3, // PERIOD_H3 TFH4, // PERIOD_H4 TFH6, // PERIOD_H6 TFH8, // PERIOD_H8 TFH12, // PERIOD_H12 TFD1 // PERIOD_D1 }; //--
以下は、多時間枠または単一時間枠を使用するための列挙体です。
//-- enum SMTF { MTF, // Use Multi-Timeframe STF // Use Single-Timeframe }; //--
EA入力プロパティ
//--- input group "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter input SMTF tfinuse = MTF; // Select Calculation in Multi or Single Timeframe input TFMTF singletf = TFH1; // Select Single Calculation TimeFrame, default PERIOD_H1 input TFMTF tfstart = TFM15; // Select Multi Timeframe calculation start input TFMTF tfclose = TFH4; // Select Multi Timeframe calculation end input int Trmaperiod = 14; // Input Triangular MA Indicator period, default 14 input ENUM_APPLIED_PRICE Trprice = PRICE_CLOSE; // Select Triangular MA Applied Price, default Price Close //--- input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading 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 string sym_prefix = ""; // Input the symbol prefix in case sensitive (if any) input string sym_suffix = ""; // Input the symbol suffix in case sensitive (if any) //-- 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; // 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 = 10; // If Not Use Automatic TP - Input TP value in Pips input YN TrailingSLTP = Yes; // Use Trailing SL/TP (Yes) or (No) input YN autotrl = Yes; // Use Automatic Trailing (Yes) or (No) input double TSval = 5; // If Not Use Automatic Trailing Input Trailing value in Pips input double TSmin = 5; // Minimum Pips to start Trailing Stop input double TPmin = 25; // 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) //--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 = 2023111; // Expert ID (Magic Number) //---
EA入力プロパティグループのグローバルストラテジーEAパラメータでは、トレーダーは多時間枠または単一時間枠のどちらのシグナル計算を使用するかを選択する必要があります。
単一時間枠(STF)を選択した場合、使用する時間枠を決定する必要があります。
EA入力プロパティで、単一計算時間枠(デフォルトはPERIOD_H1)を選択します。
多時間枠(MTF)を選択した場合、使用する時間枠シリーズを決定する必要があります。
EA入力プロパティでは、「多時間枠計算の開始を選択」および「多時間枠計算の終了を選択」するように指示されます。
TriangularMA_MTF_MCEA_Config()関数の478行目から518行目では、多時間枠と単一時間枠の処理方法が説明されています。
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(singletf==x) TFt=TFs[x]; // TF for single-timeframe if(tfstart==x) arstr=x; // multi-timeframe start calculation timeframe if(tfclose==x) arend=x; // multi-timeframe end calculation timeframe } //-- if(arstr>=arend) { Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe"); Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); } //-- switch(tfinuse) { case MTF: { TFArrays=arend-arstr+1; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=arstr+1; tftrlst=(int)TFArrays/2; TFts=TFs[tftrlst+arstr-1]; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } case STF: { TFArrays=arTFs; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2; TFts=TFt; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } }
変数ENUM_TIMEFRAMESTFs[]は、列挙オプションenumTFMTFに固有である必要があります。
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}; //-- enum TFMTF { TFM5, // PERIOD_M5 TFM15, // PERIOD_M15 TFM30, // PERIOD_M30 TFH1, // PERIOD_H1 TFH2, // PERIOD_H2 TFH3, // PERIOD_H3 TFH4, // PERIOD_H4 TFH6, // PERIOD_H6 TFH8, // PERIOD_H8 TFH12, // PERIOD_H12 TFD1 // PERIOD_D1 }; //--
次に、三角MA指標の期間、デフォルト期間14を決定します。
さらに、三角MA適用価格、デフォルトのPRICE_CLOSEも指定する必要があります。
EA入力プロパティグループの[Select Pairs to Trade]では、提供される10のオプションから取引するペアを選択します。デフォルトでは[All Forex 30 Pairs]が決定されます。
取引されるペアを設定するには、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); aretc=ArraySize(EURs); 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<aretc; 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 30 Pairs { ArrayResize(DIRI,sall,sall); arrsymbx=sall; ArraySymbolResize(); ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY); pairs="Multi Currency 30 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,aretc,aretc); 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) { //--- symbfix=false; int ptriml; int ptrimr; string insymbol=Symbol(); int sym_Lenpre=StringLen(prefix); int sym_Lensuf=StringLen(suffix); if(sym_Lenpre>0) { ptriml=StringTrimLeft(suffix); ptriml=StringTrimRight(suffix); } if(sym_Lensuf>0) { ptrimr=StringTrimLeft(suffix); ptrimr=StringTrimRight(suffix); } string sym_pre=prefix; string sym_suf=suffix; //-- 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を選択します。
Yesの場合は、列挙オプションを選択します。
- カスタムセッションでの取引
- ニュージーランドセッションでの取引
- オーストラリアシドニーセッションでの取引
- アジア東京セッションでの取引
- ヨーロッパロンドンセッションでの取引
- アメリカニューヨークセッションでの取引
したがって、EAは開始から終了までの指定された時間内のみアクティビティを実行します。
ニュージーランドセッションでの取引から米国ニューヨークセッションでの取引では、取引開始から取引終了までの時間がEAによって計算されます。
この多通貨EAに必要なすべての変数、オブジェクト、関数を宣言するために、EAのワークフローにおける構築と構成を指定するクラスを作成します。
特に、プレフィックス銘柄名やサフィックス銘柄名を処理する関数で使用される変数、およびタイムゾーンの計算は、MCEAクラスで作成されました。
//+------------------------------------------------------------------+ //| 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 slv, tpv, pip, xpip; 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 TriaMASMTF(const string symbol,ENUM_TIMEFRAMES mtf); int GetTriaMASignalMTF(string symbol); int TriaMASignalSTF(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: //--- //-- TriangularMA_MTF_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 indiname; //-- int hTriMAt[]; int hTriMAs[]; int hTriMAm[]; int hTriMAb[][11]; int ALO, dgts, arrsar, arrsymbx; int sall, arusd, aretc, arspc, arper; ulong slip; //-- double profitb[], profits[]; //-- int Buy, Sell; int ccur, psec, xtto, TFArrays, 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, TFts, TFT05, TFCWS; ENUM_TIMEFRAMES TFTri[]; //-- bool PanelExtra; //------------ MCEA(void); ~MCEA(void); //------------ //-- virtual void TriangularMA_MTF_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 CloseBuyPositions(const string symbol); void CloseSellPositions(const string symbol); void CloseAllOrders(void); void CheckClose(const string symbx); void TodayOrders(void); void UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf); void RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars); //-- 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 ModifySLTP(const string symbx,int TS_type); bool CloseAllProfit(void); bool ManualCloseAllProfit(void); //-- int PairsIdxArray(const string symbol); int ValidatePairs(const string symbol); int TFIndexArray(ENUM_TIMEFRAMES TF); int GetOpenPosition(const string symbol); int GetSignalMidTF(const string symbol); int GetCloseInWeakSignal(const string symbol,int exis); //-- string getUninitReasonText(int reasonCode); //-- //------------ //--- }; //-end class MCEA //---------//
OnInit()から呼び出される他通貨EAワークプロセスの最初で最も重要な関数はTriangularMA_MTF_MCEA_Config()です。
TriangularMA_MTF_MCEA_Config()関数では、使用するすべての銘柄が設定され、すべてのハンドル指標が使用され、エキスパートアドバイザワークフローのインクルードファイルヘッダーのいくつかの重要な機能が設定されます。
void MCEA::TriangularMA_MTF_MCEA_Config(void) { //--- //-- HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded //-- int arstr=0, arend=0; TFT05=PERIOD_M5; 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(singletf==x) TFt=TFs[x]; // TF for single-timeframe if(tfstart==x) arstr=x; // multi-timeframe start calculation timeframe if(tfclose==x) arend=x; // multi-timeframe end calculation timeframe } //-- if(arstr>=arend) { Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe"); Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); } //-- switch(tfinuse) { case MTF: { TFArrays=arend-arstr+1; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=arstr+1; tftrlst=(int)TFArrays/2; TFts=TFs[tftrlst+arstr-1]; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } case STF: { TFArrays=arTFs; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2; TFts=TFt; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } } //-- //-- Triangular MA Indicators handle for all symbol for(int x=0; x<arrsymbx; x++) { hTriMAs[x]=iCustom(DIRI[x],TFT05,indiname,Trmaperiod,Trprice); hTriMAm[x]=iCustom(DIRI[x],TFCWS,indiname,Trmaperiod,Trprice); hTriMAt[x]=iCustom(DIRI[x],TFts,indiname,Trmaperiod,Trprice); //-- for(int i=0; i<TFArrays; i++) { if(tfinuse==MTF) // MTF indicator handle { hTriMAb[x][i]=iCustom(DIRI[x],TFTri[i],indiname,Trmaperiod,Trprice); } if(tfinuse==STF) { if(TFs[i]==TFt) // Single-TF indicator handle { hTriMAb[x][i]=iCustom(DIRI[x],TFs[i],indiname,Trmaperiod,Trprice); break; } } } } //-- ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders(); //-- LotPS=(double)ALO; //-- mc_trade.SetExpertMagicNumber(magicEA); mc_trade.SetDeviationInPoints(slip); mc_trade.SetMarginMode(); Set_Time_Zone(); //-- return; //--- } //-end TriangularMA_MTF_MCEA_Config() //---------//
2.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++) { //-- if(mc.DIRI[x]==Symbol()) symbol=Symbol(); else symbol=mc.DIRI[x]; //-- 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 if(SaveOnRev==Yes) mc.CloseAllProfit(); } } 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 if(SaveOnRev==Yes) mc.CloseAllProfit(); } } } //-- 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]>0.02 && 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]>0.02 && 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(TrailingSLTP==Yes) //-- Use Trailing SL/TP (Yes) { if(autotrl==Yes) mc.ModifySLTP(symbol,1); //-- If Use Automatic Trailing (Yes) if(autotrl==No) mc.ModifySLTP(symbol,0); //-- Use Automatic Trailing (No) } } //-- mc.CheckClose(symbol); } //-- mc.psec=mc.ccur; } //-- return; //--- } //-end ExpertActionTrade() //---------//
特にタイムゾーン取引の場合、ExpertActionTrade()関数にブール型Trade_session()関数の呼び出しが追加されます。
Trade_session()がtrueの場合、EAの作業プロセスは終了するまで続行されますが、falseの場合、EAは「シグナルが弱いため取引を終了して利益を保存する(Yes)」および「」タスクのみを実行します。トレーリングストップ(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() //---------//
3.オープンポジションの取引シグナルの取得
シグナルを取得するには、ExpertActionTrade()関数はGetOpenPosition()関数を呼び出します。
int MCEA::GetOpenPosition(const string symbol) // Signal Open Position { //--- int ret=0; int rise=1, down=-1; //-- int trimOp=GetTriaMASignalMTF(symbol); int getmid=GetSignalMidTF(symbol); if(trimOp==rise && getmid==rise) ret=rise; if(trimOp==down && getmid==down) ret=down; //-- return(ret); //--- } //-end GetOpenPosition() //---------//
GetOpenPosition()関数は、シグナル計算を実行する2つの関数を呼び出します。
1. GetSignalMidTF(const string symbol); //--中間時間枠と価格変動ポジションのシグナルを取得する関数
int MCEA::GetSignalMidTF(const string symbol) // Signal Indicator Position Close in profit { //--- int ret=0; int rise=1, down=-1; //-- int br=2; //-- double TriMACI[]; //-- ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); CopyBuffer(hTriMAm[xx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2 //-- int dirmove=DirectionMove(symbol,TFCWS); //-- if(TriMACI[0]==2.0 && dirmove==rise) ret=rise; if(TriMACI[0]==1.0 && dirmove==down) ret=down; //-- return(ret); //--- } //-end GetSignalMidTF() //---------//
2.GetTriaMASignalMTF(const string symbol); //--三角移動平均の計算式への関数
GetTriaMASignalMTF()関数は、要求された時間枠に従って三角移動平均シグナルを計算する関数TriaMASMTF()を呼び出します。
int MCEA::GetTriaMASignalMTF(string symbol) { //--- int mv=0; int rise=1, down=-1; int tfloop=tfinuse==MTF ? TFArrays : 1; //-- int trimup=0, trimdw=0; //-- for(int x=0; x<tfloop; x++) { if(TriaMASMTF(symbol,TFTri[x])>0) trimup++; if(TriaMASMTF(symbol,TFTri[x])<0) trimdw++; } //-- if(trimup==tfloop) mv=rise; if(trimdw==tfloop) mv=down; //-- return(mv); //--- } //- end GetTriaMASignalMTF() //---------//
int MCEA::TriaMASMTF(const string symbol,const ENUM_TIMEFRAMES mtf) // formula Triangular MA on the requested Timeframe { //--- int ret=0; int rise=1, down=-1; int br=3; ENUM_TIMEFRAMES TFUse=tfinuse==MTF ? mtf : TFt; //-- double TriMACI[]; ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); int tx=TFIndexArray(TFUse); CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2 //Print("Symbol = "+symbol+" TF = "+EnumToString(mtf)+" TriMACI[0] = "+string(TriMACI[0])); //-- switch(tfinuse) { case MTF: { if(TriMACI[0]==2.0) ret=rise; if(TriMACI[0]==1.0) ret=down; //-- break; } case STF: { if(TriMACI[2]==1.0 && TriMACI[1]==2.0 && TriMACI[0]==2.0) ret=rise; if(TriMACI[2]==2.0 && TriMACI[1]==1.0 && TriMACI[0]==1.0) ret=down; //-- break; } } //-- return(ret); //--- } //-end TriaMASMTF() //---------//
ご覧のとおり、TriaMASMTF()関数内で2つの関数を使用して呼び出します。
- 1. int xx= PairsIdxArray(symbol)
- 2. int tx=TFIndexArray(mtf).
PairsIdxArray()関数は、要求された銘柄の名前を取得するために使用され、TFIndexArray()関数は、要求された時間枠の時間枠配列シーケンスを取得するために使用されます。
次に、適切な指標ハンドルが呼び出されて、その時間枠から三角移動平均シグナルのバッファ値を取得します。
三角移動平均指標の作者は次のように述べています。
「使用法:
色の変化をシグナルとして使用できます...」
では、三角移動平均指標のシグナルをどのように取得するのでしょうか。
三角移動平均指標のプロパティ:
#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2
SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);
valc[i] = (i>0) ?(val[i]>val[i-1]) ? 2 :(val[i]<val[i-1]) ? 1 : valc[i-1]: 0;
したがって、次のことがわかります。
- 0-DarkGray=未知のシグナル
- 1-DeepPink=売りシグナル
- 2-MediumSeaGreen=買いシグナル
したがって、TriaMASMTF()関数と同様に、CopyBuffer関数によって三角移動平均指標のバッファ1の値をシグナルとして取得できます。
double TriMACI[]; ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); int tx=TFIndexArray(TFUse); CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2
4.ChartEvent関数
多通貨EAの使用における有効性と効率性をサポートするには、注文の管理およびチャートや銘柄の変更用にいくつかの手動ボタンを作成する必要があると
考えられます。
//+------------------------------------------------------------------+ //| 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() //---------//
ワンクリックでチャート銘柄を変更するには、銘柄名のいずれかをクリックすると、OnChartEvent()が関数ChangeChartSymbol()として呼び出されます。
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() //---------//
EA取引モードの多時間枠または単一時間枠、取引セッションまたは取引タイムゾーン、および取引されるペアのオプションを追加しているため、チャートに表示される取引情報に追加情報が必要です。
チャートに表示される取引情報に情報を追加するために、TradeInfo()関数に変更を加えました。
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 tradetf=tfinuse==MTF ? EnumToString(Period()) : EnumToString(TFts); string eamode=tfinuse==MTF ? "Multi-Timeframe" : "Single-Timeframe"; 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 : "+ tradetf+ "\n :: Trade Mode : "+ eamode+ "\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() //---------//
また、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() //---------//
多通貨EA TriangularMA_MTF_MCEAのインターフェイスは次の図のようになります。
ご覧のとおり、EA名TriangularMA_MTF_MCEAの下に[M]、[C]、[R]ボタンがあります。
[M]ボタンがクリックされると、以下のように手動クリックボタンパネルが表示されます。
その後、トレーダーは手動注文管理で説明されているように注文を管理できます。
- 1.SetSL/TPAllOrders
- 2.Close All Orders
- 3.CloseAllProfits
[C]ボタンをクリックすると、30個の銘柄名またはペアのパネルボタンが表示され、いずれかのペア名または銘柄名をクリックできます。
ペア名または銘柄のいずれかがクリックされると、チャート銘柄は即座にクリックされた名前の銘柄に置き換わります。
[R]ボタンをクリックすると、多通貨EA TriangularMA_MTF_MCEAがチャートから削除されます。
そのため、EAを手動で切り離す必要はありません。
ストラテジーテスター
知られているように、MetaTrader 5ターミナルのストラテジーテスターは、戦略のテスト、複数の銘柄の取引、または利用可能なすべての銘柄と利用可能なすべての時間枠の自動取引のテストをサポートしており、これを可能にします。
したがって、この機会に、MetaTrader 5ストラテジーテスタープラットフォーム上の多通貨EAで多時間枠および単一時間枠としてTriangularMA_MTF_MCEAをテストします。
1. TriangularMA_MTF_MCEAを多時間枠モードでテストします。
/p>
2.TriangularMA_MTF_MCEAを単一時間枠モードでテストします。
結論
MQL5を使用して多時間枠モードと単一時間枠モードの両方で多通貨EAを作成した結論は次のとおりです。
- MQL5で多通貨EAを作成するのは非常に簡単で、単一通貨のEAと大差ないことがわかりました。ただし、特に複数の時間枠を持つ複数通貨EAの場合、単一の時間枠の場合よりも少し複雑になります。
- 多通貨EAを作成すると、トレーダーは取引のために多くのチャート銘柄を開く必要がないため、トレーダーの効率と有効性が向上します。
- 適切な取引戦略を適用することにより、単一通貨EAを使用する場合と比較して利益の確率が増加します。あるペアで発生した損失は、他のペアの利益でカバーされるからです。
- このTriangularMA_MTF_MCEA多通貨EAは、アイデアを学び発展させるための単なる例です。
- ストラテジーテスターのテスト結果はまだ良くありません。したがって、より正確なシグナル計算を備えたより良い戦略が実装され、より良い時間枠が追加されれば、現在の戦略よりも良い結果が得られると思います。
- TriangularMA_MTF_MCEAのストラテジーテスターテスト結果から、単一時間枠の結果が多時間枠よりも優れていることがわかります。
注:
組み込みのMQL5標準指標シグナルに基づいてシンプルな複数通貨EAを作成するアイデアをお持ちの方は、コメントでご提案ください。
この記事とMQL5多通貨EAプログラムが、トレーダーの皆さんの学習とアイデアの開発に役立つことを願っています。ご精読ありがとうございました。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/13770
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索