新增交易记录功能,支持开平仓和盈亏计算
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -201,6 +201,9 @@
|
||||
<a href="/positions/" class="{% if active_nav == 'positions' %}active{% endif %}">
|
||||
<span class="icon">📐</span> 仓位管理
|
||||
</a>
|
||||
<a href="/trades/" class="{% if active_nav == 'trades' %}active{% endif %}">
|
||||
<span class="icon">📝</span> 交易记录
|
||||
</a>
|
||||
<a href="/admin/" class="{% if active_nav == 'admin' %}active{% endif %}">
|
||||
<span class="icon">⚙️</span> 系统管理
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}交易记录{% endblock %}
|
||||
{% block heading %}交易记录{% endblock %}
|
||||
{% block breadcrumb %}开平仓记录 · 盈亏统计{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{# ═══════════════ 新建开仓 ═══════════════ #}
|
||||
<div class="section-title">新建开仓</div>
|
||||
<div class="form-card" style="margin-bottom:28px;max-width:100%;">
|
||||
<form method="post" action="/trades/open">
|
||||
<div style="display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;">
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:100px;">
|
||||
<label>品种</label>
|
||||
<select name="product_code" required>
|
||||
<option value="">--</option>
|
||||
{% for p in products %}
|
||||
<option value="{{ p }}">{{ p }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:120px;">
|
||||
<label>合约</label>
|
||||
<select name="contract_code" required>
|
||||
<option value="">--</option>
|
||||
{% for c in contracts %}
|
||||
<option value="{{ c }}">{{ c }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:70px;">
|
||||
<label>方向</label>
|
||||
<select name="direction" required>
|
||||
{% for v, label in directions %}
|
||||
<option value="{{ v }}">{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:1;min-width:140px;">
|
||||
<label>开仓日期</label>
|
||||
<input type="date" name="open_date" value="{{ today }}" required style="font-size:0.85rem;">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:80px;">
|
||||
<label>开仓价</label>
|
||||
<input type="number" name="open_price" required placeholder="1300" style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:80px;">
|
||||
<label>手续费</label>
|
||||
<input type="number" name="open_fee" value="0" style="font-size:0.9rem;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="font-size:0.82rem;padding:8px 18px;">开仓</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{# ═══════════════ 持仓中 ═══════════════ #}
|
||||
<div class="section-title">持仓中 · {{ open_trades|length }} 笔</div>
|
||||
|
||||
{% if open_trades %}
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<tr><th>品种</th><th>合约</th><th>方向</th><th>开仓日期</th><th>开仓价</th><th>手续费</th><th>操作</th></tr>
|
||||
{% for t in open_trades %}
|
||||
<tr>
|
||||
<td>{{ t.product_code }}</td>
|
||||
<td><strong>{{ t.contract_code }}</strong></td>
|
||||
<td>
|
||||
{% if t.direction == 'short' %}
|
||||
<span class="badge badge-down">空</span>
|
||||
{% else %}
|
||||
<span class="badge badge-up">多</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ t.open_date }}</td>
|
||||
<td>{{ t.open_price }}</td>
|
||||
<td>{{ t.open_fee or 0 }}</td>
|
||||
<td>
|
||||
<button style="background:var(--accent);color:#fff;border:none;padding:3px 10px;border-radius:4px;cursor:pointer;font-size:0.78rem;"
|
||||
onclick="showCloseForm({{ t.id }})">平仓</button>
|
||||
<form method="post" action="/trades/{{ t.id }}/delete" style="display:inline;">
|
||||
<button style="background:none;border:none;color:var(--na);cursor:pointer;font-size:0.78rem;" onclick="return confirm('删除此记录?')">删</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div style="text-align:center;padding:40px;color:var(--sub);">暂无持仓</div>
|
||||
{% endif %}
|
||||
|
||||
{# ═══════════════ 平仓表单(隐藏) ═══════════════ #}
|
||||
<div id="closeFormOverlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:99;" onclick="hideCloseForm()"></div>
|
||||
<div id="closeFormBox" style="display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:24px;z-index:100;width:360px;max-width:90vw;">
|
||||
<h3 style="margin-bottom:16px;">平仓</h3>
|
||||
<form method="post" id="closeForm">
|
||||
<div class="form-group">
|
||||
<label>平仓日期</label>
|
||||
<input type="date" name="close_date" value="{{ today }}" required style="font-size:0.85rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>平仓价格</label>
|
||||
<input type="number" name="close_price" required style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>手续费</label>
|
||||
<input type="number" name="close_fee" value="0" style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div style="display:flex;gap:10px;justify-content:flex-end;">
|
||||
<button type="button" class="btn" style="background:var(--th-bg);color:var(--fg);" onclick="hideCloseForm()">取消</button>
|
||||
<button type="submit" class="btn btn-primary">确认平仓</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{# ═══════════════ 已平仓 ═══════════════ #}
|
||||
{% if closed_trades %}
|
||||
<div class="section-title" style="margin-top:32px;">已平仓 · {{ closed_trades|length }} 笔</div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<tr><th>品种</th><th>合约</th><th>方向</th><th>开仓</th><th>平仓</th><th>开仓价</th><th>平仓价</th><th>盈亏</th><th>操作</th></tr>
|
||||
{% for t in closed_trades %}
|
||||
<tr>
|
||||
<td>{{ t.product_code }}</td>
|
||||
<td><strong>{{ t.contract_code }}</strong></td>
|
||||
<td>
|
||||
{% if t.direction == 'short' %}
|
||||
<span class="badge badge-down">空</span>
|
||||
{% else %}
|
||||
<span class="badge badge-up">多</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="font-size:0.8rem;">{{ t.open_date }}</td>
|
||||
<td style="font-size:0.8rem;">{{ t.close_date }}</td>
|
||||
<td>{{ t.open_price }}</td>
|
||||
<td>{{ t.close_price }}</td>
|
||||
<td>
|
||||
{% set p = t.pnl %}
|
||||
{% if p is not none %}
|
||||
<span style="font-weight:700;{% if p > 0 %}color:var(--success-fg);{% elif p < 0 %}color:var(--danger-fg);{% else %}color:var(--sub);{% endif %}">
|
||||
{% if p > 0 %}+{% endif %}{{ p }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" action="/trades/{{ t.id }}/delete" style="display:inline;">
|
||||
<button style="background:none;border:none;color:var(--na);cursor:pointer;font-size:0.78rem;" onclick="return confirm('删除此记录?')">删</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
function showCloseForm(tradeId) {
|
||||
document.getElementById('closeForm').action = '/trades/' + tradeId + '/close';
|
||||
document.getElementById('closeFormOverlay').style.display = 'block';
|
||||
document.getElementById('closeFormBox').style.display = 'block';
|
||||
}
|
||||
function hideCloseForm() {
|
||||
document.getElementById('closeFormOverlay').style.display = 'none';
|
||||
document.getElementById('closeFormBox').style.display = 'none';
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user