//+------------------------------------------------------------------+ //| HITPositionManagerEA.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.00" #include #include #include // This EA never opens new positions. It manages hedging-account tickets created by HITEntryEA. input int input_managed_magic_number = 10001; // 管理対象のマジックナンバー input ulong input_slippage_points = 10; // 決済/SL変更の許容偏差(point) input int input_position_close_after_h1_bars = 12; // 保有時間決済(H1本数、0で無効) 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引き締めを有効化 CSLTPManager g_sltp_manager; CSLTPManagerPanel g_sltp_panel; SLTPManagerPanelSettings g_sltp_settings; CHITPositionLifecycleManager g_position_lifecycle; bool g_sltp_settings_valid = false; bool g_sltp_panel_created = false; int EffectiveCloseAfterSeconds() { int close_bars = input_position_close_after_h1_bars; if(close_bars < 0) close_bars = 0; if(close_bars > 240) close_bars = 240; const int h1_seconds = PeriodSeconds(PERIOD_H1); if(close_bars <= 0 || h1_seconds <= 0) return 0; return close_bars * h1_seconds; } bool IsHedgingAccount() { return (AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING); } 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)input_managed_magic_number); g_sltp_manager.SetSymbol(_Symbol); g_sltp_manager.SetDeviationInPoints(input_slippage_points); 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 position manager 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 position manager 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), " magic=", input_managed_magic_number); } 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 position manager SLTP panel is unavailable. EA continues with input-based settings."); return true; } g_sltp_panel.SetInitialValues(); g_sltp_panel_created = true; } return true; } bool InitializePositionLifecycleManager() { return g_position_lifecycle.Init(_Symbol, (ulong)input_managed_magic_number, input_slippage_points, EffectiveCloseAfterSeconds()); } void ManageTargetPositions() { g_position_lifecycle.SetCloseAfterSeconds(EffectiveCloseAfterSeconds()); g_position_lifecycle.CloseExpiredPositions(); if(!g_sltp_settings_valid) return; if(!g_sltp_settings.manager_enabled) return; g_sltp_manager.ManagePositions(); g_sltp_manager.HighVolatilityLimit(); } int OnInit() { if(!IsHedgingAccount()) { Print("HITPositionManagerEA requires a retail hedging account. account_margin_mode=", AccountInfoInteger(ACCOUNT_MARGIN_MODE)); return INIT_FAILED; } if(!InitializePositionLifecycleManager()) return INIT_FAILED; if(!InitializeSLTPManager()) return INIT_FAILED; return INIT_SUCCEEDED; } void OnDeinit(const int reason) { if(g_sltp_panel_created) g_sltp_panel.Destroy(reason); Comment(""); ChartRedraw(0); } void OnTick() { ManageTargetPositions(); } 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 position manager panel apply failed. Please review panel values."); } }