//+------------------------------------------------------------------+ //| HIT_EA.mq5 | //| Copyright 2026, nanpin-martin.com | //| https://www.nanpin-martin.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, nanpin-martin.com" #property link "https://nanpin-martin.com/" #property version "1.01" #include #include //+------------------------------------------------------------------+ //| バッチファイル実行用の設定 //+------------------------------------------------------------------+ // Windowsプロセス起動・終了確認用 #define CREATE_NO_WINDOW 0x08000000 #define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000 #define SYNCHRONIZE 0x00100000 #define WAIT_OBJECT_0 0 #define WAIT_TIMEOUT 258 #define STILL_ACTIVE 259 struct STARTUPINFO_W { uint cb; string lpReserved; string lpDesktop; string lpTitle; uint dwX; uint dwY; uint dwXSize; uint dwYSize; uint dwXCountChars; uint dwYCountChars; uint dwFillAttribute; uint dwFlags; ushort wShowWindow; ushort cbReserved2; long lpReserved2; long hStdInput; long hStdOutput; long hStdError; }; struct PROCESS_INFORMATION { long hProcess; long hThread; uint dwProcessId; uint dwThreadId; }; #import "kernel32.dll" int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation); int WaitForSingleObject(long hHandle, uint dwMilliseconds); int GetExitCodeProcess(long hProcess, uint &lpExitCode); int CloseHandle(long hObject); long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId); #import // バッチファイルのパス string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry // プロセス完了ファイルの設定 string done_trend_file = "process_done_trend.txt"; string done_entry_file = "process_done_entry.txt"; // Python出力ファイル string trend_state_file = "trend_state.txt"; string target_prices_file = "target_prices.txt"; // Python実行中を判定するための管理ファイル string running_trend_file = "process_running_trend.txt"; string running_entry_file = "process_running_entry.txt"; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| インプットの設定 //+------------------------------------------------------------------+ //--- 入力パラメータ input double lot_size = 0.01; // ロット数 input double spread_limit = 60; // 許容スプレッド(point) input int magic_number = 10001; // マジックナンバー input int initial_order = 0; // 起動時の注文(0:なし, 1:あり) input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認 input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可 input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加 input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間 input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度 input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point) input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ input int input_entry_max_candidate_age_minutes = 45; // H1候補価格を新規発注に使う最大経過分数 input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化 input bool input_sltp_show_panel = true; // SLTP操作パネルを表示 input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化 input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化 input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間 input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化 input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化 input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率 input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率 input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化 ulong slippage = 10; // スリッページ //--- 主要な定数・設定 #define POSITION_LIMIT 48 #define ENTRY_H1_LIMIT 1 // H1本数(=1時間) #define CLOSE_H1_LIMIT 12 // H1本数(=12時間) #define HISTORY_BARS 72 #define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す #define M15_CONFIRM_BARS 30 #define M15_MIN_ENTRY_ZONE_POINTS 10 #define M15_MIN_BODY_RATIO 0.25 #define M15_REJECTION_WICK_RATIO 0.35 #define ENTRY_RETRY_SECONDS 60 #define ENTRY_RETRY_LIMIT 10 // ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定) #define TARGET_SIZE 13 #define DEFAULT_TARGET_PRICE 0.0 #define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒) #define MARKET_LOW_VOL_RANGE 0 #define MARKET_HIGH_VOL_RANGE 1 #define MARKET_LOW_VOL_UP 2 #define MARKET_HIGH_VOL_UP 3 #define MARKET_LOW_VOL_DOWN 4 #define MARKET_HIGH_VOL_DOWN 5 #define MARKET_TECHNICAL_ERROR_STOP 6 //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| EAの状態をまとめる構造体 //+------------------------------------------------------------------+ struct EAState { int trend_state; // H4 market_state(0..5、6は技術エラー停止)を格納する変数 int res_chk; // GPTの回答が正しく取得できたか double en_price[5]; // エントリー基準価格 double tp_price[5]; // 利益確定価格 double sl_price[5]; // ロスカット基準価格 bool load_trend_flg; // ★変更:トレンドを更新するタイミングか bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか int chk_cnt; // エントリー判定の試行回数 datetime last_trend_update; // ★追加:前回トレンドを更新した時刻 datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻 datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻 datetime last_chk; }; EAState g_ea; // EA全体の状態をここで管理 // initial_order 用の初回処理フラグ // H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。 bool g_init_trend_pending = false; bool g_init_entry_pending = false; // H4/H1のバー更新状態 int g_pre_bars_H4 = 0; int g_pre_bars_H1 = 0; int g_pre_bars_M15 = 0; bool g_bars_H1_check = false; bool g_bars_M15_check = false; // ティックごとの価格情報 struct TickContext { double ask; double bid; double spread; double spread_points; int digits; }; // 外部Pythonプロセスの状態 struct ExternalProcessState { long handle; uint process_id; bool active; bool exit_code_ready; uint exit_code; datetime started_at; }; ExternalProcessState g_trend_process; ExternalProcessState g_entry_process; CSLTPManager g_sltp_manager; CSLTPManagerPanel g_sltp_panel; SLTPManagerPanelSettings g_sltp_settings; bool g_sltp_settings_valid = false; bool g_sltp_panel_created = false; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 起動時の処理 //+------------------------------------------------------------------+ /** * @brief EA起動時の初期化処理を行います。 * * Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は * H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。 * H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。 */ int OnInit() // プロセス完了ファイルと実行中ファイルの状態を初期化 { PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend"); PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry"); // initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。 g_init_trend_pending = (initial_order == 1); g_init_entry_pending = (initial_order == 1); if(!InitializeSLTPManager()) return INIT_FAILED; return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| 終了時の処理 //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ResetExternalProcessState(g_trend_process); ResetExternalProcessState(g_entry_process); if(g_sltp_panel_created) g_sltp_panel.Destroy(reason); // Clear chart status text left by Comment() when the EA is removed. Comment(""); ChartRedraw(0); } //+------------------------------------------------------------------+ //| ティック毎の処理 //+------------------------------------------------------------------+ /** * @brief ティック受信ごとにEA全体の処理を制御します。 * * 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、 * H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。 * 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。 */ void OnTick() { TickContext ctx; if(!GetTickContext(ctx)) return; // 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。 ManageExpiredTrades(); // Existing-position protection stays active even while Python results are pending. ManageSLTPPositions(); // 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。 RecoverTimedOutPythonProcesses(); // H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。 ProcessTrendUpdate(g_ea); // トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。 if(!IsTrendResultReady()) return; RefreshTrendState(g_ea); // H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。 ProcessEntryUpdate(g_ea); // M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。 ProcessM15EntryTimingUpdate(); UpdateStatusComment(ctx); // ここから下は新規注文に関する処理。 if(!IsSpreadAllowed(ctx)) return; if(!IsEntryResultReady()) return; RefreshTargetPrices(g_ea); ProcessEntryDecisionIfNeeded(g_ea, ctx); } //+------------------------------------------------------------------+ //| SLTP manager panel and settings bridge //+------------------------------------------------------------------+ string SLTPBoolText(const bool value) { return value ? "ON" : "OFF"; } void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings) { settings.manager_enabled = input_sltp_manager_enabled; settings.use_breakeven = input_sltp_use_breakeven; settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips; settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips; settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven; settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours; settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips; settings.use_active_trailing = input_sltp_use_active_trailing; settings.active_breakeven_pips = input_sltp_active_breakeven_pips; settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips; settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips; settings.active_step_move_pips = input_sltp_active_step_move_pips; settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop; settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent; settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent; settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit; } bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings, const bool print_summary) { g_sltp_settings_valid = false; g_sltp_manager.SetMagicNumber((ulong)magic_number); g_sltp_manager.SetSymbol(_Symbol); g_sltp_manager.SetDeviationInPoints(slippage); g_sltp_manager.SetBreakevenSettings(settings.use_breakeven, settings.breakeven_trigger_pips, settings.breakeven_buffer_pips); g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven, settings.elapsed_breakeven_hours, settings.elapsed_breakeven_buffer_pips); g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing, settings.active_breakeven_pips, settings.active_stop_loss_offset_pips, settings.active_step_trigger_pips, settings.active_step_move_pips); g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop, settings.tp_progress_trigger_percent, settings.tp_progress_sl_lock_percent); g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit); if(!g_sltp_manager.ValidateSettings()) { Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied."); return false; } g_sltp_settings = settings; g_sltp_settings_valid = true; if(print_summary) { Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled), " BE=", SLTPBoolText(settings.use_breakeven), " ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven), " ActiveTrail=", SLTPBoolText(settings.use_active_trailing), " TPProgress=", SLTPBoolText(settings.use_tp_progress_stop), " HighVol=", SLTPBoolText(settings.use_high_volatility_limit)); } return true; } bool InitializeSLTPManager() { SLTPManagerPanelSettings initial_settings; LoadSLTPInputSettings(initial_settings); if(!ApplySLTPSettings(initial_settings, true)) return false; g_sltp_panel.Init(g_sltp_settings); if(input_sltp_show_panel) { if(!g_sltp_panel.CreatePanel()) { Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings."); return true; } g_sltp_panel.SetInitialValues(); g_sltp_panel_created = true; } return true; } void ManageSLTPPositions() { if(!g_sltp_settings_valid) return; if(!g_sltp_settings.manager_enabled) return; g_sltp_manager.ManagePositions(); g_sltp_manager.HighVolatilityLimit(); } void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(!g_sltp_panel_created) return; SLTPManagerPanelSettings candidate_settings = g_sltp_settings; if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings)) { if(!ApplySLTPSettings(candidate_settings, true)) Print("HIT SLTP panel apply failed. Please review panel values."); } } // Function implementations are kept in project headers so the EA entry points stay compact. #include #include #include #include #include