Show estimated risk, profit, and RR below manual order form.
Add a preview bar under the live order form with risk in red and profit in green; extend preview logic for all SL/TP modes across embed and standalone instances. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -37,6 +37,12 @@
|
|||||||
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
||||||
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
||||||
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
||||||
|
.order-plan-preview{display:flex;gap:18px;flex-wrap:wrap;align-items:center;margin:4px 0 10px;padding:10px 12px;background:#151a28;border:1px solid #2a3150;border-radius:8px;font-size:.85rem}
|
||||||
|
.order-preview-risk{color:#ff6b6b}.order-preview-risk strong{color:#ff8f8f;font-weight:600}
|
||||||
|
.order-preview-profit{color:#4cd97f}.order-preview-profit strong{color:#6ee7a0;font-weight:600}
|
||||||
|
.order-preview-rr{color:#cfd3ef}.order-preview-rr strong{font-weight:600;color:#dbe4ff}
|
||||||
|
.order-preview-rr.order-preview-rr-low strong{color:#ff8f8f}
|
||||||
|
.order-preview-rr.order-preview-rr-ok strong{color:#8fc8ff}
|
||||||
.form-row > button,.form-row > label{flex:0 0 auto}
|
.form-row > button,.form-row > label{flex:0 0 auto}
|
||||||
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||||||
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
||||||
@@ -240,7 +246,7 @@
|
|||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}" data-risk-percent="{{ risk_percent }}">
|
||||||
{% macro period_stats(title, s) %}
|
{% macro period_stats(title, s) %}
|
||||||
<div class="stats-period-block">
|
<div class="stats-period-block">
|
||||||
<h3>{{ title }}</h3>
|
<h3>{{ title }}</h3>
|
||||||
@@ -360,7 +366,7 @@
|
|||||||
</select>
|
</select>
|
||||||
<button type="submit">手动划转</button>
|
<button type="submit">手动划转</button>
|
||||||
</form>
|
</form>
|
||||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||||
<select id="order-direction" name="direction" required>
|
<select id="order-direction" name="direction" required>
|
||||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||||
@@ -400,9 +406,9 @@
|
|||||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
<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-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">
|
<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="display:none;font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
|
|
||||||
<button type="submit">{{ open_position_button_label }}</button>
|
<button type="submit">{{ open_position_button_label }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include 'order_plan_preview_bar.html' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||||||
@@ -827,7 +833,7 @@
|
|||||||
<script src="/static/time_close_ui.js?v=2"></script>
|
<script src="/static/time_close_ui.js?v=2"></script>
|
||||||
<script src="/static/ai_review_render.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/form_submit_guard.js?v=2"></script>
|
||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=4"></script>
|
||||||
<script>
|
<script>
|
||||||
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
||||||
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
||||||
@@ -1989,13 +1995,11 @@ function toggleSltpMode(){
|
|||||||
const slEl = document.getElementById("order-sl");
|
const slEl = document.getElementById("order-sl");
|
||||||
const tpEl = document.getElementById("order-tp");
|
const tpEl = document.getElementById("order-tp");
|
||||||
const fixedRrEl = document.getElementById("order-fixed-rr");
|
const fixedRrEl = document.getElementById("order-fixed-rr");
|
||||||
const rrPreviewEl = document.getElementById("order-rr-preview");
|
|
||||||
const slPctEl = document.getElementById("order-sl-pct");
|
const slPctEl = document.getElementById("order-sl-pct");
|
||||||
const tpPctEl = document.getElementById("order-tp-pct");
|
const tpPctEl = document.getElementById("order-tp-pct");
|
||||||
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
||||||
const pct = mode === "pct";
|
const pct = mode === "pct";
|
||||||
const fixed = mode === "fixed_rr";
|
const fixed = mode === "fixed_rr";
|
||||||
if(rrPreviewEl) rrPreviewEl.style.display = fixed ? "none" : "";
|
|
||||||
slEl.style.display = pct ? "none" : "";
|
slEl.style.display = pct ? "none" : "";
|
||||||
tpEl.style.display = (pct || fixed) ? "none" : "";
|
tpEl.style.display = (pct || fixed) ? "none" : "";
|
||||||
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
||||||
|
|||||||
@@ -37,6 +37,12 @@
|
|||||||
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
||||||
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
||||||
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
||||||
|
.order-plan-preview{display:flex;gap:18px;flex-wrap:wrap;align-items:center;margin:4px 0 10px;padding:10px 12px;background:#151a28;border:1px solid #2a3150;border-radius:8px;font-size:.85rem}
|
||||||
|
.order-preview-risk{color:#ff6b6b}.order-preview-risk strong{color:#ff8f8f;font-weight:600}
|
||||||
|
.order-preview-profit{color:#4cd97f}.order-preview-profit strong{color:#6ee7a0;font-weight:600}
|
||||||
|
.order-preview-rr{color:#cfd3ef}.order-preview-rr strong{font-weight:600;color:#dbe4ff}
|
||||||
|
.order-preview-rr.order-preview-rr-low strong{color:#ff8f8f}
|
||||||
|
.order-preview-rr.order-preview-rr-ok strong{color:#8fc8ff}
|
||||||
.form-row > button,.form-row > label{flex:0 0 auto}
|
.form-row > button,.form-row > label{flex:0 0 auto}
|
||||||
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||||||
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
||||||
@@ -240,7 +246,7 @@
|
|||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}" data-risk-percent="{{ risk_percent }}">
|
||||||
{% macro period_stats(title, s) %}
|
{% macro period_stats(title, s) %}
|
||||||
<div class="stats-period-block">
|
<div class="stats-period-block">
|
||||||
<h3>{{ title }}</h3>
|
<h3>{{ title }}</h3>
|
||||||
@@ -340,7 +346,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'order_monitor_rule_tips_gate.html' %}
|
{% include 'order_monitor_rule_tips_gate.html' %}
|
||||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||||
<select id="order-direction" name="direction" required>
|
<select id="order-direction" name="direction" required>
|
||||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||||
@@ -380,9 +386,9 @@
|
|||||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
<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-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">
|
<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="display:none;font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
|
|
||||||
<button type="submit">{{ open_position_button_label }}</button>
|
<button type="submit">{{ open_position_button_label }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include 'order_plan_preview_bar.html' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||||||
@@ -794,7 +800,7 @@
|
|||||||
<script src="/static/time_close_ui.js?v=2"></script>
|
<script src="/static/time_close_ui.js?v=2"></script>
|
||||||
<script src="/static/ai_review_render.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/form_submit_guard.js?v=2"></script>
|
||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=4"></script>
|
||||||
<script>
|
<script>
|
||||||
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
||||||
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
||||||
@@ -1915,13 +1921,11 @@ function toggleSltpMode(){
|
|||||||
const slEl = document.getElementById("order-sl");
|
const slEl = document.getElementById("order-sl");
|
||||||
const tpEl = document.getElementById("order-tp");
|
const tpEl = document.getElementById("order-tp");
|
||||||
const fixedRrEl = document.getElementById("order-fixed-rr");
|
const fixedRrEl = document.getElementById("order-fixed-rr");
|
||||||
const rrPreviewEl = document.getElementById("order-rr-preview");
|
|
||||||
const slPctEl = document.getElementById("order-sl-pct");
|
const slPctEl = document.getElementById("order-sl-pct");
|
||||||
const tpPctEl = document.getElementById("order-tp-pct");
|
const tpPctEl = document.getElementById("order-tp-pct");
|
||||||
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
||||||
const pct = mode === "pct";
|
const pct = mode === "pct";
|
||||||
const fixed = mode === "fixed_rr";
|
const fixed = mode === "fixed_rr";
|
||||||
if(rrPreviewEl) rrPreviewEl.style.display = fixed ? "none" : "";
|
|
||||||
slEl.style.display = pct ? "none" : "";
|
slEl.style.display = pct ? "none" : "";
|
||||||
tpEl.style.display = (pct || fixed) ? "none" : "";
|
tpEl.style.display = (pct || fixed) ? "none" : "";
|
||||||
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
||||||
|
|||||||
@@ -37,6 +37,12 @@
|
|||||||
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
||||||
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
||||||
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
||||||
|
.order-plan-preview{display:flex;gap:18px;flex-wrap:wrap;align-items:center;margin:4px 0 10px;padding:10px 12px;background:#151a28;border:1px solid #2a3150;border-radius:8px;font-size:.85rem}
|
||||||
|
.order-preview-risk{color:#ff6b6b}.order-preview-risk strong{color:#ff8f8f;font-weight:600}
|
||||||
|
.order-preview-profit{color:#4cd97f}.order-preview-profit strong{color:#6ee7a0;font-weight:600}
|
||||||
|
.order-preview-rr{color:#cfd3ef}.order-preview-rr strong{font-weight:600;color:#dbe4ff}
|
||||||
|
.order-preview-rr.order-preview-rr-low strong{color:#ff8f8f}
|
||||||
|
.order-preview-rr.order-preview-rr-ok strong{color:#8fc8ff}
|
||||||
.form-row > button,.form-row > label{flex:0 0 auto}
|
.form-row > button,.form-row > label{flex:0 0 auto}
|
||||||
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||||||
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
||||||
@@ -240,7 +246,7 @@
|
|||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}" data-risk-percent="{{ risk_percent }}">
|
||||||
{% macro period_stats(title, s) %}
|
{% macro period_stats(title, s) %}
|
||||||
<div class="stats-period-block">
|
<div class="stats-period-block">
|
||||||
<h3>{{ title }}</h3>
|
<h3>{{ title }}</h3>
|
||||||
@@ -340,7 +346,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'order_monitor_rule_tips_gate.html' %}
|
{% include 'order_monitor_rule_tips_gate.html' %}
|
||||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||||
<select id="order-direction" name="direction" required>
|
<select id="order-direction" name="direction" required>
|
||||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||||
@@ -380,9 +386,9 @@
|
|||||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
<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-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">
|
<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="display:none;font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
|
|
||||||
<button type="submit">{{ open_position_button_label }}</button>
|
<button type="submit">{{ open_position_button_label }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include 'order_plan_preview_bar.html' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||||||
@@ -794,7 +800,7 @@
|
|||||||
<script src="/static/time_close_ui.js?v=2"></script>
|
<script src="/static/time_close_ui.js?v=2"></script>
|
||||||
<script src="/static/ai_review_render.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/form_submit_guard.js?v=2"></script>
|
||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=4"></script>
|
||||||
<script>
|
<script>
|
||||||
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
||||||
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
||||||
@@ -1915,13 +1921,11 @@ function toggleSltpMode(){
|
|||||||
const slEl = document.getElementById("order-sl");
|
const slEl = document.getElementById("order-sl");
|
||||||
const tpEl = document.getElementById("order-tp");
|
const tpEl = document.getElementById("order-tp");
|
||||||
const fixedRrEl = document.getElementById("order-fixed-rr");
|
const fixedRrEl = document.getElementById("order-fixed-rr");
|
||||||
const rrPreviewEl = document.getElementById("order-rr-preview");
|
|
||||||
const slPctEl = document.getElementById("order-sl-pct");
|
const slPctEl = document.getElementById("order-sl-pct");
|
||||||
const tpPctEl = document.getElementById("order-tp-pct");
|
const tpPctEl = document.getElementById("order-tp-pct");
|
||||||
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
||||||
const pct = mode === "pct";
|
const pct = mode === "pct";
|
||||||
const fixed = mode === "fixed_rr";
|
const fixed = mode === "fixed_rr";
|
||||||
if(rrPreviewEl) rrPreviewEl.style.display = fixed ? "none" : "";
|
|
||||||
slEl.style.display = pct ? "none" : "";
|
slEl.style.display = pct ? "none" : "";
|
||||||
tpEl.style.display = (pct || fixed) ? "none" : "";
|
tpEl.style.display = (pct || fixed) ? "none" : "";
|
||||||
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
||||||
|
|||||||
@@ -37,6 +37,12 @@
|
|||||||
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
||||||
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
||||||
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
||||||
|
.order-plan-preview{display:flex;gap:18px;flex-wrap:wrap;align-items:center;margin:4px 0 10px;padding:10px 12px;background:#151a28;border:1px solid #2a3150;border-radius:8px;font-size:.85rem}
|
||||||
|
.order-preview-risk{color:#ff6b6b}.order-preview-risk strong{color:#ff8f8f;font-weight:600}
|
||||||
|
.order-preview-profit{color:#4cd97f}.order-preview-profit strong{color:#6ee7a0;font-weight:600}
|
||||||
|
.order-preview-rr{color:#cfd3ef}.order-preview-rr strong{font-weight:600;color:#dbe4ff}
|
||||||
|
.order-preview-rr.order-preview-rr-low strong{color:#ff8f8f}
|
||||||
|
.order-preview-rr.order-preview-rr-ok strong{color:#8fc8ff}
|
||||||
.form-row > button,.form-row > label{flex:0 0 auto}
|
.form-row > button,.form-row > label{flex:0 0 auto}
|
||||||
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||||||
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
||||||
@@ -240,7 +246,7 @@
|
|||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=18">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}" data-risk-percent="{{ risk_percent }}">
|
||||||
{% macro period_stats(title, s) %}
|
{% macro period_stats(title, s) %}
|
||||||
<div class="stats-period-block">
|
<div class="stats-period-block">
|
||||||
<h3>{{ title }}</h3>
|
<h3>{{ title }}</h3>
|
||||||
@@ -369,7 +375,7 @@
|
|||||||
</select>
|
</select>
|
||||||
<button type="submit">手动划转</button>
|
<button type="submit">手动划转</button>
|
||||||
</form>
|
</form>
|
||||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||||
<select id="order-direction" name="direction" required>
|
<select id="order-direction" name="direction" required>
|
||||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||||
@@ -409,9 +415,9 @@
|
|||||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
<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-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">
|
<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="display:none;font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
|
|
||||||
<button type="submit">{{ open_position_button_label }}</button>
|
<button type="submit">{{ open_position_button_label }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include 'order_plan_preview_bar.html' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||||||
@@ -823,7 +829,7 @@
|
|||||||
<script src="/static/time_close_ui.js?v=2"></script>
|
<script src="/static/time_close_ui.js?v=2"></script>
|
||||||
<script src="/static/ai_review_render.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/form_submit_guard.js?v=2"></script>
|
||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=4"></script>
|
||||||
<script>
|
<script>
|
||||||
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
||||||
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
||||||
@@ -1967,13 +1973,11 @@ function toggleSltpMode(){
|
|||||||
const slEl = document.getElementById("order-sl");
|
const slEl = document.getElementById("order-sl");
|
||||||
const tpEl = document.getElementById("order-tp");
|
const tpEl = document.getElementById("order-tp");
|
||||||
const fixedRrEl = document.getElementById("order-fixed-rr");
|
const fixedRrEl = document.getElementById("order-fixed-rr");
|
||||||
const rrPreviewEl = document.getElementById("order-rr-preview");
|
|
||||||
const slPctEl = document.getElementById("order-sl-pct");
|
const slPctEl = document.getElementById("order-sl-pct");
|
||||||
const tpPctEl = document.getElementById("order-tp-pct");
|
const tpPctEl = document.getElementById("order-tp-pct");
|
||||||
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
||||||
const pct = mode === "pct";
|
const pct = mode === "pct";
|
||||||
const fixed = mode === "fixed_rr";
|
const fixed = mode === "fixed_rr";
|
||||||
if(rrPreviewEl) rrPreviewEl.style.display = fixed ? "none" : "";
|
|
||||||
slEl.style.display = pct ? "none" : "";
|
slEl.style.display = pct ? "none" : "";
|
||||||
tpEl.style.display = (pct || fixed) ? "none" : "";
|
tpEl.style.display = (pct || fixed) ? "none" : "";
|
||||||
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
||||||
|
|||||||
@@ -1143,13 +1143,11 @@ function toggleSltpMode(){
|
|||||||
const slEl = document.getElementById("order-sl");
|
const slEl = document.getElementById("order-sl");
|
||||||
const tpEl = document.getElementById("order-tp");
|
const tpEl = document.getElementById("order-tp");
|
||||||
const fixedRrEl = document.getElementById("order-fixed-rr");
|
const fixedRrEl = document.getElementById("order-fixed-rr");
|
||||||
const rrPreviewEl = document.getElementById("order-rr-preview");
|
|
||||||
const slPctEl = document.getElementById("order-sl-pct");
|
const slPctEl = document.getElementById("order-sl-pct");
|
||||||
const tpPctEl = document.getElementById("order-tp-pct");
|
const tpPctEl = document.getElementById("order-tp-pct");
|
||||||
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
if(!slEl || !tpEl || !slPctEl || !tpPctEl){ return; }
|
||||||
const pct = mode === "pct";
|
const pct = mode === "pct";
|
||||||
const fixed = mode === "fixed_rr";
|
const fixed = mode === "fixed_rr";
|
||||||
if(rrPreviewEl) rrPreviewEl.style.display = fixed ? "none" : "";
|
|
||||||
slEl.style.display = pct ? "none" : "";
|
slEl.style.display = pct ? "none" : "";
|
||||||
tpEl.style.display = (pct || fixed) ? "none" : "";
|
tpEl.style.display = (pct || fixed) ? "none" : "";
|
||||||
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
if(fixedRrEl) fixedRrEl.style.display = fixed ? "" : "none";
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% include order_rule_tips_tpl %}
|
{% include order_rule_tips_tpl %}
|
||||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
||||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||||
<select id="order-direction" name="direction" required>
|
<select id="order-direction" name="direction" required>
|
||||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||||
@@ -73,9 +73,9 @@
|
|||||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
<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-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">
|
<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="display:none;font-size:.82rem;color:#8fc8ff;align-self:center">预估盈亏比:—</span>
|
|
||||||
<button type="submit">{{ open_position_button_label }}</button>
|
<button type="submit">{{ open_position_button_label }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include 'order_plan_preview_bar.html' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">实时持仓</h2>
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
data-embed-shell="1"
|
data-embed-shell="1"
|
||||||
|
data-risk-percent="{{ risk_percent }}"
|
||||||
data-page="{{ initial_tab }}"
|
data-page="{{ initial_tab }}"
|
||||||
data-balance-refresh-ms="{{ balance_refresh_seconds * 1000 }}"
|
data-balance-refresh-ms="{{ balance_refresh_seconds * 1000 }}"
|
||||||
data-price-refresh-ms="{{ price_refresh_seconds * 1000 }}"
|
data-price-refresh-ms="{{ price_refresh_seconds * 1000 }}"
|
||||||
@@ -112,7 +113,7 @@
|
|||||||
<script src="/static/time_close_ui.js?v=2"></script>
|
<script src="/static/time_close_ui.js?v=2"></script>
|
||||||
<script src="/static/ai_review_render.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/form_submit_guard.js?v=2"></script>
|
||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=4"></script>
|
||||||
<script src="/static/key_monitor_form.js?v=1"></script>
|
<script src="/static/key_monitor_form.js?v=1"></script>
|
||||||
{% include 'embed_boot_scripts.html' %}
|
{% include 'embed_boot_scripts.html' %}
|
||||||
<script src="/static/instance_embed.js?v=4"></script>
|
<script src="/static/instance_embed.js?v=4"></script>
|
||||||
|
|||||||
@@ -64,6 +64,9 @@
|
|||||||
}
|
}
|
||||||
if (tab === "trade") {
|
if (tab === "trade") {
|
||||||
if (typeof global.refreshOrderDefaults === "function") global.refreshOrderDefaults();
|
if (typeof global.refreshOrderDefaults === "function") global.refreshOrderDefaults();
|
||||||
|
if (global.ManualOrderRrPreview && typeof global.ManualOrderRrPreview.wire === "function") {
|
||||||
|
global.ManualOrderRrPreview.wire();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tab === "key_monitor" && global.KeyMonitorForm && typeof global.KeyMonitorForm.init === "function") {
|
if (tab === "key_monitor" && global.KeyMonitorForm && typeof global.KeyMonitorForm.init === "function") {
|
||||||
global.KeyMonitorForm.init();
|
global.KeyMonitorForm.init();
|
||||||
|
|||||||
@@ -19,6 +19,15 @@
|
|||||||
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
.form-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
|
||||||
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
.form-row > input:not([type=checkbox]):not([type=radio]),.form-row > select{flex:0 1 auto;width:10rem;max-width:200px;min-width:7rem}
|
||||||
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
#add-order-form #sltp-mode{min-width:12.5rem;max-width:16rem;width:auto}
|
||||||
|
.order-plan-preview{display:flex;gap:18px;flex-wrap:wrap;align-items:center;margin:4px 0 10px;padding:10px 12px;background:#151a28;border:1px solid #2a3150;border-radius:8px;font-size:.85rem}
|
||||||
|
.order-preview-risk{color:#ff6b6b}
|
||||||
|
.order-preview-risk strong{color:#ff8f8f;font-weight:600}
|
||||||
|
.order-preview-profit{color:#4cd97f}
|
||||||
|
.order-preview-profit strong{color:#6ee7a0;font-weight:600}
|
||||||
|
.order-preview-rr{color:#cfd3ef}
|
||||||
|
.order-preview-rr strong{font-weight:600;color:#dbe4ff}
|
||||||
|
.order-preview-rr.order-preview-rr-low strong{color:#ff8f8f}
|
||||||
|
.order-preview-rr.order-preview-rr-ok strong{color:#8fc8ff}
|
||||||
.form-row > button,.form-row > label{flex:0 0 auto}
|
.form-row > button,.form-row > label{flex:0 0 auto}
|
||||||
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
.form-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||||||
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
/* 复盘表单:长下拉文案需可收缩,否则会撑破四列网格 */
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* 实盘下单:币种 + 止盈止损填完后拉 /api/order_defaults 快照,在开仓按钮前显示预估盈亏比。
|
* 实盘下单:填完币种与止盈止损后,在表单下方显示预估风险 / 预估盈利 / 预估盈亏比。
|
||||||
* 仅价格 / 百分比模式;固定盈亏比模式沿用「预估止盈」,不显示预估盈亏比。
|
|
||||||
*/
|
*/
|
||||||
(function (global) {
|
(function (global) {
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -27,6 +26,26 @@
|
|||||||
return body + ":1";
|
return body + ":1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatU(v) {
|
||||||
|
if (v === null || typeof v === "undefined" || !Number.isFinite(Number(v))) return "—";
|
||||||
|
return Number(v).toFixed(2) + "U";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMetric(el, label, valueText) {
|
||||||
|
if (!el) return;
|
||||||
|
el.innerHTML = label + ":<strong>" + valueText + "</strong>";
|
||||||
|
}
|
||||||
|
|
||||||
|
function riskPercent() {
|
||||||
|
const form = $("add-order-form");
|
||||||
|
const raw =
|
||||||
|
(form && form.getAttribute("data-risk-percent")) ||
|
||||||
|
(document.body && document.body.getAttribute("data-risk-percent")) ||
|
||||||
|
"";
|
||||||
|
const n = Number(raw);
|
||||||
|
return Number.isFinite(n) && n > 0 ? n : 1;
|
||||||
|
}
|
||||||
|
|
||||||
function calcRr(direction, entry, sl, tp) {
|
function calcRr(direction, entry, sl, tp) {
|
||||||
const e = num(entry);
|
const e = num(entry);
|
||||||
const s = num(sl);
|
const s = num(sl);
|
||||||
@@ -47,6 +66,19 @@
|
|||||||
return tp / sl;
|
return tp / sl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calcTpFromFixedRr(direction, entry, sl, rr) {
|
||||||
|
const e = num(entry);
|
||||||
|
const s = num(sl);
|
||||||
|
const r = num(rr);
|
||||||
|
if (e === null || s === null || r === null || r <= 0) return null;
|
||||||
|
if (direction === "short") {
|
||||||
|
if (s <= e) return null;
|
||||||
|
return e - (s - e) * r;
|
||||||
|
}
|
||||||
|
if (s >= e) return null;
|
||||||
|
return e + (e - s) * r;
|
||||||
|
}
|
||||||
|
|
||||||
function currentMode() {
|
function currentMode() {
|
||||||
return ($("sltp-mode") && $("sltp-mode").value) || "fixed_rr";
|
return ($("sltp-mode") && $("sltp-mode").value) || "fixed_rr";
|
||||||
}
|
}
|
||||||
@@ -67,101 +99,128 @@
|
|||||||
const tp = num($("order-tp-pct") && $("order-tp-pct").value);
|
const tp = num($("order-tp-pct") && $("order-tp-pct").value);
|
||||||
return sl !== null && tp !== null && sl > 0 && tp > 0;
|
return sl !== null && tp !== null && sl > 0 && tp > 0;
|
||||||
}
|
}
|
||||||
|
if (m === "fixed_rr") {
|
||||||
|
const sl = num($("order-sl") && $("order-sl").value);
|
||||||
|
const rr = num($("order-fixed-rr") && $("order-fixed-rr").value);
|
||||||
|
return sl !== null && rr !== null && sl > 0 && rr > 0;
|
||||||
|
}
|
||||||
const sl = num($("order-sl") && $("order-sl").value);
|
const sl = num($("order-sl") && $("order-sl").value);
|
||||||
const tp = num($("order-tp") && $("order-tp").value);
|
const tp = num($("order-tp") && $("order-tp").value);
|
||||||
return sl !== null && tp !== null && sl > 0 && tp > 0;
|
return sl !== null && tp !== null && sl > 0 && tp > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hidePreview() {
|
function paintEmpty() {
|
||||||
const el = $("order-rr-preview");
|
setMetric($("order-risk-preview"), "预估风险", "—");
|
||||||
if (el) el.style.display = "none";
|
setMetric($("order-profit-preview"), "预估盈利", "—");
|
||||||
|
setMetric($("order-rr-preview"), "预估盈亏比", "—");
|
||||||
}
|
}
|
||||||
|
|
||||||
function paint(rr, state) {
|
function paintLoading() {
|
||||||
const el = $("order-rr-preview");
|
setMetric($("order-risk-preview"), "预估风险", "计算中…");
|
||||||
if (!el) return;
|
setMetric($("order-profit-preview"), "预估盈利", "计算中…");
|
||||||
const m = currentMode();
|
setMetric($("order-rr-preview"), "预估盈亏比", "计算中…");
|
||||||
if (m === "fixed_rr" || (m !== "price" && m !== "pct")) {
|
}
|
||||||
el.style.display = "none";
|
|
||||||
return;
|
function paintFail(kind) {
|
||||||
|
const msg = kind === "fetch_fail" ? "取价失败" : "无效";
|
||||||
|
setMetric($("order-risk-preview"), "预估风险", msg);
|
||||||
|
setMetric($("order-profit-preview"), "预估盈利", msg);
|
||||||
|
setMetric($("order-rr-preview"), "预估盈亏比", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function paintOk(riskU, profitU, rr) {
|
||||||
|
setMetric($("order-risk-preview"), "预估风险", formatU(riskU));
|
||||||
|
setMetric($("order-profit-preview"), "预估盈利", formatU(profitU));
|
||||||
|
const rrEl = $("order-rr-preview");
|
||||||
|
const rrText = formatRr(rr);
|
||||||
|
setMetric(rrEl, "预估盈亏比", rrText);
|
||||||
|
if (rrEl && rr !== null && Number.isFinite(Number(rr))) {
|
||||||
|
rrEl.classList.toggle("order-preview-rr-low", Number(rr) < minRr);
|
||||||
|
rrEl.classList.toggle("order-preview-rr-ok", Number(rr) >= minRr);
|
||||||
}
|
}
|
||||||
el.style.display = "";
|
}
|
||||||
if (state === "empty") {
|
|
||||||
el.textContent = "预估盈亏比:—";
|
function plannedRiskU(capital) {
|
||||||
el.style.color = "#8fc8ff";
|
const cap = num(capital);
|
||||||
return;
|
if (cap === null || cap <= 0) return null;
|
||||||
|
return Math.round((cap * riskPercent()) / 100 * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePreviewRr(m, dir, entry, data) {
|
||||||
|
if (m === "pct") {
|
||||||
|
return calcRrFromPct(
|
||||||
|
$("order-sl-pct") && $("order-sl-pct").value,
|
||||||
|
$("order-tp-pct") && $("order-tp-pct").value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (state === "loading") {
|
const sl = num($("order-sl") && $("order-sl").value);
|
||||||
el.textContent = "预估盈亏比:计算中…";
|
if (m === "fixed_rr") {
|
||||||
el.style.color = "#8fc8ff";
|
const fixed = num($("order-fixed-rr") && $("order-fixed-rr").value);
|
||||||
return;
|
if (fixed !== null && fixed > 0) return fixed;
|
||||||
|
const tp = calcTpFromFixedRr(dir, entry, sl, fixed);
|
||||||
|
return calcRr(dir, entry, sl, tp);
|
||||||
}
|
}
|
||||||
if (state === "fetch_fail") {
|
const tp = num($("order-tp") && $("order-tp").value);
|
||||||
el.textContent = "预估盈亏比:取价失败";
|
return calcRr(dir, entry, sl, tp);
|
||||||
el.style.color = "#ff8f8f";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rr === null) {
|
|
||||||
el.textContent = "预估盈亏比:无效";
|
|
||||||
el.style.color = "#ff8f8f";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.textContent = "预估盈亏比:" + formatRr(rr);
|
|
||||||
el.style.color = rr >= minRr ? "#4cd97f" : "#ff8f8f";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshNow() {
|
function refreshNow() {
|
||||||
|
if (!$("order-plan-preview")) return;
|
||||||
const m = currentMode();
|
const m = currentMode();
|
||||||
if (m === "fixed_rr") {
|
|
||||||
hidePreview();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!inputsComplete(m)) {
|
if (!inputsComplete(m)) {
|
||||||
paint(null, "empty");
|
paintEmpty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sym = currentSymbol();
|
const sym = currentSymbol();
|
||||||
const dir = currentDirection();
|
const dir = currentDirection();
|
||||||
const seq = ++fetchSeq;
|
const seq = ++fetchSeq;
|
||||||
paint(null, "loading");
|
paintLoading();
|
||||||
|
|
||||||
fetch(
|
const defaultsP = fetch(
|
||||||
"/api/order_defaults?symbol=" +
|
"/api/order_defaults?symbol=" +
|
||||||
encodeURIComponent(sym) +
|
encodeURIComponent(sym) +
|
||||||
"&direction=" +
|
"&direction=" +
|
||||||
encodeURIComponent(dir)
|
encodeURIComponent(dir)
|
||||||
)
|
).then(function (r) {
|
||||||
.then(function (r) {
|
return r.json();
|
||||||
return r.json();
|
});
|
||||||
})
|
|
||||||
.then(function (data) {
|
const capitalP = fetch("/api/account_snapshot").then(function (r) {
|
||||||
|
return r.json();
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all([defaultsP, capitalP])
|
||||||
|
.then(function (results) {
|
||||||
if (seq !== fetchSeq) return;
|
if (seq !== fetchSeq) return;
|
||||||
|
const data = results[0];
|
||||||
|
const account = results[1] || {};
|
||||||
if (!data.ok) {
|
if (!data.ok) {
|
||||||
paint(null, "fetch_fail");
|
paintFail("fetch_fail");
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m === "pct") {
|
|
||||||
const rr = calcRrFromPct(
|
|
||||||
$("order-sl-pct") && $("order-sl-pct").value,
|
|
||||||
$("order-tp-pct") && $("order-tp-pct").value
|
|
||||||
);
|
|
||||||
paint(rr, rr === null ? "invalid" : "ok");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const entry = num(data.last_price != null ? data.last_price : data.price);
|
const entry = num(data.last_price != null ? data.last_price : data.price);
|
||||||
if (entry === null) {
|
if (entry === null) {
|
||||||
paint(null, "fetch_fail");
|
paintFail("fetch_fail");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const sl = num($("order-sl") && $("order-sl").value);
|
const rr = resolvePreviewRr(m, dir, entry, data);
|
||||||
const tp = num($("order-tp") && $("order-tp").value);
|
if (rr === null) {
|
||||||
const rr = calcRr(dir, entry, sl, tp);
|
paintFail("invalid");
|
||||||
paint(rr, rr === null ? "invalid" : "ok");
|
return;
|
||||||
|
}
|
||||||
|
const capital = num(account.current_capital);
|
||||||
|
const riskU = plannedRiskU(capital);
|
||||||
|
if (riskU === null) {
|
||||||
|
paintFail("fetch_fail");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const profitU = Math.round(riskU * rr * 100) / 100;
|
||||||
|
paintOk(riskU, profitU, rr);
|
||||||
})
|
})
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
if (seq !== fetchSeq) return;
|
if (seq !== fetchSeq) return;
|
||||||
paint(null, "fetch_fail");
|
paintFail("fetch_fail");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +246,7 @@
|
|||||||
"order-sl-pct",
|
"order-sl-pct",
|
||||||
"order-tp-pct",
|
"order-tp-pct",
|
||||||
"order-fixed-rr",
|
"order-fixed-rr",
|
||||||
|
"order-leverage",
|
||||||
].forEach(function (id) {
|
].forEach(function (id) {
|
||||||
const el = $(id);
|
const el = $(id);
|
||||||
if (!el || el._rrPreviewBound) return;
|
if (!el || el._rrPreviewBound) return;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<div id="order-plan-preview" class="order-plan-preview">
|
||||||
|
<span id="order-risk-preview" class="order-preview-risk">预估风险:<strong>—</strong></span>
|
||||||
|
<span id="order-profit-preview" class="order-preview-profit">预估盈利:<strong>—</strong></span>
|
||||||
|
<span id="order-rr-preview" class="order-preview-rr">预估盈亏比:<strong>—</strong></span>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user