品种增加每点价值字段,PNL计算支持不同品种差异化配置

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fish
2026-07-28 09:49:37 +08:00
parent 5018eb2083
commit 833491b8d0
8 changed files with 66 additions and 18 deletions
+6 -1
View File
@@ -105,6 +105,10 @@
{% endfor %}
</select>
</div>
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:80px;">
<label>每点价值</label>
<input type="number" name="point_value" value="20" min="1" required style="font-size:0.9rem;">
</div>
<button type="submit" class="btn btn-primary">新建</button>
</form>
</div>
@@ -112,12 +116,13 @@
{% if products %}
<div class="table-wrap">
<table>
<tr><th>代码</th><th>名称</th><th>交易所</th><th>合约数</th><th>操作</th></tr>
<tr><th>代码</th><th>名称</th><th>交易所</th><th>每点</th><th>合约数</th><th>操作</th></tr>
{% for p in products %}
<tr>
<td><strong>{{ p.code }}</strong></td>
<td>{{ p.name }}</td>
<td>{{ p.exchange }}</td>
<td>{{ p.point_value }}</td>
<td>{{ p.contracts|length }}</td>
<td>
<form method="post" action="/admin/product/{{ p.id }}/delete" onsubmit="return confirm('删除品种 {{ p.code }} 及其所有合约?')" style="display:inline;">
+5 -5
View File
@@ -198,7 +198,7 @@
{% if p > 0 %}+{% endif %}{{ p }}
</span>
<span style="color:var(--sub);cursor:pointer;font-size:0.75rem;margin-left:4px;"
onclick="showPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }} {{ t.option_type }}', '{{ t.direction }}', {{ t.open_price }}, {{ t.close_price }}, {{ t.open_fee or 0 }}, {{ t.close_fee or 0 }}, {{ p }})" title="计算过程">&#9432;</span>
onclick="showPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }} {{ t.option_type }}', '{{ t.direction }}', {{ t.open_price }}, {{ t.close_price }}, {{ t.open_fee or 0 }}, {{ t.close_fee or 0 }}, {{ p }}, {{ t.point_value }})" title="计算过程">&#9432;</span>
{% endif %}
</td>
<td>
@@ -333,16 +333,16 @@ function hideCloseForm() {
</div>
<script>
function showPnlDrawer(title, direction, openPrice, closePrice, openFee, closeFee, result) {
function showPnlDrawer(title, direction, openPrice, closePrice, openFee, closeFee, result, pointValue) {
document.getElementById('pnlTitle').textContent = title;
var dirLabel = direction === 'sell' ? '卖' : '买';
document.getElementById('pnlFormula').textContent = '方向: ' + dirLabel + ' | 每点 20 元';
document.getElementById('pnlFormula').textContent = '方向: ' + dirLabel + ' | 每点 ' + pointValue + ' 元';
var diff = direction === 'sell' ? (openPrice - closePrice) : (closePrice - openPrice);
var gross = diff * 20;
var gross = diff * pointValue;
var fees = openFee + closeFee;
var html = '<tr style="background:var(--th-bg);"><td>项目</td><td>计算</td><td style="text-align:right;">金额</td></tr>';
html += '<tr><td>价差</td><td>' + (direction === 'sell' ? openPrice + ' - ' + closePrice : closePrice + ' - ' + openPrice) + '</td><td style="text-align:right;">' + diff.toFixed(2) + ' 点</td></tr>';
html += '<tr><td>毛利</td><td>' + diff.toFixed(2) + ' × 20</td><td style="text-align:right;">' + gross.toFixed(2) + '</td></tr>';
html += '<tr><td>毛利</td><td>' + diff.toFixed(2) + ' × ' + pointValue + '</td><td style="text-align:right;">' + gross.toFixed(2) + '</td></tr>';
html += '<tr><td>开仓手续费</td><td></td><td style="text-align:right;color:var(--danger-fg);">-' + openFee.toFixed(2) + '</td></tr>';
html += '<tr><td>平仓手续费</td><td></td><td style="text-align:right;color:var(--danger-fg);">-' + closeFee.toFixed(2) + '</td></tr>';
document.getElementById('pnlTable').innerHTML = html;
+5 -5
View File
@@ -222,7 +222,7 @@
{% if p > 0 %}+{% endif %}{{ p }}
</span>
<span style="color:var(--sub);cursor:pointer;font-size:0.75rem;margin-left:4px;"
onclick="showPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }}', '{{ t.direction }}', {{ t.open_price }}, {{ t.close_price }}, {{ t.open_fee or 0 }}, {{ t.close_fee or 0 }}, {{ p }})" title="计算过程">&#9432;</span>
onclick="showPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }}', '{{ t.direction }}', {{ t.open_price }}, {{ t.close_price }}, {{ t.open_fee or 0 }}, {{ t.close_fee or 0 }}, {{ p }}, {{ t.point_value }})" title="计算过程">&#9432;</span>
{% endif %}
</td>
<td>
@@ -349,16 +349,16 @@ function hideCloseForm() {
</div>
<script>
function showPnlDrawer(title, direction, openPrice, closePrice, openFee, closeFee, result) {
function showPnlDrawer(title, direction, openPrice, closePrice, openFee, closeFee, result, pointValue) {
document.getElementById('pnlTitle').textContent = title;
var dirLabel = direction === 'short' ? '空' : '多';
document.getElementById('pnlFormula').textContent = '方向: ' + dirLabel + ' | 每点 20 元';
document.getElementById('pnlFormula').textContent = '方向: ' + dirLabel + ' | 每点 ' + pointValue + ' 元';
var diff = direction === 'short' ? (openPrice - closePrice) : (closePrice - openPrice);
var gross = diff * 20;
var gross = diff * pointValue;
var fees = openFee + closeFee;
var html = '<tr style="background:var(--th-bg);"><td>项目</td><td>计算</td><td style="text-align:right;">金额</td></tr>';
html += '<tr><td>价差</td><td>' + (direction === 'short' ? openPrice + ' - ' + closePrice : closePrice + ' - ' + openPrice) + '</td><td style="text-align:right;">' + diff.toFixed(2) + ' 点</td></tr>';
html += '<tr><td>毛利</td><td>' + diff.toFixed(2) + ' × 20</td><td style="text-align:right;">' + gross.toFixed(2) + '</td></tr>';
html += '<tr><td>毛利</td><td>' + diff.toFixed(2) + ' × ' + pointValue + '</td><td style="text-align:right;">' + gross.toFixed(2) + '</td></tr>';
html += '<tr><td>开仓手续费</td><td></td><td style="text-align:right;color:var(--danger-fg);">-' + openFee.toFixed(2) + '</td></tr>';
html += '<tr><td>平仓手续费</td><td></td><td style="text-align:right;color:var(--danger-fg);">-' + closeFee.toFixed(2) + '</td></tr>';
document.getElementById('pnlTable').innerHTML = html;