From f9012e19e2f947e6a3cdb96c58c5aa1020da1067 Mon Sep 17 00:00:00 2001 From: Hiroaki86 Date: Sat, 13 Jun 2026 11:58:49 +0900 Subject: [PATCH] Expand API-derived TP distances --- Experts/MyProject/HIT-EA_refactor_ver6.mq5 | 3 + Experts/MyProject/HITEntryEA.mq5 | 20 +++ Include/MyLib/Signals/HITEntrySignal.mqh | 182 +++++++++++++++++++-- docs/MyProject/HIT-EA_spec_en.md | 7 + docs/MyProject/HIT-EA_spec_ja.md | 7 + docs/MyProject/HITEntryEA_spec_en.md | 7 + docs/MyProject/HITEntryEA_spec_ja.md | 7 + 7 files changed, 218 insertions(+), 15 deletions(-) diff --git a/Experts/MyProject/HIT-EA_refactor_ver6.mq5 b/Experts/MyProject/HIT-EA_refactor_ver6.mq5 index f308c27..a49fbeb 100644 --- a/Experts/MyProject/HIT-EA_refactor_ver6.mq5 +++ b/Experts/MyProject/HIT-EA_refactor_ver6.mq5 @@ -117,6 +117,9 @@ 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 = 120; // H1候補価格を新規発注に使う最大経過分数 +input double input_tp_multiplier = 1.25; // TP distance multiplier (1.0=no expansion) +input int input_min_tp_points = 0; // Minimum TP distance in points (0=disabled) +input int input_max_tp_points = 0; // Maximum expanded TP distance in points (0=disabled) input bool input_range_breakout_guard_enabled = true; // レンジ上抜け/下抜け時に逆張りLimitを退避 input ENUM_TIMEFRAMES input_range_breakout_guard_timeframe = PERIOD_M15; // レンジブレイク監視足 input int input_range_breakout_lookback_bars = 20; // レンジ高値安値の参照本数 diff --git a/Experts/MyProject/HITEntryEA.mq5 b/Experts/MyProject/HITEntryEA.mq5 index 27e4eec..3418dab 100644 --- a/Experts/MyProject/HITEntryEA.mq5 +++ b/Experts/MyProject/HITEntryEA.mq5 @@ -115,6 +115,9 @@ 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 = 120; // H1候補価格を新規発注に使う最大経過分数 +input double input_tp_multiplier = 1.25; // TP distance multiplier (1.0=no expansion) +input int input_min_tp_points = 0; // Minimum TP distance in points (0=disabled) +input int input_max_tp_points = 0; // Maximum expanded TP distance in points (0=disabled) // Existing shared HIT include files read these runtime globals. int magic_number = 10001; @@ -146,6 +149,10 @@ ulong slippage = 10; #define MARKET_HIGH_VOL_DOWN 5 #define MARKET_TECHNICAL_ERROR_STOP 6 +#define RANGE_BREAKOUT_NONE 0 +#define RANGE_BREAKOUT_UP 1 +#define RANGE_BREAKOUT_DOWN -1 + //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ @@ -193,6 +200,19 @@ bool g_bars_M15_check = false; ulong g_cancel_retry_tickets[]; datetime g_cancel_retry_at[]; +// Compatibility settings for the shared trade manager. +// HITEntryEA does not run the range-breakout monitor, so the guard remains disabled. +bool input_range_breakout_guard_enabled = false; +ENUM_TIMEFRAMES input_range_breakout_guard_timeframe = PERIOD_M15; +int input_range_breakout_lookback_bars = 20; +double input_range_breakout_max_width_multiplier = 6.0; +double input_range_breakout_buffer_multiplier = 0.20; +double input_range_breakout_near_multiplier = 0.50; +double input_range_breakout_body_multiplier = 1.50; +int input_range_breakout_cooldown_bars = 4; +int g_range_breakout_guard_direction = RANGE_BREAKOUT_NONE; +datetime g_range_breakout_guard_until = 0; + // ティックごとの価格情報 struct TickContext { diff --git a/Include/MyLib/Signals/HITEntrySignal.mqh b/Include/MyLib/Signals/HITEntrySignal.mqh index 021de45..3d383f8 100644 --- a/Include/MyLib/Signals/HITEntrySignal.mqh +++ b/Include/MyLib/Signals/HITEntrySignal.mqh @@ -1,6 +1,131 @@ #ifndef HIT_ENTRY_SIGNAL_MQH #define HIT_ENTRY_SIGNAL_MQH +//+------------------------------------------------------------------+ +//| TP expansion settings +//+------------------------------------------------------------------+ +double EffectiveTpMultiplier() + { + double multiplier = input_tp_multiplier; + if(multiplier < 1.0) + multiplier = 1.0; + if(multiplier > 100.0) + multiplier = 100.0; + + return multiplier; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +double EffectiveMinTpPoints() + { + if(input_min_tp_points <= 0) + return 0.0; + + return (double)input_min_tp_points; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +double EffectiveMaxTpPoints() + { + if(input_max_tp_points <= 0) + return 0.0; + + return (double)input_max_tp_points; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool IsBuyTargetOrderType(const int orderType) + { + return (orderType == 1 || orderType == 2); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool IsSellTargetOrderType(const int orderType) + { + return (orderType == 3 || orderType == 4); + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool IsTakeProfitDirectionValid(const int orderType, const double en, const double tp) + { + if(IsBuyTargetOrderType(orderType)) + return (tp > en); + if(IsSellTargetOrderType(orderType)) + return (tp < en); + + return false; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +double ExpandedTakeProfitPrice(const int orderType, const double en, const double api_tp) + { + int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); + double normalized_api_tp = NormalizeDouble(api_tp, digits); + + if(en <= 0.0 || api_tp <= 0.0) + return normalized_api_tp; + + if(!IsTakeProfitDirectionValid(orderType, en, api_tp)) + { + Print("[TP Adjust Skip] invalid API TP direction. orderType=", orderType, + " en=", en, " api_tp=", api_tp); + return normalized_api_tp; + } + + double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); + if(point <= 0.0) + point = Point(); + if(point <= 0.0) + return normalized_api_tp; + + double base_points = MathAbs(api_tp - en) / point; + if(base_points <= 0.0) + return normalized_api_tp; + + double final_points = base_points * EffectiveTpMultiplier(); + double min_points = EffectiveMinTpPoints(); + double max_points = EffectiveMaxTpPoints(); + + if(min_points > 0.0 && final_points < min_points) + final_points = min_points; + if(max_points > 0.0 && final_points > max_points) + final_points = max_points; + + // Never make the final target closer than the API-provided TP. + if(final_points < base_points) + final_points = base_points; + + double final_tp = 0.0; + if(IsBuyTargetOrderType(orderType)) + final_tp = en + final_points * point; + else + final_tp = en - final_points * point; + + final_tp = NormalizeDouble(final_tp, digits); + if(MathAbs(final_tp - normalized_api_tp) >= point * 0.5) + Print("[TP Adjust] orderType=", orderType, + " en=", en, + " api_tp=", normalized_api_tp, + " final_tp=", final_tp, + " base_points=", DoubleToString(base_points, 1), + " final_points=", DoubleToString(final_points, 1), + " multiplier=", DoubleToString(EffectiveTpMultiplier(), 2)); + + return final_tp; + } + //| エントリー判定が必要な場合のみ注文処理を実行する関数 //+------------------------------------------------------------------+ /** @@ -302,6 +427,19 @@ double SplitEntryPrice(const double zone_low, const double zone_high, const int return NormalizeDouble(zone_low + (zone_high - zone_low) * ratio, digits); } +//+------------------------------------------------------------------+ +//| Split-zone TP reference price +//+------------------------------------------------------------------+ +double SplitTakeProfitReferenceEntry(const int orderType, const double zone_low, const double zone_high) + { + if(IsBuyTargetOrderType(orderType)) + return zone_high; + if(IsSellTargetOrderType(orderType)) + return zone_low; + + return (zone_low + zone_high) / 2.0; + } + //+------------------------------------------------------------------+ //| 注文ロットがブローカー制約を満たすか判定する関数 //+------------------------------------------------------------------+ @@ -462,13 +600,17 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct double zone_low = state.zone_low[orderType]; double zone_high = state.zone_high[orderType]; - double tp = state.zone_tp[orderType]; + double raw_tp = state.zone_tp[orderType]; + double tp = ExpandedTakeProfitPrice(orderType, + SplitTakeProfitReferenceEntry(orderType, zone_low, zone_high), + raw_tp); double sl = state.zone_sl[orderType]; if(!HasValidZonePrices(zone_low, zone_high, tp, sl)) { Print("[Split Skip] invalid target zone. orderType=", orderType, - " zone=", zone_low, "-", zone_high, " tp=", tp, " sl=", sl, + " zone=", zone_low, "-", zone_high, + " api_tp=", raw_tp, " tp=", tp, " sl=", sl, " candidate_id=", state.zone_candidate_id); return 0; } @@ -514,29 +656,34 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct } double en = SplitEntryPrice(zone_low, zone_high, slot, split_count); - if(!IsTargetPriceOrderConditionMatched(orderType, ctx, en, tp, sl)) + double slot_tp = ExpandedTakeProfitPrice(orderType, en, raw_tp); + if(!IsTargetPriceOrderConditionMatched(orderType, ctx, en, slot_tp, sl)) { Print("[Split Skip] slot price no longer valid. key=", slot_key, - " cur=", cur_price, " en=", en, " tp=", tp, " sl=", sl); + " cur=", cur_price, " en=", en, + " api_tp=", raw_tp, " tp=", slot_tp, " sl=", sl); continue; } - if(!MeetsTradeDistanceRules(orderType, ctx, en, tp, sl)) + if(!MeetsTradeDistanceRules(orderType, ctx, en, slot_tp, sl)) continue; Print("[Split ", entry_type, " Order Try] key=", slot_key, - " en=", en, " tp=", tp, " sl=", sl, " volume=", volume); + " en=", en, " api_tp=", raw_tp, " tp=", slot_tp, + " sl=", sl, " volume=", volume); - if(SendOrder(orderType, en, tp, sl, volume, slot_key, TargetCandidateReferenceTime(state))) + if(SendOrder(orderType, en, slot_tp, sl, volume, slot_key, TargetCandidateReferenceTime(state))) { Print("[Split ", entry_type, " Order Sent] key=", slot_key, - " en=", en, " tp=", tp, " sl=", sl, " volume=", volume); + " en=", en, " api_tp=", raw_tp, " tp=", slot_tp, + " sl=", sl, " volume=", volume); sent_success++; } else { Print("[Split ", entry_type, " Order Failed] key=", slot_key, - " en=", en, " tp=", tp, " sl=", sl, " volume=", volume); + " en=", en, " api_tp=", raw_tp, " tp=", slot_tp, + " sl=", sl, " volume=", volume); } } @@ -566,13 +713,14 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx) } double en = state.en_price[orderType]; - double tp = state.tp_price[orderType]; + double raw_tp = state.tp_price[orderType]; + double tp = ExpandedTakeProfitPrice(orderType, en, raw_tp); double sl = state.sl_price[orderType]; if(!HasValidTargetPrices(en, tp, sl)) { Print("[Skip] invalid target prices. orderType=", orderType, - " en=", en, " tp=", tp, " sl=", sl, + " en=", en, " api_tp=", raw_tp, " tp=", tp, " sl=", sl, " candidate_age=", TargetCandidateAgeText(state)); return false; } @@ -580,7 +728,8 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx) bool ok = IsTargetPriceOrderConditionMatched(orderType, ctx, en, tp, sl); if(!ok) { - Print("[No ", entry_type, "] cur=", cur_price, " en=", en, " tp=", tp, " sl=", sl, + Print("[No ", entry_type, "] cur=", cur_price, " en=", en, + " api_tp=", raw_tp, " tp=", tp, " sl=", sl, " candidate_age=", TargetCandidateAgeText(state)); return false; } @@ -596,16 +745,19 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx) if(!MeetsTradeDistanceRules(orderType, ctx, en, tp, sl)) return false; - Print("[", entry_type, " Order Try at ", cur_price, "] en=", en, " tp=", tp, " sl=", sl); + Print("[", entry_type, " Order Try at ", cur_price, "] en=", en, + " api_tp=", raw_tp, " tp=", tp, " sl=", sl); if(SendOrder(orderType, en, tp, sl, lot_size, TargetCandidateCommentSuffix(state), TargetCandidateReferenceTime(state))) { - Print("[", entry_type, " Order Sent] ticket ok. en=", en, " tp=", tp, " sl=", sl); + Print("[", entry_type, " Order Sent] ticket ok. en=", en, + " api_tp=", raw_tp, " tp=", tp, " sl=", sl); return true; } - Print("[", entry_type, " Order Failed] en=", en, " tp=", tp, " sl=", sl); + Print("[", entry_type, " Order Failed] en=", en, + " api_tp=", raw_tp, " tp=", tp, " sl=", sl); return false; } diff --git a/docs/MyProject/HIT-EA_spec_en.md b/docs/MyProject/HIT-EA_spec_en.md index 4d625f1..faff4b8 100644 --- a/docs/MyProject/HIT-EA_spec_en.md +++ b/docs/MyProject/HIT-EA_spec_en.md @@ -37,6 +37,9 @@ - `m15_imbalance_min_avg_body_points = 1.0`: Minimum M15 average body in points. - `use_m15_imbalance_debug_log = false`: Enables detailed M15 impulse-confirmation logs. - `input_entry_max_candidate_age_minutes = 120`: Maximum age, in minutes, for using an H1 candidate for new execution. This blocks delayed entries when M15 confirmation appears too late. +- `input_tp_multiplier = 1.25`: Expands the API TP distance from the entry price. Values below `1.0` are clamped to `1.0`, and values above `100.0` are clamped to `100.0`. +- `input_min_tp_points = 0`: Minimum final TP distance in points. `0` disables the floor. +- `input_max_tp_points = 0`: Maximum expanded TP distance in points. `0` disables the cap. The EA never makes the final TP closer than the API-provided TP distance. - `input_range_breakout_guard_enabled = true`: Cancels adverse reversal Limit orders during range breakouts and temporarily blocks new ones. - `input_range_breakout_guard_timeframe = PERIOD_M15`: Timeframe used by the range-breakout monitor. - `input_range_breakout_lookback_bars = 20`: Closed-bar count used for range high/low and average range. The range starts from the bar before the latest closed bar. @@ -156,6 +159,8 @@ New entries are allowed only when all conditions below are satisfied: - The H1 candidate set has not exceeded `input_entry_max_candidate_age_minutes`, measured from the closed H1 bar time that produced the candidate. - The selected order type has valid `entry/tp/sl` values greater than `0.0`. - The order type is allowed by the H4 `market_state`. +- Before price-consistency and broker-distance checks, TP is recalculated from the distance between entry and the API TP, multiplied by `input_tp_multiplier`. Buy strategies place the final TP above entry, and Sell strategies place it below entry. +- When split entries are enabled, the final TP is recalculated separately for each slot from that slot's entry price. - The order-type price relationship and broker minimum distance rules are satisfied. - When `use_m15_entry_filter = true`, T2/T4 satisfy the M15 direction, rejection, and proximity checks. T1/T3 satisfy M15 impulse confirmation when `use_m15_imbalance_confirmation = true`. - When `input_range_breakout_guard_enabled = true`, T4 Sell Limit is blocked during an upward range-breakout cooldown and T2 Buy Limit is blocked during a downward range-breakout cooldown. @@ -218,6 +223,7 @@ After an H4 `market_state` reload, the EA cancels existing pending orders whose - Single and split order comments keep a valid `candidate_id` for candidate-origin expiration handling. - Split-entry order comments also include order type and slot number to prevent duplicate execution of the same strategy slot. - When `cancel_old_split_pending_on_new_zone = true`, a new valid `candidate_id` cancels older split pending orders, and an invalid or stopped `target_zones.txt` cancels all existing split pending orders for this EA/symbol/magic. +- If the API TP direction contradicts the Buy/Sell price rules, the EA does not repair it; the existing price-consistency checks skip the order. - After an H4 state update, existing pending orders that contradict the refreshed `market_state` are cancelled. - The range-breakout guard only targets pending orders matching `_Symbol` and `magic_number`; upward breakouts cancel T4 Sell Limit only, and downward breakouts cancel T2 Buy Limit only. - A failed pending-order cancellation is not retried for the same ticket until `input_cancel_retry_cooldown_seconds` has elapsed, preventing excessive per-tick trade-server requests. @@ -241,6 +247,7 @@ After an H4 `market_state` reload, the EA cancels existing pending orders whose - Added a range-breakout guard that retreats adverse reversal Limit orders. Upward breakouts cancel existing T4 Sell Limit orders and temporarily block new T4 entries; downward breakouts cancel existing T2 Buy Limit orders and temporarily block new T2 entries. - Added guard inputs for monitor timeframe, lookback bars, range-width multiplier, breakout buffer, proximity band, momentum body multiple, and cooldown bars. +- Added `input_tp_multiplier`, `input_min_tp_points`, and `input_max_tp_points` to expand API-derived TP distances for both standard orders and per-slot split entries. ### 2026-06-06 diff --git a/docs/MyProject/HIT-EA_spec_ja.md b/docs/MyProject/HIT-EA_spec_ja.md index 4c2d62c..e63e4c7 100644 --- a/docs/MyProject/HIT-EA_spec_ja.md +++ b/docs/MyProject/HIT-EA_spec_ja.md @@ -29,6 +29,9 @@ - `m15_imbalance_min_avg_body_points = 1.0`: M15平均実体の最小値(point)。 - `use_m15_imbalance_debug_log = false`: M15初動確認の詳細ログを出すか。 - `input_entry_max_candidate_age_minutes = 120`: H1候補価格を新規発注に使用できる最大経過分数。古い候補でM15条件が後から整った場合の遅延エントリーを抑止する。 +- `input_tp_multiplier = 1.25`: APIから取得したTP距離を、エントリー価格からの距離ベースで拡大する倍率。`1.0` 未満は `1.0`、`100.0` 超は `100.0` に丸める。 +- `input_min_tp_points = 0`: 拡大後TP距離の最小値(point)。`0` の場合は無効化する。 +- `input_max_tp_points = 0`: 拡大後TP距離の最大値(point)。`0` の場合は無効化する。API由来TPより近くなる場合は縮小せず、API距離を維持する。 - `input_range_breakout_guard_enabled = true`: レンジ上抜け/下抜け時に逆方向の逆張りLimit注文を退避し、新規発注も一時停止するか。 - `input_range_breakout_guard_timeframe = PERIOD_M15`: レンジブレイクを監視する時間足。 - `input_range_breakout_lookback_bars = 20`: レンジ高値・安値と平均レンジを計算する確定足本数。直近確定足の1本前から参照する。 @@ -156,6 +159,8 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて - H1候補価格が、元になったH1確定足時刻から `input_entry_max_candidate_age_minutes` 分を超えていない。 - 対象注文タイプの `entry/tp/sl` がすべて `0.0` より大きい。 - H4 `market_state` に対して注文タイプが許可されている。 +- TPは価格整合条件とブローカー距離制約の判定前に、APIのTP価格そのものではなく「エントリー価格からAPI TPまでの距離」を `input_tp_multiplier` で拡大して最終TPへ変換する。Buy系はエントリーより上、Sell系はエントリーより下へ配置する。 +- 分割エントリー有効時は、slotごとのエントリー価格を基準に各slotの最終TPを個別に計算する。 - 注文タイプごとの価格整合条件とブローカー最小距離制約を満たす。 - `use_m15_entry_filter = true` の場合、T2/T4はM15確定足の方向・反発・接近条件を満たす。T1/T3は `use_m15_imbalance_confirmation = true` の場合にM15初動確認を満たす。 - `input_range_breakout_guard_enabled = true` の場合、レンジ上抜け後のT4 Sell Limit、レンジ下抜け後のT2 Buy Limitはクールダウン終了まで新規発注しない。 @@ -218,6 +223,7 @@ H4 `market_state` の再読込後は、更新後の状態で許可されない - 通常注文と分割注文のコメントには有効な `candidate_id` を入れ、候補時刻起点の期限管理に使用する。 - 分割エントリーの注文コメントには注文タイプとslot番号も入れ、同一戦略slotの二重発注を抑止する。 - `cancel_old_split_pending_on_new_zone = true` の場合、新しい有効 `candidate_id` を読んだ時は旧candidateの分割pending注文を取消し、`target_zones.txt` が無効または停止値の場合は既存の分割pending注文をすべて取消する。 +- API由来TPの方向がBuy/Sell条件と逆の場合、EAは方向を補正せず既存の価格整合チェックで発注を見送る。 - H4状態更新後は、更新後の `market_state` と矛盾する既存pending注文を取消する。 - レンジブレイクガードは `_Symbol` と `magic_number` が一致するpending注文だけを対象にし、上方向ブレイクではT4 Sell Limit、下方向ブレイクではT2 Buy Limitのみを取消する。 - pending取消に失敗したticketは `input_cancel_retry_cooldown_seconds` の間再送せず、毎tickの過剰な取引サーバー要求を防止する。 @@ -241,6 +247,7 @@ H4 `market_state` の再読込後は、更新後の状態で許可されない - レンジ上抜け/下抜け時に逆方向の逆張りLimitを退避するレンジブレイクガードを追加した。上方向ブレイクでは既存T4 Sell Limitを取消してT4新規発注を一時停止し、下方向ブレイクでは既存T2 Buy Limitを取消してT2新規発注を一時停止する。 - ガード用inputとして、監視時間足、参照本数、レンジ幅倍率、ブレイクバッファ、接近幅、勢い判定倍率、クールダウン本数を追加した。 +- API由来TPをエントリー価格からの距離ベースで拡大する `input_tp_multiplier`, `input_min_tp_points`, `input_max_tp_points` を追加し、通常注文と分割slotごとの最終TP計算に反映した。 ### 2026-06-06 diff --git a/docs/MyProject/HITEntryEA_spec_en.md b/docs/MyProject/HITEntryEA_spec_en.md index a5becbc..656836a 100644 --- a/docs/MyProject/HITEntryEA_spec_en.md +++ b/docs/MyProject/HITEntryEA_spec_en.md @@ -25,10 +25,15 @@ The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` - `input_cancel_retry_cooldown_seconds = 60`: Ticket-level retry cooldown after pending cancellation failures. - `use_m15_entry_filter = true`: Enables M15 closed-bar confirmation. - `input_entry_max_candidate_age_minutes = 120`: Maximum age for using an H1 candidate for new execution. +- `input_tp_multiplier = 1.25`: Expands the API TP distance from the entry price. Values below `1.0` are clamped to `1.0`, and values above `100.0` are clamped to `100.0`. +- `input_min_tp_points = 0`: Minimum final TP distance in points. `0` disables the floor. +- `input_max_tp_points = 0`: Maximum expanded TP distance in points. `0` disables the cap. The EA never makes the final TP closer than the API-provided TP distance. ## 4. Entry And Exit Conditions - New pending orders are sent only after spread, H4 state, H1 candidate, M15 timing, price consistency, broker distance, volume, and same-symbol/same-magic limit checks pass. +- Before order submission, TP is recalculated from the distance between entry and the API TP, multiplied by `input_tp_multiplier`. Buy strategies place the final TP above entry, and Sell strategies place it below entry. +- Split entries recalculate the final TP separately for each slot, using that slot's entry price. - Pending orders receive `input_entry_magic_number`. - The entry EA cancels expired pending orders, pending orders that conflict with the refreshed H4 state, and stale split-entry pending orders. - Filled-position SL updates, trailing, and time-based exits are not performed by this EA. @@ -37,6 +42,7 @@ The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` - The order limit counts only pending orders and positions matching `_Symbol` and `input_entry_magic_number`. - Python process markers, process IDs, done files, and timeouts are monitored to prevent duplicate launches and stale-result reuse. +- If the API TP direction contradicts the Buy/Sell price rules, the EA does not repair it; the existing price-consistency checks skip the order. - `OrderSend` return values and `MqlTradeResult.retcode` are checked and logged. - Because the design assumes hedging accounts, per-ticket position management is handled by `HITPositionManagerEA.mq5`. @@ -48,4 +54,5 @@ The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` ## 7. Changelog +- 2026-06-13: Added `input_tp_multiplier`, `input_min_tp_points`, and `input_max_tp_points` to expand API-derived TP distances for both standard orders and per-slot split entries. - 2026-06-07: Split entry responsibilities from `HIT-EA_refactor_ver6.mq5`; moved SLTP panel and filled-position management responsibilities to `HITPositionManagerEA.mq5`. diff --git a/docs/MyProject/HITEntryEA_spec_ja.md b/docs/MyProject/HITEntryEA_spec_ja.md index 6b20852..104cd2c 100644 --- a/docs/MyProject/HITEntryEA_spec_ja.md +++ b/docs/MyProject/HITEntryEA_spec_ja.md @@ -25,10 +25,15 @@ - `input_cancel_retry_cooldown_seconds = 60`: pending取消失敗後のticket単位再試行間隔。 - `use_m15_entry_filter = true`: M15確定足確認を使うか。 - `input_entry_max_candidate_age_minutes = 120`: H1候補を新規発注に使える最大経過分数。 +- `input_tp_multiplier = 1.25`: APIから取得したTP距離を、エントリー価格からの距離ベースで拡大する倍率。`1.0` 未満は `1.0`、`100.0` 超は `100.0` に丸めます。 +- `input_min_tp_points = 0`: 拡大後TP距離の最小値(point)。`0` の場合は無効です。 +- `input_max_tp_points = 0`: 拡大後TP距離の最大値(point)。`0` の場合は無効です。ただしAPI由来TPより近くなる場合は縮小せず、API距離を維持します。 ## 4. エントリー/エグジット条件 - 新規注文はスプレッド、H4状態、H1候補、M15確認、価格整合、ブローカー距離、ロット制約、同一symbol/magicの上限を満たす場合のみ送信します。 +- TPは注文送信前に、APIのTP価格そのものではなく「エントリー価格からAPI TPまでの距離」を `input_tp_multiplier` で拡大して最終TPを計算します。Buy系はエントリーより上、Sell系はエントリーより下へ再配置します。 +- 分割エントリーではslotごとのエントリー価格を基準に、各slotの最終TPを個別に計算します。 - pending注文には `input_entry_magic_number` を付与します。 - H4状態と矛盾するpending注文、期限切れpending注文、古い分割pending注文は発注EAが取消します。 - 約定後ポジションのSL変更、時間決済、トレーリングは発注EAでは行いません。 @@ -37,6 +42,7 @@ - 発注上限は口座全体ではなく `_Symbol` と `input_entry_magic_number` が一致するpending注文 + ポジションで判定します。 - Python連携は起動中/完了ファイルとプロセスIDを監視し、二重起動と古い結果の再利用を抑止します。 +- API由来TPの方向がBuy/Sell条件と逆の場合、EAは方向を補正せず既存の価格整合チェックで発注を見送ります。 - `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時はエラーまたはretcodeをログに出します。 - hedging口座前提のため、約定後の複数ticket管理は `HITPositionManagerEA.mq5` が担当します。 @@ -48,4 +54,5 @@ ## 7. 変更履歴 +- 2026-06-13: API由来TPをエントリー価格からの距離ベースで拡大する `input_tp_multiplier`, `input_min_tp_points`, `input_max_tp_points` を追加し、通常注文と分割slotごとの最終TP計算に反映。 - 2026-06-07: `HIT-EA_refactor_ver6.mq5` から発注責務を分離し、SLTPパネルとポジション管理を `HITPositionManagerEA.mq5` へ移管する仕様を追加。