本地手续费配置(标准×2),持仓/交易记录/复盘/统计展示扣费后盈亏

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-15 15:22:40 +08:00
parent 9ba9733523
commit bea7804d47
11 changed files with 669 additions and 20 deletions
+2 -1
View File
@@ -341,7 +341,7 @@
.pos-card-head .title{font-size:1rem;font-weight:600;color:var(--text-title)}
.pos-card-meta{font-size:.75rem;color:var(--text-muted);margin-bottom:.65rem}
.pos-card-meta strong{color:var(--text-primary)}
.pos-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem .65rem;margin-bottom:.65rem}
.pos-metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem .65rem;margin-bottom:.65rem}
.pos-metrics .cell label{display:block;font-size:.68rem;color:var(--text-muted);margin-bottom:.15rem}
.pos-metrics .cell div{font-size:.88rem;color:var(--text-primary)}
.pos-metrics .cell.pnl-pos div{color:var(--profit)}
@@ -405,6 +405,7 @@
<a href="{{ url_for('positions') }}" class="{% if request.endpoint == 'positions' %}active{% endif %}">持仓监控</a>
<a href="{{ url_for('records') }}" class="{% if request.endpoint in ('records', 'trades') %}active{% endif %}">交易记录与复盘</a>
<a href="{{ url_for('stats') }}" class="{% if request.endpoint == 'stats' %}active{% endif %}">统计分析</a>
<a href="{{ url_for('fees') }}" class="{% if request.endpoint == 'fees' %}active{% endif %}">手续费配置</a>
<a href="{{ url_for('settings') }}" class="{% if request.endpoint == 'settings' %}active{% endif %}">系统设置</a>
</nav>
</header>
+67
View File
@@ -0,0 +1,67 @@
{% extends "base.html" %}
{% block title %}手续费配置 - 国内期货监控系统{% endblock %}
{% block content %}
<div class="card">
<h2>手续费倍率</h2>
<div class="card-body">
<form action="{{ url_for('fees') }}" method="post" class="form-row">
<input type="hidden" name="action" value="multiplier">
<label class="text-muted" style="font-size:.85rem">第三方标准费率 ×</label>
<input name="fee_multiplier" type="number" step="0.1" min="0" value="{{ multiplier }}" style="width:100px">
<button type="submit" class="btn-primary">保存倍率</button>
</form>
<p class="hint">默认 2 倍:从第三方拉取交易所参考标准后自动乘以该倍率写入本地表。模拟盘估算用,非实盘账单。</p>
<div class="form-row" style="margin-top:.75rem">
<form action="{{ url_for('fees') }}" method="post" style="display:inline">
<input type="hidden" name="action" value="sync">
<button type="submit" class="btn-primary">从第三方同步(AKShare</button>
</form>
<form action="{{ url_for('fees') }}" method="post" style="display:inline">
<input type="hidden" name="action" value="reload_json">
<button type="submit" class="btn-link" style="padding:.5rem 1rem;border:1px solid var(--card-border);border-radius:8px">重载本地 JSON 默认表</button>
</form>
</div>
</div>
</div>
<div class="card">
<h2>品种费率表(已含倍率)</h2>
<div class="card-body card-scroll">
<table class="trade-table">
<thead>
<tr>
<th>品种</th><th>交易所</th><th>乘数</th>
<th>开仓(元/手)</th><th>开仓(比例)</th>
<th>平昨(元/手)</th><th>平昨(比例)</th>
<th>平今(元/手)</th><th>平今(比例)</th>
<th>更新</th><th>操作</th>
</tr>
</thead>
<tbody>
{% for r in rates %}
<tr>
<form action="{{ url_for('fees') }}" method="post" style="display:contents">
<input type="hidden" name="action" value="save_row">
<input type="hidden" name="product" value="{{ r.product }}">
<td><strong>{{ r.product }}</strong></td>
<td><input name="exchange" value="{{ r.exchange or '' }}" style="width:72px;padding:.3rem"></td>
<td><input name="mult" type="number" value="{{ r.mult }}" style="width:56px;padding:.3rem"></td>
<td><input name="open_fixed" type="number" step="0.0001" value="{{ r.open_fixed }}" style="width:72px;padding:.3rem"></td>
<td><input name="open_ratio" type="number" step="0.0000001" value="{{ r.open_ratio }}" style="width:88px;padding:.3rem"></td>
<td><input name="close_yesterday_fixed" type="number" step="0.0001" value="{{ r.close_yesterday_fixed }}" style="width:72px;padding:.3rem"></td>
<td><input name="close_yesterday_ratio" type="number" step="0.0000001" value="{{ r.close_yesterday_ratio }}" style="width:88px;padding:.3rem"></td>
<td><input name="close_today_fixed" type="number" step="0.0001" value="{{ r.close_today_fixed }}" style="width:72px;padding:.3rem"></td>
<td><input name="close_today_ratio" type="number" step="0.0000001" value="{{ r.close_today_ratio }}" style="width:88px;padding:.3rem"></td>
<td class="text-muted" style="font-size:.72rem">{{ (r.updated_at or '')[:16] }}</td>
<td><button type="submit" class="btn-link">保存</button></td>
</form>
</tr>
{% else %}
<tr><td colspan="11" class="text-muted">暂无费率,请同步或重载 JSON</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<p class="hint" style="margin-top:.75rem">比例按「成交价×乘数×手数×比例」计费;元/手为固定每手。开+平合计为一笔往返手续费。</p>
</div>
{% endblock %}
+17 -4
View File
@@ -16,7 +16,7 @@
<th>成交</th><th>止损(开仓)</th><th>止盈</th>
<th>基数</th><th>杠杆</th><th>持仓分钟</th>
<th>开仓时间</th><th>平仓时间</th>
<th>盈亏(元)</th><th>结果</th><th>操作</th>
<th>盈亏(元)</th><th>手续费</th><th>净盈亏</th><th>结果</th><th>操作</th>
</tr>
</thead>
<tbody>
@@ -74,6 +74,12 @@
<input type="hidden" name="close_price" value="{{ t.close_price or '' }}">
<input type="hidden" name="symbol_name" value="{{ t.symbol_name or t.symbol }}">
</td>
<td><span class="cell-readonly text-muted">{{ t.fee if t.fee is not none else '-' }}</span></td>
<td>
<span class="cell-readonly {% if t.pnl_net and t.pnl_net > 0 %}text-profit{% elif t.pnl_net and t.pnl_net < 0 %}text-loss{% endif %}">
{{ t.pnl_net if t.pnl_net is not none else '-' }}
</span>
</td>
<td>
<span class="cell-readonly cell-edit-hide">
{% if t.result == '止盈' %}<span class="badge profit">{{ t.result }}</span>
@@ -99,7 +105,7 @@
</td>
</tr>
{% else %}
<tr><td colspan="14" class="text-muted">暂无交易记录</td></tr>
<tr><td colspan="16" class="text-muted">暂无交易记录</td></tr>
{% endfor %}
</tbody>
</table>
@@ -208,7 +214,7 @@
<table>
<thead>
<tr>
<th>平仓</th><th>品种</th><th>方向</th><th>盈亏</th><th>情绪单</th><th>详情</th><th></th>
<th>平仓</th><th>品种</th><th>方向</th><th>盈亏</th><th>手续费</th><th>净盈亏</th><th>情绪单</th><th>详情</th><th></th>
</tr>
</thead>
<tbody>
@@ -222,6 +228,12 @@
{% elif r.pnl and r.pnl < 0 %}<span class="badge loss">{{ r.pnl }}</span>
{% else %}{{ r.actual_pnl or '-' }}{% endif %}
</td>
<td class="text-muted">{{ r.fee if r.fee is not none else '-' }}</td>
<td>
{% if r.pnl_net and r.pnl_net > 0 %}<span class="badge profit">{{ r.pnl_net }}</span>
{% elif r.pnl_net and r.pnl_net < 0 %}<span class="badge loss">{{ r.pnl_net }}</span>
{% else %}-{% endif %}
</td>
<td>{% if r.is_emotion %}<span class="badge emotion">情绪单</span>{% else %}-{% endif %}</td>
<td>
<button type="button" class="btn-link review-view-btn" data-review='{{ {
@@ -233,6 +245,7 @@
"open_time": r.open_time, "close_time": r.close_time,
"holding_duration": r.holding_duration,
"initial_pnl": r.initial_pnl, "actual_pnl": r.actual_pnl, "pnl": r.pnl,
"fee": r.fee, "pnl_net": r.pnl_net,
"open_type": r.open_type,
"exit_trigger": r.exit_trigger, "exit_supplement": r.exit_supplement,
"watch_after_breakeven": r.watch_after_breakeven,
@@ -244,7 +257,7 @@
<td><a href="{{ url_for('del_review', rid=r.id) }}" class="btn-del" onclick="return confirm('删除?')"></a></td>
</tr>
{% else %}
<tr><td colspan="7" class="text-muted">暂无复盘记录</td></tr>
<tr><td colspan="9" class="text-muted">暂无复盘记录</td></tr>
{% endfor %}
</tbody>
</table>
+38 -5
View File
@@ -9,6 +9,13 @@
<div class="stat-item"><div class="label">胜率</div><div class="value">{{ rate }}%</div></div>
</div>
<div class="stat-grid">
<div class="stat-item"><div class="label">累计手续费</div><div class="value text-loss">{{ total_fee }} 元</div></div>
<div class="stat-item"><div class="label">毛盈亏合计</div><div class="value">{{ total_gross }} 元</div></div>
<div class="stat-item"><div class="label">净盈亏合计</div><div class="value {% if total_net > 0 %}text-profit{% elif total_net < 0 %}text-loss{% endif %}">{{ total_net }} 元</div></div>
<div class="stat-item"><div class="label">计费笔数</div><div class="value">{{ fee_count }}</div></div>
</div>
<div class="card">
<h2>按品种统计</h2>
<table>
@@ -28,6 +35,24 @@
</table>
</div>
<div class="card">
<h2>手续费按品种(交易记录)</h2>
<table>
<thead><tr><th>品种</th><th>笔数</th><th>累计手续费(元)</th></tr></thead>
<tbody>
{% for f in fee_by_symbol %}
<tr>
<td>{{ f.symbol_name or f.symbol }}</td>
<td>{{ f.cnt }}</td>
<td class="text-loss">{{ round(f.total_fee, 2) }}</td>
</tr>
{% else %}
<tr><td colspan="3" class="text-muted">暂无手续费数据</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="card">
<h2>按类型统计</h2>
<table>
@@ -67,22 +92,30 @@
</div>
<div class="card">
<h2>最近 10 笔交易</h2>
<h2>最近 10 笔交易记录</h2>
<table>
<thead><tr><th>品种</th><th>方向</th><th>结果</th><th>时间</th></tr></thead>
<thead><tr><th>品种</th><th>方向</th><th>毛盈亏</th><th>手续费</th><th>净盈亏</th><th>结果</th><th>时间</th></tr></thead>
<tbody>
{% for r in recent %}
<tr>
<td>{{ r.symbol_name or r.symbol }}</td>
<td><span class="badge dir">{{ '做多' if r.direction == 'long' else '做空' }}</span></td>
<td>{{ r.pnl if r.pnl is not none else '-' }}</td>
<td class="text-muted">{{ r.fee if r.fee is not none else '-' }}</td>
<td>
{% if r.pnl_net and r.pnl_net > 0 %}<span class="badge profit">{{ r.pnl_net }}</span>
{% elif r.pnl_net and r.pnl_net < 0 %}<span class="badge loss">{{ r.pnl_net }}</span>
{% else %}-{% endif %}
</td>
<td>
{% if r.result == '止盈' %}<span class="badge profit">止盈</span>
{% else %}<span class="badge loss">止损</span>{% endif %}
{% elif r.result == '止损' %}<span class="badge loss">止损</span>
{% else %}{{ r.result or '-' }}{% endif %}
</td>
<td>{{ r.created_at[:16] if r.created_at else '' }}</td>
<td>{{ r.close_time[:16] if r.close_time else (r.created_at[:16] if r.created_at else '') }}</td>
</tr>
{% else %}
<tr><td colspan="4" class="text-muted">暂无数据</td></tr>
<tr><td colspan="7" class="text-muted">暂无数据</td></tr>
{% endfor %}
</tbody>
</table>