Add daily loss force-flatten at configurable equity limit

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-03 12:42:13 +08:00
parent b6c3266a9e
commit 2081bf2da9
17 changed files with 850 additions and 97 deletions
+31 -3
View File
@@ -2463,6 +2463,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn,
active_count=_effective_active_position_count(conn, mode),
equity=capital,
mode=mode,
get_setting=get_setting,
)
margin_used = (
ctp_account_margin_used(mode) if ctp_st.get("connected") else None
@@ -2496,6 +2498,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn,
active_count=_effective_active_position_count(conn, mode),
equity=capital,
mode=mode,
get_setting=get_setting,
)
syncing = bool(ctp_st.get("connected") or ctp_st.get("connecting"))
payload = {
@@ -2858,6 +2862,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn, mode, ctp_connected=connected,
),
equity=capital,
mode=mode,
get_setting=get_setting,
)
ctp_acc = _ctp_account(mode) if connected else {}
bootstrap_live = position_hub.get_snapshot()
@@ -3270,7 +3276,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
execute_order(
conn, mode=mode, offset=offset, symbol=sym, direction=direction,
lots=lots, price=price, settings=_settings_dict(),
order_type="market",
order_type="market", urgency="stop_loss",
)
mark_close_pending(sym, direction)
# 始终写本地记录:CTP 同步依赖内存开平配对,重启后或成交回报延迟时会漏记
@@ -3795,6 +3801,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn,
active_count=_effective_active_position_count(conn, mode),
equity=_capital(conn),
mode=mode,
get_setting=get_setting,
)
if err:
conn.close()
@@ -4099,6 +4107,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn,
active_count=_effective_active_position_count(conn, mode),
equity=capital,
mode=mode,
get_setting=get_setting,
)
conn.commit()
ctp_acc = _ctp_account(mode) if ctp_st.get("connected") else {}
@@ -4227,7 +4237,10 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn = get_db()
init_strategy_tables(conn)
capital = _capital(conn)
err = assert_can_open(conn, equity=capital)
mode = get_trading_mode(get_setting)
err = assert_can_open(
conn, equity=capital, mode=mode, get_setting=get_setting,
)
if err:
conn.close()
return jsonify({"ok": False, "error": err}), 403
@@ -4748,7 +4761,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if int(plan["lots_open"] or 0) > 0:
execute_order(
conn, mode=mode, offset="close", symbol=plan["symbol"],
direction=plan["direction"], lots=int(plan["lots_open"]), price=price, settings=_settings_dict(),
direction=plan["direction"], lots=int(plan["lots_open"]), price=price,
settings=_settings_dict(), order_type="market", urgency="stop_loss",
)
except ValueError:
pass
@@ -4787,6 +4801,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
execute_order(
conn, mode=mode, offset="close", symbol=sym, direction=direction,
lots=int(plan["lots_open"] or 0), price=price, settings=_settings_dict(),
order_type="market", urgency="stop_loss",
)
except ValueError:
pass
@@ -4901,6 +4916,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn,
active_count=_effective_active_position_count(conn, mode),
equity=_capital(conn),
mode=mode,
get_setting=get_setting,
)
if err:
_notify(False, err, entry=entry, sl=sl, tp=tp, lots=0)
@@ -5065,6 +5082,17 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
notify_fn=send_wechat_msg,
interval=1,
)
from modules.risk.daily_loss_guard import start_daily_loss_guard_worker
start_daily_loss_guard_worker(
db_path=DB_PATH,
get_mode_fn=lambda: get_trading_mode(get_setting),
init_tables_fn=_init_tables,
get_capital_fn=_capital,
get_setting_fn=get_setting,
notify_fn=send_wechat_msg,
interval=2,
)
start_pending_order_worker(
db_path=DB_PATH,
get_mode_fn=lambda: get_trading_mode(get_setting),
+7
View File
@@ -818,6 +818,12 @@ def _execute_local_close(
direction = (mon.get("direction") or "long").strip().lower()
if close_pending_active(sym, direction):
return
try:
from modules.risk.account_risk_lib import should_skip_sl_tp_for_daily_loss
if should_skip_sl_tp_for_daily_loss(conn):
return
except Exception:
pass
positions = ctp_list_positions(mode)
pos = _find_position(positions, sym, direction)
if not pos:
@@ -849,6 +855,7 @@ def _execute_local_close(
lots=lots,
price=mark,
order_type="market",
urgency="stop_loss",
)
mark_close_pending(sym, direction)
_close_all_monitors_for_symbol(conn, sym, direction)