接入 SimNow 模拟盘与期货下单、策略及品种推荐功能。
新增 vnpy CTP 桥接、以损定仓/固定张数、趋势回调与滚仓策略、按资金推荐品种及交易风控;模拟盘走 SimNow,实盘预留期货公司配置。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -483,6 +483,9 @@
|
||||
<h1 class="site-title">国内期货 · 交易监控 + 复盘<span class="site-title-sub">FUTURES MONITOR SYSTEM</span></h1>
|
||||
<button type="button" class="nav-backdrop" id="nav-backdrop" aria-label="关闭菜单" hidden></button>
|
||||
<nav class="site-nav" id="site-nav">
|
||||
<a href="{{ url_for('trade_page') }}" class="{% if request.endpoint == 'trade_page' %}active{% endif %}">期货下单</a>
|
||||
<a href="{{ url_for('recommend_page') }}" class="{% if request.endpoint == 'recommend_page' %}active{% endif %}">品种推荐</a>
|
||||
<a href="{{ url_for('strategy_page') }}" class="{% if request.endpoint in ('strategy_page', 'strategy_records_page') %}active{% endif %}">策略交易</a>
|
||||
<a href="{{ url_for('plans') }}" class="{% if request.endpoint == 'plans' %}active{% endif %}">开单计划</a>
|
||||
<a href="{{ url_for('keys') }}" class="{% if request.endpoint == 'keys' %}active{% endif %}">关键位监控</a>
|
||||
<a href="{{ url_for('positions') }}" class="{% if request.endpoint == 'positions' %}active{% endif %}">持仓监控</a>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<div class="market-chart-empty" id="market-chart-empty">请选择合约并点击「查看」</div>
|
||||
<div class="market-chart-loading" id="market-chart-loading">连接中…</div>
|
||||
</div>
|
||||
<p class="hint">数据来源:新浪财经。K 线由后台自动刷新并经 SSE 推送到前端;支持滚轮/拖拽缩放。可视区内自动标注最高/最低价。</p>
|
||||
<p class="hint">数据来源:新浪财经。拖拽左右平移、滚轮缩放;按住图表上下拖动可平移价格轴。可视区内自动标注最高/最低价。</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}品种推荐 - 国内期货监控系统{% endblock %}
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<h2>品种推荐 · 按资金筛选</h2>
|
||||
<p class="hint">当前权益 <strong class="text-accent">{{ '%.2f'|format(capital) }}</strong> 元({{ trading_mode_label }})。
|
||||
优先展示可开 1 手且 1% 风险规则下较友好的品种;灰色为保证金不足。</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="trade-table-wrap">
|
||||
<table class="trade-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>品种</th><th>交易所</th><th>参考价</th><th>1手保证金</th><th>建议最低资金</th><th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in rows %}
|
||||
<tr class="rec-{{ r.status }}">
|
||||
<td><strong>{{ r.name }}</strong> <span class="text-muted">{{ r.ths }}</span></td>
|
||||
<td>{{ r.exchange }}</td>
|
||||
<td>{% if r.price %}{{ r.price }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.margin_one_lot %}{{ r.margin_one_lot }}{% else %}—{% endif %}</td>
|
||||
<td>{% if r.min_capital_one_lot %}{{ r.min_capital_one_lot }}{% else %}—{% endif %}</td>
|
||||
<td><span class="badge {% if r.status=='ok' %}profit{% elif r.status=='blocked' %}loss{% else %}planned{% endif %}">{{ r.status_label }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
+38
-3
@@ -3,13 +3,48 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="card">
|
||||
<h2>实盘资金</h2>
|
||||
<h2>交易模式</h2>
|
||||
<form action="{{ url_for('settings') }}" method="post">
|
||||
<input type="hidden" name="action" value="trading">
|
||||
<div class="form-grid" style="max-width:640px">
|
||||
<div class="field">
|
||||
<label>交易通道</label>
|
||||
<select name="trading_mode">
|
||||
<option value="simulation" {% if trading_mode == 'simulation' %}selected{% endif %}>模拟盘 · SimNow(vnpy CTP)</option>
|
||||
<option value="live" {% if trading_mode == 'live' %}selected{% endif %}>实盘 · 期货公司 CTP(后期接入)</option>
|
||||
</select>
|
||||
</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>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>单笔风险比例(以损定仓,%)</label>
|
||||
<input name="risk_percent" type="number" step="0.1" min="0.1" max="100" value="{{ risk_percent }}">
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary" style="margin-top:.75rem">保存交易设置</button>
|
||||
</form>
|
||||
<p class="hint" style="margin-top:.75rem">
|
||||
<strong>模拟盘</strong>连接上期 SimNow 仿真柜台(非本地假资金)。在 <code>.env</code> 配置
|
||||
<code>SIMNOW_USER</code>、<code>SIMNOW_PASSWORD</code> 等,在「期货下单」页点击连接 CTP。<br>
|
||||
<strong>实盘</strong>后期配置 <code>CTP_LIVE_*</code> 对接你的期货公司。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>参考资金</h2>
|
||||
<form action="{{ url_for('settings') }}" method="post" class="form-row">
|
||||
<input type="hidden" name="action" value="capital">
|
||||
<input name="live_capital" type="number" step="0.01" min="0" placeholder="实盘资金(元)" value="{{ live_capital }}" style="flex:1;min-width:200px;max-width:320px">
|
||||
<input name="live_capital" type="number" step="0.01" min="0" placeholder="参考权益(元)" value="{{ live_capital }}" style="flex:1;min-width:200px;max-width:320px">
|
||||
<button type="submit" class="btn-primary">保存</button>
|
||||
</form>
|
||||
<p class="hint" style="margin-top:.75rem">用于持仓监控的风险比例、仓位占比计算,保存在数据库中。</p>
|
||||
<p class="hint" style="margin-top:.75rem">
|
||||
CTP 未连接时用于<strong>品种推荐</strong>与以损定仓估算;SimNow/实盘登录成功后自动改用<strong>柜台权益</strong>。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}策略交易 - 国内期货监控系统{% endblock %}
|
||||
{% block content %}
|
||||
<div class="split-grid">
|
||||
<div class="card">
|
||||
<h2>趋势回调</h2>
|
||||
{% if active_trend %}
|
||||
<p class="hint">运行中 #{{ active_trend.id }} {{ active_trend.symbol }} {{ active_trend.direction }}
|
||||
已开 {{ active_trend.lots_open or 0 }}/{{ active_trend.target_lots }} 手</p>
|
||||
<form id="trend-stop-form" class="form-row">
|
||||
<input type="hidden" name="plan_id" value="{{ active_trend.id }}">
|
||||
<button type="button" class="btn-primary" id="btn-trend-stop">结束计划</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form id="trend-form" class="form-compact">
|
||||
<div class="form-line line-2">
|
||||
<div class="symbol-wrap"><input class="symbol-input" name="symbol" placeholder="合约" required><div class="symbol-dropdown"></div></div>
|
||||
<select name="direction"><option value="long">做多</option><option value="short">做空</option></select>
|
||||
</div>
|
||||
<div class="form-line line-3">
|
||||
<input name="stop_loss" type="number" step="any" placeholder="止损" required>
|
||||
<input name="add_upper" type="number" step="any" placeholder="补仓边界" required>
|
||||
<input name="take_profit" type="number" step="any" placeholder="止盈" required>
|
||||
</div>
|
||||
<div class="form-line line-2">
|
||||
<input name="risk_percent" type="number" step="0.1" value="{{ risk_percent }}" placeholder="风险%">
|
||||
<button type="button" class="btn-primary" id="btn-trend-preview">预览</button>
|
||||
</div>
|
||||
</form>
|
||||
<pre id="trend-preview" class="hint" style="white-space:pre-wrap;margin-top:.75rem"></pre>
|
||||
<button type="button" class="btn-primary" id="btn-trend-exec" hidden>确认执行首仓</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>顺势加仓(滚仓)</h2>
|
||||
<p class="hint">须先有「下单监控」持仓;最多 3 腿;止盈锁首仓。</p>
|
||||
{% if monitors %}
|
||||
<form id="roll-form" class="form-compact">
|
||||
<select name="monitor_id" required>
|
||||
{% for m in monitors %}
|
||||
<option value="{{ m.id }}">{{ m.symbol }} {{ m.direction }} {{ m.lots }}手</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-line line-2">
|
||||
<input name="new_stop_loss" type="number" step="any" placeholder="新统一止损" required>
|
||||
<input name="risk_percent" type="number" step="0.1" value="2" placeholder="总风险%">
|
||||
</div>
|
||||
<div class="form-line line-2">
|
||||
<input name="add_price" type="number" step="any" placeholder="加仓参考价">
|
||||
<button type="button" class="btn-primary" id="btn-roll-preview">预览</button>
|
||||
</div>
|
||||
<pre id="roll-preview" class="hint" style="white-space:pre-wrap"></pre>
|
||||
<button type="button" class="btn-primary" id="btn-roll-exec" hidden>执行滚仓</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="empty-hint">请先在「期货下单」开仓并建立监控。</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint"><a href="{{ url_for('strategy_records_page') }}">策略交易记录 →</a></p>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script src="{{ url_for('static', filename='js/strategy.js') }}"></script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}策略记录 - 国内期货监控系统{% endblock %}
|
||||
{% block content %}
|
||||
<div class="split-grid">
|
||||
<div class="card card-scroll">
|
||||
<h2>趋势回调</h2>
|
||||
{% if trend_rows %}
|
||||
<ul class="list">{% for r in trend_rows %}
|
||||
<li class="list-item"><span>{{ r.symbol }} {{ r.result_label }} · {{ r.closed_at or r.created_at }}</span></li>
|
||||
{% endfor %}</ul>
|
||||
{% else %}<p class="empty-hint">暂无记录</p>{% endif %}
|
||||
</div>
|
||||
<div class="card card-scroll">
|
||||
<h2>顺势加仓</h2>
|
||||
{% if roll_rows %}
|
||||
<ul class="list">{% for r in roll_rows %}
|
||||
<li class="list-item"><span>{{ r.symbol }} {{ r.result_label }} · {{ r.closed_at or r.created_at }}</span></li>
|
||||
{% endfor %}</ul>
|
||||
{% else %}<p class="empty-hint">暂无记录</p>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,96 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}期货下单 - 国内期货监控系统{% endblock %}
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/trade.css') }}">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="trade-page">
|
||||
<div class="trade-top-bar">
|
||||
<span class="badge dir">{{ trading_mode_label }}</span>
|
||||
<span class="badge {% if ctp_status.connected %}profit{% else %}planned{% endif %}" id="ctp-badge">
|
||||
{% if ctp_status.connected %}CTP 已连接{% else %}CTP 未连接{% endif %}
|
||||
</span>
|
||||
<span class="badge {% if risk_status.can_trade %}profit{% else %}loss{% endif %}" id="risk-badge">{{ risk_status.status_label }}</span>
|
||||
<span class="text-muted">权益 <strong id="cap-display">{{ '%.2f'|format(capital) }}</strong> 元</span>
|
||||
<button type="button" class="btn-primary" id="btn-ctp-connect" style="padding:.4rem .9rem;font-size:.8rem">连接 CTP</button>
|
||||
</div>
|
||||
|
||||
<div class="card trade-order-card">
|
||||
<div class="trade-tabs">
|
||||
<span class="active">期货下单</span>
|
||||
<a href="{{ url_for('recommend_page') }}">品种推荐</a>
|
||||
<a href="{{ url_for('strategy_page') }}">策略交易</a>
|
||||
</div>
|
||||
|
||||
<div class="trade-input-row">
|
||||
<div class="symbol-wrap trade-field">
|
||||
<label class="text-label">品种</label>
|
||||
<input type="text" id="trade-symbol" class="symbol-input" placeholder="主力合约 rb2610" autocomplete="off" value="">
|
||||
<div class="symbol-dropdown"></div>
|
||||
<div class="symbol-selected" id="sym-selected"></div>
|
||||
</div>
|
||||
<div class="trade-field">
|
||||
<label class="text-label">手数</label>
|
||||
<input type="number" id="trade-lots" min="1" step="1" value="1">
|
||||
</div>
|
||||
<div class="trade-field">
|
||||
<label class="text-label">价格</label>
|
||||
<input type="number" id="trade-price" step="any" placeholder="限价">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="risk-fields" class="trade-risk-row" {% if sizing_mode != 'risk' %}hidden{% endif %}>
|
||||
<div class="trade-field"><label class="text-label">止损</label><input type="number" id="trade-sl" step="any"></div>
|
||||
<div class="trade-field"><label class="text-label">止盈</label><input type="number" id="trade-tp" step="any"></div>
|
||||
</div>
|
||||
|
||||
<div class="trade-btn-row">
|
||||
<button type="button" class="trade-btn long" id="btn-open-long">
|
||||
<span class="btn-price" id="px-long">—</span>
|
||||
<span class="btn-label">加多</span>
|
||||
<span class="btn-sub" id="max-long">≤—</span>
|
||||
</button>
|
||||
<button type="button" class="trade-btn lock" id="btn-open-short">
|
||||
<span class="btn-price" id="px-short">—</span>
|
||||
<span class="btn-label">加空</span>
|
||||
<span class="btn-sub" id="max-short">≤—</span>
|
||||
</button>
|
||||
<button type="button" class="trade-btn close" id="btn-close-long">
|
||||
<span class="btn-sub">平多</span>
|
||||
<span class="btn-label">平多</span>
|
||||
<span class="btn-sub" id="pos-long">≤0</span>
|
||||
</button>
|
||||
<button type="button" class="trade-btn close" id="btn-close-short">
|
||||
<span class="btn-sub">平空</span>
|
||||
<span class="btn-label">平空</span>
|
||||
<span class="btn-sub" id="pos-short">≤0</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="trade-footer" id="trade-footer">
|
||||
<p class="hint">SimNow 模拟盘:请先连接 CTP。输入品种与手数后显示跳动价值与价格精度。</p>
|
||||
{% if ctp_status.last_error %}<p class="text-loss" style="font-size:.78rem">{{ ctp_status.last_error }}</p>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if ctp_positions %}
|
||||
<div class="card">
|
||||
<h2>CTP 持仓(SimNow / 柜台)</h2>
|
||||
<ul class="list">
|
||||
{% for p in ctp_positions %}
|
||||
<li class="list-item">
|
||||
<span>{{ p.symbol }} {{ '多' if p.direction=='long' else '空' }} {{ p.lots }}手 @ {{ p.avg_price }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
window.TRADE_SIZING_MODE = {{ sizing_mode|tojson }};
|
||||
window.TRADE_RISK_PERCENT = {{ risk_percent }};
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='js/trade.js') }}"></script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user