Fix intraday profit amount and hide TP/SL cancel for day trades.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-09 09:55:09 +08:00
parent 44546d1a96
commit 23ba725c89
9 changed files with 67 additions and 13 deletions
+7 -2
View File
@@ -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/<int:order_id>/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,
+7 -2
View File
@@ -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/<int:order_id>/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,
+7 -2
View File
@@ -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/<int:order_id>/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,
@@ -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';
@@ -166,11 +166,15 @@
<div class="pos-ex-orders-title">交易所止盈止损</div>
<div class="pos-ex-order-row">
<span class="pos-ex-order-main" id="ex-sl-text-{{ o.id }}">止损:加载中…</span>
{% if not intraday_discipline %}
<button type="button" class="pos-ex-cancel-btn" id="ex-sl-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'sl')">撤单</button>
{% endif %}
</div>
<div class="pos-ex-order-row">
<span class="pos-ex-order-main" id="ex-tp-text-{{ o.id }}">止盈:加载中…</span>
{% if not intraday_discipline %}
<button type="button" class="pos-ex-cancel-btn" id="ex-tp-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'tp')">撤单</button>
{% endif %}
</div>
</div>
</div>
+1
View File
@@ -14,6 +14,7 @@
</head>
<body
data-embed-shell="1"
data-intraday-discipline="{% if intraday_discipline %}1{% else %}0{% endif %}"
data-risk-percent="{{ risk_percent }}"
data-page="{{ initial_tab }}"
data-position-sizing-mode="{{ position_sizing_mode }}"
+10 -2
View File
@@ -22,6 +22,7 @@
</head>
<body
data-page="{{ page }}"
data-intraday-discipline="{% if intraday_discipline %}1{% else %}0{% endif %}"
data-risk-percent="{{ risk_percent }}"
data-position-sizing-mode="{{ position_sizing_mode }}"
data-btc-leverage="{{ btc_leverage }}"
@@ -248,11 +249,15 @@
<div class="pos-ex-orders-title">交易所止盈止损</div>
<div class="pos-ex-order-row">
<span class="pos-ex-order-main" id="ex-sl-text-{{ o.id }}">止损:加载中…</span>
{% if not intraday_discipline %}
<button type="button" class="pos-ex-cancel-btn" id="ex-sl-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'sl')">撤单</button>
{% endif %}
</div>
<div class="pos-ex-order-row">
<span class="pos-ex-order-main" id="ex-tp-text-{{ o.id }}">止盈:加载中…</span>
{% if not intraday_discipline %}
<button type="button" class="pos-ex-cancel-btn" id="ex-tp-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'tp')">撤单</button>
{% endif %}
</div>
</div>
</div>
@@ -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';
+4 -3
View File
@@ -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, "&quot;");
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"
? `<button type="button" class="pos-ex-cancel-btn btn-cancel-order" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-order-id="${oid}" data-channel="${ch}">撤单</button>`
: "";
const planHint = o.channel === "plan" ? '<span class="pos-ex-plan-hint">(下单监控)</span>' : "";
@@ -3193,7 +3194,7 @@
</div>
<div class="pos-ex-orders">
<div class="pos-ex-orders-title">交易所止盈止损</div>
${renderExTpslRows(exchangeId, symbol, cond, tickMap, tpsl, pos.contracts)}
${renderExTpslRows(exchangeId, symbol, cond, tickMap, tpsl, pos.contracts, intraday)}
</div>
${renderOrdersCollapse(exchangeId, symbol, cond, reg, tickMap)}
</div>`;
+22
View File
@@ -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