期权交易"权利金"改为"开仓价";新增期权双买交易功能,支持跨式策略开平仓及组合盈亏分析

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fish
2026-07-28 14:24:49 +08:00
parent 6228c139ef
commit af3e359d24
6 changed files with 642 additions and 6 deletions
+51 -1
View File
@@ -179,4 +179,54 @@ class OptionTrade(Base):
result = (self.open_price - self.close_price) * mul - (self.open_fee or 0) - (self.close_fee or 0)
else:
result = (self.close_price - self.open_price) * mul - (self.open_fee or 0) - (self.close_fee or 0)
return round(result, 2)
return round(result, 2)
class DualOptionTrade(Base):
__tablename__ = "dual_option_trades"
id: Mapped[int] = mapped_column(primary_key=True)
product_code: Mapped[str] = mapped_column(String(10))
contract_code: Mapped[str] = mapped_column(String(10), index=True)
strike_price: Mapped[float] = mapped_column(Float)
call_open_price: Mapped[float] = mapped_column(Float)
put_open_price: Mapped[float] = mapped_column(Float)
call_open_fee: Mapped[float | None] = mapped_column(Float, nullable=True, default=0)
put_open_fee: Mapped[float | None] = mapped_column(Float, nullable=True, default=0)
open_date: Mapped[date] = mapped_column(Date)
point_value: Mapped[int] = mapped_column(Integer, default=20)
close_date: Mapped[date | None] = mapped_column(Date, nullable=True)
call_close_price: Mapped[float | None] = mapped_column(Float, nullable=True)
put_close_price: Mapped[float | None] = mapped_column(Float, nullable=True)
call_close_fee: Mapped[float | None] = mapped_column(Float, nullable=True, default=0)
put_close_fee: Mapped[float | None] = mapped_column(Float, nullable=True, default=0)
status: Mapped[str] = mapped_column(String(10), default="open")
@property
def pnl(self) -> float | None:
if self.call_close_price is None or self.put_close_price is None:
return None
mul = self.point_value
call_pnl = (self.call_close_price - self.call_open_price) * mul - (self.call_open_fee or 0) - (self.call_close_fee or 0)
put_pnl = (self.put_close_price - self.put_open_price) * mul - (self.put_open_fee or 0) - (self.put_close_fee or 0)
return round(call_pnl + put_pnl, 2)
@property
def total_premium(self) -> float:
return self.call_open_price + self.put_open_price
@property
def total_open_fee(self) -> float:
return (self.call_open_fee or 0) + (self.put_open_fee or 0)
@property
def total_cost(self) -> float:
return self.total_premium * self.point_value + self.total_open_fee
@property
def breakeven_upper(self) -> float:
return self.strike_price + self.total_premium
@property
def breakeven_lower(self) -> float:
return self.strike_price - self.total_premium