Apply 200k scope when CTP offline; trailing breakeven order UX.

When SimNow or live CTP is disconnected, default to the four-product whitelist regardless of reference capital. Trailing breakeven defaults off; when enabled hide take-profit and risk-reward, monitor exits via trailing stop only. Document both behaviors in TRADING.md and FEATURES.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-27 23:57:11 +08:00
parent 4f4c4bb9fc
commit e18d5feb72
12 changed files with 220 additions and 48 deletions
+14 -6
View File
@@ -30,7 +30,7 @@ from position_sizing import (
)
from product_recommend import (
assert_product_allowed_for_capital,
is_small_account,
should_apply_small_account_scope,
small_account_scope_hint,
SMALL_ACCOUNT_SCOPE_LABEL,
)
@@ -96,6 +96,7 @@ from trading_context import (
get_sizing_mode,
get_trailing_be_tick_buffer,
get_trading_mode,
is_ctp_connected,
trading_mode_label,
)
from ctp_symbol import ths_to_vnpy_symbol
@@ -1629,6 +1630,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
rec_cache = _recommend_payload(conn)
if rec_cache.get("needs_refresh"):
_schedule_recommend_refresh()
ctp_connected = is_ctp_connected(get_setting)
return render_template(
"trade.html",
trading_mode=mode,
@@ -1651,8 +1653,10 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
recommend_rows=rec_cache.get("rows") or [],
recommend_updated_at=rec_cache.get("updated_at"),
night_session=is_night_trading_session(),
small_account_scope=is_small_account(capital),
small_account_scope_hint=small_account_scope_hint(),
small_account_scope=should_apply_small_account_scope(
capital, ctp_connected=ctp_connected,
),
small_account_scope_hint=small_account_scope_hint(ctp_connected=ctp_connected),
product_categories=PRODUCT_CATEGORIES,
)
finally:
@@ -2156,7 +2160,9 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if err:
conn.close()
return jsonify({"ok": False, "error": err}), 403
scope_err = assert_product_allowed_for_capital(sym, _capital(conn))
scope_err = assert_product_allowed_for_capital(
sym, _capital(conn), ctp_connected=is_ctp_connected(get_setting),
)
if scope_err:
conn.close()
return jsonify({"ok": False, "error": scope_err}), 403
@@ -2220,8 +2226,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if offset.startswith("open"):
from zoneinfo import ZoneInfo
sl = d.get("stop_loss")
tp = d.get("take_profit")
trailing_be = 1 if d.get("trailing_be") else 0
tp = None if trailing_be else d.get("take_profit")
open_ts = datetime.now(ZoneInfo("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
vt_order_id = str(result.get("order_id") or "")
mid = _upsert_open_monitor(
@@ -2515,7 +2521,9 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn.close()
return jsonify({"ok": False, "error": err}), 403
capital = _capital(conn)
scope_err = assert_product_allowed_for_capital(sym, capital)
scope_err = assert_product_allowed_for_capital(
sym, capital, ctp_connected=is_ctp_connected(get_setting),
)
if scope_err:
conn.close()
return jsonify({"ok": False, "error": scope_err}), 403