双买交易行权价拆分为看涨行权价和看跌行权价,支持不同价位
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -48,9 +48,13 @@
|
||||
<option value="">-- 先选品种 --</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:90px;">
|
||||
<label>行权价</label>
|
||||
<input type="number" step="any" name="strike_price" required placeholder="1300" style="font-size:0.9rem;">
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:100px;">
|
||||
<label>看涨行权价</label>
|
||||
<input type="number" step="any" name="call_strike_price" required placeholder="1300" style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:100px;">
|
||||
<label>看跌行权价</label>
|
||||
<input type="number" step="any" name="put_strike_price" required placeholder="1280" style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;flex:0 0 auto;min-width:100px;">
|
||||
<label>看涨开仓价</label>
|
||||
@@ -83,12 +87,13 @@
|
||||
{% if open_trades %}
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<tr><th>品种</th><th>合约</th><th>行权价</th><th>开仓日期</th><th>看涨开仓价</th><th>看跌开仓价</th><th>C手续费</th><th>P手续费</th><th>总成本</th><th>操作</th></tr>
|
||||
<tr><th>品种</th><th>合约</th><th>C行权价</th><th>P行权价</th><th>开仓日期</th><th>看涨开仓价</th><th>看跌开仓价</th><th>C手续费</th><th>P手续费</th><th>总成本</th><th>操作</th></tr>
|
||||
{% for t in open_trades %}
|
||||
<tr>
|
||||
<td>{{ t.product_code }}</td>
|
||||
<td><strong>{{ t.contract_code.replace(t.product_code, '', 1) }}</strong></td>
|
||||
<td>{{ t.strike_price }}</td>
|
||||
<td>{{ t.call_strike_price }}</td>
|
||||
<td>{{ t.put_strike_price }}</td>
|
||||
<td>{{ t.open_date }} {{ weekdays[t.open_date.weekday()] }}</td>
|
||||
<td>{{ t.call_open_price }}</td>
|
||||
<td>{{ t.put_open_price }}</td>
|
||||
@@ -99,7 +104,7 @@
|
||||
<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>
|
||||
<button style="background:var(--success-bg);color:var(--success-fg);border:1px solid var(--success);padding:3px 10px;border-radius:4px;cursor:pointer;font-size:0.78rem;margin-left:8px;"
|
||||
onclick="showEditForm({{ t.id }}, '{{ t.product_code }}', '{{ t.contract_code }}', {{ t.strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, '{{ t.open_date }}', null, null, null, null, null, 'open')">编辑</button>
|
||||
onclick="showEditForm({{ t.id }}, '{{ t.product_code }}', '{{ t.contract_code }}', {{ t.call_strike_price }}, {{ t.put_strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, '{{ t.open_date }}', null, null, null, null, null, 'open')">编辑</button>
|
||||
<form method="post" action="/dual-options/{{ t.id }}/delete" style="display:inline;margin-left:8px;">
|
||||
<button style="background:transparent;color:#dc2626;border:1px solid #ef4444;padding:3px 10px;border-radius:4px;cursor:pointer;font-size:0.78rem;" onclick="confirmDelete(event, '确定删除此记录?', this.closest('form').action)">删除</button>
|
||||
</form>
|
||||
@@ -153,12 +158,13 @@
|
||||
<div class="section-title">已平仓 · {{ 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><th>盈亏</th><th>操作</th></tr>
|
||||
<tr><th>品种</th><th>合约</th><th>C行权价</th><th>P行权价</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.replace(t.product_code, '', 1) }}</strong></td>
|
||||
<td>{{ t.strike_price }}</td>
|
||||
<td>{{ t.call_strike_price }}</td>
|
||||
<td>{{ t.put_strike_price }}</td>
|
||||
<td style="font-size:0.8rem;">{{ t.open_date }} {{ weekdays[t.open_date.weekday()] }}</td>
|
||||
<td style="font-size:0.8rem;">{{ t.close_date }} {{ weekdays[t.close_date.weekday()] }}</td>
|
||||
<td>{{ (t.close_date - t.open_date).days }}天</td>
|
||||
@@ -172,12 +178,12 @@
|
||||
{% if p > 0 %}+{% endif %}{{ p }}
|
||||
</span>
|
||||
<span style="color:var(--sub);cursor:pointer;font-size:0.75rem;margin-left:4px;"
|
||||
onclick="showDualPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }} {{ t.strike_price }}', {{ t.strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_close_price }}, {{ t.put_close_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, {{ t.call_close_fee or 0 }}, {{ t.put_close_fee or 0 }}, {{ p }}, {{ t.point_value }})" title="盈亏分析">ⓘ</span>
|
||||
onclick="showDualPnlDrawer('{{ t.product_code }} {{ t.contract_code.replace(t.product_code, '', 1) }}', {{ t.call_strike_price }}, {{ t.put_strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_close_price }}, {{ t.put_close_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, {{ t.call_close_fee or 0 }}, {{ t.put_close_fee or 0 }}, {{ p }}, {{ t.point_value }})" title="盈亏分析">ⓘ</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button style="background:var(--success-bg);color:var(--success-fg);border:1px solid var(--success);padding:3px 10px;border-radius:4px;cursor:pointer;font-size:0.78rem;"
|
||||
onclick="showEditForm({{ t.id }}, '{{ t.product_code }}', '{{ t.contract_code }}', {{ t.strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, '{{ t.open_date }}', {{ t.call_close_price }}, {{ t.put_close_price }}, {{ t.call_close_fee or 0 }}, {{ t.put_close_fee or 0 }}, '{{ t.close_date }}', 'closed')">编辑</button>
|
||||
onclick="showEditForm({{ t.id }}, '{{ t.product_code }}', '{{ t.contract_code }}', {{ t.call_strike_price }}, {{ t.put_strike_price }}, {{ t.call_open_price }}, {{ t.put_open_price }}, {{ t.call_open_fee or 0 }}, {{ t.put_open_fee or 0 }}, '{{ t.open_date }}', {{ t.call_close_price }}, {{ t.put_close_price }}, {{ t.call_close_fee or 0 }}, {{ t.put_close_fee or 0 }}, '{{ t.close_date }}', 'closed')">编辑</button>
|
||||
<form method="post" action="/dual-options/{{ t.id }}/delete" style="display:inline;margin-left:8px;">
|
||||
<button style="background:transparent;color:#dc2626;border:1px solid #ef4444;padding:3px 10px;border-radius:4px;cursor:pointer;font-size:0.78rem;" onclick="confirmDelete(event, '确定删除此记录?', this.closest('form').action)">删除</button>
|
||||
</form>
|
||||
@@ -256,8 +262,12 @@ function hideCloseForm() {
|
||||
<input type="text" name="contract_code" id="editContract" required style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>行权价</label>
|
||||
<input type="number" step="any" name="strike_price" id="editStrike" required style="font-size:0.9rem;">
|
||||
<label>看涨行权价</label>
|
||||
<input type="number" step="any" name="call_strike_price" id="editCallStrike" required style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>看跌行权价</label>
|
||||
<input type="number" step="any" name="put_strike_price" id="editPutStrike" required style="font-size:0.9rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>开仓日期</label>
|
||||
@@ -319,9 +329,9 @@ function hideCloseForm() {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showDualPnlDrawer(title, strikePrice, callOpen, putOpen, callClose, putClose, callOpenFee, putOpenFee, callCloseFee, putCloseFee, pnl, pointValue) {
|
||||
function showDualPnlDrawer(title, callStrike, putStrike, callOpen, putOpen, callClose, putClose, callOpenFee, putOpenFee, callCloseFee, putCloseFee, pnl, pointValue) {
|
||||
document.getElementById('pnlTitle').textContent = title + ' 双买分析';
|
||||
document.getElementById('pnlFormula').textContent = '行权价: ' + strikePrice + ' | 每点 ' + pointValue + ' 元';
|
||||
document.getElementById('pnlFormula').textContent = 'C行权价: ' + callStrike + ' P行权价: ' + putStrike + ' | 每点 ' + pointValue + ' 元';
|
||||
|
||||
var totalPremium = callOpen + putOpen;
|
||||
var totalOpenFee = callOpenFee + putOpenFee;
|
||||
@@ -329,8 +339,8 @@ function showDualPnlDrawer(title, strikePrice, callOpen, putOpen, callClose, put
|
||||
var totalFee = totalOpenFee + totalCloseFee;
|
||||
var premiumRmb = totalPremium * pointValue;
|
||||
var totalCost = premiumRmb + totalOpenFee;
|
||||
var beUpper = strikePrice + totalPremium;
|
||||
var beLower = strikePrice - totalPremium;
|
||||
var beUpper = callStrike + totalPremium;
|
||||
var beLower = putStrike - totalPremium;
|
||||
var callPnl = (callClose - callOpen) * pointValue - callOpenFee - callCloseFee;
|
||||
var putPnl = (putClose - putOpen) * pointValue - putOpenFee - putCloseFee;
|
||||
|
||||
@@ -347,15 +357,15 @@ function showDualPnlDrawer(title, strikePrice, callOpen, putOpen, callClose, put
|
||||
html += '<tr><td>开仓手续费</td><td>C:' + callOpenFee + ' + P:' + putOpenFee + '</td><td style="text-align:right;color:var(--danger-fg);">-' + totalOpenFee.toFixed(2) + '</td></tr>';
|
||||
html += '<tr><td>平仓手续费</td><td>C:' + callCloseFee + ' + P:' + putCloseFee + '</td><td style="text-align:right;color:var(--danger-fg);">-' + totalCloseFee.toFixed(2) + '</td></tr>';
|
||||
html += '<tr style="font-weight:600;"><td>总成本</td><td>' + premiumRmb.toFixed(2) + ' + ' + totalOpenFee.toFixed(2) + '</td><td style="text-align:right;">' + totalCost.toFixed(2) + '</td></tr>';
|
||||
html += '<tr><td>盈亏平衡点(上)</td><td>' + strikePrice + ' + ' + totalPremium.toFixed(2) + '</td><td style="text-align:right;">' + beUpper.toFixed(2) + '</td></tr>';
|
||||
html += '<tr><td>盈亏平衡点(下)</td><td>' + strikePrice + ' - ' + totalPremium.toFixed(2) + '</td><td style="text-align:right;">' + beLower.toFixed(2) + '</td></tr>';
|
||||
html += '<tr><td>盈亏平衡点(上)</td><td>' + callStrike + ' + ' + totalPremium.toFixed(2) + '</td><td style="text-align:right;">' + beUpper.toFixed(2) + '</td></tr>';
|
||||
html += '<tr><td>盈亏平衡点(下)</td><td>' + putStrike + ' - ' + totalPremium.toFixed(2) + '</td><td style="text-align:right;">' + beLower.toFixed(2) + '</td></tr>';
|
||||
html += '<tr style="background:var(--th-bg);"><td colspan="3"></td></tr>';
|
||||
html += '<tr><td>看涨盈亏</td><td>(' + callClose + ' - ' + callOpen + ') × ' + pointValue + ' - ' + callOpenFee + ' - ' + callCloseFee + '</td><td style="text-align:right;font-weight:600;' + colorFn(callPnl) + '">' + signed(callPnl) + '</td></tr>';
|
||||
html += '<tr><td>看跌盈亏</td><td>(' + putClose + ' - ' + putOpen + ') × ' + pointValue + ' - ' + putOpenFee + ' - ' + putCloseFee + '</td><td style="text-align:right;font-weight:600;' + colorFn(putPnl) + '">' + signed(putPnl) + '</td></tr>';
|
||||
document.getElementById('pnlTable').innerHTML = html;
|
||||
|
||||
var insight = '<b style="' + colorFn(pnl) + '">组合盈亏 = ' + signed(pnl) + '</b><br>';
|
||||
insight += '最大亏损 = ' + totalCost.toFixed(2) + ' 元(标的价格 = ' + strikePrice + ' 时)<br>';
|
||||
insight += '最大亏损 = ' + totalCost.toFixed(2) + ' 元(标的价格在 ' + putStrike + ' ~ ' + callStrike + ' 区间时)<br>';
|
||||
insight += '盈利区间: 标的价格 > ' + beUpper.toFixed(2) + ' 或 < ' + beLower.toFixed(2);
|
||||
|
||||
document.getElementById('pnlInsight').innerHTML = insight;
|
||||
@@ -363,10 +373,11 @@ function showDualPnlDrawer(title, strikePrice, callOpen, putOpen, callClose, put
|
||||
document.getElementById('pnlBox').style.display = 'block';
|
||||
}
|
||||
|
||||
function showEditForm(id, productCode, contractCode, strike, callOpen, putOpen, callOpenFee, putOpenFee, openDate, callClose, putClose, callCloseFee, putCloseFee, closeDate, status) {
|
||||
function showEditForm(id, productCode, contractCode, callStrike, putStrike, callOpen, putOpen, callOpenFee, putOpenFee, openDate, callClose, putClose, callCloseFee, putCloseFee, closeDate, status) {
|
||||
document.getElementById('editForm').action = '/dual-options/' + id + '/edit';
|
||||
document.getElementById('editContract').value = contractCode;
|
||||
document.getElementById('editStrike').value = strike;
|
||||
document.getElementById('editCallStrike').value = callStrike;
|
||||
document.getElementById('editPutStrike').value = putStrike;
|
||||
document.getElementById('editOpenDate').value = openDate;
|
||||
document.getElementById('editCallOpenPrice').value = callOpen;
|
||||
document.getElementById('editPutOpenPrice').value = putOpen;
|
||||
|
||||
Reference in New Issue
Block a user