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%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%0A%20%20%20%20from%20qsmile%20import%20SVIModel%2C%20fit%0A%20%20%20%20from%20qsmile.core.coords%20import%20XCoord%2C%20YCoord%0A%20%20%20%20from%20qsmile.data.prices%20import%20OptionChain%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_02()%3A%0A%20%20%20%20%22%22%22Render%20the%20notebook%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%20Volatility%20Smile%20Modelling%20with%20qsmile%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20demonstrates%20**qsmile**%2C%20a%20library%20for%20fitting%20parametric%0A%20%20%20%20%20%20%20%20volatility%20smile%20models%20to%20option%20chain%20data.%0A%0A%20%20%20%20%20%20%20%20We'll%20walk%20through%20the%20core%20workflow%3A%0A%20%20%20%20%20%20%20%201.%20Construct%20a%20%60SmileData%60%20from%20mid%20implied%20volatilities%0A%20%20%20%20%20%20%20%202.%20Fit%20the%20**SVI**%20(Stochastic%20Volatility%20Inspired)%20model%0A%20%20%20%20%20%20%20%203.%20Inspect%20fit%20quality%20and%20explore%20parameter%20sensitivity%0A%0A%20%20%20%20%20%20%20%20The%20SVI%20raw%20parameterisation%20models%20total%20implied%20variance%20as%3A%0A%0A%20%20%20%20%20%20%20%20%24%24w(k)%20%3D%20a%20%2B%20b%5Cleft(%5Crho(k%20-%20m)%20%2B%20%5Csqrt%7B(k%20-%20m)%5E2%20%2B%20%5Csigma%5E2%7D%5Cright)%24%24%0A%0A%20%20%20%20%20%20%20%20where%20%24k%20%3D%20%5Cln(K%2FF)%24%20is%20log-moneyness.%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_04()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20market%20data%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%23%23%20Market%20Data%0A%0A%20%20%20%20%20%20%20%20We%20load%20a%20real%20S%26P%20500%20(SPX)%20option%20chain%20from%20parquet%20and%20build%0A%20%20%20%20%20%20%20%20an%20%60OptionChain%60%20to%20calibrate%20a%20consistent%20forward%20and%20discount%0A%20%20%20%20%20%20%20%20factor%20from%20put-call%20parity.%20The%20resulting%20implied%20volatilities%20are%0A%20%20%20%20%20%20%20%20then%20extracted%20via%20%60to_smile_data()%60%2C%20giving%20a%20clean%20smile%20with%20the%0A%20%20%20%20%20%20%20%20characteristic%20equity%20skew.%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_05()%3A%0A%20%20%20%20%22%22%22Load%20real%20SPX%20market%20data%20from%20parquet.%22%22%22%0A%20%20%20%20_root%20%3D%20Path(__file__).resolve().parent.parent.parent.parent%0A%20%20%20%20_pq%20%3D%20sorted(_root.glob(%22parquet%2Fchains%2F*.parquet%22))%5B-1%5D%0A%20%20%20%20df_raw%20%3D%20pd.read_parquet(_pq)%0A%0A%20%20%20%20expiry%20%3D%20float(df_raw%5B%22daysToExpiry%22%5D.iloc%5B0%5D)%20%2F%20365.0%0A%0A%20%20%20%20%23%20Merge%20calls%2Fputs%20on%20common%20strikes%0A%20%20%20%20_cols%20%3D%20%5B%22strike%22%2C%20%22bid%22%2C%20%22ask%22%5D%0A%20%20%20%20calls%20%3D%20df_raw%5Bdf_raw%5B%22optionType%22%5D%20%3D%3D%20%22call%22%5D%5B_cols%5D.set_index(%22strike%22)%0A%20%20%20%20puts%20%3D%20df_raw%5Bdf_raw%5B%22optionType%22%5D%20%3D%3D%20%22put%22%5D%5B_cols%5D.set_index(%22strike%22)%0A%20%20%20%20merged%20%3D%20calls.join(puts%2C%20lsuffix%3D%22_c%22%2C%20rsuffix%3D%22_p%22%2C%20how%3D%22inner%22).sort_index()%0A%0A%20%20%20%20%23%20Build%20OptionChain%20%E2%86%92%20denoise%20%E2%86%92%20calibrate%20F%2C%20DF%20%E2%86%92%20extract%20vols%0A%20%20%20%20_strikes%20%3D%20merged.index.values.astype(np.float64)%0A%20%20%20%20raw_prices%20%3D%20OptionChain(%0A%20%20%20%20%20%20%20%20strikes%3D_strikes%2C%0A%20%20%20%20%20%20%20%20call_bid%3Dmerged%5B%22bid_c%22%5D.values.astype(np.float64)%2C%0A%20%20%20%20%20%20%20%20call_ask%3Dmerged%5B%22ask_c%22%5D.values.astype(np.float64)%2C%0A%20%20%20%20%20%20%20%20put_bid%3Dmerged%5B%22bid_p%22%5D.values.astype(np.float64)%2C%0A%20%20%20%20%20%20%20%20put_ask%3Dmerged%5B%22ask_p%22%5D.values.astype(np.float64)%2C%0A%20%20%20%20%20%20%20%20expiry%3Dexpiry%2C%0A%20%20%20%20)%0A%20%20%20%20prices%20%3D%20raw_prices.denoise()%0A%0A%20%20%20%20%23%20Convert%20to%20SmileData%20in%20vol%20coordinates%20(consistent%20F%20and%20DF)%0A%20%20%20%20sd%20%3D%20prices.to_smile_data().transform(XCoord.FixedStrike%2C%20YCoord.Volatility)%0A%20%20%20%20strikes%20%3D%20sd.x%0A%20%20%20%20ivs%20%3D%20sd.y_mid%0A%20%20%20%20return%20expiry%2C%20ivs%2C%20sd%2C%20strikes%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_06(ivs%2C%20sd%2C%20strikes)%3A%0A%20%20%20%20%22%22%22Display%20the%20option%20chain%20as%20an%20interactive%20table.%22%22%22%0A%20%20%20%20_sd_lm%20%3D%20sd.transform(XCoord.LogMoneynessStrike%2C%20YCoord.TotalVariance)%0A%20%20%20%20df%20%3D%20pd.DataFrame(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Strike%22%3A%20strikes%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22IV%20(%25)%22%3A%20(ivs%20*%20100).round(1)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Log-Moneyness%22%3A%20_sd_lm.x.round(4)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Total%20Variance%22%3A%20_sd_lm.y_mid.round(6)%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5Bmo.md(%22%23%23%23%20Option%20Chain%20Data%22)%2C%20df%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_07()%3A%0A%20%20%20%20%22%22%22Render%20a%20section%20divider.%22%22%22%0A%20%20%20%20mo.md(r%22%22%22---%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_08()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20SVI%20fitting%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%23%23%20SVI%20Fitting%0A%0A%20%20%20%20%20%20%20%20We%20fit%20the%20SVI%20raw%20parameterisation%20to%20the%20market%20data%20using%0A%20%20%20%20%20%20%20%20%60fit%60%2C%20which%20minimises%20the%20sum%20of%20squared%20residuals%20in%0A%20%20%20%20%20%20%20%20total-variance%20space%20via%20%60scipy.optimize.least_squares%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_09(sd)%3A%0A%20%20%20%20%22%22%22Fit%20SVI%20to%20the%20SmileData%20and%20display%20results.%22%22%22%0A%20%20%20%20result%20%3D%20fit(sd%2C%20SVIModel)%0A%20%20%20%20p%20%3D%20result.params%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.md(%22%23%23%23%20Fitted%20SVI%20Parameters%22)%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%20Parameter%20%7C%20Value%20%7C%20Description%20%7C%0A%20%20%20%20%7C-----------%7C-------%7C-------------%7C%0A%20%20%20%20%7C%20%24a%24%20%7C%20%7Bp.a%3A.6f%7D%20%7C%20Vertical%20translation%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(correlation)%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%0A%20%20%20%20**RMSE%3A**%20%7Bresult.rmse%3A.2e%7D%20%26nbsp%3B%26nbsp%3B%20**Converged%3A**%20%7B%22Yes%22%20if%20result.success%20else%20%22No%22%7D%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%20p%2C%20result%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_10(expiry%2C%20result%2C%20sd)%3A%0A%20%20%20%20%22%22%22Plot%20market%20data%20vs%20fitted%20SVI%20smile.%22%22%22%0A%20%20%20%20_sd_lm%20%3D%20sd.transform(XCoord.LogMoneynessStrike%2C%20YCoord.Volatility)%0A%20%20%20%20_k_market%20%3D%20_sd_lm.x%0A%20%20%20%20k_fine%20%3D%20np.linspace(_k_market.min()%20-%200.05%2C%20_k_market.max()%20%2B%200.05%2C%20200)%0A%20%20%20%20iv_fitted%20%3D%20result.params.implied_vol(k_fine%2C%20expiry)%0A%0A%20%20%20%20fig%20%3D%20go.Figure()%0A%20%20%20%20fig.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_market%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_sd_lm.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%20marker%3D%7B%22size%22%3A%2010%2C%20%22color%22%3A%20%22%23E74C3C%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Market%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig.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%3Dk_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Div_fitted%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%20fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Implied%20Volatility%20Smile%3A%20Market%20vs%20SVI%20Fit%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Log-Moneyness%20%20k%20%3D%20ln(K%2FF)%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%3D450%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22x%22%3A%200.02%2C%20%22y%22%3A%200.98%7D%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(fig)%0A%20%20%20%20return%20iv_fitted%2C%20k_fine%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_11(result%2C%20sd)%3A%0A%20%20%20%20%22%22%22Plot%20fit%20residuals.%22%22%22%0A%20%20%20%20_sd_lm%20%3D%20sd.transform(XCoord.LogMoneynessStrike%2C%20YCoord.Volatility)%0A%20%20%20%20_k_market%20%3D%20_sd_lm.x%0A%0A%20%20%20%20fig_resid%20%3D%20go.Figure()%0A%20%20%20%20fig_resid.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%3D_k_market%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dresult.residuals%20*%201e4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker_color%3D%22%232FA4A9%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Residual%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig_resid.add_hline(y%3D0%2C%20line_dash%3D%22dash%22%2C%20line_color%3D%22grey%22)%0A%20%20%20%20fig_resid.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Fit%20Residuals%20(Total%20Variance%20%C3%97%2010%E2%81%B4)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Log-Moneyness%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Residual%20(bps%20of%20total%20var)%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%3D350%2C%0A%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(fig_resid)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_13()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20parameter%20explorer%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%23%23%20Parameter%20Explorer%0A%0A%20%20%20%20%20%20%20%20Use%20the%20sliders%20below%20to%20see%20how%20each%20SVI%20parameter%20shapes%20the%20smile.%0A%20%20%20%20%20%20%20%20The%20**blue**%20curve%20is%20the%20fitted%20smile%20from%20above%3B%20the%20**orange**%20curve%0A%20%20%20%20%20%20%20%20shows%20the%20effect%20of%20your%20parameter%20changes.%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_14(p)%3A%0A%20%20%20%20%22%22%22Create%20sliders%20for%20SVI%20parameters.%22%22%22%0A%20%20%20%20%23%20Ranges%20are%20data-adaptive%3A%20centred%20on%20the%20fitted%20value%20with%20room%20to%20explore%0A%20%20%20%20sl_a%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3Dmin(-1.0%2C%20p.a%20*%203)%2C%0A%20%20%20%20%20%20%20%20stop%3Dmax(1.0%2C%20p.a%20*%203)%2C%0A%20%20%20%20%20%20%20%20value%3Dround(p.a%2C%204)%2C%0A%20%20%20%20%20%20%20%20step%3D0.005%2C%0A%20%20%20%20%20%20%20%20label%3D%22a%20(level)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20sl_b%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D0.001%2C%0A%20%20%20%20%20%20%20%20stop%3Dmax(2.0%2C%20p.b%20*%202)%2C%0A%20%20%20%20%20%20%20%20value%3Dround(p.b%2C%204)%2C%0A%20%20%20%20%20%20%20%20step%3Dmax(0.01%2C%20p.b%20*%200.01)%2C%0A%20%20%20%20%20%20%20%20label%3D%22b%20(wings)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20sl_rho%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D-0.999%2C%0A%20%20%20%20%20%20%20%20stop%3D0.999%2C%0A%20%20%20%20%20%20%20%20value%3Dround(min(max(p.rho%2C%20-0.999)%2C%200.999)%2C%204)%2C%0A%20%20%20%20%20%20%20%20step%3D0.001%2C%0A%20%20%20%20%20%20%20%20label%3D%22%5Cu03c1%20(skew)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20sl_m%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3Dmin(-1.0%2C%20p.m%20*%203)%2C%0A%20%20%20%20%20%20%20%20stop%3Dmax(1.0%2C%20p.m%20*%203)%2C%0A%20%20%20%20%20%20%20%20value%3Dround(p.m%2C%204)%2C%0A%20%20%20%20%20%20%20%20step%3D0.01%2C%0A%20%20%20%20%20%20%20%20label%3D%22m%20(shift)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20sl_sigma%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3Dmin(0.001%2C%20p.sigma%20%2F%202)%2C%0A%20%20%20%20%20%20%20%20stop%3Dmax(2.0%2C%20p.sigma%20*%204)%2C%0A%20%20%20%20%20%20%20%20value%3Dround(p.sigma%2C%204)%2C%0A%20%20%20%20%20%20%20%20step%3Dmax(0.001%2C%20p.sigma%20*%200.05)%2C%0A%20%20%20%20%20%20%20%20label%3D%22%5Cu03c3%20(curvature)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5Bsl_a%2C%20sl_b%2C%20sl_rho%2C%20sl_m%2C%20sl_sigma%5D)%0A%20%20%20%20return%20sl_a%2C%20sl_b%2C%20sl_m%2C%20sl_rho%2C%20sl_sigma%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_15(expiry%2C%20iv_fitted%2C%20k_fine%2C%20sl_a%2C%20sl_b%2C%20sl_m%2C%20sl_rho%2C%20sl_sigma)%3A%0A%20%20%20%20%22%22%22Plot%20fitted%20vs%20explorer%20smile%20side%20by%20side.%22%22%22%0A%20%20%20%20explorer_params%20%3D%20SVIModel(a%3Dsl_a.value%2C%20b%3Dsl_b.value%2C%20rho%3Dsl_rho.value%2C%20m%3Dsl_m.value%2C%20sigma%3Dsl_sigma.value)%0A%20%20%20%20iv_explorer%20%3D%20explorer_params.implied_vol(k_fine%2C%20expiry)%0A%0A%20%20%20%20fig_explore%20%3D%20go.Figure()%0A%20%20%20%20fig_explore.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%3Dk_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Div_fitted%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%2C%20%22dash%22%3A%20%22dash%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Fitted%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig_explore.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%3Dk_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Div_explorer%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%23E67E22%22%2C%20%22width%22%3A%202.5%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Explorer%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig_explore.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22SVI%20Parameter%20Explorer%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Log-Moneyness%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%3D450%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22x%22%3A%200.02%2C%20%22y%22%3A%200.98%7D%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(fig_explore)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_16()%3A%0A%20%20%20%20%22%22%22Render%20a%20section%20divider.%22%22%22%0A%20%20%20%20mo.md(r%22%22%22---%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_17()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20total%20variance%20view%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%23%23%20Total%20Variance%20View%0A%0A%20%20%20%20%20%20%20%20Practitioners%20often%20work%20in%20total-variance%20space%20%24w(k)%20%3D%20%5Csigma_%7BIV%7D%5E2%20%5Ccdot%20T%24%0A%20%20%20%20%20%20%20%20because%20the%20SVI%20formula%20is%20linear%20in%20that%20domain.%20Below%20we%20plot%20the%20fitted%0A%20%20%20%20%20%20%20%20total%20variance%20curve%20alongside%20the%20market%20observations.%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_18(k_fine%2C%20result%2C%20sd)%3A%0A%20%20%20%20%22%22%22Plot%20total%20variance%3A%20market%20vs%20SVI.%22%22%22%0A%20%20%20%20_sd_lm%20%3D%20sd.transform(XCoord.LogMoneynessStrike%2C%20YCoord.TotalVariance)%0A%20%20%20%20_w_market%20%3D%20_sd_lm.y_mid%0A%20%20%20%20_w_fit%20%3D%20result.evaluate(k_fine)%0A%0A%20%20%20%20fig_w%20%3D%20go.Figure()%0A%20%20%20%20fig_w.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_sd_lm.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_w_market%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%20marker%3D%7B%22size%22%3A%2010%2C%20%22color%22%3A%20%22%23E74C3C%22%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Market%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig_w.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%3Dk_fine%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_w_fit%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%20fig_w.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Total%20Implied%20Variance%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Log-Moneyness%20%20k%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22w(k)%20%3D%20%CF%83%C2%B2%20%C2%B7%20T%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%20%20%20%20legend%3D%7B%22x%22%3A%200.02%2C%20%22y%22%3A%200.98%7D%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(fig_w)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20cell_23()%3A%0A%20%20%20%20%22%22%22Render%20the%20conclusion.%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%23%20Summary%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20demonstrated%20the%20core%20**qsmile**%20SVI%20fitting%20workflow%3A%0A%0A%20%20%20%20%20%20%20%20-%20**%60SmileData.from_mid_vols%60**%20%E2%80%94%20construct%20a%20validated%20smile%20container%20from%20mid%20IVs%0A%20%20%20%20%20%20%20%20-%20**%60fit%60**%20%E2%80%94%20generic%20least-squares%20calibration%20of%20any%20%60SmileModel%60%0A%20%20%20%20%20%20%20%20-%20**%60SmileResult%60**%20%E2%80%94%20fitted%20parameters%2C%20residuals%2C%20RMSE%2C%20and%20%60evaluate(k)%60%0A%20%20%20%20%20%20%20%20-%20**%60SVIModel.evaluate%60%20%2F%20%60SVIModel.implied_vol%60**%20%E2%80%94%20direct%20model%20evaluation%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Full%20Option%20Chain%20Pipeline%0A%0A%20%20%20%20%20%20%20%20For%20a%20complete%20bid%2Fask%20workflow%20starting%20from%20raw%20option%20prices%2C%20see%20the%0A%20%20%20%20%20%20%20%20**Chain%20Demo**%20notebook%20which%20walks%20through%3A%0A%0A%20%20%20%20%20%20%20%201.%20%60OptionChain%60%20%E2%80%94%20bid%2Fask%20prices%20with%20auto-calibrated%20forward%20%26%20discount%20factor%0A%20%20%20%20%20%20%20%202.%20%60SmileData%60%20%E2%80%94%20unified%20container%20with%20**coordinate%20transforms**%20between%0A%20%20%20%20%20%20%20%20%20%20%20any%20combination%20of%20X-coords%20(Strike%2C%20Moneyness%2C%20Log-Moneyness%2C%20Standardised)%0A%20%20%20%20%20%20%20%20%20%20%20and%20Y-coords%20(Price%2C%20Volatility%2C%20Variance%2C%20Total%20Variance)%0A%20%20%20%20%20%20%20%203.%20%60fit(sd%2C%20model)%60%20%E2%80%94%20SVI%20fit%20directly%20from%20a%20%60SmileData%60%0A%0A%20%20%20%20%20%20%20%20**Next%20steps**%20%E2%80%94%20future%20versions%20will%20add%20SVI-JW%20parameterisation%2C%0A%20%20%20%20%20%20%20%20multi-expiry%20surface%20fitting%2C%20and%20arbitrage-free%20enforcement.%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
e554735a349ce3085838f6012421b8fc