Harden HIT entry and manager state handling

This commit is contained in:
Hiroaki86
2026-06-14 22:02:17 +09:00
parent 7b11d44d66
commit 52067c1973
10 changed files with 107 additions and 120 deletions
+34 -2
View File
@@ -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起動を処理する関数
//+------------------------------------------------------------------+
-82
View File
@@ -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
+31 -5
View File
@@ -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,