import%20marimo%0A%0A__generated_with%20%3D%20%220.18.4%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0Awith%20app.setup%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%20%20%20%20from%20plotly.subplots%20import%20make_subplots%0A%0A%20%20%20%20from%20qsmile%20import%20(%0A%20%20%20%20%20%20%20%20SABRModel%2C%0A%20%20%20%20%20%20%20%20SampleDataReader%2C%0A%20%20%20%20%20%20%20%20SVIModel%2C%0A%20%20%20%20%20%20%20%20XCoord%2C%0A%20%20%20%20%20%20%20%20YCoord%2C%0A%20%20%20%20%20%20%20%20fit%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_intro()%3A%0A%20%20%20%20%22%22%22Notebook%20introduction.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%20qsmile%20demo%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20walks%20through%20the%20**qsmile%20calculaition%20flow**%20using%20real%0A%20%20%20%20%20%20%20%20S%26P%20500%20(SPX)%20option-chain%20data.%0A%0A%20%20%20%20%20%20%20%20%7C%20%23%20%7C%20Layer%20%7C%20Key%20classes%20%2F%20functions%20%7C%0A%20%20%20%20%20%20%20%20%7C---%7C-------%7C------------------------%7C%0A%20%20%20%20%20%20%20%20%7C%201%20%7C%20**Option%20chain**%20%7C%20%60OptionChain%60%20%E2%80%94%20load%2C%20filter%2C%20calibrate%20%24F%24%2C%20%24D%24%20%7C%0A%20%20%20%20%20%20%20%20%7C%202%20%7C%20**VolData**%20%7C%20%60to_vols()%60%2C%20coordinate%20transforms%20%7C%0A%20%20%20%20%20%20%20%20%7C%203%20%7C%20**Model%20fitting**%20%7C%20%60fit(sd%2C%20SVIModel)%60%2C%20%60fit(sd%2C%20SABRModel)%60%20%7C%0A%20%20%20%20%20%20%20%20%7C%204%20%7C%20**Ancillary**%20%7C%20volume%20%2F%20open%20interest%20passthrough%20%7C%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_chain_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20option-chain%20section.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%201%20%C2%B7%20OptionChain%20%E2%80%94%20Real%20SPX%20Data%0A%0A%20%20%20%20%20%20%20%20We%20load%20a%20real%20SPX%20chain%20from%20parquet%2C%20then%20**filter%20first**%20to%0A%20%20%20%20%20%20%20%20remove%20arbitrageable%20quotes%20before%20calibrating%20forward%20and%0A%20%20%20%20%20%20%20%20discount%20factor.%0A%0A%20%20%20%20%20%20%20%20The%20filtering%20pipeline%20applies%20five%20sequential%20checks%3A%0A%0A%20%20%20%20%20%20%20%201.%20**Zero-bid**%20%E2%80%94%20remove%20strikes%20where%20either%20bid%20is%20zero%0A%20%20%20%20%20%20%20%202.%20**Put-call%20parity%20monotonicity**%20%E2%80%94%20enforce%20%24C_%5Ctext%7Bmid%7D%20-%20P_%5Ctext%7Bmid%7D%24%20decreasing%20in%20%24K%24%0A%20%20%20%20%20%20%20%203.%20**Call%2Fput%20mid%20monotonicity**%20%E2%80%94%20calls%20decreasing%2C%20puts%20increasing%0A%20%20%20%20%20%20%20%204.%20**Sub-intrinsic**%20%E2%80%94%20drop%20strikes%20priced%20below%20intrinsic%20value%0A%20%20%20%20%20%20%20%205.%20**Parity%20residual**%20%E2%80%94%20trim%20large%20deviations%20from%20calibrated%20parity%0A%0A%20%20%20%20%20%20%20%20After%20filtering%2C%20forward%20%24F%24%20and%20discount%20factor%20%24D%24%20are%0A%20%20%20%20%20%20%20%20**calibrated%20from%20put-call%20parity**%20on%20the%20clean%20data%3A%0A%0A%20%20%20%20%20%20%20%20%24%24C_%7B%5Cmathrm%7Bmid%7D%7D%20-%20P_%7B%5Cmathrm%7Bmid%7D%7D%20%5Capprox%20D(F%20-%20K)%24%24%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_load_data()%3A%0A%20%20%20%20%22%22%22Load%20real%20SPX%20option%20chain%20from%20parquet.%22%22%22%0A%20%20%20%20reader%20%3D%20SampleDataReader()%0A%20%20%20%20chain_raw%20%3D%20reader.get_chain(%22SPX%22%2C%20%222026-04-03%22%2C%20%222026-06-30%22)%0A%20%20%20%20return%20(chain_raw%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_build_and_filter(chain_raw)%3A%0A%20%20%20%20%22%22%22Filter%20the%20raw%20chain%2C%20then%20show%20before%2Fafter%20comparison.%22%22%22%0A%20%20%20%20chain%20%3D%20chain_raw.filter()%0A%0A%20%20%20%20_n_raw%20%3D%20len(chain_raw.strikes)%0A%20%20%20%20_n_clean%20%3D%20len(chain.strikes)%0A%20%20%20%20_vol_raw%20%3D%20%22Yes%22%20if%20chain_raw.volume%20is%20not%20None%20else%20%22No%22%0A%20%20%20%20_vol_cln%20%3D%20%22Yes%22%20if%20chain.volume%20is%20not%20None%20else%20%22No%22%0A%20%20%20%20_oi_raw%20%3D%20%22Yes%22%20if%20chain_raw.open_interest%20is%20not%20None%20else%20%22No%22%0A%20%20%20%20_oi_cln%20%3D%20%22Yes%22%20if%20chain.open_interest%20is%20not%20None%20else%20%22No%22%0A%0A%20%20%20%20_filter_table%20%3D%20f%22%22%22%5C%0A%20%20%20%20%23%23%23%20Before%20%26%20after%20filtering%0A%0A%20%20%20%20%7C%20Metric%20%7C%20Raw%20%7C%20Filtered%20%7C%0A%20%20%20%20%7C--------%7C----%3A%7C---------%3A%7C%0A%20%20%20%20%7C%20Strikes%20%7C%20%7B_n_raw%7D%20%7C%20%7B_n_clean%7D%20%7C%0A%20%20%20%20%7C%20Removed%20%7C%20%E2%80%94%20%7C%20%7B_n_raw%20-%20_n_clean%7D%20%7C%0A%20%20%20%20%7C%20Volume%20attached%20%7C%20%7B_vol_raw%7D%20%7C%20%7B_vol_cln%7D%20%7C%0A%20%20%20%20%7C%20OI%20attached%20%7C%20%7B_oi_raw%7D%20%7C%20%7B_oi_cln%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20_meta_table%20%3D%20f%22%22%22%5C%0A%20%20%20%20%23%23%23%20Metadata%0A%0A%20%20%20%20%7C%20Field%20%7C%20Value%20%7C%0A%20%20%20%20%7C-------%7C------%3A%7C%0A%20%20%20%20%7C%20Date%20%7C%20%7Bchain.metadata.date.strftime(%22%25Y-%25m-%25d%22)%7D%20%7C%0A%20%20%20%20%7C%20Expiry%20%7C%20%7Bchain.metadata.expiry.strftime(%22%25Y-%25m-%25d%22)%7D%20%7C%0A%20%20%20%20%7C%20Day%20count%20%7C%20%7Bchain.metadata.daycount.value%7D%20%7C%0A%20%20%20%20%7C%20%24T%24%20(years)%20%7C%20%7Bchain.metadata.texpiry%3A.4f%7D%20%7C%0A%20%20%20%20%7C%20Forward%20%24F%24%20%7C%20%7Bchain.metadata.forward%3A%2C.2f%7D%20%7C%0A%20%20%20%20%7C%20Discount%20factor%20%24D%24%20%7C%20%7Bchain.metadata.discount_factor%3A.6f%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bmo.md(_filter_table)%2C%20mo.md(_meta_table)%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22start%22%2C%0A%20%20%20%20%20%20%20%20gap%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(chain%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_chain_plot(chain%2C%20chain_raw)%3A%0A%20%20%20%20%22%22%22Plot%20raw%20vs%20filtered%20bid%2Fask%20prices.%22%22%22%0A%20%20%20%20_fig%20%3D%20make_subplots(%0A%20%20%20%20%20%20%20%20rows%3D1%2C%0A%20%20%20%20%20%20%20%20cols%3D2%2C%0A%20%20%20%20%20%20%20%20subplot_titles%3D%5B%22Raw%20(all%20strikes)%22%2C%20%22Filtered%20(clean)%22%5D%2C%0A%20%20%20%20%20%20%20%20shared_yaxes%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20for%20_col%2C%20src%2C%20title%20in%20%5B(1%2C%20chain_raw%2C%20%22Raw%22)%2C%20(2%2C%20chain%2C%20%22Filtered%22)%5D%3A%0A%20%20%20%20%20%20%20%20for%20label%2C%20mid%2C%20bid%2C%20ask%2C%20color%20in%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22Calls%22%2C%20src.call_mid%2C%20src.call_bid%2C%20src.call_ask%2C%20%22%232196F3%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22Puts%22%2C%20src.put_mid%2C%20src.put_bid%2C%20src.put_ask%2C%20%22%23E88D7D%22)%2C%0A%20%20%20%20%20%20%20%20%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3Dsrc.strikes%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3Dmid%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%2Blines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20error_y%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22symmetric%22%3A%20False%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22array%22%3A%20(ask%20-%20mid).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arrayminus%22%3A%20(mid%20-%20bid).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%22%7Blabel%7D%20(%7Btitle%7D)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22color%22%3A%20color%2C%20%22size%22%3A%204%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20color%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3D(_col%20%3D%3D%201)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20col%3D_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20_x_lo%20%3D%20min(float(chain_raw.strikes.min())%2C%20float(chain.strikes.min()))%0A%20%20%20%20_x_hi%20%3D%20max(float(chain_raw.strikes.max())%2C%20float(chain.strikes.max()))%0A%20%20%20%20_y_lo%20%3D%20min(%0A%20%20%20%20%20%20%20%20float(chain_raw.call_bid.min())%2C%0A%20%20%20%20%20%20%20%20float(chain_raw.put_bid.min())%2C%0A%20%20%20%20%20%20%20%20float(chain.call_bid.min())%2C%0A%20%20%20%20%20%20%20%20float(chain.put_bid.min())%2C%0A%20%20%20%20)%0A%20%20%20%20_y_hi%20%3D%20max(%0A%20%20%20%20%20%20%20%20float(chain_raw.call_ask.max())%2C%0A%20%20%20%20%20%20%20%20float(chain_raw.put_ask.max())%2C%0A%20%20%20%20%20%20%20%20float(chain.call_ask.max())%2C%0A%20%20%20%20%20%20%20%20float(chain.put_ask.max())%2C%0A%20%20%20%20)%0A%20%20%20%20_x_pad%20%3D%20(_x_hi%20-%20_x_lo)%20*%200.05%0A%20%20%20%20_y_pad%20%3D%20(_y_hi%20-%20_y_lo)%20*%200.05%0A%20%20%20%20_fig.update_xaxes(%0A%20%20%20%20%20%20%20%20title_text%3D%22Strike%22%2C%0A%20%20%20%20%20%20%20%20range%3D%5B_x_lo%20-%20_x_pad%2C%20_x_hi%20%2B%20_x_pad%5D%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_yaxes(%0A%20%20%20%20%20%20%20%20title_text%3D%22Price%22%2C%0A%20%20%20%20%20%20%20%20range%3D%5B_y_lo%20-%20_y_pad%2C%20_y_hi%20%2B%20_y_pad%5D%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Option%20Prices%20%E2%80%94%20Raw%20vs%20Filtered%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D400%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_sd_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20VolData%20section.%22%22%22%0A%20%20%20%20_x_table%20%3D%20(%0A%20%20%20%20%20%20%20%20%22%7C%20X-coordinate%20%7C%20Formula%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%22%7C-------------%7C---------%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%22%7C%20FixedStrike%20%7C%20%24K%24%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%22%7C%20MoneynessStrike%20%7C%20%24K%20%2F%20F%24%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20r%22%7C%20LogMoneynessStrike%20%7C%20%24%5Cln(K%2FF)%24%20%7C%22%0A%20%20%20%20%20%20%20%20%22%5Cn%22%0A%20%20%20%20%20%20%20%20r%22%7C%20StandardisedStrike%20%7C%20%24%5Cln(K%2FF)%20%2F%20(%5Csigma_%5Ctext%7BATM%7D%5Csqrt%7BT%7D)%24%20%7C%22%0A%20%20%20%20)%0A%20%20%20%20_y_table%20%3D%20(%0A%20%20%20%20%20%20%20%20%22%7C%20Y-coordinate%20%7C%20Formula%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%22%7C-------------%7C---------%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%22%7C%20Price%20%7C%20option%20price%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20r%22%7C%20Volatility%20%7C%20%24%5Csigma%24%20%7C%22%0A%20%20%20%20%20%20%20%20%22%5Cn%22%0A%20%20%20%20%20%20%20%20r%22%7C%20Variance%20%7C%20%24%5Csigma%5E2%24%20%7C%22%0A%20%20%20%20%20%20%20%20%22%5Cn%22%0A%20%20%20%20%20%20%20%20r%22%7C%20TotalVariance%20%7C%20%24%5Csigma%5E2%20T%24%20%7C%22%0A%20%20%20%20)%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%202%20%C2%B7%20VolData%20%26%20Coordinate%20Transforms%0A%0A%20%20%20%20%20%20%20%20%60.to_vols()%60%20delta-blends%20call%2Fput%20implied%20vols%20into%0A%20%20%20%20%20%20%20%20**(FixedStrike%2C%20Volatility)**%20using%20Black-76%20call-delta%20weights.%0A%0A%20%20%20%20%20%20%20%20From%20there%2C%20%60.transform(x%2C%20y)%60%20moves%20freely%20between%20any%20combination%3A%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bmo.md(_x_table)%2C%20mo.md(_y_table)%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22start%22%2C%0A%20%20%20%20%20%20%20%20gap%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_smile_data(chain)%3A%0A%20%20%20%20%22%22%22Create%20VolData%20in%20price%20and%20vol%20coordinates.%22%22%22%0A%20%20%20%20sd_vols%20%3D%20chain.to_vols()%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%23%23%23%20VolData%20containers%0A%0A%20%20%20%20%7C%20Container%20%7C%20X%20coord%20%7C%20Y%20coord%20%7C%20Points%20%7C%0A%20%20%20%20%7C-----------%7C---------%7C---------%7C-------%3A%7C%0A%20%20%20%20%7C%20%60sd_vols%60%20%7C%20%7Bsd_vols.current_x_coord.name%7D%20%7C%20%7Bsd_vols.current_y_coord.name%7D%20%7C%20%7Blen(sd_vols.x)%7D%20%7C%0A%20%20%20%20%7C%20Volume%20attached%20%7C%20%7B%22Yes%22%20if%20sd_vols.volume%20is%20not%20None%20else%20%22No%22%7D%20%7C%0A%20%20%20%20%7C%20Open%20interest%20attached%20%7C%20%7B%22Yes%22%20if%20sd_vols.open_interest%20is%20not%20None%20else%20%22No%22%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%20(sd_vols%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_transform_grid(sd_vols)%3A%0A%20%20%20%20%22%22%22Plot%20the%20same%20smile%20in%20four%20coordinate%20systems.%22%22%22%0A%20%20%20%20views%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22FixedStrike%20%2F%20Volatility%22%2C%20XCoord.FixedStrike%2C%20YCoord.Volatility%2C%20%22Strike%22%2C%20%22%CF%83%22)%2C%0A%20%20%20%20%20%20%20%20(%22MoneynessStrike%20%2F%20Volatility%22%2C%20XCoord.MoneynessStrike%2C%20YCoord.Volatility%2C%20%22K%2FF%22%2C%20%22%CF%83%22)%2C%0A%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22LogMoneyness%20%2F%20TotalVariance%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20XCoord.LogMoneynessStrike%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20YCoord.TotalVariance%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22ln(K%2FF)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%CF%83%C2%B2T%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Standardised%20%2F%20TotalVariance%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20XCoord.StandardisedStrike%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20YCoord.TotalVariance%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22k%CC%83%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%CF%83%C2%B2T%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D%0A%0A%20%20%20%20_fig%20%3D%20make_subplots(rows%3D2%2C%20cols%3D2%2C%20subplot_titles%3D%5Bv%5B0%5D%20for%20v%20in%20views%5D)%0A%20%20%20%20colors%20%3D%20%5B%22%232196F3%22%2C%20%22%23E88D7D%22%2C%20%22%232FA4A9%22%2C%20%22%239B59B6%22%5D%0A%0A%20%20%20%20for%20idx%2C%20(_title%2C%20xc%2C%20yc%2C%20xlabel%2C%20ylabel)%20in%20enumerate(views)%3A%0A%20%20%20%20%20%20%20%20v%20%3D%20sd_vols.transform(xc%2C%20yc)%0A%20%20%20%20%20%20%20%20_row%2C%20_col%20%3D%20divmod(idx%2C%202)%0A%20%20%20%20%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3Dv.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3Dv.y_mid%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%2Blines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22color%22%3A%20colors%5Bidx%5D%2C%20%22size%22%3A%205%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20colors%5Bidx%5D%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20row%3D_row%20%2B%201%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20col%3D_col%20%2B%201%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_fig.update_xaxes(title_text%3Dxlabel%2C%20row%3D_row%20%2B%201%2C%20col%3D_col%20%2B%201)%0A%20%20%20%20%20%20%20%20_fig.update_yaxes(title_text%3Dylabel%2C%20row%3D_row%20%2B%201%2C%20col%3D_col%20%2B%201)%0A%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Same%20Smile%20%E2%80%94%20Four%20Coordinate%20Systems%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D620%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_svi_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20SVI%20fitting.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%203%20%C2%B7%20SVI%20Model%20Fit%0A%0A%20%20%20%20%20%20%20%20Stochastic%20Volatility%20Inspired%20parametrisation%20(Gatheral%2C%202004)%3A%0A%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20w(k)%20%3D%20a%20%2B%20b%5Cbigl%5B%5Crho%5C%2C(k%20-%20m)%20%2B%20%5Csqrt%7B(k%20-%20m)%5E2%20%2B%20%5Csigma%5E2%7D%5Cbigr%5D%0A%20%20%20%20%20%20%20%20%24%24%0A%0A%20%20%20%20%20%20%20%20where%20%24k%20%3D%20%5Cln(K%2FF)%24%20is%20log-moneyness%20and%20%24w%20%3D%20%5Csigma%5E2%20T%24%20is%0A%20%20%20%20%20%20%20%20total%20implied%20variance.%0A%0A%20%20%20%20%20%20%20%20%60fit(sd%2C%20SVIModel)%60%20transforms%20data%20to%20the%20model's%20native%0A%20%20%20%20%20%20%20%20**(LogMoneynessStrike%2C%20TotalVariance)**%20coordinates%20automatically.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_svi_fit(sd_vols)%3A%0A%20%20%20%20%22%22%22Fit%20SVI%20to%20the%20market%20smile.%22%22%22%0A%20%20%20%20svi_result%20%3D%20fit(sd_vols%2C%20SVIModel)%0A%20%20%20%20p%20%3D%20svi_result.model%0A%0A%20%20%20%20_params_table%20%3D%20f%22%22%22%0A%20%20%20%20%23%23%23%20SVI%20Parameters%0A%0A%20%20%20%20%7C%20Parameter%20%7C%20Value%20%7C%20Meaning%20%7C%0A%20%20%20%20%7C-----------%7C------%3A%7C--------%7C%0A%20%20%20%20%7C%20%24a%24%20%7C%20%7Bp.a%3A.6f%7D%20%7C%20Vertical%20shift%20%7C%0A%20%20%20%20%7C%20%24b%24%20%7C%20%7Bp.b%3A.6f%7D%20%7C%20Wing%20slope%20%7C%0A%20%20%20%20%7C%20%24%5C%5Crho%24%20%7C%20%7Bp.rho%3A.6f%7D%20%7C%20Skew%20%7C%0A%20%20%20%20%7C%20%24m%24%20%7C%20%7Bp.m%3A.6f%7D%20%7C%20Horizontal%20shift%20%7C%0A%20%20%20%20%7C%20%24%5C%5Csigma%24%20%7C%20%7Bp.sigma%3A.6f%7D%20%7C%20ATM%20curvature%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20_diag_table%20%3D%20f%22%22%22%0A%20%20%20%20%23%23%23%20Fit%20Diagnostics%0A%0A%20%20%20%20%7C%20Metric%20%7C%20Value%20%7C%0A%20%20%20%20%7C--------%7C------%3A%7C%0A%20%20%20%20%7C%20**RMSE**%20%7C%20%7Bsvi_result.rmse%3A.2e%7D%20%7C%0A%20%20%20%20%7C%20**Converged**%20%7C%20%7B%22Yes%22%20if%20svi_result.success%20else%20%22No%22%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bmo.md(_params_table)%2C%20mo.md(_diag_table)%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22start%22%2C%0A%20%20%20%20%20%20%20%20gap%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(svi_result%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_svi_plot(sd_vols%2C%20svi_result)%3A%0A%20%20%20%20%22%22%22Overlay%20SVI%20fit%20on%20market%20vols.%22%22%22%0A%20%20%20%20_fwd%20%3D%20sd_vols.metadata.forward%0A%20%20%20%20_k_fine%20%3D%20np.linspace(sd_vols.x.min()%20*%200.95%2C%20sd_vols.x.max()%20*%201.05%2C%20300)%0A%20%20%20%20_log_k%20%3D%20np.log(_k_fine%20%2F%20_fwd)%0A%20%20%20%20_iv_svi%20%3D%20svi_result.model.transform(XCoord.LogMoneynessStrike%2C%20YCoord.Volatility).evaluate(_log_k)%0A%0A%20%20%20%20_fig%20%3D%20go.Figure()%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dsd_vols.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dsd_vols.y_mid%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20error_y%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22symmetric%22%3A%20False%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22array%22%3A%20((sd_vols.y_ask%20-%20sd_vols.y_mid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arrayminus%22%3A%20((sd_vols.y_mid%20-%20sd_vols.y_bid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%208%2C%20%22color%22%3A%20%22%23E88D7D%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Market%20(bid%2Fask)%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D_k_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_iv_svi%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%232FA4A9%22%2C%20%22width%22%3A%202.5%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22SVI%20fit%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22SVI%20Fit%20vs%20Market%20Implied%20Vols%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Strike%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Implied%20Volatility%20(%25)%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D400%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_sabr_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20SABR%20fitting.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%204%20%C2%B7%20SABR%20Model%20Fit%0A%0A%20%20%20%20%20%20%20%20Hagan%20(2002)%20SABR%20lognormal%20implied%20volatility%20approximation.%0A%20%20%20%20%20%20%20%20The%20SABR%20model%20describes%20the%20joint%20dynamics%20of%20a%20forward%20%24F%24%0A%20%20%20%20%20%20%20%20and%20its%20stochastic%20volatility%20%24%5Calpha%24%3A%0A%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%20%20%20%20dF%20%26%3D%20%5Calpha%5C%2C%20F%5E%5Cbeta%5C%2C%20dW_1%20%5C%5C%0A%20%20%20%20%20%20%20%20d%5Calpha%20%26%3D%20%5Cnu%5C%2C%20%5Calpha%5C%2C%20dW_2%20%5C%5C%0A%20%20%20%20%20%20%20%20%5Clangle%20dW_1%2C%20dW_2%20%5Crangle%20%26%3D%20%5Crho%5C%2C%20dt%0A%20%20%20%20%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%20%20%20%20%24%24%0A%0A%20%20%20%20%20%20%20%20Four%20fitted%20parameters%3A%20%24%5Calpha%24%20(initial%20vol)%2C%20%24%5Cbeta%24%20(CEV%20exponent)%2C%0A%20%20%20%20%20%20%20%20%24%5Crho%24%20(correlation)%2C%20%24%5Cnu%24%20(vol-of-vol).%0A%0A%20%20%20%20%20%20%20%20%60fit(sd%2C%20SABRModel)%60%20transforms%20to%20the%20model's%20native%0A%20%20%20%20%20%20%20%20**(LogMoneynessStrike%2C%20Volatility)**%20coordinates.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_sabr_fit(sd_vols)%3A%0A%20%20%20%20%22%22%22Fit%20SABR%20to%20the%20market%20smile.%22%22%22%0A%20%20%20%20sabr_result%20%3D%20fit(sd_vols%2C%20SABRModel)%0A%20%20%20%20sp%20%3D%20sabr_result.model%0A%0A%20%20%20%20_params_table%20%3D%20f%22%22%22%0A%20%20%20%20%23%23%23%20SABR%20Parameters%0A%0A%20%20%20%20%7C%20Parameter%20%7C%20Value%20%7C%20Meaning%20%7C%0A%20%20%20%20%7C-----------%7C------%3A%7C--------%7C%0A%20%20%20%20%7C%20%24%5C%5Calpha%24%20%7C%20%7Bsp.alpha%3A.6f%7D%20%7C%20Initial%20vol%20%7C%0A%20%20%20%20%7C%20%24%5C%5Cbeta%24%20%7C%20%7Bsp.beta%3A.6f%7D%20%7C%20CEV%20exponent%20%7C%0A%20%20%20%20%7C%20%24%5C%5Crho%24%20%7C%20%7Bsp.rho%3A.6f%7D%20%7C%20Correlation%20%7C%0A%20%20%20%20%7C%20%24%5C%5Cnu%24%20%7C%20%7Bsp.nu%3A.6f%7D%20%7C%20Vol-of-vol%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20_diag_table%20%3D%20f%22%22%22%0A%20%20%20%20%23%23%23%20Fit%20Diagnostics%0A%0A%20%20%20%20%7C%20Metric%20%7C%20Value%20%7C%0A%20%20%20%20%7C--------%7C------%3A%7C%0A%20%20%20%20%7C%20**RMSE**%20%7C%20%7Bsabr_result.rmse%3A.2e%7D%20%7C%0A%20%20%20%20%7C%20**Converged**%20%7C%20%7B%22Yes%22%20if%20sabr_result.success%20else%20%22No%22%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bmo.md(_params_table)%2C%20mo.md(_diag_table)%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22start%22%2C%0A%20%20%20%20%20%20%20%20gap%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(sabr_result%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_sabr_plot(sabr_result%2C%20sd_vols)%3A%0A%20%20%20%20%22%22%22Overlay%20SABR%20fit%20on%20market%20vols.%22%22%22%0A%20%20%20%20_fwd%20%3D%20sd_vols.metadata.forward%0A%20%20%20%20_k_fine%20%3D%20np.linspace(sd_vols.x.min()%20*%200.95%2C%20sd_vols.x.max()%20*%201.05%2C%20300)%0A%20%20%20%20_log_k%20%3D%20np.log(_k_fine%20%2F%20_fwd)%0A%20%20%20%20_iv_sabr%20%3D%20sabr_result.model.evaluate(_log_k)%0A%0A%20%20%20%20_fig%20%3D%20go.Figure()%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dsd_vols.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dsd_vols.y_mid%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20error_y%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22symmetric%22%3A%20False%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22array%22%3A%20((sd_vols.y_ask%20-%20sd_vols.y_mid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arrayminus%22%3A%20((sd_vols.y_mid%20-%20sd_vols.y_bid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%208%2C%20%22color%22%3A%20%22%23E88D7D%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Market%20(bid%2Fask)%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D_k_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_iv_sabr%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%237E57C2%22%2C%20%22width%22%3A%202.5%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22SABR%20fit%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22SABR%20Fit%20vs%20Market%20Implied%20Vols%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Strike%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Implied%20Volatility%20(%25)%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D400%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_comparison_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20model%20comparison%20section.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%205%20%C2%B7%20Model%20Comparison%0A%0A%20%20%20%20%20%20%20%20Both%20SVI%20and%20SABR%20fits%20overlaid%20on%20the%20same%20market%20data%20for%0A%20%20%20%20%20%20%20%20direct%20visual%20comparison.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_model_comparison(sabr_result%2C%20sd_vols%2C%20svi_result)%3A%0A%20%20%20%20%22%22%22Compare%20SVI%20and%20SABR%20fits%20on%20the%20same%20plot.%22%22%22%0A%20%20%20%20_fwd%20%3D%20sd_vols.metadata.forward%0A%20%20%20%20_k_fine%20%3D%20np.linspace(sd_vols.x.min()%20*%200.95%2C%20sd_vols.x.max()%20*%201.05%2C%20300)%0A%20%20%20%20_log_k%20%3D%20np.log(_k_fine%20%2F%20_fwd)%0A%0A%20%20%20%20_iv_svi%20%3D%20svi_result.model.transform(XCoord.LogMoneynessStrike%2C%20YCoord.Volatility).evaluate(_log_k)%0A%20%20%20%20_iv_sabr%20%3D%20sabr_result.model.evaluate(_log_k)%0A%0A%20%20%20%20_fig%20%3D%20go.Figure()%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dsd_vols.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dsd_vols.y_mid%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20error_y%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%20%22data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22symmetric%22%3A%20False%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22array%22%3A%20((sd_vols.y_ask%20-%20sd_vols.y_mid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22arrayminus%22%3A%20((sd_vols.y_mid%20-%20sd_vols.y_bid)%20*%20100).tolist()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%208%2C%20%22color%22%3A%20%22%23E88D7D%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Market%20(bid%2Fask)%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D_k_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_iv_svi%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%232FA4A9%22%2C%20%22width%22%3A%202.5%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%22SVI%20%20(RMSE%20%7Bsvi_result.rmse%3A.2e%7D)%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D_k_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_iv_sabr%20*%20100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%237E57C2%22%2C%20%22width%22%3A%202.5%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%22SABR%20(RMSE%20%7Bsabr_result.rmse%3A.2e%7D)%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22SVI%20vs%20SABR%20%E2%80%94%20Model%20Comparison%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Strike%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Implied%20Volatility%20(%25)%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D420%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22orientation%22%3A%20%22h%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22yanchor%22%3A%20%22top%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20-0.15%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22xanchor%22%3A%20%22center%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%200.5%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_vol_oi_intro()%3A%0A%20%20%20%20%22%22%22Introduce%20volume%20%2F%20open%20interest%20section.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%206%20%C2%B7%20Volume%20%26%20Open%20Interest%20Passthrough%0A%0A%20%20%20%20%20%20%20%20Optional%20%60volume%60%20and%20%60open_interest%60%20arrays%20flow%20through%20the%0A%20%20%20%20%20%20%20%20entire%20pipeline%20%E2%80%94%20from%20%60OptionChain%60%20through%20%60filter()%60%2C%0A%20%20%20%20%20%20%20%20%60to_vols()%60%2C%20and%0A%20%20%20%20%20%20%20%20%60VolData.transform()%60.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_vol_oi_demo(chain)%3A%0A%20%20%20%20%22%22%22Show%20volume%20%2F%20OI%20surviving%20the%20pipeline.%22%22%22%0A%20%20%20%20sd_with_vol%20%3D%20chain.to_vols()%0A%20%20%20%20sd_transformed%20%3D%20sd_with_vol.transform(XCoord.LogMoneynessStrike%2C%20YCoord.TotalVariance)%0A%0A%20%20%20%20_fig%20%3D%20make_subplots(%0A%20%20%20%20%20%20%20%20rows%3D2%2C%0A%20%20%20%20%20%20%20%20cols%3D1%2C%0A%20%20%20%20%20%20%20%20subplot_titles%3D%5B%22Volume%20by%20Strike%22%2C%20%22Open%20Interest%20by%20Strike%22%5D%2C%0A%20%20%20%20%20%20%20%20shared_xaxes%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Bar(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dchain.strikes%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dchain.volume%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker_color%3D%22%232196F3%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Volume%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Bar(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dchain.strikes%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dchain.open_interest%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker_color%3D%22%239B59B6%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Open%20Interest%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D2%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Volume%20%26%20Open%20Interest%20%E2%80%94%20Preserved%20Through%20Pipeline%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D450%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_xaxes(title_text%3D%22Strike%22%2C%20row%3D2%2C%20col%3D1)%0A%20%20%20%20_fig.update_yaxes(title_text%3D%22Volume%22%2C%20row%3D1%2C%20col%3D1)%0A%20%20%20%20_fig.update_yaxes(title_text%3D%22Open%20Interest%22%2C%20row%3D2%2C%20col%3D1)%0A%0A%20%20%20%20_vol%20%3D%20lambda%20o%3A%20%22%E2%9C%93%22%20if%20o.volume%20is%20not%20None%20else%20%22%E2%9C%97%22%20%20%23%20noqa%3A%20E731%0A%20%20%20%20_oi%20%3D%20lambda%20o%3A%20%22%E2%9C%93%22%20if%20o.open_interest%20is%20not%20None%20else%20%22%E2%9C%97%22%20%20%23%20noqa%3A%20E731%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.plotly(_fig)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%7C%20Pipeline%20stage%20%7C%20Volume%3F%20%7C%20OI%3F%20%7C%0A%20%20%20%20%7C----------------%7C%3A-------%3A%7C%3A---%3A%7C%0A%20%20%20%20%7C%20%60OptionChain%60%20(raw)%20%7C%20%7B_vol(chain)%7D%20%7C%20%7B_oi(chain)%7D%20%7C%0A%20%20%20%20%7C%20%60to_vols()%60%20%7C%20%7B_vol(sd_with_vol)%7D%20%7C%20%7B_oi(sd_with_vol)%7D%20%7C%0A%20%20%20%20%7C%20%60transform(LogMoneyness%2C%20TotalVar)%60%20%7C%20%7B_vol(sd_transformed)%7D%20%7C%20%7B_oi(sd_transformed)%7D%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_summary()%3A%0A%20%20%20%20%22%22%22Conclude%20the%20notebook.%22%22%22%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20---%0A%20%20%20%20%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20%20%20%20%20%7C%20Step%20%7C%20API%20%7C%20What%20it%20does%20%7C%0A%20%20%20%20%20%20%20%20%7C------%7C-----%7C-------------%7C%0A%20%20%20%20%20%20%20%20%7C%20Load%20%7C%20%60OptionChain(...)%60%20%7C%20Stores%20bid%2Fask%20prices%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Clean%20%7C%20%60.filter()%60%20%7C%205-filter%20arbitrage%20removal%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Calibrate%20%7C%20automatic%20%7C%20Forward%20%24F%24%20and%20discount%20factor%20%24D%24%20from%20put-call%20parity%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Convert%20%7C%20%60.to_vols()%60%20%7C%20Delta-blended%20implied%20vols%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Transform%20%7C%20%60.transform(x%2C%20y)%60%20%7C%20Any%20%24(X%2C%20Y)%24%20coordinate%20pair%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Fit%20%7C%20%60fit(sd%2C%20SVIModel)%60%20%2F%20%60fit(sd%2C%20SABRModel)%60%20%7C%20Parametric%20smile%20fit%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Ancillary%20%7C%20%60volume%60%2C%20%60open_interest%60%20%7C%20Optional%20data%20carried%20through%20pipeline%20%7C%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
10f11bf547c051a87c6d1f2a38e7caa1