//+------------------------------------------------------------------+ //| BLESSING for GBPJPY.mq4 | //| Copyright © 2022-2025 HANDY SYSTEMS, All Rights Reserved. | //| https://handy-systems.com | //+------------------------------------------------------------------+ #property strict //PRODUCTIONモードでコンパイルする時は、ここから下をコメントアウトする。 //#define _DEVELOPMENT //PRODUCTIONモードでコンパイルする時は、ここから上をコメントアウトする。 //EA-BANK口座縛りにする時は、ここから下のコメントアウトを解除する。 //#define _EA_BANK //EA-BANK口座縛りにする時は、ここから上のコメントアウトを解除する。 //GogoJungle形式コメントにする時は、ここから下のコメントアウトを解除する。 //#define _GOGOJUNGLE //GogoJungle形式コメントにする時は、ここから上のコメントアウトを解除する。 //MQL5.com形式EAにする時は、ここから下のコメントアウトを解除する。 //#define _MQL5_COM //MQL5.com形式EAにする時は、ここから上のコメントアウトを解除する。 //LET'S REAL形式EAにする時は、ここから下のコメントアウトを解除する。 //#define _LETS_REAL //LET'S REAL形式EAにする時は、ここから上のコメントアウトを解除する。 #include //----------EA-BANK certification begin #ifdef _EA_BANK #include #endif // _EA_BANK //----------EA-BANK certification end #property copyright "Copyright © 2022-2025 HANDY SYSTEMS, All Rights Reserved." #ifndef _GOGOJUNGLE //GogoJungleでは外部リンクは許可されていないため、ここから下の行はGogoJungleでは無視する #property link "https://www.handy-systems.com/" //GogoJungleでは外部リンクは許可されていないため、ここから上の行はGogoJungleでは無視する #endif // _GOGOJUNGLE #property icon "HANDY-SYSTEMS-LOGO.ico" #ifdef _EA_BANK #property version "1.2" // _EA_BANK #endif #ifdef _GOGOJUNGLE #property version "1.4" // _GOGOJUNGLE #endif // _GOGOJUNGLE #ifdef _MQL5_COM #property version "1.2" // _MQL5_COM #endif #ifdef _LETS_REAL #property version "1.0" // _LETS_REAL #else #property version "1.4" // ACCOUNT-FREE #endif #ifdef _DEVELOPMENT #define dinput input #else #define dinput #endif // _DEVELOPMENT_ #ifdef _GOGOJUNGLE const string STR_EA_ID = "44085"; const string STR_EA_NAME = STR_EA_ID + ":" + "BLESSING_for_GBPJPY"; #else const string STR_EA_NAME = "BLESSING_for_GBPJPY"; #endif // _GOGOJUNGLE const string STR_OP_BUY = "BUY"; const string STR_OP_SELL = "SELL"; input int MagicNumber = 84001; // MagicNumber input double Lots = 0.11; // Lots input double MaxSpread = 3.0; // MaxSpread (pips) input double TakeProfit_pips = 890.0; // TakeProfit (pips) input double StopLoss_pips = 250.0; // StopLoss (pips) dinput double Rikaku_pips = 350.0; dinput double Songiri_pips = 225.0; //トレイリングストップのパラメータ dinput int TrailingStopStartPips = 280; dinput int TrailingStopPips = 20; //指値切り下げのパラメータ dinput int ReLimitActionPips = 35; dinput int ReLimitPips = 30; //スリッページ int Slippage = 3; //リトライ回数 const int MAX_ORDER_REPEAT = 5; //マーケットオープン待機時間(秒) const int TIME_WAIT_FOR_MARKET_OPEN = 3600; int xBars = 0, xxBars = 0; double BuyStop = 0, SellStop = DBL_MAX; double BuyLimit = DBL_MAX, SellLimit = 0; //最大ポジション数を、下記で入力指定して下さい。 int maxposition = 1; //ローソク足始値のみに稼働させる場合は、trueにして下さい。 bool CandleStartStarting = true; //最適化制御パラメータ #define OPTIMIZE_RF 0x0001 // RF #define OPTIMIZE_TR 0x0002 // 取引数 #define OPTIMIZE_WR 0x0004 // 勝率 // 最適化タイプの種類 enum OPTYPE { OPTYPE_RF_ONLY = OPTIMIZE_RF, // RF OPTYPE_TR_ONLY = OPTIMIZE_TR, // 取引数 OPTYPE_WR_ONLY = OPTIMIZE_WR, // 勝率 OPTYPE_RF_TR = OPTIMIZE_RF | OPTIMIZE_TR, // RF+取引数 OPTYPE_RF_WR = OPTIMIZE_RF | OPTIMIZE_WR, // RF+勝率 OPTYPE_TR_WR = OPTIMIZE_TR | OPTIMIZE_WR, // 取引数+勝率 OPTYPE_RF_TR_WR = OPTIMIZE_RF | OPTIMIZE_TR | OPTIMIZE_WR, // RF+取引数+勝率 OPTYPE_NONE = 0 // なし }; dinput OPTYPE OP_Type = OPTYPE_RF_ONLY; // 最適化タイプ // 相場タイプの種類 enum MKTTYPE { MKTTYPE_NONE = 0x0000, // なし MKTTYPE_TRENDING = 0x0001, // トレンド相場 MKTTYPE_RANGE = 0x0002, // レンジ相場 MKTTYPE_BOTH = 0x0003 // トレンド+レンジ相場 }; MKTTYPE MKT_Type = MKTTYPE_NONE; // 相場タイプ //エントリールールの各変数を下記に貼りつけます。 dinput int MA_Period1 = 20; // 短期移動平均線 dinput int MA_Period2 = 50; // 長期移動平均線 //エントリーフィルターの各変数を下記に貼りつけます。 dinput int BB_Period = 20; // ボリンジャーバンドの計算期間 dinput double BB_Deviation = 2.5; // ボリンジャーバンドの偏差 dinput double BB_Width = 0.30; // ボリンジャーバンドの幅% dinput double MA_Deviation = 2.0; // 移動平均線の乖離% dinput int ADX_Trend_Period = 10; // ADX(トレンド)の計算期間 dinput double ADX_Trend_Level = 21.5; // ADX(トレンド)の基準レベル dinput int ADX_Trend_Duration = 25; // ADX(トレンド)の継続期間 dinput int ADX_Range_Period = 100; // ADX(レンジ)の計算期間 dinput double ADX_Range_Level = 11.5; // ADX(レンジ)の基準レベル dinput int ADX_Range_Duration = 20; // ADX(レンジ)の継続期間 dinput int ATR_Period_Filter = 26; // ATRの計算期間 dinput double ATR_Volatility_Threshold = 1.25; // ボラティリティ上昇判定の閾値 dinput int Loss_Lookback_Count = 3; // 損失チェックの遡り本数 dinput int Max_Consecutive_Losses = 12; // 許容連続損失回数 dinput double Max_Loss_Pips = 1000.0; // 最大損失pips dinput double High_Vol_Loss_Limit = 980.0; // 高ボラティリティ時の損失制限(pips) //決済ルールの各変数を下記に貼りつけます。 dinput int BB_TP_Period = 30; // 利確ボリンジャーバンドの計算期間 dinput double BB_TP_Deviation = 4.5; // 利確ボリンジャーバンドの偏差 dinput int BB_SL_Period = 750; // 損切りボリンジャーバンドの計算期間 dinput double BB_SL_Deviation = 1.0; // 損切りボリンジャーバンドの偏差 dinput double TP_Delta = 0.04; // 利確価格の増減pips // グローバル変数 datetime lastEntryRestrictionTime = 0; // 最後のエントリー制御時刻 int restrictionCount = 0; // エントリー制御回数 #ifdef _LETS_REAL // LET'S REALの認証用コードを定義する int lr_product_id=759; // PRODUCT ID #import "wininet.dll" int InternetAttemptConnect(int x); int InternetOpenW(string &sAgent,int lAccessType,string &sProxyName,string &sProxyBypass,int lFlags); int InternetConnectW(int hInternet,string &szServerName,int nServerPort,string &lpszUsername,string &lpszPassword,int dwService,int dwFlags,int dwContext); int HttpOpenRequestW(int hConnect,string &Verb,string &ObjectName,string &Version,string &Referer,string &AcceptTypes,uint dwFlags,int dwContext); int HttpSendRequestW(int hRequest,string &lpszHeaders,int dwHeadersLength,uchar &lpOptional[],int dwOptionalLength); int HttpQueryInfoW(int hRequest,int dwInfoLevel,int &lpvBuffer[],int &lpdwBufferLength,int &lpdwIndex); int InternetReadFile(int hFile,uchar &sBuffer[],int lNumBytesToRead,int &lNumberOfBytesRead); int InternetCloseHandle(int hInet); #import #define OPEN_TYPE_PRECONFIG 0 #define FLAG_KEEP_CONNECTION 0x00400000 #define FLAG_PRAGMA_NOCACHE 0x00000100 #define FLAG_RELOAD 0x80000000 #define SERVICE_HTTP 3 #define CloseHandle InternetCloseHandle(lr_session);InternetCloseHandle(lr_connect);InternetCloseHandle(lr_request);InternetCloseHandle(lr_send); string lr_is_demo="0", lr_platform="MT4_EA", lr_version="1.07", lr_host="api.lets-real.com", lr_path="index.php?route=api/register", lr_vers="HTTP/1.1", lr_verb="POST", lr_head="Content-Type: application/x-www-form-urlencoded", lr_useragent="Mozilla", lr_result, lr_nill, lr_postdata, lr_ct, lr_msg, lr_msg1="Authentication Failed! ", lr_msg2=" from lets-real.com "; int lr_port=80,lr_session,lr_connect,lr_readfile,lr_request,lr_send,lr_auth_failure_times; bool lr_auth_success=false,lr_auth_exec=true; datetime lr_auth_time; #endif // _LETS_REAL //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { #ifdef _EA_BANK //----------EA-BANK certification begin if(!auth()) { return -1; } //----------EA-BANK certification end //認証OKの文字列を表示する Comment("EA-BANK認証:OK"); #endif // _EA_BANK #ifdef _LETS_REAL // LET'S REALの認証用コードを定義する lr_is_demo=IsDemo()?"1":"0"; if(IsTesting()) { lr_auth_exec=false; lr_auth_success=true; } if(lr_auth_exec && !IsDllsAllowed()) { lr_msg=lr_msg1+"Please allow use of DLL "+lr_msg2; Alert(lr_msg); Print(lr_msg); ExpertRemove(); return(INIT_FAILED); } #endif // _LETS_REAL //使用しているインジケータを非表示にする HideTestIndicators(true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { #ifdef _EA_BANK //----------EA-BANK certification begin if(!auth()) { return; } //----------EA-BANK certification end #endif // _EA_BANK #ifdef _LETS_REAL // LET'S REALの認証用コードを定義する if(lr_auth_exec && TimeCurrent()>=lr_auth_time) { CloseHandle string lr_p0,lr_p1,lr_p2,lr_p3; char lr_data[]; lr_p0=IntegerToString(IsTradeAllowed()); lr_p1=AccountCompany(); lr_p2=IntegerToString(AccountNumber()); lr_p3=StringSubstr(WindowExpertName(),StringLen(WindowExpertName())-8,8); lr_postdata="trade_allowed="+lr_p0+"&fx_company="+lr_p1+"&fx_account="+lr_p2+"&key="+lr_p3+"&ver="+lr_version+"&product_id="+IntegerToString(lr_product_id)+"&platform="+lr_platform+"&is_demo="+lr_is_demo; StringToCharArray(lr_postdata,lr_data,0,WHOLE_ARRAY,CP_UTF8); lr_session=InternetOpenW(lr_useragent,OPEN_TYPE_PRECONFIG,lr_nill,lr_nill,0); lr_connect=InternetConnectW(lr_session,lr_host,lr_port,lr_nill,lr_nill,SERVICE_HTTP,0,0); lr_request=HttpOpenRequestW(lr_connect,lr_verb,lr_path,lr_vers,lr_nill,lr_nill,FLAG_KEEP_CONNECTION|FLAG_RELOAD|FLAG_PRAGMA_NOCACHE,0); lr_send=HttpSendRequestW(lr_request,lr_head,StringLen(lr_head),lr_data,ArraySize(lr_data)-1); if(lr_send<=0) { lr_msg=lr_msg1+lr_msg2+"\n"+"Please check your network."+"\n"+ "InternetAttemptConnect="+IntegerToString(InternetAttemptConnect(0))+"\n"+ "session="+IntegerToString(lr_session)+"\n"+ "connect="+IntegerToString(lr_connect)+"\n"+ "request="+IntegerToString(lr_request)+"\n"+ "send="+IntegerToString(lr_send); Comment(lr_msg); return; } else { uchar response[100]; int dwBytes1; lr_result=""; while(InternetReadFile(lr_request,response,0,dwBytes1)) { lr_readfile=InternetReadFile(lr_request,response,100,dwBytes1); if(dwBytes1<=0) break; lr_result=lr_result+CharArrayToString(response,0,dwBytes1); } string lr_to_split=lr_result; string lr_sep=","; string lr_respara[]; ushort lr_u_sep=StringGetCharacter(lr_sep,0); int k=StringSplit(lr_to_split,lr_u_sep,lr_respara); if(k>0) { for(int j=0; j4?60:5; lr_auth_time=TimeCurrent()+seconds; lr_msg=lr_msg1+lr_to_split+lr_msg2; Comment(lr_msg); Print(lr_result,lr_msg2); } else { lr_auth_success=true; lr_auth_failure_times=0; lr_auth_time=TimeCurrent()+43200; Print("Authentication Success "+lr_msg2); if(StringLen(lr_msg)>0) Comment(""); } } } if(!lr_auth_success) return; #endif // _LETS_REAL int i; int ticket; int CountBuy = 0,CountSell = 0; double profit; bool res; double xpoint = Point; // 小数点以下の桁数に応じてPipsの値を調整する if (Digits() == 3 || Digits() == 5) { xpoint = xpoint * 10; } //ローソク足始値のみ稼働(選択式)の場合、ココカラ if(Bars != xBars || CandleStartStarting == false) { xBars = Bars; //-------- ポジションのクローズ -------- // 所有しているポジションをクローズする for(i=OrdersTotal()-1; i>=0; i--) { //オーダー選択(エラーを生じた場合、ループから抜け出す) if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false) { Print("OrderSelect returned the error of ", GetLastError() ); break; } //オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る) if (OrderSymbol() != Symbol()) continue; //マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る) if (OrderMagicNumber() != MagicNumber) continue; if (OrderType() == OP_BUY) { profit = Bid - OrderOpenPrice(); // 買いポジションだった場合の、含み損益を計算する // オーダーを成り行き決済する if (profit >= Rikaku_pips * xpoint || profit <= -Songiri_pips * xpoint || Exit2() == 2) { res = WrapperOrderClose(OrderTicket(), OrderLots(), Bid, NULL, Green); } } if (OrderType() == OP_SELL) { profit = OrderOpenPrice() - Ask; // 売りポジションだった場合の、含み損益を計算する // オーダーを成り行き決済する if (profit >= Rikaku_pips * xpoint || profit <= -Songiri_pips * xpoint || Exit1() == 1) { res = WrapperOrderClose(OrderTicket(), OrderLots(), Ask, NULL, Green); } } } //-------- ポジションのクローズ(ココマデ) -------- //-------- ポジションのトレーリング -------- // 所有しているポジションのSL, TPをトレールする for(i=OrdersTotal()-1; i>=0; i--) { //オーダー選択(エラーを生じた場合、ループから抜け出す) if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false) { Print("OrderSelect returned the error of ", GetLastError() ); break; } //オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る) if (OrderSymbol() != Symbol()) continue; //マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る) if (OrderMagicNumber() != MagicNumber) continue; if (OrderType() == OP_BUY) { profit = Bid - OrderOpenPrice(); // 買いポジションだった場合の、含み損益を計算する // TrailingStopを確認する if (profit >= TrailingStopStartPips * xpoint && OrderStopLoss() < NormalizeDouble(Bid - TrailingStopPips * xpoint, Digits())) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStopPips * xpoint, OrderTakeProfit(), 0, Green); } // 指値の置きなおしを確認する else if (Bid <= NormalizeDouble(OrderOpenPrice() - ReLimitActionPips * xpoint, Digits()) && OrderTakeProfit() != NormalizeDouble(OrderOpenPrice() + ReLimitPips * xpoint, Digits())) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), OrderOpenPrice() + ReLimitPips * xpoint, 0, Green); } } if (OrderType() == OP_SELL) { profit = OrderOpenPrice() - Ask; // 売りポジションだった場合の、含み損益を計算する // TrailingStopを確認する if (profit >= TrailingStopStartPips * xpoint && OrderStopLoss() > NormalizeDouble(Ask + TrailingStopPips * xpoint, Digits())) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailingStopPips * xpoint, OrderTakeProfit(), 0, Green); } // 指値の置きなおしを確認する else if (Ask >= NormalizeDouble(OrderOpenPrice() + ReLimitActionPips * xpoint, Digits()) && OrderTakeProfit() != NormalizeDouble(OrderOpenPrice() - ReLimitPips * xpoint, Digits())) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), OrderOpenPrice() - ReLimitPips * xpoint, 0, Green); } } } //-------- ポジションのトレーリング(ココマデ) -------- //-------- 新規ポジションのエントリー -------- // ポジションの数をカウントする for(i=OrdersTotal()-1; i>=0; i--) { //オーダー選択(エラーを生じた場合、ループから抜け出す) if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false) { Print("OrderSelect returned the error of ", GetLastError() ); break; } //オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る) if (OrderSymbol() != Symbol()) continue; //マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る) if (OrderMagicNumber() != MagicNumber) continue; if (OrderType() == OP_BUY) { CountBuy = CountBuy + 1; } if (OrderType() == OP_SELL) { CountSell = CountSell + 1; } } double lots = Lots; double correct_volume; string message; //注文数量をチェック if (!CheckVolumeValue(Lots, correct_volume, message)) { // 注文数量が不正な場合は、適切な数量を設定する Print(message); lots = correct_volume; } // エントリー条件を確認し、成立していればエントリーを行う if (Entry() == 1 && CountBuy < maxposition && xxBars != Bars) { // 取引資金をチェック if (!CheckMoneyForTrade(OrderSymbol(), lots, OrderType())) { return; } ticket = WrapperOrderSend(Symbol(), OP_BUY, lots, Ask, Slippage, 0, 0, STR_EA_NAME + " " + STR_OP_BUY, MagicNumber, 0, Blue); // エントリーに成功していれば、TP, SLをセットする if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() - StopLoss_pips * xpoint, OrderOpenPrice() + TakeProfit_pips * xpoint, 0, MediumSeaGreen); } } xxBars = Bars; } else if (Entry() == 2 && CountSell < maxposition && xxBars != Bars) { // 取引資金をチェック if (!CheckMoneyForTrade(OrderSymbol(), lots, OrderType())) { return; } ticket = WrapperOrderSend(Symbol(), OP_SELL, lots, Bid, Slippage, 0, 0, STR_EA_NAME + " " + STR_OP_SELL, MagicNumber, 0, Red); // エントリーに成功していれば、TP, SLをセットする if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() + StopLoss_pips * xpoint, OrderOpenPrice() - TakeProfit_pips * xpoint, 0, MediumSeaGreen); } } xxBars = Bars; } //-------- 新規ポジションのエントリー(ココマデ) -------- } // ローソク足始値のみ稼働(選択式)の範囲は、ココマデ //-------- ポジションのTP, SLのセット -------- // ポジションにTP, SLをセットする for(i=OrdersTotal()-1; i>=0; i--) { //オーダー選択(エラーを生じた場合、ループから抜け出す) if (OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false) { Print("OrderSelect returned the error of ", GetLastError() ); break; } //オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る) if (OrderSymbol() != Symbol()) continue; //マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る) if (OrderMagicNumber() != MagicNumber) continue; // 買いポジションの場合 if (OrderType() == OP_BUY) { profit = Bid - OrderOpenPrice(); // 買いポジションだった場合の、含み損益を計算する // TP, SLがどちらも設定されていなければ、TP, SLを設定する if (OrderStopLoss() == 0 && OrderTakeProfit() == 0) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() - StopLoss_pips * xpoint, OrderOpenPrice() + TakeProfit_pips * xpoint, 0, MediumSeaGreen); } } // 売りポジションの場合 if (OrderType() == OP_SELL) { profit = OrderOpenPrice() - Ask; // 売りポジションだった場合の、含み損益を計算する // TP, SLがどちらも設定されていなければ、TP, SLを設定する if (OrderStopLoss() == 0 && OrderTakeProfit() == 0) { res = WrapperOrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() + StopLoss_pips * xpoint, OrderOpenPrice() - TakeProfit_pips * xpoint, 0, MediumSeaGreen); } } } //-------- ポジションのTP, SLのセット(ココマデ) -------- } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリー総括 | //+------------------------------------------------------------------+ int Entry() { if (Entry_Rule1() == 1 && (Entry_Filter1() == 1 || Entry_Filter1() == 3) && (Entry_Filter2() == 1 || Entry_Filter2() == 3) && (Entry_Filter3() == 1 || Entry_Filter3() == 3) && (Entry_Filter4() == 1 || Entry_Filter4() == 3) && (Entry_Filter5() == 1 || Entry_Filter5() == 3) ) { return(1); } else if (Entry_Rule1() == 2 && (Entry_Filter1() == 2 || Entry_Filter1() == 3) && (Entry_Filter2() == 2 || Entry_Filter2() == 3) && (Entry_Filter3() == 2 || Entry_Filter3() == 3) && (Entry_Filter4() == 2 || Entry_Filter4() == 3) && (Entry_Filter5() == 2 || Entry_Filter5() == 3) ) { return(2); } else { return(0); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 売りポジションの決済総括 | //+------------------------------------------------------------------+ int Exit1() { if (Exit_Rule1() == 3 && Exit_Rule2() == 3 && Exit_Rule3() == 3 && Exit_Rule4() == 3 && Exit_Rule5() == 3) { return(0); } else if (Exit_Rule1() == 1) { return(1); } else if( Exit_Rule2() == 1) { return(1); } else if (Exit_Rule3() == 1) { return(1); } else if( Exit_Rule4() == 1) { return(1); } else if (Exit_Rule5() == 1) { return(1); } else { return(0); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 買いポジションの決済総括 | //+------------------------------------------------------------------+ int Exit2() { if (Exit_Rule1() == 3 && Exit_Rule2() == 3 && Exit_Rule3() == 3 && Exit_Rule4() == 3 && Exit_Rule5() == 3) { return(0); } else if (Exit_Rule1() == 2) { return(2); } else if (Exit_Rule2() == 2) { return(2); } else if (Exit_Rule3() == 2) { return(2); } else if (Exit_Rule4() == 2) { return(2); } else if (Exit_Rule5() == 2) { return(2); } else { return(0); } } //+------------------------------------------------------------------+ //| 注文数量の正確さをチェックする | //+------------------------------------------------------------------+ bool CheckVolumeValue(double volume,double &correct_volume, string &message) { #ifdef _MQL5_COM // MQL5.com自動検査環境の検出 bool isMQL5Testing = (AccountBalance() <= 1.0 && IsTesting()); if (isMQL5Testing) { // MQL5.com環境では無条件に最小ロットサイズを使用 correct_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); message=StringFormat("Volume is changed to theminimal allowed SYMBOL_VOLUME_MIN=%.2f",correct_volume); return(true); } #endif // _MQL5_COM_ //取引操作で許可される最小数量 double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); if(volumemax_volume) { message=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); correct_volume = max_volume; return(false); } //数量変更の最小ステップを取得する double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP); int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { message=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); correct_volume = ratio*volume_step; return(false); } message="Correct volume value"; correct_volume = volume; return(true); } //+------------------------------------------------------------------+ //| 取引資金が不足しているかをチェックする | //+------------------------------------------------------------------+ bool CheckMoneyForTrade(string symbol, double lots,int type) { double free_margin = AccountFreeMarginCheck(symbol, type, lots); // 資金が不足している場合 if(free_margin < 0) { string op = (type == OP_BUY ? "Buy" : "Sell"); Print("Not enough money for ", op," ",lots, " ", symbol, " Error code=", GetLastError()); return false; } return(true); } //+------------------------------------------------------------------+ #ifdef _DEVELOPMENT //+------------------------------------------------------------------+ //| OnTester - 指定された最適化タイプで最適化する                 | //+------------------------------------------------------------------+ double OnTester() { // 取引数の最適化基準値を1000に設定する const double TRADES_STANDARD = 1000.0; // 最適化基準値を初期化する double optimization_value = 0.0; double recovery_factor = 0.0; double trades_optimization_factor = 0.0; double win_rate = 0.0; // リカバリーファクターを計算するため、純益と証拠金ベースの最大ドローダウンを取得する double profit = TesterStatistics(STAT_PROFIT); double max_drawdown = TesterStatistics(STAT_EQUITY_DD); // 最大ドローダウンが0以外の場合は、リカバリーファクターを計算する if(max_drawdown != 0) { recovery_factor = profit / max_drawdown; } // 取引数を取得する double trades = TesterStatistics(STAT_TRADES); // 取引数が0以外の場合は、勝率(総勝ち数/総取引数)を計算する if(trades != 0) { win_rate = TesterStatistics(STAT_PROFIT_TRADES) / trades; } // 取引数の最適化係数を求める trades_optimization_factor = trades / TRADES_STANDARD; // 最適化基準値 = 最適化タイプに応じた要素の値の積算値 switch(OP_Type) { case OPTYPE_RF_ONLY: optimization_value = recovery_factor; break; case OPTYPE_TR_ONLY: optimization_value = trades_optimization_factor; break; case OPTYPE_WR_ONLY: optimization_value = win_rate; break; case OPTYPE_RF_TR: optimization_value = recovery_factor * trades_optimization_factor; break; case OPTYPE_RF_WR: optimization_value = recovery_factor * win_rate; break; case OPTYPE_TR_WR: optimization_value = trades_optimization_factor * win_rate; break; case OPTYPE_RF_TR_WR: optimization_value = recovery_factor * trades_optimization_factor * win_rate; break; case OPTYPE_NONE: optimization_value = 0.0; break; default: optimization_value = 0.0; break; } return(optimization_value); } //+------------------------------------------------------------------+ #endif // _DEVELOPMENT //+------------------------------------------------------------------+ //| マーケットがオープンしているか確認する           | //+------------------------------------------------------------------+ bool IsMarketOpen(string symbol = NULL, int mode = SYMBOL_TRADE_MODE_FULL) { datetime currentTime = TimeCurrent(); // 指定されたシンボルの取引時間を取得 int tradingHours = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE); // 取引時間に基づいてマーケットの状態を判断 if (tradingHours == SYMBOL_TRADE_MODE_DISABLED) { // 取引不可 return false; } else if (tradingHours == SYMBOL_TRADE_MODE_CLOSEONLY) { if (mode == SYMBOL_TRADE_MODE_CLOSEONLY) { // 決済注文のみ可能 return true; } else { // 取引不可 return false; } } else if (tradingHours == SYMBOL_TRADE_MODE_FULL) { // 通常取引可能 return true; } // 上記以外の場合は取引不可と判断 return false; } //+------------------------------------------------------------------+ //| 価格をpips単位から通貨単位に変換する | //+------------------------------------------------------------------+ double PipsToPrice( double pips // 通貨単位に変換するpips値 ) { // 換算結果の価格値を宣言する double price = 0; // ブローカーの小数点以下桁数保持単位に応じて、換算のための倍数を計算する int digits = Digits(); // 3桁・5桁のFXブローカーの場合 if(digits == 3 || digits == 5){ price = pips / MathPow(10, digits) * 10; } // 2桁・4桁のFXブローカーの場合 if(digits == 2 || digits == 4){ price = pips / MathPow(10, digits); } // 価格を有効桁数で丸める price = NormalizeDouble(price, digits); return(price); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| トレンド相場の場合、trueを返す | //+------------------------------------------------------------------+ bool IsTrending(int from = 1) { //ADXが所定の期間中、指定値以上の時は、トレンド相場が継続しているものとする for(int i = from; i <= ADX_Trend_Duration; i++) { //ADXが指定値より小さい場合は、トレンドが継続していないとして、falseを返す double adx = iADX(NULL, 0, ADX_Trend_Period, PRICE_CLOSE, MODE_MAIN, i); if(adx < ADX_Trend_Level) { return(false); } } return(true); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| レンジ相場の場合、trueを返す | //+------------------------------------------------------------------+ bool IsRanging(int from = 1) { //ADXが所定の期間中、指定値以下の時は、レンジ相場が継続しているものとする for(int i = from; i <= ADX_Range_Duration; i++) { //ADXが指定値より大きい場合は、レンジが継続していないとして、falseを返す double adx = iADX(NULL, 0, ADX_Range_Period, PRICE_CLOSE, MODE_MAIN, i); if(adx > ADX_Range_Level) { return(false); } } return(true); } //+------------------------------------------------------------------+ //| トレンド+レンジ相場の場合、trueを返す | //+------------------------------------------------------------------+ bool IsBoth(int from = 1) { return(IsTrending(from) && IsRanging(from)); } //+------------------------------------------------------------------+ //| 相場タイプを返す           | //+------------------------------------------------------------------+ MKTTYPE GetMktType(int from = 1) { MKTTYPE type = MKTTYPE_NONE; if(IsTrending(from) && IsRanging(from)) { type = MKTTYPE_BOTH; } else if(IsTrending(from) && !IsRanging(from)) { type = MKTTYPE_TRENDING; } else if(!IsTrending(from) && IsRanging(from)) { type = MKTTYPE_RANGE; } return(type); } //+------------------------------------------------------------------+ //| 相場タイプの文字列を返す       | //+------------------------------------------------------------------+ string MktTypeToString(MKTTYPE type) { switch(type) { case MKTTYPE_NONE: return(""); case MKTTYPE_TRENDING: return("TRENDING"); case MKTTYPE_RANGE: return("RANGE"); case MKTTYPE_BOTH: return("BOTH"); default: return(""); } return(""); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリールール1 | //+------------------------------------------------------------------+ int Entry_Rule1() { //エントリールール1を差し替える時は、下記を差し替えて下さい。 #ifdef _DEVELOPMENT Comment(MktTypeToString(GetMktType())); #endif // _DEVELOPMENT // 短期移動平均線が、長期移動平均線を下回ったら「売り」 // 短期移動平均線が、長期移動平均線を上回ったら「買い」 double ma11 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 1); double ma12 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 2); double ma21 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 1); double ma22 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 2); // 短期移動平均線が長期移動平均線を上抜け(ゴールデンクロス)で「買い」 if(ma11 > ma21 && ma12 <= ma22) { return(1); } // 買い // 短期移動平均線が長期移動平均線を下抜け(デッドクロス)で「売り」 else if(ma11 < ma21 && ma12 >= ma22) { return(2); } // 売り return(0); //エントリールール1を差し替える時は、ココマデを差し替えて下さい。 } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター1 | //+------------------------------------------------------------------+ int Entry_Filter1() { //エントリーフィルター1を差し替える時は、下記を差し替えて下さい。 //ボリンジャーバンドの幅(上側ボリンジャーバンド―下側ボリンジャーバンドの値)が、指定%以上の時にエントリーすることが可能 double upper_bb1 = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 1); double lower_bb1 = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 1); //ボリンジャーバンドの幅(上側ボリンジャーバンド―下側ボリンジャーバンドの値)が、指定%より小さい時はエントリーできない if((upper_bb1 - lower_bb1) / Close[1] * 100.0 < BB_Width) { return(0); } // エントリーできない //エントリーフィルター1を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター2 | //+------------------------------------------------------------------+ int Entry_Filter2() { //エントリーフィルター2を差し替える時は、下記を差し替えて下さい。 // 移動平均線に対し価格が、指定%以上乖離したら「エントリーしない」。 double ma1 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 1); // 移動平均線に対し価格が、指定%以上、上に乖離したら「エントリーしない」。 if (ma1 < Close[1] && (Close[1] - ma1) / ma1 > MA_Deviation / 100.0) { return(0); } // エントリーしない // 移動平均線に対し価格が、指定%以上、下に乖離したら「エントリーしない」。 else if (ma1 > Close[1] && (ma1 - Close[1]) / ma1 > MA_Deviation / 100.0) { return(0); } // エントリーしない //エントリーフィルター2を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター3 | //+------------------------------------------------------------------+ int Entry_Filter3() { //エントリーフィルター3を差し替える時は、下記を差し替えて下さい。 double ma11 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 1); double ma12 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 2); double ma21 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 1); double ma22 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 2); if(IsBoth()) { // トレンド相場、レンジ相場のいずれも発生している場合は、短期移動平均線に対して順張りエントリー if(ma11 > ma12) { return(1); } // 買い else if(ma11 < ma12) { return(2); } // 売り else { return(0); } // エントリーしない } else if(IsRanging() && !IsTrending()) { // レンジ相場が発生していたら、ローソク足が短期移動平均線を超えた方向にエントリー if(Close[1] > ma11) { return(1); } // 買い else if(Close[1] < ma11) { return(2); } // 売り else { return(0); } // エントリーしない } else if(IsTrending() && !IsRanging()) { // トレンド相場が発生していたら、長期移動平均線に対して逆張りエントリー if(ma21 > ma22) { return(2); } // 売り else if(ma21 < ma22) { return(1); } // 買い else { return(0); } // エントリーしない } else { //トレンド相場、レンジ相場のいずれも発生していなければ、エントリーしない return(0); } //エントリーフィルター3を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター4 | //+------------------------------------------------------------------+ int Entry_Filter4() { //エントリーフィルター4を差し替える時は、下記を差し替えて下さい。 double spread = MarketInfo(NULL, MODE_SPREAD); if(Digits == 3 || Digits == 5) spread /= 10.0; if(spread > MaxSpread) return(0); // トレード不許可 else return(3); // トレード許可 //エントリーフィルター4を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター5 | //+------------------------------------------------------------------+ int Entry_Filter5() { //エントリーフィルター5を差し替える時は、下記を差し替えて下さい。 // 制限の自動解除 if (TimeCurrent() > lastEntryRestrictionTime + (restrictionCount > 0 ? 3600 * MathPow(4, restrictionCount) : 0)) { lastEntryRestrictionTime = 0; restrictionCount = 0; } // すでに制限中の場合は即座にエントリー拒否 if (lastEntryRestrictionTime > 0) { return(0); } // 損失管理のための計算 int consecutive_losses = 0; double total_loss_per_lot = 0.0; // 過去の取引履歴を確認 for(int i = OrdersHistoryTotal()-1; i >= MathMax(0, OrdersHistoryTotal()-Loss_Lookback_Count); i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { // pipsベースでの損益計算 double pips_multiplier = (Digits == 3 || Digits == 5) ? 10 : 1; double pip_value = Point * pips_multiplier; double trade_pips; if(OrderType() == OP_BUY) { trade_pips = (OrderClosePrice() - OrderOpenPrice()) / pip_value; } else { trade_pips = (OrderOpenPrice() - OrderClosePrice()) / pip_value; } // 1ロットあたりの損失pipsを計算 double loss_per_lot = MathAbs(trade_pips) / OrderLots(); if(trade_pips < 0) { consecutive_losses++; total_loss_per_lot += loss_per_lot; } else { break; // 利益が出た取引で終了 } } } } // 現在のボラティリティチェック double atr = iATR(NULL, 0, ATR_Period_Filter, 1); double atr_ma = 0; for(int i = 1; i <= ATR_Period_Filter; i++) { atr_ma += iATR(NULL, 0, ATR_Period_Filter, i); } atr_ma /= ATR_Period_Filter; bool is_high_volatility = (atr > atr_ma * ATR_Volatility_Threshold); // リスク管理による制御 if(consecutive_losses >= Max_Consecutive_Losses && total_loss_per_lot > Max_Loss_Pips) { // 制限時間と制限回数を設定 lastEntryRestrictionTime = TimeCurrent(); restrictionCount++; return(0); } if(is_high_volatility && total_loss_per_lot > High_Vol_Loss_Limit) { // 制限時間と制限回数を設定 lastEntryRestrictionTime = TimeCurrent(); restrictionCount++; return(0); } //エントリーフィルター5を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール1 | //+------------------------------------------------------------------+ int Exit_Rule1() { // 決済ルール1を差し替える時は、下記を差し替えて下さい。 //短期移動平均線が、長期移動平均線を下回ったら「決済売り」 //短期移動平均線が、長期移動平均線を上回ったら「決済買い」 double ma11 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 1); double ma12 = iMA(NULL, 0, MA_Period1, 0, MODE_SMA, PRICE_CLOSE, 2); double ma21 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 1); double ma22 = iMA(NULL, 0, MA_Period2, 0, MODE_SMA, PRICE_CLOSE, 2); //短期移動平均線が、長期移動平均線を下回ったら(デッドクロス)「決済売り」 if(ma11 < ma21 && ma12 >= ma22) { return(2); } //決済売り //短期移動平均線が、長期移動平均線を上回ったら(ゴールデンクロス)「決済買い」 else if(ma11 > ma21 && ma12 <= ma22) { return(1); } //決済買い else { return(0); } // 決済ルール1を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール2 | //+------------------------------------------------------------------+ int Exit_Rule2() { // 決済ルール2を差し替える時は、下記を差し替えて下さい。 // 終値が利確ボリンジャーバンドの値を超えている場合、利確決済 double upper_bb1 = iBands(NULL, 0, BB_TP_Period, BB_TP_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 1); double lower_bb1 = iBands(NULL, 0, BB_TP_Period, BB_TP_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 1); double upper_bb2 = iBands(NULL, 0, BB_TP_Period, BB_TP_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 2); double lower_bb2 = iBands(NULL, 0, BB_TP_Period, BB_TP_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 2); // 終値が上側の利確ボリンジャーバンドの値より大きければ、「決済売り」 if(Close[1] > upper_bb1 && Close[2] <= upper_bb2) { return(2); } // 決済売り // 終値が下側の利確ボリンジャーバンドの値より小さければ、「決済買い」 else if(Close[1] < lower_bb1 && Close[2] >= lower_bb2) { return(1); } // 決済買い else { return(0); } // 決済ルール2を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール3 | //+------------------------------------------------------------------+ int Exit_Rule3() { // 決済ルール3を差し替える時は、下記を差し替えて下さい。 // 終値が損切りボリンジャーバンドの値を超えている場合、損切り決済 double upper_bb1 = iBands(NULL, 0, BB_SL_Period, BB_SL_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 1); double lower_bb1 = iBands(NULL, 0, BB_SL_Period, BB_SL_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 1); double upper_bb2 = iBands(NULL, 0, BB_SL_Period, BB_SL_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 2); double lower_bb2 = iBands(NULL, 0, BB_SL_Period, BB_SL_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 2); // 終値が上側の損切りボリンジャーバンドの値より大きければ、「決済買い」 if(Close[1] > upper_bb1 && Close[2] <= upper_bb2) { return(1); } // 決済買い // 終値が下側の損切りボリンジャーバンドの値より小さければ、「決済売り」 else if(Close[1] < lower_bb1 && Close[2] >= lower_bb2) { return(2); } // 決済売り else { return(0); } // 決済ルール3を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール4 | //+------------------------------------------------------------------+ int Exit_Rule4() { // 決済ルール4を差し替える時は、下記を差し替えて下さい。 double tp_price = OrderOpenPrice(); if(OrderType() == OP_BUY) { // 買いオーダーの場合、所定の差分値をプラスした価格を終値が下回った場合、「決済売り」 tp_price += iBarShift(NULL, 0, OrderOpenTime()) * PipsToPrice(TP_Delta); if(Close[1] < tp_price && Close[2] >= tp_price && (Bid - OrderOpenPrice()) > 0.0) { return(2); } // 決済売り } else if(OrderType() == OP_SELL) { // 売りオーダーの場合、所定の差分値をマイナスした価格を終値が上回った場合、「決済買い」 tp_price -= iBarShift(NULL, 0, OrderOpenTime()) * PipsToPrice(TP_Delta); if(Close[1] > tp_price && Close[2] <= tp_price && (OrderOpenPrice() - Ask) > 0.0) { return(1); } // 決済買い } // 決済ルール4を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール5 | //+------------------------------------------------------------------+ int Exit_Rule5() { // 決済ルール5を差し替える時は、下記を差し替えて下さい。 // 決済ルール5を差し替える時は、ココマデを差し替えて下さい。 return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| トレード関数群  | //+------------------------------------------------------------------+ // OrderSendのラッパー関数 //  マーケットの制約に合う形にSL、TPを修正したのち発注し // OederSendのエラー時のリトライおよびエラー処理を実施する int WrapperOrderSend(string symbol, // シンボル int cmd, // 注文の種類 double volume, // ロット double price, // 注文価格 int slippage, // スリッページ double stoploss, // StopLoss double takeprofit, // TakeProfit string comment=NULL, // コメント int magic=0, // マジックナンバー datetime expiration=0, // 有効期限 color arrow_color=clrNONE // 矢印のカラー ) { int i; int err = 0; // エラーNo. int res = 0; // OrderSendの戻り値 // マーケットがオープンするまで待機する datetime currentTime = TimeCurrent(); datetime waitEndTime = currentTime + TIME_WAIT_FOR_MARKET_OPEN; while (TimeCurrent() < waitEndTime) { // マーケットがオープンしていたら、ループを抜ける if (IsMarketOpen()) { break; } // 次のリトライまで500msec待つ Sleep(500); } // MAX_ORDER_REPEAT回数だけリトライする for ( i=0; i