diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 89f21a4..261ad1f 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -7739,7 +7739,7 @@ def api_price_snapshot(): leverage=leverage, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, contracts=abs(_position_row_effective_contracts(prow)) if prow else None, - contract_size=float(get_contract_size(r["symbol"])) if r["symbol"] else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=ex_metrics.get("mark_price") if ex_metrics else price, avg_entry_price=avg_entry, funds_decimals=FUNDS_DECIMALS, @@ -7798,6 +7798,10 @@ def api_price_snapshot(): @app.route("/api/order//cancel_tpsl", methods=["POST"]) @login_required def api_order_cancel_tpsl(order_id): + from lib.trade.trade_policy_lib import is_intraday_trading_profile + + if is_intraday_trading_profile(TRADE_POLICY): + return jsonify({"ok": False, "msg": "日内纪律账户禁止撤销交易所止盈止损"}), 403 data = request.get_json(silent=True) or {} role = (data.get("role") or "").strip().lower() if role not in ("sl", "tp"): @@ -7883,6 +7887,7 @@ def api_order_place_tpsl(order_id): pass from lib.trade.order_monitor_display_lib import enrich_active_monitor_tpsl_json + ex_sym = resolve_monitor_exchange_symbol(row) display_extra = enrich_active_monitor_tpsl_json( row, stop_loss, @@ -7890,7 +7895,7 @@ def api_order_place_tpsl(order_id): slots, position_row=prow, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, - contract_size=float(get_contract_size(symbol)) if symbol else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=live_price, calc_rr_ratio_fn=calc_rr_ratio, format_price_fn=format_price_for_symbol, diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index a05193d..488d664 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -7603,7 +7603,7 @@ def api_price_snapshot(): leverage=leverage, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, contracts=abs(_position_row_effective_contracts(prow)) if prow else None, - contract_size=float(get_contract_size(r["symbol"])) if r["symbol"] else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=ex_metrics.get("mark_price") if ex_metrics else price, avg_entry_price=avg_entry, funds_decimals=FUNDS_DECIMALS, @@ -7660,6 +7660,10 @@ def api_price_snapshot(): @app.route("/api/order//cancel_tpsl", methods=["POST"]) @login_required def api_order_cancel_tpsl(order_id): + from lib.trade.trade_policy_lib import is_intraday_trading_profile + + if is_intraday_trading_profile(TRADE_POLICY): + return jsonify({"ok": False, "msg": "日内纪律账户禁止撤销交易所止盈止损"}), 403 data = request.get_json(silent=True) or {} role = (data.get("role") or "").strip().lower() if role not in ("sl", "tp"): @@ -7750,6 +7754,7 @@ def api_order_place_tpsl(order_id): pass from lib.trade.order_monitor_display_lib import enrich_active_monitor_tpsl_json + ex_sym = resolve_monitor_exchange_symbol(row) display_extra = enrich_active_monitor_tpsl_json( row, stop_loss, @@ -7757,7 +7762,7 @@ def api_order_place_tpsl(order_id): slots, position_row=prow, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, - contract_size=float(get_contract_size(symbol)) if symbol else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=live_price, calc_rr_ratio_fn=calc_rr_ratio, format_price_fn=format_price_for_symbol, diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index a6e9471..23236dc 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -7300,7 +7300,7 @@ def api_price_snapshot(): leverage=leverage, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, contracts=abs(_position_row_effective_contracts(prow)) if prow else None, - contract_size=float(get_contract_size(r["symbol"])) if r["symbol"] else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=ex_metrics.get("mark_price") if ex_metrics else price, avg_entry_price=avg_entry, funds_decimals=FUNDS_DECIMALS, @@ -7686,6 +7686,10 @@ def api_key_kline(): @app.route("/api/order//cancel_tpsl", methods=["POST"]) @login_required def api_order_cancel_tpsl(order_id): + from lib.trade.trade_policy_lib import is_intraday_trading_profile + + if is_intraday_trading_profile(TRADE_POLICY): + return jsonify({"ok": False, "msg": "日内纪律账户禁止撤销交易所止盈止损"}), 403 data = request.get_json(silent=True) or {} role = (data.get("role") or "").strip().lower() if role not in ("sl", "tp"): @@ -7771,6 +7775,7 @@ def api_order_place_tpsl(order_id): pass from lib.trade.order_monitor_display_lib import enrich_active_monitor_tpsl_json + ex_sym = resolve_monitor_exchange_symbol(row) display_extra = enrich_active_monitor_tpsl_json( row, stop_loss, @@ -7778,7 +7783,7 @@ def api_order_place_tpsl(order_id): slots, position_row=prow, exchange_notional=ex_metrics.get("notional") if ex_metrics else None, - contract_size=float(get_contract_size(symbol)) if symbol else 1.0, + contract_size=float(get_contract_size(ex_sym)) if ex_sym else 1.0, mark_price=live_price, calc_rr_ratio_fn=calc_rr_ratio, format_price_fn=format_price_for_symbol, diff --git a/lib/instance/templates/embed_boot_scripts.html b/lib/instance/templates/embed_boot_scripts.html index 1fbcdd5..47dc661 100644 --- a/lib/instance/templates/embed_boot_scripts.html +++ b/lib/instance/templates/embed_boot_scripts.html @@ -757,10 +757,13 @@ function paintExchangeTpslRow(orderId, tpsl){ const tpText = document.getElementById(`ex-tp-text-${orderId}`); const slBtn = document.getElementById(`ex-sl-cancel-${orderId}`); const tpBtn = document.getElementById(`ex-tp-cancel-${orderId}`); + const intraday = (document.body && document.body.getAttribute("data-intraday-discipline")) === "1"; if(slText) slText.innerText = formatExTpslLine('sl', data.sl); if(tpText) tpText.innerText = formatExTpslLine('tp', data.tp); - if(slBtn) slBtn.disabled = !(data.sl && data.sl.order_id); - if(tpBtn) tpBtn.disabled = !(data.tp && data.tp.order_id); + if(!intraday){ + if(slBtn) slBtn.disabled = !(data.sl && data.sl.order_id); + if(tpBtn) tpBtn.disabled = !(data.tp && data.tp.order_id); + } } function toggleTpslModalMode(){ const mode = (document.getElementById('tpsl-modal-mode')||{}).value || 'price'; diff --git a/lib/instance/templates/embed_page_fragment.html b/lib/instance/templates/embed_page_fragment.html index 71103e6..2dad742 100644 --- a/lib/instance/templates/embed_page_fragment.html +++ b/lib/instance/templates/embed_page_fragment.html @@ -166,11 +166,15 @@
交易所止盈止损
止损:加载中… + {% if not intraday_discipline %} + {% endif %}
止盈:加载中… + {% if not intraday_discipline %} + {% endif %}
diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html index d189d1f..c9910cc 100644 --- a/lib/instance/templates/embed_shell.html +++ b/lib/instance/templates/embed_shell.html @@ -14,6 +14,7 @@ 交易所止盈止损
止损:加载中… + {% if not intraday_discipline %} + {% endif %}
止盈:加载中… + {% if not intraday_discipline %} + {% endif %}
@@ -1295,10 +1300,13 @@ function paintExchangeTpslRow(orderId, tpsl){ const tpText = document.getElementById(`ex-tp-text-${orderId}`); const slBtn = document.getElementById(`ex-sl-cancel-${orderId}`); const tpBtn = document.getElementById(`ex-tp-cancel-${orderId}`); + const intraday = (document.body && document.body.getAttribute("data-intraday-discipline")) === "1"; if(slText) slText.innerText = formatExTpslLine('sl', data.sl); if(tpText) tpText.innerText = formatExTpslLine('tp', data.tp); - if(slBtn) slBtn.disabled = !(data.sl && data.sl.order_id); - if(tpBtn) tpBtn.disabled = !(data.tp && data.tp.order_id); + if(!intraday){ + if(slBtn) slBtn.disabled = !(data.sl && data.sl.order_id); + if(tpBtn) tpBtn.disabled = !(data.tp && data.tp.order_id); + } } function toggleTpslModalMode(){ const mode = (document.getElementById('tpsl-modal-mode')||{}).value || 'price'; diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index 0482cff..87fdcce 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -2808,8 +2808,9 @@ return { sl, tp }; } - function renderExTpslRows(exchangeId, symbol, cond, tickMap, resolvedTpsl, contracts) { + function renderExTpslRows(exchangeId, symbol, cond, tickMap, resolvedTpsl, contracts, intradayDiscipline) { const symAttr = esc(symbol || "").replace(/"/g, """); + const intraday = !!intradayDiscipline; let { sl, tp } = pickExTpslOrders(cond); const plan = resolvedTpsl || {}; if (!sl && plan.sl != null && plan.sl !== "") { @@ -2827,7 +2828,7 @@ const px = orderTriggerOrPrice(o); const trig = px != null ? fmtSymbolPrice(px, symbol, tickMap) : "—"; const cancelBtn = - oid && o.channel !== "plan" + !intraday && oid && o.channel !== "plan" ? `` : ""; const planHint = o.channel === "plan" ? '(下单监控)' : ""; @@ -3193,7 +3194,7 @@
交易所止盈止损
- ${renderExTpslRows(exchangeId, symbol, cond, tickMap, tpsl, pos.contracts)} + ${renderExTpslRows(exchangeId, symbol, cond, tickMap, tpsl, pos.contracts, intraday)}
${renderOrdersCollapse(exchangeId, symbol, cond, reg, tickMap)} `; diff --git a/tests/test_order_monitor_display_lib.py b/tests/test_order_monitor_display_lib.py index 600c12d..5e65d73 100644 --- a/tests/test_order_monitor_display_lib.py +++ b/tests/test_order_monitor_display_lib.py @@ -115,6 +115,28 @@ def test_apply_order_price_display_fields_live_sl(): assert payload["reward_at_tp_usdt"] > 0 +def test_apply_order_price_display_fields_gate_contract_size(): + payload = {} + apply_order_price_display_fields( + payload, + direction="short", + entry_price=62063.4, + initial_stop_loss=62650, + stop_loss=62650, + take_profit=61200, + calc_rr_ratio_fn=_calc_rr, + exchange_tpsl={}, + symbol="BTC/USDT:USDT", + margin_capital=48, + leverage=10, + contracts=78.0, + contract_size=0.0001, + avg_entry_price=62063.4, + ) + assert payload["reward_at_tp_usdt"] is not None + assert abs(payload["reward_at_tp_usdt"] - 6.73) < 0.1 + + def test_calc_latest_risk_amount_long(): rf = calc_risk_fraction("long", 100, 95) assert rf is not None and abs(rf - 0.05) < 1e-9