@@ -48,9 +48,13 @@
< option value = "" > -- 先选品种 --< / option >
< / select >
< / div >
< div class = "form-group" style = "margin-bottom:0;flex:0 0 auto;min-width:9 0px;" >
< 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:10 0px;" >
< 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 = "editCall Strike" 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 ( 'editCall Strike' ) . value = callStrike ;
document . getElementById ( 'editPutStrike' ) . value = putStrike ;
document . getElementById ( 'editOpenDate' ) . value = openDate ;
document . getElementById ( 'editCallOpenPrice' ) . value = callOpen ;
document . getElementById ( 'editPutOpenPrice' ) . value = putOpen ;