feat(order): show estimated RR before open across four exchanges

Add shared manual_order_rr_preview.js to fetch order_defaults after symbol and TP/SL inputs complete, display estimated profit-loss ratio before submit in price and percentage modes (and fixed RR), unified for risk and full-margin sizing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-16 16:19:32 +08:00
parent 869728ce10
commit f9257b64e4
7 changed files with 326 additions and 0 deletions
@@ -376,6 +376,7 @@
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
<input id="order-sl-pct" name="sl_pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
<input id="order-tp-pct" name="tp_pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
<span id="order-rr-preview" class="order-rr-preview" style="font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
<button type="submit">{{ open_position_button_label }}</button>
</form>
</div>
@@ -789,6 +790,7 @@
<script src="/static/time_close_ui.js?v=2"></script>
<script src="/static/ai_review_render.js?v=2"></script>
<script src="/static/form_submit_guard.js?v=2"></script>
<script src="/static/manual_order_rr_preview.js?v=1"></script>
<script>
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
@@ -1675,6 +1677,7 @@ function refreshOrderTpPreview(entryPx){
const entry = entryPx != null && Number.isFinite(Number(entryPx)) ? Number(entryPx) : sl;
const tp = calcTpFromFixedRr(direction, entry, sl, rr);
preview.textContent = tp == null ? "预估止盈:—" : ("预估止盈:" + formatPriceForInput(tp));
if(window.ManualOrderRrPreview) ManualOrderRrPreview.schedule();
}
function calcClientRr(direction, entry, sl, tp){
const e = Number(entry), s = Number(sl), t = Number(tp);
@@ -1947,6 +1950,7 @@ function refreshOrderDefaults(){
}
const px = data.last_price || data.price;
if(px) refreshOrderTpPreview(px);
if(window.ManualOrderRrPreview) ManualOrderRrPreview.schedule();
}).catch(()=>{});
}
@@ -2026,12 +2030,16 @@ function toggleSltpMode(){
slPctEl.required = pct;
tpPctEl.required = pct;
refreshOrderTpPreview();
if(window.ManualOrderRrPreview) ManualOrderRrPreview.schedule();
}
if(sltpModeEl){
sltpModeEl.addEventListener("change", toggleSltpMode);
loadFixedRrPref();
toggleSltpMode();
}
if(window.ManualOrderRrPreview){
ManualOrderRrPreview.wire({ minRr: MANUAL_MIN_PLANNED_RR });
}
["order-sl","order-fixed-rr","order-direction"].forEach(function(id){
const el = document.getElementById(id);
if(el) el.addEventListener("input", function(){ refreshOrderTpPreview(); });