"""Python 3 standard-library scenario generator. No broker/data connection. Place beside example-scenario.json and run python portfolio_lab.py. Writes python-expiry.csv and python-time-price.csv. """ import csv import json import math from pathlib import Path def option_value(price, strike, kind, minutes, iv, rate): if minutes <= 0: return max(price - strike if kind == 'C' else strike - price, 0) years = minutes / (365 * 24 * 60) discounted = strike * math.exp(-rate * years) if price <= 0: return discounted if kind == 'P' else 0 if iv <= 0: return max(price - discounted if kind == 'C' else discounted - price, 0) vol_time = iv * math.sqrt(years) d1 = (math.log(price / strike) + (rate + iv * iv / 2) * years) / vol_time d2 = d1 - vol_time cdf = lambda x: (1 + math.erf(x / math.sqrt(2))) / 2 return max(0, price * cdf(d1) - discounted * cdf(d2) if kind == 'C' else discounted * cdf(-d2) - price * cdf(-d1)) def pnl(price, minutes, cfg): return sum(leg['quantity'] * (option_value(price, leg['strike'], leg['type'], minutes, cfg['annual_iv'], cfg['annual_rate']) - leg['premium']) * cfg['multiplier_usd'] - abs(leg['quantity']) * cfg['entry_fee_per_contract_usd'] for leg in cfg['legs']) def main(): root = Path(__file__).resolve().parent cfg = json.loads((root / 'example-scenario.json').read_text(encoding='utf-8')) low, high = cfg['range'] prices = [low + (high - low) * i / (cfg['price_steps'] - 1) for i in range(cfg['price_steps'])] with (root / 'python-expiry.csv').open('w', newline='', encoding='utf-8') as f: out = csv.writer(f) out.writerow(['settlement_price', 'net_expiry_pnl_usd', 'data_basis']) for price in prices: out.writerow([price, round(pnl(price, 0, cfg), 4), 'synthetic_example']) with (root / 'python-time-price.csv').open('w', newline='', encoding='utf-8') as f: out = csv.writer(f) out.writerow(['underlying_price', 'calendar_minutes_remaining', 'model_pnl_usd', 'expiry_pnl_usd', 'annual_iv', 'annual_rate', 'basis']) for price in prices: for i in range(cfg['time_steps']): minutes = cfg['minutes_remaining'] * i / (cfg['time_steps'] - 1) out.writerow([price, minutes, round(pnl(price, minutes, cfg), 4), round(pnl(price, 0, cfg), 4), cfg['annual_iv'], cfg['annual_rate'], 'synthetic_black_scholes']) print('Generated both Python scenario CSVs; synthetic only.') if __name__ == '__main__': main()