//+------------------------------------------------------------------+ //| オープン・クローズ別々で書き込み(TP/SL対応) | //+------------------------------------------------------------------+ // 各計測用パラメータ input bool Measurement = true; // 計測ログcsv作成(実行スプレッド・スリッページ等) int err, fp; string filename; double OSpread, CSpread; uint StartOrderTimestamp, OrderCloseTimestamp; double Order_Price, Close_Price; double Open_Yakujyou_Price, Close_Yakujou_Price; double Open_Spread, Close_Spread; double Open_Slippage, Close_Slippage; uint OpenLatency, CloseLatency; double profitpips; string Timeframe = (Period() == 1? "M1": Period() == 5? "M5": Period() == 15? "M15": Period() == 30? "M30": Period() == 60? "H1": Period() == 240? "H4": Period() == 1440? "D1": Period() == 10080? "W1": "MN1"); string Open_Type, Close_Type; datetime OrderCloseTime_bak = 0, OrderOpenTime_bak = 0; int V0; // 指値逆指値注文時_[]内はリピート数+2? int k, open_type_Buy[12], open_type_Sell[12]; int Ticket_Buy[12], Ticket_Sell[12]; double Gapentry[12], GapentryBuy[12], GapentrySell[12]; int OnInit()// return(0)の直前に挿入 { // ファイル出力初期化処理 if (Measurement) FileInit(); //+------------------------------------------------------------------+ return(0); } void OnTick() // 優先が低いので最後に挿入 { // 決済がTP/SLなら情報取得 if (Measurement) ClosedTradeTPSL(); //+------------------------------------------------------------------+ } //+------------------------------------------------------------------+ //| ポジションのクローズ | //+------------------------------------------------------------------+ // OrderCloseの前後に挟む // 買い CSpread = Ask - Bid; // スプレッド計測 OrderCloseTimestamp = GetTickCount();// レイテンシー計測 Close_Price = Bid; // 決済売り注文を入れる価格 V0 = (int)Volume[0];// Volume[0]の値 res = OrderClose(OrderTicket(), OrderLots(), Bid, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) // 履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } // オーダー確認(通貨ペアとマジックナンバーが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { CloseTradeInfo(); } } // 売り CSpread = Ask - Bid; //スプレッド計測 OrderCloseTimestamp = GetTickCount(); // レイテンシー計測 Close_Price = Ask; // 決済買い注文を入れる価格 V0 = (int)Volume[0];// Volume[0]の値 res = OrderClose(OrderTicket(), OrderLots(), Ask, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) // 履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } // オーダー確認(通貨ペアとマジックナンバーが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { CloseTradeInfo(); } } //+------------------------------------------------------------------+ //| ポジションのオープン | //+------------------------------------------------------------------+ // ticketの前後を挟む // 買い OSpread = Ask - Bid;// スプレッド計測 StartOrderTimestamp = GetTickCount();// レイテンシー計測 Order_Price = Ask;// 買い注文を入れる価格 V0 = (int)Volume[0];// Volume[0]の値 ticket = OrderSend(Symbol(), OP_BUY, CalculateLots(MM_Risk, StopLoss_pips), Ask, Slippage, Ask - StopLoss_pips * xpoint, Ask + TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Blue); // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if (OrderSelect(ticket, SELECT_BY_TICKET) == true && Measurement == true) { OpenTradeInfo(); } // 売り OSpread = Ask - Bid;// スプレッド計測 StartOrderTimestamp = GetTickCount();// レイテンシー計測 Order_Price = Bid;// 売り注文を入れる価格 V0 = (int)Volume[0];// Volume[0]の値 ticket = OrderSend(Symbol(), OP_SELL, CalculateLots(MM_Risk, StopLoss_pips), Bid, Slippage, Bid + StopLoss_pips * xpoint, Bid - TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Red); // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if (OrderSelect(ticket, SELECT_BY_TICKET) == true && Measurement == true) { OpenTradeInfo(); } //+------------------------------------------------------------------+ //| 実行スプレッド・スリッページ・実行スプレッド計測・ファイル作成 | //+------------------------------------------------------------------+ // ファイル初期化 int FileInit() { filename = AccountCompany() + "_スリッページログ.csv";// ファイル名を決める fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) if(fp==INVALID_HANDLE) { err = GetLastError(); printf("Error occured: [%d] %s", err, ErrorDescription(err)); return(0.0); } FileWrite(fp, "注文番号", "注文時間", "時刻", "分", "取引種別", "注文価格", "約定価格", "スプレッド(pips)", "スリッページ(pips)", "レイテンシー(ms)", "損益(pips)", "数量", "通貨ペア", "時間足", "EA名", "マジックナンバー", "Volume[0]", "書込時Volume[0]", "書込時i"); // ファイルを閉じる FileClose(fp); return(0); } // トレード情報(成行用) void OpenTradeInfo() { OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー計測 Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化 Open_Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化 Open_Slippage = NormalizeDouble(OrderType() == OP_BUY? Order_Price - Open_Yakujyou_Price : Open_Yakujyou_Price - Order_Price, Digits) / xpoint; // スリッページ、桁合わせ Open_Spread = NormalizeDouble(OSpread, Digits) / xpoint; // スプレッド、桁合わせ Open_Type = OrderType() == OP_BUY? "Buy" : "Sell"; FileWriteingOpen(); // 書き込み処理 } void CloseTradeInfo() { Close_Price = NormalizeDouble(Close_Price, Digits); // 売り注文価格を正規化 Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(OrderType() == OP_BUY? Close_Yakujou_Price - Close_Price : Close_Price - Close_Yakujou_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = NormalizeDouble(CSpread, Digits) / xpoint; // スプレッド、桁合わせ profitpips = NormalizeDouble(OrderType() == OP_BUY? (OrderClosePrice() - OrderOpenPrice()) / xpoint : (OrderOpenPrice() - OrderClosePrice()) / xpoint, 1); Close_Type = "Close"; FileWriteingClose(); // 書き込み処理 } // ファイル書き込み void FileWriteingOpen() { for(int i = 0; i < 3000; i++) { FileClose(fp); // ファイルが開きっぱなしで開けないエラーを防ぐ fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)、失敗戻り値は-1 if (fp != INVALID_HANDLE) { FileSeek(fp, 0, SEEK_END); FileWrite(fp, OrderTicket(), OrderOpenTime(), Hour(), Minute(), Open_Type, Order_Price, Open_Yakujyou_Price, Open_Spread, Open_Slippage, OpenLatency, "---", CalculateLots(MM_Risk, MaxStopLoss_pips), Symbol(), Timeframe, WindowExpertName(), OrderMagicNumber(), V0, Volume[0], i); FileClose(fp); break; } } if (fp == -1) Print("Error=", GetLastError(), " ファイルの書き込みに失敗しました"); } void FileWriteingClose() { for(int i = 0; i < 3000; i++) { FileClose(fp); // ファイルが開きっぱなしで開けないエラーを防ぐ fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv)、失敗戻り値は-1 if (fp != INVALID_HANDLE) { FileSeek(fp, 0, SEEK_END); FileWrite(fp, OrderTicket(), OrderCloseTime(), Hour(), Minute(), Close_Type, Close_Price, Close_Yakujou_Price, Close_Spread, Close_Slippage, CloseLatency, profitpips, CalculateLots(MM_Risk, MaxStopLoss_pips), Symbol(), Timeframe, WindowExpertName(), OrderMagicNumber(), V0, Volume[0], i); FileClose(fp); break; } } if (fp == -1) Print("Error=", GetLastError(), " ファイルの書き込みに失敗しました"); } // TP/SL時の検出_コメント欄の[tp]等の仕様で判別。最後尾以外の仕様は要アレンジ void ClosedTradeTPSL() { for(int i=OrdersHistoryTotal()-1; i>=0; i--) { //オーダー選択(エラーを生じた場合、ループから抜け出す) if (OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) == false) { Print("OrderSelect returned the error of ", GetLastError() ); break; } //オーダー確認(通貨ペアが一致しない場合は、for文の先頭に戻る) if (OrderSymbol() != Symbol()) continue; //マジックナンバー確認(マジックナンバーが一致しない場合は、for文の先頭に戻る) if (OrderMagicNumber() != MagicNumber) continue; // 決済時間に更新がなければループ処理終了 if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderCloseTime() == OrderCloseTime_bak) break; if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderCloseTime() > OrderCloseTime_bak) // 決済時間が最新であれば { OrderCloseTime_bak = OrderCloseTime(); int length = StringLen(OrderComment());//StringLenは文字数を返す if (length >= 4) { // TP/SL決済の確認 string tpsl = StringSubstr(OrderComment(), length-4, 4); if (tpsl == "[tp]" || tpsl == "[sl]") { Close_Price = NormalizeDouble((tpsl == "[tp]"? OrderTakeProfit() : OrderStopLoss()), Digits); // 売り注文価格を正規化 Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(OrderType() == OP_BUY? Close_Yakujou_Price - Close_Price : Close_Price - Close_Yakujou_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = MarketInfo(NULL,MODE_SPREAD) / 10; // スプレッド、桁合わせ profitpips = NormalizeDouble(OrderType() == OP_BUY? (OrderClosePrice() - OrderOpenPrice()) / xpoint : (OrderOpenPrice() - OrderClosePrice()) / xpoint, 1); Close_Type = tpsl == "[tp]"? "TP" : "SL"; FileWriteingClose(); // 書き込み処理 break; } } } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| オープンが指値・逆指値の場合_以下以外は、上記と同じで記述 | //+------------------------------------------------------------------+ datetime OrderOpenTime_bak = 0; void OnTick() { // エントリーが指値・逆指値の場合検知 OpenedTradeGap() } //+------------------------------------------------------------------+ //| ポジションのオープン | //+------------------------------------------------------------------+ //ループがある場合、kで代入 //ticket = OrderSend処理の後に挿入 // 買い // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if (OrderSelect(ticket, SELECT_BY_TICKET) == true) { Ticket_Buy[k] = OrderTicket(); open_type_Buy[k] = OrderType(); GapentryBuy[k] = OrderOpenPrice(); } // 売り // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if (OrderSelect(ticket, SELECT_BY_TICKET) == true) { Ticket_Sell[k] = OrderTicket(); open_type_Sell[k] = OrderType(); GapentrySell[k] = OrderOpenPrice(); } //+------------------------------------------------------------------+ // 指値逆指値時の検出 void OpenedTradeGap() { for(int 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 || OrderType() == OP_SELL) && OrderOpenTime() <= OrderOpenTime_bak) break; if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderOpenTime() > OrderOpenTime_bak)// エントリー時間が最新であれば。 { OrderOpenTime_bak = OrderOpenTime(); for(k=1; k<=Repeat_count ; k++) { if (Ticket_Buy[k] != OrderTicket() && Ticket_Sell[k] != OrderTicket()) continue; if (Ticket_Buy[k] == OrderTicket() || Ticket_Sell[k] == OrderTicket()) { Open_Type = OrderType() == OP_BUY && open_type_Buy[k] == OP_BUYSTOP? "BuyStop" : OrderType() == OP_BUY && open_type_Buy[k] == OP_BUYLIMIT? "BuyLimit" : OrderType() == OP_SELL && open_type_Sell[k] == OP_SELLSTOP? "SellStop" : "SellLimit"; Order_Price = OrderType() == OP_BUY? GapentryBuy[k] : GapentrySell[k]; Open_Yakujyou_Price = OrderOpenPrice(); Open_Spread = MarketInfo(NULL,MODE_SPREAD) / 10; Open_Slippage = Order_Price - Open_Yakujyou_Price; // 逆指値との差 OpenLatency = 0; FileWriteingOpen(); } break; } break; } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| オープン・クローズ一緒に書き込み(旧バージョン) | //+------------------------------------------------------------------+ // 各計測用パラメータ input bool Measurement = false; // 計測ログcsv作成(実行スプレッド・スリッページ等) int err, fp; double Order_Price, Close_Price; double Open_Yakujyou_Price, Close_Yakujou_Price; double Open_Spread, Close_Spread; double Open_Slippage, Close_Slippage; uint OpenLatency, CloseLatency; string filename; double profitpips; int OnInit() { // return(0)の直前に挿入 // ファイル出力初期化処理 if (Measurement) FileInit(); return(0); } //+------------------------------------------------------------------+ //| ポジションのクローズ | //+------------------------------------------------------------------+ // OrderCloseの前後に挟む // 買い double CSpread = Ask - Bid; // スプレッド計測 uint OrderCloseTimestamp = GetTickCount(); // レイテンシー計測 Close_Price = Bid; // 決済売り注文を入れる価格 res = OrderClose(OrderTicket(), OrderLots(), Bid, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) // 履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } // オーダー確認(通貨ペアとマジックナンバーが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { Close_Price = NormalizeDouble(Close_Price, Digits); // 売り注文価格を正規化 Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(Close_Yakujou_Price - Close_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = NormalizeDouble(CSpread, Digits) / xpoint; // スプレッド、桁合わせ profitpips = NormalizeDouble((OrderClosePrice() - OrderOpenPrice()) / xpoint, 1); FileWriteing(); // 書き込み処理 } } // 売り double CSpread = Ask - Bid; // スプレッド計測 uint OrderCloseTimestamp = GetTickCount(); // レイテンシー計測 Close_Price = Ask; // 決済買い注文を入れる価格 res = OrderClose(OrderTicket(), OrderLots(), Ask, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) // 履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } // オーダー確認(通貨ペアとマジックナンバーが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { Close_Price = NormalizeDouble(Close_Price , Digits); // 買い注文価格を正規化 Close_Yakujou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(Close_Price - Close_Yakujou_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = NormalizeDouble(CSpread, Digits) / xpoint; // スプレッド、桁合わせ profitpips = NormalizeDouble((OrderOpenPrice() - OrderClosePrice()) / xpoint, 1); FileWriteing(); // 書き込み処理 } } //+------------------------------------------------------------------+ //| ポジションのオープン | //+------------------------------------------------------------------+ // ticketの前後を挟む // 買い double OSpread = Ask - Bid; // スプレッド計測 uint StartOrderTimestamp = GetTickCount(); // レイテンシー計測 Order_Price = Ask; // 買い注文を入れる価格 ticket = OrderSend(Symbol(), OP_BUY, CalculateLots(MM_Risk, MaxStopLoss_pips), Ask, Slippage, Ask - StopLoss_pips * xpoint, Ask + TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Blue); if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー計測 Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化 Open_Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化 Open_Slippage = NormalizeDouble(Order_Price - Open_Yakujyou_Price, Digits) / xpoint; // スリッページ、桁合わせ Open_Spread = NormalizeDouble(OSpread, Digits) / xpoint; // スプレッド、桁合わせ } } // 売り double OSpread = Ask - Bid; // スプレッド計測 uint StartOrderTimestamp = GetTickCount(); // レイテンシー計測 Order_Price = Bid; // 売り注文を入れる価格 ticket = OrderSend(Symbol(), OP_SELL, CalculateLots(MM_Risk, MaxStopLoss_pips), Bid, Slippage, Bid + StopLoss_pips * xpoint, Bid - TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Red); if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー計測 Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化 Open_Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化 Open_Slippage = NormalizeDouble(Open_Yakujyou_Price - Order_Price, Digits) / xpoint; // スリッページ、桁合わせ Open_Spread = NormalizeDouble(OSpread, Digits) / xpoint; // スプレッド、桁合わせ } } // 以下適当な空いてる場所に挿入 //+------------------------------------------------------------------+ //| 実行スプレッド・スリッページ・実行スプレッド計測 | //+------------------------------------------------------------------+ // ファイル初期化 int FileInit() { filename = AccountCompany() + "_スリッページログ.csv";// ファイル名を決める fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) if(fp==INVALID_HANDLE) { err = GetLastError(); printf("Error occured: [%d] %s", err, ErrorDescription(err)); return(0.0); } FileWrite(fp, "注文時間", "注文価格", "約定価格", "買/売", "ロット", "OpenSpread", "OpenSlippage", "OpenLatency", "決済時間", "決済注文価格", "決済約定価格", "CloseSpread", "CloseSlippage", "CloseLatency", "損益pips", "通貨ペア", "時間足", "EA名"); // ファイルを閉じる FileClose(fp); return(0); } // ファイル書き込み void FileWriteing() { fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) string Timeframe = (Period() == 1? "M1": Period() == 5? "M5": Period() == 15? "M15": Period() == 30? "M30": Period() == 60? "H1": Period() == 240? "H4": Period() == 1440? "D1": Period() == 10080? "W1": "MN1"); if (fp != INVALID_HANDLE) { FileSeek(fp, 0, SEEK_END); FileWrite(fp, OrderOpenTime(), Order_Price, Open_Yakujyou_Price, OrderType()==0? "Buy": "Sell", CalculateLots(MM_Risk, MaxStopLoss_pips), Open_Spread, Open_Slippage, OpenLatency, OrderCloseTime(), Close_Price, Close_Yakujou_Price, Close_Spread, Close_Slippage, CloseLatency, profitpips, Symbol(), Timeframe, WindowExpertName()); FileClose(fp); } } //+------------------------------------------------------------------+ // 以下サンプルEA //+------------------------------------------------------------------+ //| AMX-USDJPY.mq4 | //| Copyright 2021, TNK.Co.,Ltd.| //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, TNK" #property link "https://note.com/tnk_system" //#property version "2.2" //スリッページ・レイテンシー計測 #property strict #include //ユーザー入力用パラメーター input double Lots = 0.28; // ロット(単利運用時) input double MaxSpread_pips = 3.0; // 許容スプレッド(Pips) input int TakeProfit_pips = 130; // 利確指値(Pips) input int StopLoss_pips = 90; // 損切逆指値(Pips) input int GMT = 2; // GMT(冬時間) input int Summertime = 1; // サマータイム(1:米/2:英/0:無し) input int MagicNumber = 8691310; // マジックナンバー(他EAと重複不可) input string _Comment = "AMX-USDJPY_2.2"; // 通知用コメント //input bool MM_ON = false; // 複利機能 enum MM_Select{ Fixed, // 0:単利/固定 FreeMargin, // 1:複利/余剰証拠金 Balance, // 2:複利/残高 }; input MM_Select MM_ON = Fixed; // 複利機能(0:固定/1:余剰証拠金/2:残高) input double MM_Risk = 1.0; // リスク%(余剰証拠金/残高の何%か) //内部設定 int Maxposition = 1; // 最大ポジション int Slippage = 10; // 許容スリッページ(Point) bool Tokyo = true; // エントリー(東京時間) bool London = true; // エントリー(ロンドン時間) bool WeekendClose = true; // 週末クローズ bool YearendClose = true; // 12/25~1/3クローズ //ローソク足始値のみで稼働:「true」 bool CandleStartStartingEntry = true; // エントリー bool CandleStartStartingTrailing = true; // トレイリング bool CandleStartStartingExit = false; // 決済 //バーカウント・桁合わせ用 int xBarsEntry = 0, xBarsExit = 0, xBarsTrailing = 0; int xBars=0, xxBars=0; double xpoint; //決済ルールの各変数 //成行決済 int Rikaku_pips = 9000; // 成行利確シグナルPips int Songiri_pips = 12000; // 成行損切シグナルPips //トレーリング /*input bool Modify = false; // トレーリングストップ input int TrailingStopLossStart_pips = 40; // トレール開始損益Pips input int TrailingStopLoss_pips = 100; // トレール時のBid/Askからの値幅Pips */ //エントリーフィルター int MA_PERIOD = 100; // 移動平均線の計算期間 int CandleCheckCount1 = 40; // HLマージンチェック/ローソク足何本前まで?(買い) int HL_margin1 = 30; // HLマージンチェック/高値安値の差pips(買い) int CandleCheckCount2 = 40; // HLマージンチェック/ローソク足何本前まで?(売り) int HL_margin2 = 40; // HLマージンチェック/高値安値の差pips(売り) int CandleCheckCount_H = 20; // HCマージンチェック/ローソク足何本前まで?(買い) int HC_margin = 50; // HCマージンチェック/高値終値の差pips(買い) int CandleCheckCount_L = 32; // LCマージンチェック/ローソク足何本前まで?(売り) int LC_margin = 180; // LCマージンチェック/安値終値の差pips(売り) int Day_Buy = 22; // 買い開始日 int Day_Sell = 10; // 売り開始日 //エントリー時間(サーバー時間) bool GMT_Kadou_OK1 = false; // エントリー時間(買い) bool GMT_Kadou_OK1_noFilter = false; // エントリー時間(買い) bool GMT_Kadou_OK2 = false; // エントリー時間(売り) bool GMT_Kadou_OK2_noFilter = false; // エントリー時間(売り) //ポジション決済(サーバー時間) bool PositionClose1 = false; // ポジション決済(買い) bool PositionClose2 = false; // ポジション決済(売り) //計測用パラメータ input bool Measurement = false; // 計測スイッチ int err, fp; double Yakujyou_Price; double Open_Spread, Close_Spread; double Open_Slippage, Close_Slippage; uint OpenLatency, CloseLatency; string filename; double profitpips; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| tester function | //+------------------------------------------------------------------+ /*double OnTester() { // リカバリーファクター return(NormalizeDouble(TesterStatistics(STAT_PROFIT) / TesterStatistics(STAT_EQUITY_DD), 2)); // 勝率 // return(NormalizeDouble(100*TesterStatistics(STAT_PROFIT_TRADES) / TesterStatistics(STAT_TRADES), 2)); }*/ //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // 小数点以下の桁数に応じてPipsの値を調整する xpoint = Point(); if (Digits() == 3 || Digits() == 5) { xpoint = xpoint * 10; } // チャート表示コメント string LotsComment; if (MM_ON == Fixed) LotsComment = DoubleToStr(Lots,2); else LotsComment = //DoubleToStr(CalculateLots(MM_Risk, StopLoss_pips),1) " (" + DoubleToStr(MM_Risk,1) +"%)"; Comment("MagicNo.:" + DoubleToStr(MagicNumber,0) + "\n" + "Lots:" + LotsComment + " MM_Mode:" + (string)MM_ON + "\n" + "Sp:" + DoubleToStr(MaxSpread_pips, 1) + " TP/SL:" + DoubleToStr(TakeProfit_pips,0) + "/" + DoubleToStr(StopLoss_pips,0) ); // 使用しているインジケータを非表示にする HideTestIndicators(true); // ファイル出力初期化処理 if (Measurement == true) { filename = AccountCompany() + "_SlippageLog.csv";// ファイル名を決める fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) if(fp==INVALID_HANDLE) { err = GetLastError(); printf("Error occured: [%d] %s", err, ErrorDescription(err)); return(0.0); } FileWrite(fp, "OpenTime", "CloseTime", "OpenPrice", "ClosePrice", "OrderType", "ProfitPips", "OpenSpread", "OpenSlippage", "OpenLatency", "CloseSpread", "CloseSlippage", "CloseLatency", "CurrencyPair", "ExpertName"); // ファイルを閉じる FileClose(fp); } return(0); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // サマータイム調整・時間制御 GetSummertimeShift(); // ポジションをクローズ PositionClose(); // トレーリング //Trailing(); // ポジションのエントリー PositionOpen(); // TP, SLの再設定 SetTPSL(); // チャート表示コメント string LotsComment; if (MM_ON == Fixed) LotsComment = DoubleToStr(Lots,2); else LotsComment = DoubleToStr(CalculateLots(MM_Risk, StopLoss_pips),2) + " (" + DoubleToStr(MM_Risk,1) +"%)"; Comment("MagicNo.:" + DoubleToStr(MagicNumber,0) + "\n" + "Lots:" + LotsComment + " MM_Mode:" + (string)MM_ON + "\n" + "Sp:" + DoubleToStr(MaxSpread_pips, 1) + " TP/SL:" + DoubleToStr(TakeProfit_pips,0) + "/" + DoubleToStr(StopLoss_pips,0) ); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 補正関数 | //+------------------------------------------------------------------+ void GetSummertimeShift() { int MON, SUN_day, xGMT, xTime, xxTime; int summertime_shift = 0; datetime gmtadjusted; // GMT+9を基準に、どれだけずれているかを算出する------------------------ MON = TimeMonth(TimeCurrent()); // 何月? SUN_day = TimeDay(TimeCurrent()) - TimeDayOfWeek(TimeCurrent()); // その週の日曜日は何日? if (Summertime == 2) // 英国式の場合 { if ((MON == 3 && SUN_day >= 25) || (MON >= 4 && MON <= 9) || (MON == 10 && SUN_day <= 24)) //3月で、その週の日曜日が25日以上/4月~9月/10月で、その週の日曜日が23日以下 { summertime_shift = 1; } else { summertime_shift = 0; } } else if (Summertime == 1) // 米国式の場合 { if ((MON == 3 && SUN_day >= 8) || (MON >= 4 && MON <= 10) || (MON == 11 && SUN_day <= 0)) //3月で、その週の日曜日が8日以上/4月~10月/11月で、その週の日曜日が存在しない { summertime_shift = 1; } else { summertime_shift = 0; } } else // サマータイム無しの場合 { summertime_shift = 0; } xGMT = GMT - 9 + summertime_shift;//GMT+9を基準に //GMT+9基準でどれだけずれているかを算出する(ココマデ)-------------------- //+------------------------------------------------------------------+ //| 時間制御 | //+------------------------------------------------------------------+ //---- トレード許可時間の判定 ---- xTime = TimeHour(TimeCurrent()) - xGMT; // 日本時間 xxTime = TimeHour(TimeCurrent()) - (GMT -2); // サーバー時間(サマータイム計算なし) gmtadjusted = TimeCurrent() - 60 * 60 * xGMT; if (xTime < 0) { xTime = xTime + 24; } else if (xTime > 23) { xTime = xTime - 24; } if (xxTime < 0) { xxTime = xxTime + 24; } else if (xxTime > 23) { xxTime = xxTime - 24; } // ポジションクローズ時間(買い_サーバー時間) if (xxTime == 1 || xxTime == 18) { PositionClose1 = true; } else { PositionClose1 = false; } // エントリー時間(買い_サーバー時間) if (Minute() == 0 && ((Day() >= Day_Buy && Day() <= 24) || Day() == 31) && // 00分、10~24,31日 TimeDayOfWeek(TimeCurrent()) != 1 && // 月曜日を除く xxTime == 9 && London == true) // 9時に買い { GMT_Kadou_OK1 = true; } else { GMT_Kadou_OK1 = false; } // エントリー時間フィルターなし用(買い_サーバー時間) if (Minute() == 0 && Day() >= 25 && Day() <= 30 && // 00分、25~30日 xxTime == 9 && London == true) // 9時に買い { GMT_Kadou_OK1_noFilter = true; } else { GMT_Kadou_OK1_noFilter = false; } // ポジションクローズ時間(売り_サーバー時間) if (xxTime == 1 || xxTime == 9) { PositionClose2 = true; } else { PositionClose2 = false; } // エントリー時間(売り_サーバー時間) if (Minute() == 0 && Day() >= Day_Sell && Day() <= 22 && // 00分、10~22日 xxTime == 3 && Tokyo == true) // 3時に売り { GMT_Kadou_OK2 = true; } else { GMT_Kadou_OK2 = false; } // エントリー時間フィルターなし用(売り_サーバー時間) if (Minute() == 0 && Day() >= 23 && // 00分、23~31日 xxTime == 3 && Tokyo == true) // 3時に売り { GMT_Kadou_OK2_noFilter = true; } else { GMT_Kadou_OK2_noFilter = false; } // ここまで、エグジットとトレーリングは、取引時間に関係なく実施する //---- トレード許可時間の判定(ココマデ) ---- } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| ポジションのクローズ | //+------------------------------------------------------------------+ void PositionClose() { int i; double profit; bool res; //ローソク足始値のみ稼働(選択式)の場合、ココカラ if(Bars != xBars || CandleStartStartingExit == 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(false) == 2 || PositionClose1 == true) { double CSpread = Ask - Bid;// スプレッド計測 uint OrderCloseTimestamp = GetTickCount();// レイテンシー計測 double Close_Price = Bid;// 決済売り注文を入れる価格 res = OrderClose(OrderTicket(), OrderLots(), Bid, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) //履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } //オーダー確認(通貨ペアが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol()) { //マジックナンバー確認(マジックナンバーが一致した場合は、次の処理へ進む if (OrderMagicNumber() == MagicNumber) { Close_Price = NormalizeDouble(Close_Price, Digits); // 売り注文価格を正規化 Yakujyou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(Yakujyou_Price - Close_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = NormalizeDouble(CSpread, Digits) / xpoint; // スプレッド、桁合わせ profitpips = NormalizeDouble((OrderClosePrice() - OrderOpenPrice()) / xpoint, 1); /*Print("Slippage = ", DoubleToString(Close_Slippage, Digits), " Latency = ", CloseLatency, " OOT = ", OrderOpenTime(), " OCT = ", OrderCloseTime(), " OOP = ", OrderOpenPrice(), " YJP = ", Yakujyou_Price, " OSp = ", Open_Spread, " OSl = ", Open_Slippage, " CSp = ", Close_Spread, " CSl = ", Close_Slippage); */ fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) if (fp != INVALID_HANDLE) { FileSeek(fp, 0, SEEK_END); FileWrite(fp, OrderOpenTime(), OrderCloseTime(), OrderOpenPrice(), Yakujyou_Price, "buy", profitpips, Open_Spread, Open_Slippage, OpenLatency, Close_Spread, Close_Slippage, CloseLatency, Symbol(), WindowExpertName()); FileClose(fp); } } } } } } if (OrderType() == OP_SELL) { profit = OrderOpenPrice() - Ask; // 売りポジションだった場合の、含み損益を計算する if (profit >= Rikaku_pips * xpoint || profit <= -Songiri_pips * xpoint || Exit1(true) == 1 || PositionClose2 == true) { double CSpread = Ask - Bid;// スプレッド計測 uint OrderCloseTimestamp = GetTickCount();// レイテンシー計測 double Close_Price = Ask;// 決済買い注文を入れる価格 res = OrderClose(OrderTicket(), OrderLots(), Ask, NULL, Green); if (res == true && Measurement == true) { CloseLatency = GetTickCount() - OrderCloseTimestamp; // レイテンシー計測 if(OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY)==false) //履歴を選択 { Print("Access to history failed with error (",GetLastError(),")"); return; } //オーダー確認(通貨ペアが一致した場合は、次の処理へ進む if (OrderSymbol() == Symbol()) { //マジックナンバー確認(マジックナンバーが一致した場合は、次の処理へ進む if (OrderMagicNumber() == MagicNumber) { Close_Price = NormalizeDouble(Close_Price , Digits); // 買い注文価格を正規化 Yakujyou_Price = NormalizeDouble(OrderClosePrice(), Digits); // 実際約定した価格 Close_Slippage = NormalizeDouble(Close_Price - Yakujyou_Price, Digits) / xpoint; // スリッページ、桁合わせ Close_Spread = NormalizeDouble(CSpread, Digits) / xpoint; // スプレッド、桁合わせ profitpips = NormalizeDouble((OrderOpenPrice() - OrderClosePrice()) / xpoint, 1); /*Print("Slippage = ", DoubleToString(Close_Slippage, Digits), " Latency = ", CloseLatency, " OOT = ", OrderOpenTime(), " OCT = ", OrderCloseTime(), " OOP = ", OrderOpenPrice(), " YJP = ", Yakujyou_Price, " OSp = ", Open_Spread, " OSl = ", Open_Slippage, " CSp = ", Close_Spread, " CSl = ", Close_Slippage); */ fp = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_CSV, ',');// ファイルオープン(csv) if (fp != INVALID_HANDLE) { FileSeek(fp, 0, SEEK_END); FileWrite(fp, OrderOpenTime(), OrderCloseTime(), OrderOpenPrice(), OrderClosePrice(), "sell", profitpips, Open_Spread, Open_Slippage, OpenLatency, Close_Spread, Close_Slippage, CloseLatency, Symbol(), WindowExpertName()); FileClose(fp); } } } } } } } // 所有しているポジションをクローズする(ココマデ) } //ローソク足始値のみ稼働(ココマデ) } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| トレーリング | //+------------------------------------------------------------------+ /*void Trailing() { int i; double profit; bool res; // トレーリングのローソク足始値のみ稼働(選択式) if(Bars != xBarsTrailing || CandleStartStartingTrailing == false) { xBarsTrailing = 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; // トレイルON、OFF if (Modify == true) { if (OrderType() == OP_BUY) { profit = Bid - OrderOpenPrice(); // 買いポジションだった場合の含み損益を計算する // 含み益が一定値以上の場合、SLを引き上げる if (profit >= TrailingStopLossStart_pips * xpoint && OrderStopLoss() < NormalizeDouble(Bid - TrailingStopLossStart_pips * xpoint, Digits())) { res = OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStopLoss_pips * xpoint, OrderTakeProfit(), 0, MediumSeaGreen); } } if (OrderType() == OP_SELL) { profit = OrderOpenPrice() - Ask; // 売りポジションだった場合の含み損益を計算する // 含み益が一定値以上の場合、逆指値を引き上げる if (profit >= TrailingStopLossStart_pips * xpoint && OrderStopLoss() > NormalizeDouble(Ask + TrailingStopLossStart_pips * xpoint, Digits())) { res = OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailingStopLoss_pips * xpoint, OrderTakeProfit(), 0, MediumSeaGreen); } } } } // 所有しているポジションのストップをトレールする(ココマデ) } // トレーリングのローソク足始値のみ稼働(ココマデ) }*/ //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| ポジションのオープン | //+------------------------------------------------------------------+ void PositionOpen() { int i; int ticket; int CountBuy = 0,CountSell = 0; bool res; // エントリー判断のローソク足始値のみ稼働(選択式) if(Bars != xBarsEntry || CandleStartStartingEntry == false) { xBarsEntry = 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) { CountBuy = CountBuy + 1; } if (OrderType() == OP_SELL) { CountSell = CountSell + 1; } } // ポジションの数をカウントする(ココマデ) // エントリー条件を確認し、成立していればエントリーを行う if (Entry(true) == 1 // 買いエントリー && CountSell == 0 && CountBuy < Maxposition && xxBars != Bars && (GMT_Kadou_OK1 == true || GMT_Kadou_OK1_noFilter == true)) { ticket = OrderSend(Symbol(), OP_BUY, CalculateLots(MM_Risk, StopLoss_pips), Ask, Slippage, Ask - StopLoss_pips * xpoint, Ask + TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Blue); // エントリーが失敗であれば、TPSLを分割して注文する if (ticket == -1) { double OSpread = Ask - Bid;// スプレッド計測 uint StartOrderTimestamp = GetTickCount();// レイテンシー計測 double Order_Price = Ask;// 買い注文を入れる価格 ticket = OrderSend(Symbol(), OP_BUY, CalculateLots(MM_Risk, StopLoss_pips), Ask, Slippage, 0, 0, _Comment, MagicNumber, 0, Blue); // エントリーに成功していれば、TP, SLをセットする if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー計測 Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化 Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化 Open_Slippage = NormalizeDouble(Order_Price - Yakujyou_Price, Digits) / xpoint; // スリッページ、桁合わせ Open_Spread = NormalizeDouble(OSpread, Digits) / xpoint; // スプレッド、桁合わせ res = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() - StopLoss_pips * xpoint, OrderOpenPrice() + TakeProfit_pips * xpoint, 0, MediumSeaGreen); //Print("Slippage = ", DoubleToString(Open_Slippage,Digits), // " Latency= ", OpenLatency); } } } xxBars = Bars; } if (Entry(false) == 2 // 売りエントリー && CountBuy == 0 && CountSell < Maxposition && xxBars != Bars && (GMT_Kadou_OK2 == true || GMT_Kadou_OK2_noFilter == true)) { ticket = OrderSend(Symbol(), OP_SELL, CalculateLots(MM_Risk, StopLoss_pips), Bid, Slippage, Bid + StopLoss_pips * xpoint, Bid - TakeProfit_pips * xpoint, _Comment, MagicNumber, 0, Red); // エントリーが失敗であれば、TPSLを分割して注文する if (ticket == -1) { double OSpread = Ask - Bid;// スプレッド計測 uint StartOrderTimestamp = GetTickCount();// レイテンシー計測 double Order_Price = Bid;// 売り注文を入れる価格 ticket = OrderSend(Symbol(), OP_SELL, CalculateLots(MM_Risk, StopLoss_pips), Bid, Slippage, 0, 0, _Comment, MagicNumber, 0, Red); // エントリーに成功していれば、TP, SLをセットする if (ticket != -1) { // チケットを使ってオーダーを選択(エラーを生じた場合、何もしない) if( OrderSelect( ticket, SELECT_BY_TICKET ) == true ) { OpenLatency = GetTickCount() - StartOrderTimestamp; // レイテンシー計測 Order_Price = NormalizeDouble(Order_Price , Digits); // 買い注文価格を正規化 Yakujyou_Price = NormalizeDouble(OrderOpenPrice(), Digits); // 実際約定した価格、正規化 Open_Slippage = NormalizeDouble(Yakujyou_Price - Order_Price, Digits) / xpoint; // スリッページ、桁合わせ Open_Spread = NormalizeDouble(OSpread, Digits) / xpoint; // スプレッド、桁合わせ res = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() + StopLoss_pips * xpoint, OrderOpenPrice() - TakeProfit_pips * xpoint, 0, MediumSeaGreen); //Print("Slippage = ", DoubleToString(Open_Slippage,Digits), // " Latency= ", OpenLatency); } } } xxBars = Bars; } } // エントリー判断のローソク足始値のみ稼働(ココマデ) } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| TakeProfit, StopLoss | //+------------------------------------------------------------------+ void SetTPSL() { int i; double profit; bool res; // ポジションに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 = OrderModify(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 = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() + StopLoss_pips * xpoint, OrderOpenPrice() - TakeProfit_pips * xpoint, 0, MediumSeaGreen); } } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 複利機能 | //+------------------------------------------------------------------+ // 複利機能のロット数を計算する double CalculateLots(double risk, // 許容するリスク int sl_pips) // ストップロス { // バックテスト時は、バックテスト用の複利機能を使用する if (IsTesting()) return(CalculateLots_forTest(risk, sl_pips)); else return(CalculateLots_forReal(risk, sl_pips)); } // 複利機能のロット数を計算する(実トレード用) double CalculateLots_forReal(double risk, // 許容するリスク int sl_pips) // ストップロス { double freemargin; // アカウントの余剰証拠金 double balance; // アカウントの口座残高 double tickvalue; // 1ロット1pip当たりの証拠金通貨相当額 double lotstep; // サーバのロット数の最小刻み制限 double maxlots; // サーバの最大ロット数制限 double minlots; // サーバの最小ロット数制限 double lotsize = Lots; // ロットサイズ // 複利機能を使わない場合、Lotsを返す if (MM_ON == Fixed) return(Lots); freemargin = AccountFreeMargin(); balance = AccountBalance(); tickvalue = MarketInfo(NULL, MODE_TICKVALUE); lotstep = MarketInfo(NULL, MODE_LOTSTEP); maxlots = MarketInfo(NULL, MODE_MAXLOT); minlots = MarketInfo(NULL, MODE_MINLOT); // tickvalueはpipsではなくpointなので、小数点以下の桁数に応じて補正する if (Digits() == 3 || Digits() == 5) tickvalue = tickvalue * 10; // 許容するリスクとSLの幅から、ロットサイズを計算する。 if (MM_ON == FreeMargin) // 余剰証拠金方式 { lotsize = (freemargin * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%) / (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額 } else if (MM_ON == Balance) // 残高方式 { lotsize = (balance * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%) / (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額 } // サーバのロット数の刻みに合わせてロット数を修正 lotsize = MathFloor(lotsize / lotstep) * lotstep; // サーバの最小ロット数・最大ロット数で補正をかける lotsize = MathMax(lotsize, minlots); lotsize = MathMin(lotsize, maxlots); return(lotsize); } // 複利機能のロット数を計算する(バックテスト用) double CalculateLots_forTest(double risk, // 許容するリスク int sl_pips) // ストップロス { double freemargin; // アカウントの余剰証拠金 double balance; // アカウントの口座残高 double tickvalue; // 1ロット1pip当たりの証拠金通貨相当額 double lotstep; // サーバのロット数の最小刻み制限 double maxlots; // サーバの最大ロット数制限 double minlots; // サーバの最小ロット数制限 double lotamount; // 1ロットの通貨数 double lotsize = Lots; // ロットサイズ double conv; // 口座通貨種類による補正係数 // 複利機能を使わない場合、Lotsを返す if (MM_ON == Fixed) return(Lots); freemargin = AccountFreeMargin(); balance = AccountBalance(); tickvalue = MarketInfo(NULL, MODE_TICKVALUE); lotstep = MarketInfo(NULL, MODE_LOTSTEP); maxlots = MarketInfo(NULL, MODE_MAXLOT); minlots = MarketInfo(NULL, MODE_MINLOT); lotamount = MarketInfo(NULL, MODE_LOTSIZE); // 1万通貨*1pips = $1 = 100円と仮定し、1ロット1pipの変動が口座通貨でいくらに相当するか計算 // 1 lot = 10万通貨 // 口座通貨 = JPY : tickvalue = 1000円/(lot・pip) // 口座通貨 = USD : tickvalue = $10/(lot・pip) conv = 1; if (AccountCurrency() == "JPY") conv = 100; tickvalue = lotamount / 10000 * conv; // 許容するリスクとSLの幅から、ロットサイズを計算する。 if (MM_ON == FreeMargin) // 余剰証拠金方式 { lotsize = (freemargin * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%) / (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額 } else if (MM_ON == Balance) // 残高方式 { lotsize = (balance * risk / 100.0) // 許容するリスク (余剰証拠金のrisk%) / (sl_pips * tickvalue); // 1ロットでSLにかかった時の金額 } // サーバのロット数の刻みに合わせてロット数を修正 lotsize = MathFloor(lotsize / lotstep) * lotstep; // サーバの最小ロット数・最大ロット数で補正をかける lotsize = MathMax(lotsize, minlots); lotsize = MathMin(lotsize, maxlots); return(lotsize); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリー総括 | //+------------------------------------------------------------------+ int Entry(bool isbuy) { if (Entry_Rule1(isbuy) == 1 && (Entry_Filter1(isbuy) == 1 || Entry_Filter1(isbuy) == 3) && (Entry_Filter2(isbuy) == 1 || Entry_Filter2(isbuy) == 3) && (Entry_Filter3(isbuy) == 1 || Entry_Filter3(isbuy) == 3) && (Entry_Filter4(isbuy) == 1 || Entry_Filter4(isbuy) == 3) && (Entry_Filter5(isbuy) == 1 || Entry_Filter5(isbuy) == 3) && (Entry_Filter6(isbuy) == 1 || Entry_Filter6(isbuy) == 3) && (Entry_Filter7(isbuy) == 1 || Entry_Filter7(isbuy) == 3) ) { return(1); } else if (Entry_Rule1(isbuy) == 2 && (Entry_Filter1(isbuy) == 2 || Entry_Filter1(isbuy) == 3) && (Entry_Filter2(isbuy) == 2 || Entry_Filter2(isbuy) == 3) && (Entry_Filter3(isbuy) == 2 || Entry_Filter3(isbuy) == 3) && (Entry_Filter4(isbuy) == 2 || Entry_Filter4(isbuy) == 3) && (Entry_Filter5(isbuy) == 2 || Entry_Filter5(isbuy) == 3) && (Entry_Filter6(isbuy) == 2 || Entry_Filter6(isbuy) == 3) && (Entry_Filter7(isbuy) == 2 || Entry_Filter7(isbuy) == 3) ) { return(2); } else { return(0); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 売りポジションの決済総括 | //+------------------------------------------------------------------+ int Exit1(bool isbuy) { if (Exit_Rule1(isbuy) == 3 && Exit_Rule2(isbuy) == 3 && Exit_Rule3(isbuy) == 3 && Exit_Rule4(isbuy) == 3 && Exit_Rule5(isbuy) == 3) { return(0); } else if (Exit_Rule1(isbuy) == 1) { return(1); } else if( Exit_Rule2(isbuy) == 1) { return(1); } else if (Exit_Rule3(isbuy) == 1) { return(1); } else if( Exit_Rule4(isbuy) == 1) { return(1); } else if (Exit_Rule5(isbuy) == 1) { return(1); } else { return(0); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 買いポジションの決済総括 | //+------------------------------------------------------------------+ int Exit2(bool isbuy) { if (Exit_Rule1(isbuy) == 3 && Exit_Rule2(isbuy) == 3 && Exit_Rule3(isbuy) == 3 && Exit_Rule4(isbuy) == 3 && Exit_Rule5(isbuy) == 3) { return(0); } else if (Exit_Rule1(isbuy) == 2) { return(2); } else if (Exit_Rule2(isbuy) == 2) { return(2); } else if (Exit_Rule3(isbuy) == 2) { return(2); } else if (Exit_Rule4(isbuy) == 2) { return(2); } else if (Exit_Rule5(isbuy) == 2) { return(2); } else { return(0); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリールール1 | //+------------------------------------------------------------------+ int Entry_Rule1(bool isbuy) { //エントリールール1 // 時間制御によるエントリー可能時間でエントリー判定 if (GMT_Kadou_OK1 == true || GMT_Kadou_OK1_noFilter == true) { return(1); } // 買い if (GMT_Kadou_OK2 == true || GMT_Kadou_OK2_noFilter == true) { return(2); } // 売り return(0); // エントリー出来ない //エントリールール1ココマデ } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター1 | //+------------------------------------------------------------------+ int Entry_Filter1(bool isbuy) { //エントリーフィルター1 // スプレッドフィルター double spread = MarketInfo(NULL, MODE_SPREAD); if (Digits == 3 || Digits == 5) spread /= 10.0; if (spread > MaxSpread_pips) { return(0); } // トレード不許可 else { return(3); } // トレード許可 //エントリーフィルター1ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター2 | //+------------------------------------------------------------------+ int Entry_Filter2(bool isbuy) { //エントリーフィルター2 // 12/25~1/3まではエントリーしない int NGMonth = Month(); int NGDay = Day(); if (YearendClose == true && ((NGMonth == 12 && NGDay >= 25) || (NGMonth == 1 && NGDay <= 3)) ) { return(0); } // エントリー出来ない //エントリーフィルター2ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター3 | //+------------------------------------------------------------------+ int Entry_Filter3(bool isbuy) { //エントリーフィルター3 // 過去値動きによるエントリー制御 // 過去〇本の最高値、最安値を求める double MostHigh1 = High[iHighest(NULL, PERIOD_H1, MODE_HIGH, CandleCheckCount1, 1)]; double MostLow1 = Low[iLowest(NULL, PERIOD_H1, MODE_LOW , CandleCheckCount1, 1)]; double MostHigh2 = High[iHighest(NULL, PERIOD_H1, MODE_HIGH, CandleCheckCount2, 1)]; double MostLow2 = Low[iLowest(NULL, PERIOD_H1, MODE_LOW , CandleCheckCount2, 1)]; // 過去◯本に◯◯pips以内の値動きだったらエントリー禁止 if (isbuy == true && MostHigh1 - MostLow1 < HL_margin1 * xpoint) { return(0); } // エントリー出来ない if (isbuy == false && MostHigh2 - MostLow2 < HL_margin2 * xpoint) { return(0); } // エントリー出来ない //エントリーフィルター3ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター4 | //+------------------------------------------------------------------+ int Entry_Filter4(bool isbuy) { //エントリーフィルター4 // 過去値動きによるエントリー制御 // 過去〇本の最高値、最安値を求める double MostHigh = High[iHighest(NULL, PERIOD_H1, MODE_HIGH, CandleCheckCount_H, 1)]; double MostLow = Low[iLowest(NULL, PERIOD_H1, MODE_LOW , CandleCheckCount_L, 1)]; double HC = MostHigh - Close[1]; double LC = Close[1] - MostLow; // 過去◯本の、高値と1本前終値の差が◯◯pips以上だったら買いエントリー禁止 if (isbuy == true && HC > HC_margin * xpoint) { return(0); } // エントリー出来ない // 過去◯本の、安値と1本前終値の差が◯◯pips以上だったら売りエントリー禁止 if (isbuy == false && LC > LC_margin * xpoint) { return(0); } // エントリー出来ない //エントリーフィルター4ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター5 | //+------------------------------------------------------------------+ int Entry_Filter5(bool isbuy) { //エントリーフィルター5 // MAを宣言 double MA_fast1 = iMA(NULL, PERIOD_H1, MA_PERIOD, 0, MODE_EMA, PRICE_CLOSE, 1); // 1本前の短期MA // 価格が長期移動平均線より上なら「買い」、下なら「売り」 if (isbuy == true && GMT_Kadou_OK1 == true && Close[1] > MA_fast1) { return(1); } // 買い if (isbuy == false && GMT_Kadou_OK2 == true && Close[1] Close[1]) { return(1); } // 買い if (isbuy == false && GMT_Kadou_OK2 == true && MA1 < Close[1]) { return(2); } // 売り // フィルターなし if (isbuy == true && GMT_Kadou_OK1_noFilter == true) { return(1); } // 買い if (isbuy == false && GMT_Kadou_OK2_noFilter == true) { return(2); } // 売り return(0); // エントリー出来ない //エントリーフィルター6ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリーフィルター7 | //+------------------------------------------------------------------+ int Entry_Filter7(bool isbuy) { //エントリーフィルター7 //エントリーフィルター7ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール1 | //+------------------------------------------------------------------+ int Exit_Rule1(bool isbuy) { // 決済ルール1 // 決済ルール1ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール2 | //+------------------------------------------------------------------+ int Exit_Rule2(bool isbuy) { // 決済ルール2 // 決済ルール2ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール3 | //+------------------------------------------------------------------+ int Exit_Rule3(bool isbuy) { // 決済ルール3 // 決済ルール3ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール4 | //+------------------------------------------------------------------+ int Exit_Rule4(bool isbuy) { // 決済ルール4 // 決済ルール4ココマデ return(3); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 決済ルール5 | //+------------------------------------------------------------------+ int Exit_Rule5(bool isbuy) { // 決済ルール5 // 決済ルール5ココマデ return(3); } //+------------------------------------------------------------------+