Harden HIT entry and manager state handling
This commit is contained in:
@@ -134,7 +134,6 @@ ulong slippage = 10;
|
||||
//--- 主要な定数・設定
|
||||
#define POSITION_LIMIT 48
|
||||
#define ENTRY_H1_LIMIT 2 // H1本数(=2時間)
|
||||
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
|
||||
#define HISTORY_BARS 72
|
||||
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
|
||||
#define M15_CONFIRM_BARS 30
|
||||
@@ -375,6 +374,17 @@ void ConfigurePythonGatewayPaths()
|
||||
Print("Python app dir: ", python_app_dir);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
/**
|
||||
* @brief The split entry/manager design requires ticket-based hedging positions.
|
||||
*/
|
||||
bool IsHedgingAccount()
|
||||
{
|
||||
return (AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 起動時の処理
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -391,6 +401,13 @@ int OnInit()
|
||||
magic_number = input_entry_magic_number;
|
||||
slippage = input_slippage_points;
|
||||
|
||||
if(!IsHedgingAccount())
|
||||
{
|
||||
Print("HITEntryEA requires a retail hedging account. account_margin_mode=",
|
||||
AccountInfoInteger(ACCOUNT_MARGIN_MODE));
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
ConfigurePythonGatewayPaths();
|
||||
|
||||
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
|
||||
@@ -459,6 +476,11 @@ void OnTick()
|
||||
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
|
||||
ProcessEntryUpdate(g_ea);
|
||||
|
||||
// Read completed H1 results before spread gating so stale split orders and state updates are not delayed.
|
||||
bool entry_result_ready = IsEntryResultReady();
|
||||
if(entry_result_ready)
|
||||
RefreshTargetPrices(g_ea);
|
||||
|
||||
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
|
||||
ProcessM15EntryTimingUpdate();
|
||||
|
||||
@@ -468,10 +490,9 @@ void OnTick()
|
||||
if(!IsSpreadAllowed(ctx))
|
||||
return;
|
||||
|
||||
if(!IsEntryResultReady())
|
||||
if(!entry_result_ready)
|
||||
return;
|
||||
|
||||
RefreshTargetPrices(g_ea);
|
||||
ProcessEntryDecisionIfNeeded(g_ea, ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,8 +94,6 @@ void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
|
||||
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);
|
||||
@@ -111,13 +109,13 @@ bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
|
||||
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);
|
||||
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())
|
||||
if(settings.manager_enabled && !g_sltp_manager.ValidateSettings())
|
||||
{
|
||||
Print("HIT position manager SLTP settings rejected. Manager is disabled until valid settings are applied.");
|
||||
Print("HIT position manager SLTP settings rejected. Previous valid settings remain active.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -512,14 +512,46 @@ bool IsProcessResultReady(const string done_file, const string running_file, con
|
||||
|
||||
if(!FileIsExist(result_file))
|
||||
{
|
||||
Print("[", label, "] done exists but result file is missing: ", result_file);
|
||||
return false;
|
||||
Print("[", label, "] done exists but result file is missing: ", result_file);
|
||||
DeleteDoneFile(done_file);
|
||||
DeleteRunningFile(running_file);
|
||||
ResetExternalProcessState(process);
|
||||
MarkProcessRetryPending(label);
|
||||
return false;
|
||||
}
|
||||
|
||||
DeleteRunningFile(running_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
/**
|
||||
* @brief Mark a missing-result Python run for immediate retry on the next tick.
|
||||
*/
|
||||
void MarkProcessRetryPending(const string label)
|
||||
{
|
||||
if(label == "trend")
|
||||
{
|
||||
g_ea.trend_state = MARKET_TECHNICAL_ERROR_STOP;
|
||||
g_ea.load_trend_flg = false;
|
||||
g_init_trend_pending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(label == "entry")
|
||||
{
|
||||
g_ea.res_chk = 0;
|
||||
g_ea.zone_res_chk = 0;
|
||||
g_ea.load_target_flg = false;
|
||||
g_bars_H1_check = false;
|
||||
g_bars_M15_check = false;
|
||||
g_ea.chk_cnt = 0;
|
||||
g_init_entry_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Python開始可能状態を返す関数
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
@@ -25,26 +25,6 @@ bool GetTickContext(TickContext &ctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 期限切れ注文・期限切れポジションを処理する関数
|
||||
//+------------------------------------------------------------------+
|
||||
/**
|
||||
* @brief 期限切れの未約定注文と保有ポジションを処理します。
|
||||
*
|
||||
* 未約定注文はENTRY_H1_LIMIT時間、保有ポジションはCLOSE_H1_LIMIT時間を基準に判定します。
|
||||
* 新規注文条件とは独立して、OnTickの早い段階で実行される想定です。
|
||||
*/
|
||||
void ManageExpiredTrades()
|
||||
{
|
||||
CleanupPendingOrderCancelAttempts();
|
||||
|
||||
if(OrdersTotal() > 0)
|
||||
CancelExpiredOrders();
|
||||
|
||||
if(PositionsTotal() > 0)
|
||||
CloseExpiredPositions();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| H4更新検知とトレンド判定Python起動を処理する関数
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
@@ -1068,86 +1068,4 @@ bool CancelExpiredOrders()
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 時間が経過したポジションをクローズする関数
|
||||
//+------------------------------------------------------------------+
|
||||
/**
|
||||
* @brief 実時間でCLOSE_H1_LIMIT時間を超えた保有ポジションをクローズします。
|
||||
*
|
||||
* @return 1件以上クローズに成功した場合はtrue。
|
||||
*
|
||||
* 対象は`_Symbol` と `magic_number` が一致するポジションのみです。
|
||||
*/
|
||||
bool CloseExpiredPositions()
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// ポジションを逆順でループ
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
string position_symbol = PositionGetSymbol(i);
|
||||
if(position_symbol!="")
|
||||
{
|
||||
// Magic Number とシンボルでフィルタリング
|
||||
if(position_symbol != _Symbol)
|
||||
continue;
|
||||
if(PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
// ポジションのエントリー時刻を取得
|
||||
datetime entry_time = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
|
||||
int expiration_seconds = CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1);
|
||||
if(entry_time <= 0 || expiration_seconds <= 0)
|
||||
continue;
|
||||
|
||||
if(TimeCurrent() - entry_time >= expiration_seconds)
|
||||
{
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult trade_result = {};
|
||||
|
||||
// ポジションタイプに応じてリクエストを設定
|
||||
int position_type = (int)PositionGetInteger(POSITION_TYPE);
|
||||
request.action = TRADE_ACTION_DEAL;
|
||||
request.position = PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
|
||||
request.symbol = position_symbol; // シンボル
|
||||
request.volume = PositionGetDouble(POSITION_VOLUME); // ポジションサイズ
|
||||
request.price = (position_type == POSITION_TYPE_BUY)
|
||||
? SymbolInfoDouble(position_symbol, SYMBOL_BID) // BUYの場合はBIDでクローズ
|
||||
: SymbolInfoDouble(position_symbol, SYMBOL_ASK); // SELLの場合はASKでクローズ
|
||||
request.deviation = slippage;
|
||||
request.type = (position_type == POSITION_TYPE_BUY)
|
||||
? ORDER_TYPE_SELL // BUYポジションをSELLでクローズ
|
||||
: ORDER_TYPE_BUY; // SELLポジションをBUYでクローズ
|
||||
request.type_filling = GetOrderFillingPolicy(position_symbol); // 注文執行ポリシー
|
||||
request.magic = magic_number;
|
||||
|
||||
// 注文送信
|
||||
if(!OrderSend(request, trade_result))
|
||||
{
|
||||
Print("Failed to close position. Ticket: ", request.position, " Error: ", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 結果の確認
|
||||
if(trade_result.retcode == TRADE_RETCODE_DONE || trade_result.retcode == TRADE_RETCODE_DONE_PARTIAL)
|
||||
{
|
||||
Print("Position closed successfully due to a time limit. Ticket: ", request.position);
|
||||
result = true; // 少なくとも1つ成功した場合
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to close position. Ticket: ", request.position, " Retcode: ", trade_result.retcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position at index ", i, ". Error: ", GetLastError());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -335,12 +335,14 @@ public:
|
||||
continue;
|
||||
|
||||
double candidate_sl = 0.0;
|
||||
const double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
const double evaluation_price = (type == POSITION_TYPE_BUY) ? tick.bid : tick.ask;
|
||||
if (!CalcHighVolatilitySL(type,
|
||||
evaluation_price,
|
||||
open_m1,
|
||||
open_m3,
|
||||
open_m5,
|
||||
evaluation_price,
|
||||
position_open_price,
|
||||
open_m1,
|
||||
open_m3,
|
||||
open_m5,
|
||||
open_m10,
|
||||
open_m15,
|
||||
pip_size,
|
||||
@@ -590,6 +592,7 @@ private:
|
||||
/// @return いずれかの時間足でしきい値を超え、SL候補を出力した場合は true。
|
||||
bool CalcHighVolatilitySL(const ENUM_POSITION_TYPE type,
|
||||
const double current_price,
|
||||
const double position_open_price,
|
||||
const double open_m1,
|
||||
const double open_m3,
|
||||
const double open_m5,
|
||||
@@ -612,13 +615,36 @@ private:
|
||||
if (!has_candidate)
|
||||
return false;
|
||||
|
||||
if (!IsProfitProtectingStopLoss(type, candidate_sl, position_open_price))
|
||||
return false;
|
||||
|
||||
sl_value = NormalizeDouble(candidate_sl, digits);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief 急変時SL候補が建値より不利にならないことを確認する。
|
||||
bool IsProfitProtectingStopLoss(const ENUM_POSITION_TYPE type,
|
||||
const double candidate_sl,
|
||||
const double open_price)
|
||||
{
|
||||
if (open_price <= 0.0)
|
||||
return false;
|
||||
|
||||
const double point = SymbolInfoDouble(m_symbol, SYMBOL_POINT);
|
||||
const double tolerance = point * 0.1;
|
||||
|
||||
if (type == POSITION_TYPE_BUY)
|
||||
return (candidate_sl >= open_price - tolerance);
|
||||
|
||||
if (type == POSITION_TYPE_SELL)
|
||||
return (candidate_sl <= open_price + tolerance);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief 1本の時間足始値から急変幅を評価し、有効なSL候補なら最良候補へ反映する。
|
||||
void EvaluateHighVolatilityOpen(const ENUM_POSITION_TYPE type,
|
||||
const double current_price,
|
||||
const double current_price,
|
||||
const double open_price,
|
||||
const double limit_pips,
|
||||
const double rate_ratio,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
`HITEntryEA.mq5` is the entry-only Expert Advisor. It runs the H4/H1 Python signal workflow, applies the M15 confirmation rules, and submits pending orders. It does not manage filled positions. Stop management, trailing, and time-based position exits are delegated to `HITPositionManagerEA.mq5`.
|
||||
|
||||
The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` / `input_managed_magic_number`. The operating assumption is a retail hedging account.
|
||||
The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` / `input_managed_magic_number`. The operating assumption is a retail hedging account, and initialization fails on non-hedging accounts.
|
||||
|
||||
## 2. Indicators
|
||||
|
||||
@@ -45,12 +45,14 @@ The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number`
|
||||
- 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.
|
||||
- When the range-breakout guard is enabled, upward breakout warning/confirmation cancels existing T4 Sell Limit orders and blocks new T4 entries until cooldown expiry. Downward breakout warning/confirmation cancels existing T2 Buy Limit orders and blocks new T2 entries.
|
||||
- H1 Python results, candidate timestamps, and stale split-pending cleanup are processed before the spread gate; excessive spread only blocks new order submission.
|
||||
- Filled-position SL updates, trailing, and time-based exits are not performed by this EA.
|
||||
|
||||
## 5. Risk Management
|
||||
|
||||
- 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 a done file exists but the expected result file is missing, the EA clears the done/running state and marks the same workflow for retry on the next tick.
|
||||
- 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.
|
||||
- The range-breakout guard only touches pending orders matching `_Symbol` and `input_entry_magic_number`; upward breakouts cancel T4 Sell Limit only, and downward breakouts cancel T2 Buy Limit only.
|
||||
- `OrderSend` return values and `MqlTradeResult.retcode` are checked and logged.
|
||||
@@ -64,6 +66,7 @@ The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number`
|
||||
|
||||
## 7. Changelog
|
||||
|
||||
- 2026-06-14: Added initialization failure on non-hedging accounts. Moved H1 result loading before spread gating, added retry recovery for done-without-result Python states, and removed the unused filled-position time-exit path from the entry EA side.
|
||||
- 2026-06-13: Connected the range-breakout guard from `HIT-EA_refactor_ver6.mq5` to the entry EA, including T4 Sell Limit retreat on upward breakouts, T2 Buy Limit retreat on downward breakouts, and cooldown-based new-entry blocking.
|
||||
- 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`.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
`HITEntryEA.mq5` は、H4/H1の外部Python判定とM15確認を使って新規pending注文までを実行する発注専用EAです。約定後ポジションのSL移動、トレーリング、時間決済は行わず、同じマジックナンバーを監視する `HITPositionManagerEA.mq5` に委譲します。
|
||||
|
||||
2つのEAは `_Symbol` と `input_entry_magic_number` / `input_managed_magic_number` の一致で連携します。運用口座はhedging口座を前提とします。
|
||||
2つのEAは `_Symbol` と `input_entry_magic_number` / `input_managed_magic_number` の一致で連携します。運用口座はhedging口座を前提とし、非hedging口座では初期化に失敗します。
|
||||
|
||||
## 2. 使用インジケータ
|
||||
|
||||
@@ -45,12 +45,14 @@
|
||||
- pending注文には `input_entry_magic_number` を付与します。
|
||||
- H4状態と矛盾するpending注文、期限切れpending注文、古い分割pending注文は発注EAが取消します。
|
||||
- レンジブレイクガードがONの場合、M15監視足で上方向ブレイク警戒/確定を検出すると既存T4 Sell Limitを取消し、T4新規発注をクールダウン終了まで停止します。下方向ブレイクでは既存T2 Buy Limitを取消し、T2新規発注を停止します。
|
||||
- H1 Python結果の読み込み、候補時刻更新、古い分割pending取消はスプレッド判定より前に実行し、スプレッド超過は新規発注だけを停止します。
|
||||
- 約定後ポジションのSL変更、時間決済、トレーリングは発注EAでは行いません。
|
||||
|
||||
## 5. リスク管理
|
||||
|
||||
- 発注上限は口座全体ではなく `_Symbol` と `input_entry_magic_number` が一致するpending注文 + ポジションで判定します。
|
||||
- Python連携は起動中/完了ファイルとプロセスIDを監視し、二重起動と古い結果の再利用を抑止します。
|
||||
- doneファイルが存在しても結果ファイルが欠落している場合は、done/running状態を破棄し、次tickで同じ処理を再実行できる状態へ戻します。
|
||||
- API由来TPの方向がBuy/Sell条件と逆の場合、EAは方向を補正せず既存の価格整合チェックで発注を見送ります。
|
||||
- レンジブレイクガードは `_Symbol` と `input_entry_magic_number` が一致するpending注文だけを対象にし、上方向ではT4 Sell Limit、下方向ではT2 Buy Limitのみを取消します。
|
||||
- `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時はエラーまたはretcodeをログに出します。
|
||||
@@ -64,6 +66,7 @@
|
||||
|
||||
## 7. 変更履歴
|
||||
|
||||
- 2026-06-14: 非hedging口座での初期化停止を追加。H1結果読み込みをスプレッド判定前へ移動し、doneのみ残るPython不整合時の再実行復旧を追加。発注EA側に残っていた未使用の約定後時間決済経路を削除。
|
||||
- 2026-06-13: `HIT-EA_refactor_ver6.mq5` と同等のレンジブレイクガードを発注EAへ接続。レンジ上抜け時のT4 Sell Limit退避、レンジ下抜け時のT2 Buy Limit退避、およびクールダウン中の新規発注停止を反映。
|
||||
- 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` へ移管する仕様を追加。
|
||||
|
||||
@@ -41,6 +41,7 @@ The managed set is limited to positions whose `POSITION_SYMBOL` equals `_Symbol`
|
||||
- On every tick, the EA first evaluates ticket-based time exits and then applies SLTP management.
|
||||
- Time exits close target tickets when `POSITION_TIME` is older than `input_position_close_after_h1_bars * PeriodSeconds(PERIOD_H1)` by using `CTrade::PositionClose(ticket)`.
|
||||
- SLTP management applies only candidates that improve the current SL in the profit-protection direction, preserving the current TP with `CTrade::PositionModify(ticket, new_sl, current_tp)`.
|
||||
- High-volatility stop tightening only accepts candidates that are at or beyond breakeven: at or above entry for BUY positions and at or below entry for SELL positions.
|
||||
|
||||
## 5. Risk Management
|
||||
|
||||
@@ -49,6 +50,7 @@ The managed set is limited to positions whose `POSITION_SYMBOL` equals `_Symbol`
|
||||
- Different magic numbers, different symbols, and manual-position equivalents are ignored.
|
||||
- Logs include ticket, symbol, magic, position type, trade retcode, and `GetLastError()`.
|
||||
- Standard breakeven and active trailing cannot be enabled together; settings validation rejects that conflict.
|
||||
- When `input_sltp_manager_enabled=false`, contradictory detailed SLTP settings do not stop the EA; time exits continue to run. Detailed settings are validated when SLTP management is enabled.
|
||||
|
||||
## 6. Unit Test Scope
|
||||
|
||||
@@ -58,5 +60,6 @@ The managed set is limited to positions whose `POSITION_SYMBOL` equals `_Symbol`
|
||||
|
||||
## 7. Changelog
|
||||
|
||||
- 2026-06-14: Allowed the EA to continue time-exit management when SLTP master is off even if detailed SLTP settings conflict. Added breakeven protection to high-volatility stop tightening so loss-side SL candidates are discarded.
|
||||
- 2026-06-13: Synchronized SLTP input defaults with `HIT-EA_refactor_ver6.mq5` and documented each default value.
|
||||
- 2026-06-07: Split position-management responsibilities from `HIT-EA_refactor_ver6.mq5` and defined a hedging-account, ticket-based manager EA.
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
- `OnTick()` では、まずticket単位で保有時間決済を評価し、その後SLTP管理を実行します。
|
||||
- 時間決済は `POSITION_TIME` から `input_position_close_after_h1_bars * PeriodSeconds(PERIOD_H1)` 以上経過した対象ticketを `CTrade::PositionClose(ticket)` で閉じます。
|
||||
- SLTP管理は、対象ticketの現在SLより利益保護方向へ改善する候補だけを `CTrade::PositionModify(ticket, new_sl, current_tp)` で反映します。
|
||||
- 急変時SL引き締めは、BUYでは建値以上、SELLでは建値以下となる候補だけを採用し、損失側へのSL候補は破棄します。
|
||||
|
||||
## 5. リスク管理
|
||||
|
||||
@@ -49,6 +50,7 @@
|
||||
- magic違い、symbol違い、手動ポジション相当には触れません。
|
||||
- ログにはticket、symbol、magic、position type、retcode、`GetLastError()` を含めます。
|
||||
- 通常ブレークイーブンとアクティブトレーリングの同時ONは設定検証で拒否します。
|
||||
- `input_sltp_manager_enabled=false` の場合、SLTP詳細設定に矛盾があってもEA全体は停止せず、時間決済を継続します。SLTP管理をONにする時点で詳細設定を検証します。
|
||||
|
||||
## 6. 単体テスト
|
||||
|
||||
@@ -58,5 +60,6 @@
|
||||
|
||||
## 7. 変更履歴
|
||||
|
||||
- 2026-06-14: SLTPマスターOFF時は詳細設定の矛盾でEA全体を停止しないよう変更。急変時SL引き締めに建値保護条件を追加し、損失側SL候補を採用しないようにした。
|
||||
- 2026-06-13: SLTP関連inputの既定値を `HIT-EA_refactor_ver6.mq5` と同じ初期状態に同期し、仕様書へ各既定値を明記。
|
||||
- 2026-06-07: `HIT-EA_refactor_ver6.mq5` からポジション管理責務を分離し、hedging口座専用のticket単位管理EAとして新規定義。
|
||||
|
||||
Reference in New Issue
Block a user