feat(PRICING-003): use true GLD backing for hedge contract count
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from datetime import date, timedelta
|
||||
|
||||
@@ -7,6 +8,7 @@ from app.core.pricing.black_scholes import (
|
||||
BlackScholesInputs,
|
||||
black_scholes_price_and_greeks,
|
||||
)
|
||||
from app.domain.instruments import gld_ounces_per_share
|
||||
from app.models.option import Greeks, OptionContract
|
||||
from app.models.strategy import HedgingStrategy
|
||||
from app.strategies.base import BaseStrategy, StrategyConfig
|
||||
@@ -47,7 +49,8 @@ class ProtectivePutStrategy(BaseStrategy):
|
||||
|
||||
@property
|
||||
def hedge_units(self) -> float:
|
||||
return self.config.portfolio.gold_value / self.config.spot_price
|
||||
"""Gold ounces to hedge (canonical portfolio weight)."""
|
||||
return self.config.portfolio.gold_ounces
|
||||
|
||||
@property
|
||||
def strike(self) -> float:
|
||||
@@ -57,6 +60,20 @@ class ProtectivePutStrategy(BaseStrategy):
|
||||
def term_years(self) -> float:
|
||||
return self.spec.months / 12.0
|
||||
|
||||
@property
|
||||
def gld_backing(self) -> float:
|
||||
"""GLD ounces per share for contract count calculation."""
|
||||
return float(gld_ounces_per_share())
|
||||
|
||||
@property
|
||||
def contract_count(self) -> int:
|
||||
"""Number of GLD option contracts needed.
|
||||
|
||||
GLD options cover 100 shares each. Each share represents ~0.0919 oz
|
||||
(expense-ratio adjusted). Formula: ceil(gold_ounces / (100 * backing)).
|
||||
"""
|
||||
return math.ceil(self.hedge_units / (100 * self.gld_backing))
|
||||
|
||||
def build_contract(self) -> OptionContract:
|
||||
pricing = black_scholes_price_and_greeks(
|
||||
BlackScholesInputs(
|
||||
@@ -73,8 +90,8 @@ class ProtectivePutStrategy(BaseStrategy):
|
||||
strike=self.strike,
|
||||
expiry=date.today() + timedelta(days=max(1, round(365 * self.term_years))),
|
||||
premium=pricing.price,
|
||||
quantity=1.0,
|
||||
contract_size=self.hedge_units,
|
||||
quantity=float(self.contract_count),
|
||||
contract_size=100 * self.gld_backing,
|
||||
underlying_price=self.config.spot_price,
|
||||
greeks=Greeks(
|
||||
delta=pricing.delta,
|
||||
@@ -114,7 +131,7 @@ class ProtectivePutStrategy(BaseStrategy):
|
||||
payoff_at_threshold = contract.payoff(threshold_price)
|
||||
hedged_value_at_threshold = self.config.portfolio.gold_value_at_price(threshold_price) + payoff_at_threshold
|
||||
protected_ltv = self.config.portfolio.loan_amount / hedged_value_at_threshold
|
||||
floor_value = contract.strike * self.hedge_units
|
||||
floor_value = contract.strike * contract.notional_units
|
||||
return {
|
||||
"strategy": self.name,
|
||||
"threshold_price": round(threshold_price, 2),
|
||||
|
||||
Reference in New Issue
Block a user