From 131bb369305a83c4751e2a17f64f8bb126330bdd Mon Sep 17 00:00:00 2001 From: dekun Date: Sun, 4 Oct 2026 09:16:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=9E=E7=9B=98=E9=A1=B6?= =?UTF-8?q?=E6=A0=8F=E8=AF=AF=E6=98=BE=E7=A4=BA=E6=A8=A1=E6=8B=9F=E7=9B=98?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E8=B5=84=E9=87=91=EF=BC=9A=E6=97=A0=E4=BA=A4?= =?UTF-8?q?=E6=98=93=E6=89=80=E4=BD=99=E9=A2=9D=E6=97=B6=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=20=E2=80=94=EF=BC=8C=E5=88=87=E6=A8=A1=E5=BC=8F=E6=B8=85?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- app.py | 30 +++++++++++++++---- lib/instance/runtime_config_lib.py | 7 +++++ .../templates/embed_boot_scripts.html | 14 +++++++++ lib/instance/templates/index.html | 14 +++++++++ lib/sim/register.py | 6 ++++ 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index efcaff3..abccc95 100644 --- a/app.py +++ b/app.py @@ -2652,6 +2652,8 @@ friendly_exchange_error = friendly_okx_error def invalidate_account_balance_cache() -> None: ACCOUNT_BALANCE_CACHE["updated_at"] = 0 + ACCOUNT_BALANCE_CACHE["funding_usdt"] = None + ACCOUNT_BALANCE_CACHE["trading_usdt"] = None def get_exchange_capitals(force=False): @@ -2664,11 +2666,15 @@ def get_exchange_capitals(force=False): try: funding = _fetch_usdt_by_types(["funding"]) trading = _fetch_usdt_by_types(["swap", "trading", "spot"]) + # 显式写入(含 0 / None),避免模式切换后残留旧缓存 ACCOUNT_BALANCE_CACHE["funding_usdt"] = funding ACCOUNT_BALANCE_CACHE["trading_usdt"] = trading ACCOUNT_BALANCE_CACHE["updated_at"] = now_ts except Exception: - pass + # 拉取失败不沿用旧值 + ACCOUNT_BALANCE_CACHE["funding_usdt"] = None + ACCOUNT_BALANCE_CACHE["trading_usdt"] = None + ACCOUNT_BALANCE_CACHE["updated_at"] = 0 return ACCOUNT_BALANCE_CACHE["funding_usdt"], ACCOUNT_BALANCE_CACHE["trading_usdt"] @@ -5258,7 +5264,13 @@ def render_main_page(page="options", embed_mode=None): else: funding_capital, trading_capital = None, None funding_usdt = round(funding_capital, FUNDS_DECIMALS) if funding_capital is not None else None - current_capital = round(trading_capital, FUNDS_DECIMALS) if trading_capital is not None else round(local_current_capital, FUNDS_DECIMALS) + # 顶栏交易账户只展示交易所余额;勿回退会话 current_capital(模拟盘残留会污染实盘显示) + current_capital = ( + round(trading_capital, FUNDS_DECIMALS) if trading_capital is not None else None + ) + capital_for_sizing = ( + current_capital if current_capital is not None else round(local_current_capital, FUNDS_DECIMALS) + ) options_trading_usdc = None options_funding_usdc = None options_funding_usdt = None @@ -5309,7 +5321,7 @@ def render_main_page(page="options", embed_mode=None): options_trading_btc = None options_margin_mode = "coin" options_underly = "ETH" - recommended_capital = get_recommended_capital(current_capital) + recommended_capital = get_recommended_capital(capital_for_sizing) key_list = ( conn.execute("SELECT * FROM key_monitors").fetchall() if plan.key_list else [] ) @@ -5336,7 +5348,7 @@ def render_main_page(page="options", embed_mode=None): if plan.orders: raw_order_list = conn.execute("SELECT * FROM order_monitors WHERE status='active'").fetchall() for o in raw_order_list: - order_list.append(enrich_order_item(row_to_dict(o), current_capital)) + order_list.append(enrich_order_item(row_to_dict(o), capital_for_sizing)) enrich_orders_force_close( order_list, FORCE_CLOSE_ENABLED, @@ -5705,7 +5717,13 @@ def api_account_snapshot(): force_refresh = (request.args.get("force") or "").strip().lower() in ("1", "true", "yes") funding_capital, trading_capital = get_exchange_capitals(force=force_refresh) funding_usdt = round(funding_capital, FUNDS_DECIMALS) if funding_capital is not None else None - current_capital = round(trading_capital, FUNDS_DECIMALS) if trading_capital is not None else round(local_current_capital, FUNDS_DECIMALS) + # 顶栏只展示交易所余额;勿用会话资金回退(避免模拟盘 30U 残留到实盘) + current_capital = ( + round(trading_capital, FUNDS_DECIMALS) if trading_capital is not None else None + ) + capital_for_sizing = ( + current_capital if current_capital is not None else round(local_current_capital, FUNDS_DECIMALS) + ) options_trading_usdc = None options_funding_usdc = None options_funding_usdt = None @@ -5739,7 +5757,7 @@ def api_account_snapshot(): options_trading_btc = None options_margin_mode = "coin" options_underly = "ETH" - recommended_capital = get_recommended_capital(current_capital) + recommended_capital = get_recommended_capital(capital_for_sizing) from lib.trade.trade_labels_lib import count_position_limit_active_monitors position_limit_count = count_position_limit_active_monitors(conn) diff --git a/lib/instance/runtime_config_lib.py b/lib/instance/runtime_config_lib.py index 98725c3..cdd2f3a 100644 --- a/lib/instance/runtime_config_lib.py +++ b/lib/instance/runtime_config_lib.py @@ -71,6 +71,13 @@ def apply_env_reload(env_path: str, get_db: Callable, changed_keys: list[str], g set_trading_mode(get_db, raw) except Exception: pass + # 清余额缓存,避免模拟盘资金残留到实盘顶栏 + try: + from app import invalidate_account_balance_cache + + invalidate_account_balance_cache() + except Exception: + pass from lib.env.env_schema import updates_need_restart return {"restart_required": updates_need_restart(groups, changed_keys)} diff --git a/lib/instance/templates/embed_boot_scripts.html b/lib/instance/templates/embed_boot_scripts.html index 34aeb18..acc8003 100644 --- a/lib/instance/templates/embed_boot_scripts.html +++ b/lib/instance/templates/embed_boot_scripts.html @@ -1212,9 +1212,13 @@ function applyAccountSnapshot(data){ applyOptionsFundsVisibility(!coinMode); if(data.funding_usdt != null && data.funding_usdt !== ""){ setFundsFieldText("total-capital", `${Number(data.funding_usdt).toFixed(2)}U`); + } else if("funding_usdt" in data){ + setFundsFieldText("total-capital", "—"); } if(data.total_funds != null && data.total_funds !== ""){ setFundsFieldText("total-funds", `${Number(data.total_funds).toFixed(2)}U`); + } else if("total_funds" in data){ + setFundsFieldText("total-funds", "—"); } if(data.current_capital != null && data.current_capital !== "" && !Number.isNaN(Number(data.current_capital))){ setFundsFieldText( @@ -1226,6 +1230,16 @@ function applyAccountSnapshot(data){ data.options_margin_mode ) ); + } else if("current_capital" in data){ + setFundsFieldText( + "current-capital", + formatTradingAccountLabel( + null, + data.options_trading_eth, + data.options_trading_btc, + data.options_margin_mode + ) + ); } if(!coinMode && (data.options_funding_usdc != null || data.options_funding_usdt != null || data.options_funding_eth != null)){ const optFunding = formatOptionsFundingLabel( diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index c632560..c6f01eb 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -1691,9 +1691,13 @@ function applyAccountSnapshot(data){ applyOptionsFundsVisibility(!coinMode); if(data.funding_usdt != null && data.funding_usdt !== ""){ setFundsFieldText("total-capital", `${Number(data.funding_usdt).toFixed(2)}U`); + } else if("funding_usdt" in data){ + setFundsFieldText("total-capital", "—"); } if(data.total_funds != null && data.total_funds !== ""){ setFundsFieldText("total-funds", `${Number(data.total_funds).toFixed(2)}U`); + } else if("total_funds" in data){ + setFundsFieldText("total-funds", "—"); } if(data.current_capital != null && data.current_capital !== "" && !Number.isNaN(Number(data.current_capital))){ setFundsFieldText( @@ -1705,6 +1709,16 @@ function applyAccountSnapshot(data){ data.options_margin_mode ) ); + } else if("current_capital" in data){ + setFundsFieldText( + "current-capital", + formatTradingAccountLabel( + null, + data.options_trading_eth, + data.options_trading_btc, + data.options_margin_mode + ) + ); } if(!coinMode && (data.options_funding_usdc != null || data.options_funding_usdt != null || data.options_funding_eth != null)){ const optFunding = formatOptionsFundingLabel( diff --git a/lib/sim/register.py b/lib/sim/register.py index 9b3387d..68a1da3 100644 --- a/lib/sim/register.py +++ b/lib/sim/register.py @@ -92,6 +92,12 @@ def install_sim_trading(app: Flask, repo_root: str, app_module: Any = None) -> N saved = set_trading_mode(get_db, mode) except ValueError as e: return jsonify({"ok": False, "msg": str(e)}), 400 + try: + from app import invalidate_account_balance_cache + + invalidate_account_balance_cache() + except Exception: + pass return jsonify({"ok": True, "mode": saved, **_status_payload()}) @app.route("/api/sim/reset", methods=["POST"])