feat: 计仓改为固定手数/固定金额,推荐过滤与CTP保证金,下单与持仓UI优化
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+27
-6
@@ -54,14 +54,18 @@
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>计仓模式</label>
|
||||
<select name="position_sizing_mode">
|
||||
<option value="risk" {% if position_sizing_mode == 'risk' %}selected{% endif %}>以损定仓</option>
|
||||
<option value="fixed" {% if position_sizing_mode == 'fixed' %}selected{% endif %}>固定张数</option>
|
||||
<select name="position_sizing_mode" id="position-sizing-mode">
|
||||
<option value="fixed" {% if position_sizing_mode == 'fixed' %}selected{% endif %}>固定手数</option>
|
||||
<option value="amount" {% if position_sizing_mode in ('amount', 'risk') %}selected{% endif %}>固定金额</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>单笔风险比例(以损定仓,%)</label>
|
||||
<input name="risk_percent" type="number" step="0.1" min="0.1" max="100" value="{{ risk_percent }}">
|
||||
<div class="field" id="field-fixed-lots" {% if position_sizing_mode in ('amount', 'risk') %}hidden{% endif %}>
|
||||
<label>固定手数(手)</label>
|
||||
<input name="fixed_lots" type="number" step="1" min="1" value="{{ fixed_lots }}">
|
||||
</div>
|
||||
<div class="field" id="field-fixed-amount" {% if position_sizing_mode not in ('amount', 'risk') %}hidden{% endif %}>
|
||||
<label>固定金额(元)</label>
|
||||
<input name="fixed_amount" type="number" step="100" min="1" value="{{ fixed_amount }}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>保证金占用上限(%)</label>
|
||||
@@ -146,3 +150,20 @@
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
(function () {
|
||||
var sel = document.getElementById('position-sizing-mode');
|
||||
var lotsField = document.getElementById('field-fixed-lots');
|
||||
var amountField = document.getElementById('field-fixed-amount');
|
||||
function syncSizingFields() {
|
||||
if (!sel) return;
|
||||
var isAmount = sel.value === 'amount';
|
||||
if (lotsField) lotsField.hidden = isAmount;
|
||||
if (amountField) amountField.hidden = !isAmount;
|
||||
}
|
||||
if (sel) sel.addEventListener('change', syncSizingFields);
|
||||
syncSizingFields();
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
+13
-8
@@ -31,7 +31,11 @@
|
||||
<div class="status-row">
|
||||
<span class="text-muted">计仓</span>
|
||||
<strong id="sizing-label">{{ sizing_mode_label }}</strong>
|
||||
{% if sizing_mode == 'risk' %}<span class="text-muted">· 单笔风险 {{ risk_percent }}%</span>{% endif %}
|
||||
{% if sizing_mode == 'fixed' %}
|
||||
<span class="text-muted">· {{ fixed_lots }} 手</span>
|
||||
{% elif sizing_mode in ('amount', 'risk') %}
|
||||
<span class="text-muted">· {{ '%.0f'|format(fixed_amount) }} 元</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,8 +57,8 @@
|
||||
</div>
|
||||
<div class="trade-field" id="field-lots">
|
||||
<label class="text-label">手数</label>
|
||||
<input type="number" id="trade-lots" min="1" step="1" value="1" {% if sizing_mode == 'risk' %}hidden{% endif %}>
|
||||
<input type="text" id="trade-lots-calc" class="lots-auto" readonly placeholder="填写止损后自动计算" {% if sizing_mode != 'risk' %}hidden{% endif %}>
|
||||
<input type="text" id="trade-lots-calc" class="lots-auto" readonly placeholder="—">
|
||||
<input type="hidden" id="trade-lots" value="{{ fixed_lots if sizing_mode == 'fixed' else '1' }}">
|
||||
<p class="hint lots-warn text-loss" id="lots-warn" hidden></p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,8 +99,6 @@
|
||||
<p class="hint" id="trade-metrics-hint">填写品种后显示精度与每跳价值;策略自动化请用 <a href="{{ url_for('strategy_page') }}">策略交易</a>。</p>
|
||||
{% if ctp_status.last_error %}
|
||||
<p class="text-loss ctp-install-hint" style="font-size:.78rem;margin-top:.35rem">{{ ctp_status.last_error }}</p>
|
||||
{% else %}
|
||||
<p class="text-muted ctp-install-hint" style="font-size:.72rem;margin-top:.35rem">报单需安装 vnpy 并连接 CTP(SimNow 模拟盘)。</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,7 +116,9 @@
|
||||
<div class="card trade-card trade-card-full" id="recommend">
|
||||
<h2>品种推荐</h2>
|
||||
<div class="card-body">
|
||||
<p class="hint">最大手数 = floor(权益 × 保证金上限 <strong>{{ max_margin_pct }}%</strong> ÷ 1手保证金);当前权益 <strong class="text-accent" id="rec-capital">{{ '%.2f'|format(capital) }}</strong> 元。参考止损/止盈按 20 跳、盈亏比 2:1 估算。
|
||||
<p class="hint">最大手数 = floor(权益 × 保证金上限 <strong>{{ max_margin_pct }}%</strong> ÷ 1手保证金);当前权益 <strong class="text-accent" id="rec-capital">{{ '%.2f'|format(capital) }}</strong> 元。
|
||||
{% if sizing_mode == 'fixed' %}仅显示最大手数 ≥ <strong>{{ fixed_lots }}</strong> 手的品种。{% endif %}
|
||||
保证金优先读取 CTP 柜台合约信息。
|
||||
{% if recommend_updated_at %}<span class="text-muted">每日后台更新 · 最近 {{ recommend_updated_at }}</span>{% else %}<span class="text-muted" id="rec-updated">等待今日后台刷新…</span>{% endif %}
|
||||
</p>
|
||||
<div class="trade-table-wrap">
|
||||
@@ -135,7 +139,7 @@
|
||||
<td>{% if r.price %}{{ r.price }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.ref_stop_loss %}{{ r.ref_stop_loss }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.ref_take_profit %}{{ r.ref_take_profit }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.margin_one_lot %}{{ r.margin_one_lot }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.margin_one_lot %}{{ r.margin_one_lot }}{% if r.margin_source == 'ctp' %} <span class="text-muted">(柜台)</span>{% endif %}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.open_fee_one_lot is defined and r.open_fee_one_lot is not none %}{{ r.open_fee_one_lot }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.max_lots is not none and r.max_lots > 0 %}{{ r.max_lots }}{% else %}—{% endif %}</td>
|
||||
<td><span class="badge {% if r.status=='ok' %}profit{% else %}planned{% endif %}">{{ r.status_label }}</span></td>
|
||||
@@ -154,7 +158,8 @@
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
window.TRADE_SIZING_MODE = {{ sizing_mode|tojson }};
|
||||
window.TRADE_RISK_PERCENT = {{ risk_percent }};
|
||||
window.TRADE_FIXED_LOTS = {{ fixed_lots|tojson }};
|
||||
window.TRADE_FIXED_AMOUNT = {{ fixed_amount|tojson }};
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='js/trade.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user