//+------------------------------------------------------------------+ //| 001-USER-FRIENDLY-EA.mq4 | //| Copyright (c) 2024, HANDY SYSTEMS with TNK, All rights reserved | //| | //+------------------------------------------------------------------+ #property copyright "Copyright (c) 2024, HANDY SYSTEMS with TNK, All rights reserved" #property version "1.0" #property strict #include // MM type enum MM_Type { Fixed = 0, // Fixed FreeMargin = 1, // FreeMargin Barance = 2, // Balance AddCredit = 3 // AddCredit }; // SUMMERTIME type enum SUMMERTIME_Type { none = 0, // none US = 1, // US UK = 2 // UK }; input int MagicNumber = 12345; // MagicNumber input double Lots = 0.1; // Lots input double StopLoss_pips = 10000.0; // StopLoss (pips) input double StopLoss_pips_buy = 10000.0; // StopLoss buy (pips) input double StopLoss_pips_sell = 10000.0; // StopLoss sell (pips) input double MaxStopLoss_pips = 10000.0; // MaxStopLoss (pips) input MM_Type MM_ON = Fixed; // MM Type input double MM_Risk = 0.1; // MM Risk input SUMMERTIME_Type Summertime = none; // Summertime Type //-------------------------------------------------------------------- // T-038_MagicChohukuAlert: マジックナンバー重複アラート //-------------------------------------------------------------------- // マジックナンバー重複セットアラート // これを仕込んだEA同士でマジックナンバーが重複した場合アラートを出す static bool check_duplicate = true; static const string kEA_NAME = (string)MagicNumber; //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-039_AutoChartSet: 自動チャートセット //-------------------------------------------------------------------- //6桁のFX通貨ペアなら変換可。CFDなど6文字以外のものは検知しない。 //チャートセット固定用 string SYMBOL1 = "GBPJPY"; // シンボル名(頭6文字) //string SYMBOL2 = "GOLD"; // シンボル名(頭4文字) int Chart_TimeFrame = PERIOD_M15; // タイムフレーム //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-042_EA-Condition: チャートにEA状態表示 //-------------------------------------------------------------------- // EAの状態を表示アレンジ // EAの状態を表示 bool Pass = true; int CT = 0; int ChartWarning; // この変数は、チャート表示やチャートコメント表示と連動 //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-044_TradeHistry-pips: トレード履歴・pipsをチャートに表示 //-------------------------------------------------------------------- // チャートにトレード履歴表示・データ表示用 double tes = 0.0; // 外付け手数料(PIPS換算) int sf, tof; datetime hf; double totalpips = 0, ProfitFactor = 0; double plus_profit = 0, minus_profit = 0; double minus_count = 0, plus_count = 0; double RRR, WinPer; double TradeCounts; //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-045_AutoSpread: オートスプレッド //-------------------------------------------------------------------- double MaxSpread_pips = 4.0; // 許容スプレッド(Pips) input double AllowSpread = 10.0; // 許容スプレッドPips(0:自動) // スプレッド計測用 double MeasureSpread, SpreadMin = 1000, SpreadMax = 0, SpreadSum = 0, SpreadAve = 0; double SpreadMin1 = 100, SpreadMax1 = 0, SpreadSum1 = 0, SpreadAve1 = 0; int TickCount = 0, TickCount1 = 0, lastBars; // オートスプレッド用 double Adjustspread = 5.0; // 平均スプレッド加算用宣言 double AllowMaxSpread = 8.0; // 自動最大許容スプレッド double Adjustspread_Margin = 2.0; // 自動スプレッド調整幅 double Adjustspread_Margin1 = 1.0; // 自動スプレッド調整幅(1:00) //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-046_Slippage_Latency: スリッページ・レイテンシー計測 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| オープン・クローズ別々で書き込み(TP/SL対応) | //+------------------------------------------------------------------+ // 各計測用パラメータ input bool Measurement = true; // 計測ログcsv作成(実行スプレッド・スリッページ等) double xpoint = 0; 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]; //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-049_VisualModeButton: チャートコメントON/OFF切替ボタン //-------------------------------------------------------------------- // ビジュアルモード切替ボタン bool VisualMode; //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-051_EquityCheck: 証拠金チェック //-------------------------------------------------------------------- // グローバル変数 // 証拠金チェック int aCmd = 0; //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //----------------------------------------------------------------- // T-038_MagicChohukuAlert: マジックナンバー重複アラート //----------------------------------------------------------------- // マジックナンバー重複セットアラート if (check_duplicate) { double term_global_var; if (GlobalVariableGet(kEA_NAME, term_global_var)) { Alert("Magic numbers are duplicated" +"\n"+ "マジックナンバー重複"); } const datetime mutex_time = GlobalVariableSet(kEA_NAME, 1.0); if (mutex_time == 0) { const int errcode = GetLastError(); Print("GlobalVariableSet: ERRCODE[", errcode, "]:", ErrorDescription(errcode)); } } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-039_AutoChartSet: 自動チャートセット //----------------------------------------------------------------- // チャート自動変更・シンボル・チャートコメント・EA名・状態表示 if (!IsTesting()) { ChartSet(); // チャート自動変更 } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-040_CenterSymbol: チャート中央にシンボル等表示 //----------------------------------------------------------------- if (!IsTesting()) { CenterSymbol(); } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-042_EA-Condition: チャートにEA状態表示 //----------------------------------------------------------------- if (IsTesting() == false) { EA_test(); EventSetTimer(60); } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-043_ChartComment: チャートコメント右側用 //----------------------------------------------------------------- // シンボル・チャートコメント・状態表示 if (!IsTesting()) { //CenterSymbol(); // 別途センターシンボルを利用する場合は、チャートコメントより先に記載。でないとシンボルがコメントより手前に表示される。 ChartComment(); } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-044_TradeHistry-pips: トレード履歴・pipsをチャートに表示 //----------------------------------------------------------------- // トレード履歴をチャートに表示(ライン・pips) history(); PosHis(); //----------------------------------------------------------------- //----------------------------------------------------------------- // T-045_AutoSpread:オートスプレッド //----------------------------------------------------------------- // 初期化スプレッド(バックテスト時または手動時、それ以外や自動) if (IsTesting() || AllowSpread != 0) MaxSpread_pips = AllowSpread; if (AllowSpread == 0) MaxSpread_pips = AllowMaxSpread; //----------------------------------------------------------------- //----------------------------------------------------------------- // T-046_Slippage_Latency: スリッページ・レイテンシー計測 //----------------------------------------------------------------- // ファイル出力初期化処理 if (Measurement) FileInit(); //----------------------------------------------------------------- //----------------------------------------------------------------- // T-049_VisualModeButton: チャートコメントON/OFF切替ボタン //----------------------------------------------------------------- //+------------------------------------------------------------------+ // チャート自動変更・シンボル・チャートコメント・状態表示 if (!IsTesting()) { ChartSet(); // チャート自動変更 CenterSymbol(); // 中央のシンボル ChartComment(); // チャートコメント EA_test(); // 状態表示 EventSetTimer(60); // 状態表示 } //+------------------------------------------------------------------+ // トレード履歴をチャートに表示(ライン・pips) history(); PosHis(); //+------------------------------------------------------------------+ // ビジュアルモード切り替えボタン作成 Button("Visual", WindowExpertName(), StringLen(WindowExpertName()) * 12, 0, CHART_COLOR_BACKGROUND, 1); { ObjectSetInteger(0, "Visual", OBJPROP_STATE, true); ObjectSetInteger(0, "Visual", OBJPROP_BORDER_COLOR, clrGray); VisualMode = true; } //+------------------------------------------------------------------+ //----------------------------------------------------------------- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //----------------------------------------------------------------- // T-038_MagicChohukuAlert: マジックナンバー重複アラート //----------------------------------------------------------------- // マジックナンバー重複用 if (check_duplicate) { if (!GlobalVariableDel(kEA_NAME)) { const int errcode = GetLastError(); Print("GlobalVariableDel: ERRCODE[", errcode, "]:", ErrorDescription(errcode)); } } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-042_EA-Condition: チャートにEA状態表示 //----------------------------------------------------------------- EventKillTimer(); ObjectDelete("EA_label"); //----------------------------------------------------------------- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //----------------------------------------------------------------- // T-040_CenterSymbol - チャート中央にシンボル等表示 //----------------------------------------------------------------- if (!IsTesting()) { CenterSymbol(); } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-042_EA-Condition: チャートにEA状態表示 //----------------------------------------------------------------- if (IsTesting() == false) { CT++; EA_test(); } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-043_ChartComment - チャートコメント右側用 //----------------------------------------------------------------- // チャートコメント・状態表示 if (!IsTesting()) { ChartComment(); // チャートコメント } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-044_TradeHistry-pips: トレード履歴・pipsをチャートに表示 //----------------------------------------------------------------- // チャートにトレード線とpips表示 if (IsTesting() == false || IsVisualMode() == true) { if (sf != Seconds() && OrdersTotal() > 0) { PosHis(); sf = Seconds(); } if ((hf != iTime((string)0, 60, 0) && Seconds() > 30) || tof != OrdersHistoryTotal()) { history(); hf = iTime((string)0, 60, 0); tof = OrdersHistoryTotal(); } } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-045_AutoSpread:オートスプレッド //----------------------------------------------------------------- // スプレッド値取得 if (!IsTesting() && AllowSpread == 0) { MeasureSpread = MarketInfo(Symbol(),MODE_SPREAD) / 10; MeasureSP(); //PipsObject(); // チャートにスプレッドデータ表示 } //----------------------------------------------------------------- //----------------------------------------------------------------- // T-046_Slippage_Latency: スリッページ・レイテンシー計測 //----------------------------------------------------------------- // TODO: オーダー取引機能がないため、本機能はまだ実装されていない //----------------------------------------------------------------- //----------------------------------------------------------------- // T-048_VolumeEntry: 半ティック稼働 //----------------------------------------------------------------- //半ティック稼働 //xBarsの判定ではなく、Volume[0]で始値と、その後数ティック判定を行う //Volume[0]は始値。ただし始値で注文が判定されないこともあり、数ティック判定を予備で行うと約定しやすい。 //全ティック稼働に比べ、処理が軽くなる。 //開発塾のxBars判定では、始値の1ティック目しか判定を行えない //数ティック判定を行うタイミングで決済処理がある場合は、連続発注・決済を繰り返すこともある。 //全ティックでのバックテストで、連続発注が無いかチェック必要 //連続防止のコードも以下記載(1ポジション用) //計測の結果、通常10~20ティックまであればエントリー補助判定としては機能した(それ以上ではレートが変わりすぎるなど問題あり) //スプレッド判定がタイトな朝方などでは、判定ティック数を増やして対応も可能 // // TODO: オーダー取引機能がないため、本機能はまだ実装されていない //----------------------------------------------------------------- //----------------------------------------------------------------- // T-046_Slippage_Latency: スリッページ・レイテンシー計測 //----------------------------------------------------------------- // 決済がTP/SLなら情報取得 if (Measurement) ClosedTradeTPSL(); //----------------------------------------------------------------- } //-------------------------------------------------------------------- // T-042_EA-Condition: チャートにEA状態表示 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| EAの状態を表示 右上・チャートやチャートコメントと連動 | //+------------------------------------------------------------------+ void OnTimer() { EA_test(); if (CT == 0) EA_label ("更新待機中", clrYellow); ChartWarning = 1; // この変数は、チャート表示やチャートコメント表示と連動 ChartSet2(); CT = 0; } void EA_test() { string label1 = "EA稼働中"; string label2 = "口座認証失敗"; string label3 = "トレード不許可"; string label4 = "通信エラー"; string labelx = label1; if (Pass == false) labelx = label2; else if (IsTradeAllowed() == false) labelx = label3; else if (IsConnected() == false) labelx = label4; if (Pass == false) { EA_label (label2, clrOrangeRed); ChartWarning = 2; ChartSet2(); } else if (IsTradeAllowed() == false) { EA_label (label3, clrOrangeRed); ChartWarning = 3; ChartSet2(); } else if (IsConnected() == false) { EA_label (label4, clrOrangeRed); ChartWarning = 4; ChartSet2(); } else { EA_label (label1, clrLime); ChartWarning = 0; ChartSet2(); } } void EA_label(string text, color clr) { ObjectCreate(0, "EA_label", OBJ_LABEL, 0, 0, 0); ObjectSetString(0, "EA_label", OBJPROP_TEXT, text); ObjectSetInteger(0, "EA_label", OBJPROP_COLOR, clr); ObjectSetInteger(0, "EA_label", OBJPROP_XDISTANCE, 6); ObjectSetInteger(0, "EA_label", OBJPROP_YDISTANCE, 24); ObjectSetInteger(0, "EA_label", OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, "EA_label", OBJPROP_SELECTABLE, false); ObjectSetInteger(0, "EA_label", OBJPROP_HIDDEN, true); ObjectSetString(0, "EA_label", OBJPROP_FONT, "Segoe UI"); ObjectSetInteger(0, "EA_label", OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, "EA_label", OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER); ObjectSetInteger(0, "EA_label", OBJPROP_BACK, false); } // 状態によるチャート配色変更 void ChartSet2() { color ChartWar1 = ChartWarning >= 2? clrDarkGray : clrWhite; color ChartWar2 = ChartWarning >= 2? clrDimGray : clrOlive; color ChartWar3 = ChartWarning >= 2? clrSilver : clrBeige; if (!IsTesting()) { ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrBlack); ChartSetInteger(0, CHART_COLOR_FOREGROUND, ChartWar1); ChartSetInteger(0, CHART_COLOR_GRID, clrLightSlateGray); ChartSetInteger(0, CHART_COLOR_CHART_UP, ChartWar2); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, ChartWar2); ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrBlack); ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, ChartWar3); ChartSetInteger(0, CHART_COLOR_CHART_LINE, ChartWar2); ChartSetInteger(0, CHART_COLOR_VOLUME, ChartWar2); ChartSetInteger(0, CHART_COLOR_ASK, clrRed); ChartSetInteger(0, CHART_COLOR_STOP_LEVEL, clrRed); ChartSetInteger(0, CHART_SHIFT, true); //ChartSetDouble(0, CHART_SHIFT_SIZE, ShiftPer); ChartSetInteger(0, CHART_AUTOSCROLL, true); //ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる //ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる ChartSetInteger(0, CHART_FOREGROUND, false); ChartSetInteger(0, CHART_SHOW_GRID, false); ChartSetInteger(0, CHART_SHOW_ONE_CLICK, false); ChartSetInteger(0, CHART_SHOW_OHLC, false); ChartSetInteger(0, CHART_SHOW_PERIOD_SEP, true); ChartSetInteger(0, CHART_SHOW_ASK_LINE, true); ChartSetInteger(0, CHART_SCALE, 3); } } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-039_AutoChartSet: 自動チャートセット //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| チャート自動セット(初期化工程) | //+------------------------------------------------------------------+ void ChartSet() { // 気配値強制表示&自動切替 int chartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS); // チャート幅の計算 int textWidth = 200;//StringLen(WindowExpertName()) * 12; // 固定値pxまたはテキストの幅の計算 double ShiftPer = textWidth * 100 / chartWidth; if (!IsTesting()) { if (StringSubstr(Symbol(), 0, 6) != SYMBOL1 || Period() != Chart_TimeFrame) { SymbolSelect(SYMBOL1 + StringSubstr(Symbol(), 6, StringLen(Symbol())), true); ChartSetSymbolPeriod(0, SYMBOL1 + StringSubstr(Symbol(), 6, StringLen(Symbol())), Chart_TimeFrame); } // 現在のシンボルが4文字の場合。無しならコメントアウト /*if (StringSubstr(Symbol(), 0, 4) != SYMBOL2 || Period() != Chart_TimeFrame) { SymbolSelect(SYMBOL2 + StringSubstr(Symbol(), StringSubstr(Symbol(), 0, 4) == SYMBOL2? 4 : 6, StringLen(Symbol())), true); ChartSetSymbolPeriod(0, SYMBOL2 + StringSubstr(Symbol(), StringSubstr(Symbol(), 0, 4) == SYMBOL2? 4 : 6, StringLen(Symbol())), Chart_TimeFrame); }*/ ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrBlack); ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrWhite); ChartSetInteger(0, CHART_COLOR_GRID, clrLightSlateGray); ChartSetInteger(0, CHART_COLOR_CHART_UP, clrOlive); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrOlive); ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrBlack); ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrBeige); ChartSetInteger(0, CHART_COLOR_CHART_LINE, clrOlive); ChartSetInteger(0, CHART_COLOR_VOLUME, clrOlive); ChartSetInteger(0, CHART_COLOR_ASK, clrRed); ChartSetInteger(0, CHART_COLOR_STOP_LEVEL, clrRed); ChartSetInteger(0, CHART_SHIFT, true); ChartSetDouble(0, CHART_SHIFT_SIZE, ShiftPer); ChartSetInteger(0, CHART_AUTOSCROLL, true); //ChartSetInteger(0, CHART_SHOW_DATE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる //ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, true); // これを入れるとなぜか表示範囲が狭くなる ChartSetInteger(0, CHART_FOREGROUND, false); ChartSetInteger(0, CHART_SHOW_GRID, false); ChartSetInteger(0, CHART_SHOW_ONE_CLICK, false); ChartSetInteger(0, CHART_SHOW_OHLC, false); ChartSetInteger(0, CHART_SHOW_PERIOD_SEP, true); ChartSetInteger(0, CHART_SHOW_ASK_LINE, true); ChartSetInteger(0, CHART_SCALE, 3); ChartSetInteger(0, CHART_MODE, CHART_CANDLES); } } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- // T-040_CenterSymbol - チャート中央にシンボル等表示 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| チャートの中央にシンボルを描画する | //+------------------------------------------------------------------+ void CenterSymbol() { string TEXT1 = StringSubstr(Symbol(), 0, 6); string TEXT2 = (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") + "/" + DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD) / 10, 1); int FontSize = 36; int chartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS); int chartHeight = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS); int textWidth = StringLen(TEXT1) * FontSize / 2; // テキストの幅の計算 int textHeight = FontSize; // テキストの高さ // テキストの中心からの座標を計算 int x = (chartWidth - textWidth) / 2 + textWidth / 2; int y = (chartHeight - textHeight) / 2 + textHeight / 2; DrawTextInCenter("Symbol1", TEXT1, x, y - FontSize, FontSize, C'60, 60, 60'); DrawTextInCenter("Symbol2", TEXT2, x, y + FontSize, FontSize, C'60, 60, 60'); } void DrawTextInCenter(string Symbolname, string label_text, int pos_x, int pos_y, int s, color clr= clrBlack) { ObjectCreate(Symbolname, OBJ_LABEL, 0, 0, 0); ObjectSetString(0, Symbolname, OBJPROP_TEXT, label_text); ObjectSetInteger(0, Symbolname, OBJPROP_FONTSIZE, s); ObjectSetString(0, Symbolname, OBJPROP_FONT, "Segoe UI"); ObjectSetInteger(0, Symbolname, OBJPROP_XDISTANCE, pos_x); ObjectSetInteger(0, Symbolname, OBJPROP_YDISTANCE, pos_y); ObjectSetInteger(0, Symbolname, OBJPROP_COLOR, clr); ObjectSetInteger(0, Symbolname, OBJPROP_BACK, true); ObjectSetInteger(0, Symbolname, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, Symbolname, OBJPROP_ANCHOR, ANCHOR_CENTER); } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- // T-043_ChartComment - チャートコメント右側用 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| 複利ロット計算    | //+------------------------------------------------------------------+ double CalculateLots(double risk, double lots) { return (risk * lots); } //+------------------------------------------------------------------+ //| チャートコメント表示 | //+------------------------------------------------------------------+ void ChartComment() { // 状態によって色変更 color clrChartWar = ChartWarning >= 2? clrNONE : clrWhite; color clrChartWarPP = ChartWarning >= 2? clrNONE : totalpips < 0? clrOrangeRed : clrWhite; color clrChartWarPF = ChartWarning >= 2? clrNONE : 0 < ProfitFactor && ProfitFactor < 1? clrOrangeRed : clrWhite; string LotsComment; if (MM_ON == Fixed) LotsComment = DoubleToStr(Lots,2); else LotsComment = DoubleToStr(CalculateLots(MM_Risk, StopLoss_pips),2) + " (" + DoubleToStr(MM_Risk,1) +"%)"; string Comment0 = "Magic : " + (string)MagicNumber; string Comment1 = "Lots : " + LotsComment; string Comment2 = "MM : " + (MM_ON == 0 ? "Fixed" : MM_ON == 1 ? "FreeMargin" : MM_ON == 2 ? "Balance" : "AddCredit"); string Comment3 = "Summertime : " + (Summertime == 0 ? "none" : Summertime == 1 ? "US" : "UK"); string Comment4 = "Spread Lim/Ave : " + DoubleToStr(MaxSpread_pips,1) + "/" + DoubleToStr(SpreadAve,1); string Comment5 = "Stoploss B/S : " + DoubleToStr(StopLoss_pips_buy, 0) + "/" + DoubleToStr(StopLoss_pips_sell, 0); string Comment6 = "Swap B/S : " + DoubleToStr(MarketInfo(Symbol(),MODE_SWAPLONG), 2) + "/" + DoubleToStr(MarketInfo(Symbol(),MODE_SWAPSHORT), 2); string Comment7 = "TradeCounts : " + DoubleToStr(TradeCounts, 0); string Comment8 = "Profit (pips) : " + DoubleToStr(totalpips, 1); string Comment9 = (plus_profit == 0 || minus_profit == 0? "Profit factor : ---" : "Profit factor : " + DoubleToStr(ProfitFactor, 2)); string Comment10 = (plus_profit == 0 || minus_profit == 0? "RRR/Win% : ---/---" : "RRR/Win% : " + DoubleToStr(RRR, 2) + "/" + DoubleToStr(WinPer, 1)); CommentLabel("ComObj0", Comment0, 4, 38, 10, clrYellow); CommentLabel("ComObj1", Comment1, 4, 58, 10, clrYellow); CommentLabel("ComObj2", Comment2, 6, 82, 8, clrChartWar); CommentLabel("ComObj3", Comment3, 6, 100, 8, clrChartWar); CommentLabel("ComObj4", Comment4, 6, 118, 8, clrChartWar); CommentLabel("ComObj5", Comment5, 6, 136, 8, clrChartWarPP); CommentLabel("ComObj6", Comment6, 6, 154, 8, clrChartWarPF); CommentLabel("ComObj7", Comment7, 6, 172, 8, clrChartWar); CommentLabel("ComObj8", Comment8, 6, 190, 8, clrChartWar); CommentLabel("ComObj9", Comment9, 6, 208, 8, clrChartWar); CommentLabel("ComObj10", Comment10, 6, 226, 8, clrChartWar); } void CommentLabel(string ComName, string ComText, int ComPos_x, int ComPos_y, int ComSize, color ComClr= clrBlack) { ComName = ComName; ObjectCreate(ComName, OBJ_LABEL, 0, 0, 0); ObjectSetString (0, ComName, OBJPROP_TEXT, ComText); ObjectSetInteger(0, ComName, OBJPROP_XDISTANCE, ComPos_x); ObjectSetInteger(0, ComName, OBJPROP_YDISTANCE, ComPos_y); ObjectSetInteger(0, ComName, OBJPROP_FONTSIZE, ComSize); ObjectSetInteger(0, ComName, OBJPROP_COLOR, ComClr); ObjectSetString (0, ComName, OBJPROP_FONT, "Segoe UI"); ObjectSetInteger(0, ComName, OBJPROP_BACK, true); ObjectSetInteger(0, ComName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, ComName, OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, ComName, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER); } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- // T-044_TradeHistry-pips: トレード履歴・pipsをチャートに表示 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| チャートにトレード履歴表示(チャートコメントは別処理バージョン) | //+------------------------------------------------------------------+ void PosHis() { int res; double pips = 0; for (int i = OrdersTotal() - 1; i >= 0; i--) { res = OrderSelect(i, SELECT_BY_POS); if (OrderSymbol() != Symbol() || OrderType() > 1 || OrderMagicNumber() != MagicNumber) continue; pips += trend((string)OrderTicket(), OrderOpenTime(), OrderOpenPrice(), Time[0], OrderType() == 0 ? Bid : Ask, OrderType()); } } //+------------------------------------------------------------------+ void history() { int res; totalpips = 0; plus_profit = 0; minus_profit = 0;//, ProfitFactor = 0; minus_count = 0; plus_count = 0; TradeCounts = 0; // トレード履歴を検索 for (int i = OrdersHistoryTotal() - 1; i >= 0; i--) { res = OrderSelect(i, SELECT_BY_POS, MODE_HISTORY); if (OrderSymbol() != Symbol() || OrderType() > 1 || OrderMagicNumber() != MagicNumber) continue; // 合計pips計算 totalpips += trend((string)OrderTicket(), OrderOpenTime(), OrderOpenPrice(), OrderCloseTime(), OrderClosePrice(), OrderType()); // プロフィットファクター・RRR・勝率計算 if (OrderProfit() < 0) { minus_profit -= OrderProfit(); minus_count += 1; } else if (OrderProfit() >= 0) { plus_profit += OrderProfit(); plus_count += 1; } if (minus_profit != 0 && plus_count != 0 && minus_count != 0) { ProfitFactor = plus_profit / minus_profit; RRR = (plus_profit / plus_count) / (minus_profit / minus_count); WinPer = (plus_count * 100) / (plus_count + minus_count); } TradeCounts = minus_count + plus_count; } } //+------------------------------------------------------------------+ double trend(string obj_name, datetime Time1, double Close1, datetime Time2, double Close2, int type) { double pips = (double)DoubleToStr((type == 0 ? Close2 - Close1 : Close1 - Close2) / Point() * 0.1 - tes, 1); int Shift2 = iBarShift(NULL, 0, Time2); datetime Timex = iTime(NULL, 0, Shift2 + 1); // トレード線 ObjectDelete("hislt" + obj_name); ObjectCreate(0, "hislt" + obj_name, OBJ_TREND, 0, Time1, Close1, Time2, Close2); ObjectSetInteger(0, "hislt" + obj_name, OBJPROP_COLOR, type == 0 ? clrDodgerBlue : clrOrangeRed); ObjectSetInteger(0, "hislt" + obj_name, OBJPROP_STYLE, 0); ObjectSetInteger(0, "hislt" + obj_name, OBJPROP_WIDTH, 2); ObjectSetInteger(0, "hislt" + obj_name, OBJPROP_SELECTABLE, false); // オブジェクトの選択可否設定 ObjectSetInteger(0, "hislt" + obj_name, OBJPROP_RAY_RIGHT, false); // 右に線を延長 // トレード線内のpips表示 // 文字本体 ObjectDelete("hislx" + obj_name); ObjectCreate(0, "hislx" + obj_name, OBJ_TEXT, 0, Timex, Close2); ObjectSetInteger(0, "hislx" + obj_name, OBJPROP_COLOR, pips < 0 ? clrOrangeRed : !IsTesting()? clrLime : clrYellow);//type == 0 ? BuyColor : SellColor); ObjectSetInteger(0, "hislx" + obj_name, OBJPROP_SELECTABLE, false); // オブジェクトの選択可否設定 ObjectSetInteger(0, "hislx" + obj_name, OBJPROP_FONTSIZE, 12); // フォントサイズ ObjectSetInteger(0, "hislx" + obj_name, OBJPROP_ANCHOR, ANCHOR_RIGHT); // 描画位置 ObjectSetString(0, "hislx" + obj_name, OBJPROP_TEXT, DoubleToStr(pips, 1)); // 表示するテキスト ObjectSetString(0, "hislx" + obj_name, OBJPROP_FONT, "Segoe UI Semibold"); // フォント return(pips); } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-045_AutoSpread: オートスプレッド //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| スプレッド計測・オートスプレッド | //+------------------------------------------------------------------+ void MeasureSP() { TickCount++; SpreadSum += MeasureSpread; SpreadMin = SpreadMin == 0 ? SpreadMin = MeasureSpread : SpreadMin; if (TickCount > 0 && SpreadSum > 0) SpreadAve = SpreadSum / TickCount; if (SpreadMax < MeasureSpread) SpreadMax = MeasureSpread; if (SpreadMin > MeasureSpread) SpreadMin = MeasureSpread; // 月足のバー更新時に累積値リセット if (lastBars != iBars(NULL, PERIOD_MN1)) { lastBars = iBars(NULL, PERIOD_MN1); SpreadSum = 0; TickCount = 0; } // オートスプレッド計算 Adjustspread = SpreadAve + Adjustspread_Margin; // 平均にマージン加算 MaxSpread_pips = MathMin(Adjustspread, AllowMaxSpread); // 内部設定の最大値とマージン加算を比較し小さい方を採用 } //+------------------------------------------------------------------+ // コメント部にスプレッドデータ表示 void PipsObject() { // 1:00スプ考慮しない場合 string Data1 = "Tradeable limit : " + DoubleToStr(MaxSpread_pips,1) + " "; string Data2 = "MarketInfo : "+DoubleToStr(MeasureSpread,1) + " "; string Data3 = "Average : " + DoubleToStr(SpreadAve,1) + " "; string Data4 = "Max : " + DoubleToStr(SpreadMax,1) + " "; string Data5 = "Min : " + (SpreadMin==1000? "---" : DoubleToStr(SpreadMin,1)) + " "; label("SP0", "[Spread data (pips)]" + " ", 0, 114, 11, clrWhite); label("SP1", Data1, 0, 88, 11, clrYellow); label("SP2", Data2, 0, 66, 11, clrWhite); label("SP3", Data3, 0, 44, 11, clrWhite); label("SP4", Data4, 0, 22, 11, clrWhite); label("SP5", Data5, 0, 0, 11, clrWhite); } //+------------------------------------------------------------------+ void label(string name, string label_text, int pos_x, int pos_y, int s, color clr= clrBlack) { name = name; ObjectCreate(name, OBJ_LABEL, 0, 0, 0); ObjectSetString (0, name, OBJPROP_TEXT, label_text); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, s); ObjectSetString (0, name, OBJPROP_FONT, "Segoe UI"); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER); ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, pos_x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, pos_y); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_BACK, true); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-046_Slippage_Latency: スリッページ・レイテンシー計測 //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| 実行スプレッド・スリッページ・実行スプレッド計測・ファイル作成 | //+------------------------------------------------------------------+ // ファイル初期化 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; } } } } } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-049_VisualModeButton: チャートコメントON/OFF切替ボタン //-------------------------------------------------------------------- //+------------------------------------------------------------------+ //| ビジュアルモード切替ボタン(EA表示名アレンジ) | //+------------------------------------------------------------------+ void OnChartEvent(const int id, //イベントID const long &lparam, //long型イベント const double &dparam, //double型イベント const string &sparam) //string型イベント { int xx = StringLen(WindowExpertName()) * 12; if(id == CHARTEVENT_OBJECT_CLICK) { if(ObjectGetInteger(0,"Visual",OBJPROP_STATE) == true) { if(sparam == "Visual") { VisualMode = true; history(); PosHis(); Button("Visual", WindowExpertName(), xx, 0, CHART_COLOR_BACKGROUND, 1); ObjectSetInteger(0, "Visual", OBJPROP_STATE, true); ObjectSetInteger(0, "Visual", OBJPROP_BORDER_COLOR, clrGray); EA_label ("状態ロード中...", clrWhite); } } else { VisualMode = false; ObjectsDeleteAll(); Button("Visual", WindowExpertName(), xx, 0, CHART_COLOR_BACKGROUND, 1); ObjectSetInteger(0, "Visual", OBJPROP_STATE, false); ObjectSetInteger(0, "Visual", OBJPROP_BORDER_COLOR, clrSilver); ChartComment(); for(int i=2; i<=15; i++) { ObjectDelete(0,"ComObj"+(string)i); } EA_label ("状態表示OFF", clrWhite); } } } //| ボタン仕様 void Button(string name, string text, int x, int y ,color clr, int a) { int xx = StringLen(WindowExpertName()) * 12 - 26; ObjectCreate(0,name,OBJ_BUTTON,ChartWindowFind(),0,0); // ボタンの作成をする(この段階ではデザインや場所が指定されていない枠だけのボタン ObjectSetInteger(0,name,OBJPROP_COLOR,clrWhite); // ボタンの文字色を設定する ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); // ボタンを選択して移動したり消したりしないようにするための設定 ObjectSetInteger(0,name,OBJPROP_HIDDEN,true); // ボタンがオブジェクトのリストに表示されないようにするための設定 ObjectSetString (0,name,OBJPROP_TEXT,text); // ボタンに表示するテキストを設定する ObjectSetString (0,name,OBJPROP_FONT,"Segoe UI"); // ボタンの文字のフォントを設定する ObjectSetInteger(0,name,OBJPROP_FONTSIZE,8); // ボタンの文字サイズを設定する ObjectSetInteger(0,name,OBJPROP_CORNER,a); // ボタンの基準位置をきめる(右上・左上・左下・右下) ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x); // ボタンの基準位置からのX座標を設定 ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y); // ボタンの基準位置からのY座標を設定 ObjectSetInteger(0,name,OBJPROP_XSIZE,xx); // ボタンの横幅の設定 ObjectSetInteger(0,name,OBJPROP_YSIZE,24); // ボタンの縦幅の設定 ObjectSetInteger(0,name,OBJPROP_BGCOLOR,clr); // ボタンの色の設定 //ObjectSetInteger(0,name,OBJPROP_BORDER_COLOR,clrGray); // ボタンの枠線の色を設定 基本的にはボタン色と一緒で問題なくて、枠線を付けたい時だけ別にする //ObjectSetInteger(0,name,OBJPROP_STATE,false); // ボタンの状態を設定(押されている状態か、押されていない状態か) 最初は押されていない状態で大丈夫 ObjectSetInteger(0,name,OBJPROP_BACK,false); // オブジェクトの背景表示設定 //ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_RIGHT_UPPER); } //+------------------------------------------------------------------+ //-------------------------------------------------------------------- //-------------------------------------------------------------------- // T-051_EquityCheck: 証拠金チェック //-------------------------------------------------------------------- // 任意の空いているスペース //+------------------------------------------------------------------+ bool EquityCheck() { // 証拠金不足・トレード許可チェック double usedMoney = AccountEquity() - AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips)); if (!( (AccountStopoutMode() == 0 && usedMoney > 0.0 && (AccountEquity() / usedMoney) * 100 <= AccountStopoutLevel()) || (AccountStopoutMode() == 0 && usedMoney > 0.0 && AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips)) <= 0) || (AccountStopoutMode() == 1 && AccountFreeMarginCheck(Symbol(), aCmd, CalculateLots(MM_Risk, StopLoss_pips)) <= AccountStopoutLevel()) ) && IsTradeAllowed() == true) // トレード許可判定 { return(true); } else return(false); } //+------------------------------------------------------------------+ // ※StopLoss_pipsの変数は、仕様により要変更 // 参考サイト // https://autofx100.com/2021/03/01/ordersend-error-134-not-enough-money/ //--------------------------------------------------------------------