gryps2/UI-code/T-046_Slippage_Latency.txt
super.admin ae3f0ebf03 convert
2025-05-30 14:58:21 +02:00

1876 lines
No EOL
136 KiB
Text
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+------------------------------------------------------------------+
//| オープン・クローズ別々で書き込み(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 <stdlib.mqh>
//ユーザー入力用パラメーター
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] <MA_fast1)
{
return(2);
} // 売り
// フィルターなし
if (isbuy == true && GMT_Kadou_OK1_noFilter == true)
{
return(1);
} // 買い
if (isbuy == false && GMT_Kadou_OK2_noFilter == true)
{
return(2);
} // 売り
return(0);
//エントリーフィルター5ココマデ
return(3);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| エントリーフィルター6 |
//+------------------------------------------------------------------+
int Entry_Filter6(bool isbuy)
{
//エントリーフィルター6
// MAを宣言
double MA1 = iMA(NULL, PERIOD_M15, 20, 0, MODE_SMA, PRICE_CLOSE, 1);
// 価格が短期移動平均線の下なら「買い」、上なら「売り」
if (isbuy == true && GMT_Kadou_OK1 == true && MA1 > 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);
}
//+------------------------------------------------------------------+