gryps2/EA-code/handy_systems/RELEASE/84001-BLESSING for GBPJPY/1.4.1/BLESSING for GBPJPY.mq4
super.admin ae3f0ebf03 convert
2025-05-30 14:58:21 +02:00

110 KiB
Raw Permalink Blame History

//+------------------------------------------------------------------+
//| 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 <stdlib.mqh>
//----------EA-BANK certification begin
#ifdef _EA_BANK
#include <auth.mqh>
#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 bool Env_Filter_Enabled = true; // 環境認識フィルター有効化
dinput double Kairi_Judge_percent1 = 0.2; // 乖離率1 (%)
dinput double Kairi_Judge_percent2 = 2.2; // 乖離率2 (%)
 
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; j<k; j++)
{
StringReplace(lr_respara[j],"{","");
StringReplace(lr_respara[j],"}","");
int lr_position=StringFind(lr_respara[j],":",0);
lr_respara[j]=StringSubstr(lr_respara[j],lr_position+1);
}
}
else
{
ArrayResize(lr_respara,1);
lr_respara[0]="false";
}
if(lr_respara[0]!="true")
{
lr_auth_success=false;
lr_auth_failure_times++;
int seconds=lr_auth_failure_times>4?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 && (Env_Filter() == 1 || Env_Filter() == 3)
&& (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 && (Env_Filter() == 2 || Env_Filter() == 3)
&& (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(volume<min_volume)
{
message=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
correct_volume = min_volume;
return(false);
}
 
//取引操作で許可される最大数量
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
if(volume>max_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を差し替える時は、ココマデを差し替えて下さい。
}
//+------------------------------------------------------------------+
 
//+------------------------------------------------------------------+
//| トレンド判断関数 |
//+------------------------------------------------------------------+
int Trend_Judge()
{
double MA_Middle1 = iMA(NULL,PERIOD_H1, 80, 0, MODE_SMA, PRICE_CLOSE, 1);
double MA_Long1 = iMA(NULL,PERIOD_H1,320, 0, MODE_SMA, PRICE_CLOSE, 1);
double MA_Middle2 = iMA(NULL,PERIOD_H1, 80, 0, MODE_SMA, PRICE_CLOSE, 3);
double MA_Long2 = iMA(NULL,PERIOD_H1,320, 0, MODE_SMA, PRICE_CLOSE, 3);
 
int UP_Trend = 0; //アップトレンドを0~3段階評価
 
if (MA_Middle1 > MA_Long1) {
UP_Trend = UP_Trend+1;
}
if (MA_Middle1-MA_Middle2 > 0) {
UP_Trend = UP_Trend+1;
}
if (MA_Long1-MA_Long2 > 0) {
UP_Trend = UP_Trend+1;
}
 
return(UP_Trend);
}
//+------------------------------------------------------------------+
//| 乖離判断関数 |
//+------------------------------------------------------------------+
double Kairi_Judge()
{
// 長期移動平均線に対し短期移動平均線が、指定%以上、上に乖離したら「売り」、下に乖離したら「買い」。
double MA1 = iMA(NULL,PERIOD_M5, 3, 0, MODE_SMA, PRICE_CLOSE, 1);
double MA2 = iMA(NULL,PERIOD_H1, 320, 0, MODE_SMA, PRICE_CLOSE, 1);
double Long_Kairi = (MA1-MA2)/iClose(NULL,PERIOD_M5,1)*100;
 
return(Long_Kairi);
}
//+------------------------------------------------------------------+
//| 環境認識フィルター |
//+------------------------------------------------------------------+
int Env_Filter()
{
// 環境認識フィルターが無効の場合はスキップ
if(!Env_Filter_Enabled)
return(3);
 
// トレンド判断
int trend = Trend_Judge();
 
// 価格乖離判断
double kairi = Kairi_Judge();
 
// アップトレンド+中期のMAが下に乖離で「買い」
if ((trend >= 2 && kairi <= Kairi_Judge_percent1) || kairi <= -Kairi_Judge_percent2)
{
return(1); // 買いのみ許可
}
// ダウントレンド+中期のMAが上に乖離で「売り」
else if ((trend <= 1 && kairi >= -Kairi_Judge_percent1) || kairi >= Kairi_Judge_percent2)
{
return(2); // 売りのみ許可
}
 
// どちらの条件も満たさない場合は両方向許可
return(3);
}
 
//+------------------------------------------------------------------+
//| エントリーフィルター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<MAX_ORDER_REPEAT; i++ )
{
res = OrderSend(symbol,
cmd,
volume,
NormalizeDouble(price, Digits()),
slippage,
NormalizeDouble(stoploss, Digits()),
NormalizeDouble(takeprofit, Digits()),
comment,
magic,
expiration,
arrow_color);
 
// オーダー発注に成功した場合、チケットNo.を返し関数を終了する
if ( res != -1 ) return(res);
 
// オーダー発注に失敗した場合、エラーを表示したのちリトライする
if ( res == -1 )
{
err = GetLastError();
Print("OrderSend return error: code=",err, ", Error=", ErrorDescription(err));
// 次のリトライまで500msec待つ
Sleep(500);
}
}
 
return(res);
}
 
// OrderModifyのラッパー関数
//  マーケットの制約に合う形にSL、TPを修正したのち発注し
// OederModifyのエラー時のリトライおよびエラー処理を実施する
bool WrapperOrderModify(int ticket, // チケットナンバー
double price, // 注文価格
double stoploss, // StopLoss
double takeprofit, // TakeProfit
datetime expiration, // 有効期限
color arrow_color // 矢印のカラー
)
{
int i;
int err = 0; // エラーNo.
bool res = false; // OrderModifyの戻り値
 
// マーケットがオープンするまで待機する
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<MAX_ORDER_REPEAT; i++ )
{
res = OrderModify(ticket,
NormalizeDouble(price, Digits()),
NormalizeDouble(stoploss, Digits()),
NormalizeDouble(takeprofit, Digits()),
expiration,
arrow_color);
 
// オーダー発注に成功した場合、終了フラグを返す
if (res) return(res);
 
// オーダー発注に失敗した場合、エラーを表示したのちリトライする
if ( !res )
{
err = GetLastError();
Print("OrderModify return error: code=",err, ", Error=", ErrorDescription(err));
// 次のリトライまで500msec待つ
Sleep(500);
}
}
 
return(res);
}
 
// OrderCloseのラッパー関数
//  マーケットの制約に合う形にSL、TPを修正したのち発注し
// OederCloseのエラー時のリトライおよびエラー処理を実施する
bool WrapperOrderClose(int ticket, // チケットナンバー
double lots, // ロットサイズ
double price, // 注文価格
int slippage, // スリッページ
color arrow_color // 矢印のカラー
)
{
int i;
int err = 0; // エラーNo.
bool res = false; // OrderCloseの戻り値
 
// マーケットがオープンするまで待機する
datetime currentTime = TimeCurrent();
datetime waitEndTime = currentTime + TIME_WAIT_FOR_MARKET_OPEN;
 
while (TimeCurrent() < waitEndTime)
{
// マーケットがオープンしていたら、ループを抜ける
if (IsMarketOpen(NULL, SYMBOL_TRADE_MODE_CLOSEONLY))
{
break;
}
// 次のリトライまで500msec待つ
Sleep(500);
}
 
// MAX_ORDER_REPEAT回数だけリトライする
for ( i=0; i<MAX_ORDER_REPEAT; i++ )
{
res = OrderClose(ticket,
lots,
NormalizeDouble(price, Digits()),
slippage,
arrow_color);
 
// オーダー発注に成功した場合、終了フラグを返す
if ( res ) return(res);
 
// オーダー発注に失敗した場合、エラーを表示したのちリトライする
if ( !res )
{
err = GetLastError();
Print("OrderClose return error: code=",err, ", Error=", ErrorDescription(err));
// 次のリトライまで500msec待つ
Sleep(500);
}
}
 
return(res);
}