%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22marimo%3D%3D0.20.4%22%2C%0A%23%20%20%20%20%20%22basanos%22%2C%0A%23%20%20%20%20%20%22numpy%3E%3D2.0.0%22%2C%0A%23%20%20%20%20%20%22polars%3E%3D1.0.0%22%2C%0A%23%20%20%20%20%20%22plotly%3E%3D6.0.0%22%2C%0A%23%20%5D%0A%23%20%5Btool.uv.sources%5D%0A%23%20basanos%20%3D%20%7B%20path%20%3D%20%22..%2F..%2F..%22%2C%20editable%20%3D%20true%20%7D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.20.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%20import%20polars%20as%20pl%0A%0A%20%20%20%20from%20basanos.math%20import%20BasanosConfig%2C%20BasanosEngine%0A%20%20%20%20from%20basanos.math._signal%20import%20shrink2id%0A%0A%0A%40app.cell%0Adef%20cell_01()%3A%0A%20%20%20%20%22%22%22Render%20the%20shrinkage%20guide%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%20%F0%9F%94%AC%20Basanos%20Shrinkage%20Guide%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20provides%20**theoretical%20background**%20and%20**empirical%20guidance**%0A%20%20%20%20%20%20%20%20on%20how%20shrinkage%20toward%20the%20identity%20matrix%20affects%20the%20Basanos%20optimizer.%0A%0A%20%20%20%20%20%20%20%20%23%23%20What%20this%20notebook%20covers%0A%0A%20%20%20%20%20%20%20%201.%20%F0%9F%93%90%20**Theory**%20%E2%80%94%20why%20shrinkage%20helps%20and%20what%20it%20does%20to%20eigenvalues%0A%20%20%20%20%20%20%20%202.%20%F0%9F%8E%9A%EF%B8%8F%20**Interactive%20sweep**%20%E2%80%94%20Sharpe%20ratio%20vs.%20shrinkage%20intensity%20(%CE%BB)%0A%20%20%20%20%20%20%20%203.%20%F0%9F%93%8A%20**Condition%20number**%20%E2%80%94%20how%20%CE%BB%20affects%20matrix%20conditioning%0A%20%20%20%20%20%20%20%204.%20%F0%9F%97%BA%EF%B8%8F%20**Parameter%20map**%20%E2%80%94%20joint%20effect%20of%20portfolio%20size%20%C3%97%20lookback%20%C3%97%20%CE%BB%0A%20%20%20%20%20%20%20%205.%20%F0%9F%92%A1%20**Practical%20recommendations**%20%E2%80%94%20when%20to%20use%20strong%20vs.%20light%20shrinkage%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%0Adef%20cell_02()%3A%0A%20%20%20%20%22%22%22Render%20separator.%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%0Adef%20cell_03()%3A%0A%20%20%20%20%22%22%22Render%20the%20theory%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%20%F0%9F%93%90%20Theoretical%20Background%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20The%20curse%20of%20dimensionality%20in%20covariance%20estimation%0A%0A%20%20%20%20%20%20%20%20Given%20%24T%24%20observations%20of%20%24n%24%20assets%2C%20the%20sample%20correlation%20matrix%0A%20%20%20%20%20%20%20%20%24%5Chat%7BC%7D%24%20is%20an%20unbiased%20estimator%20of%20the%20true%20correlation%20%24C%24%20%E2%80%94%20but%20its%0A%20%20%20%20%20%20%20%20**eigenvalues%20are%20biased**%20when%20%24n%20%2F%20T%24%20is%20non-negligible.%20%20The%0A%20%20%20%20%20%20%20%20Marchenko%E2%80%93Pastur%20law%20(1967)%20characterises%20this%20bias%3A%20small%20eigenvalues%0A%20%20%20%20%20%20%20%20are%20deflated%20and%20large%20eigenvalues%20are%20inflated%2C%20causing%20the%20matrix%0A%20%20%20%20%20%20%20%20to%20be%20ill-conditioned%20and%20difficult%20to%20invert%20reliably.%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Linear%20shrinkage%20toward%20the%20identity%0A%0A%20%20%20%20%20%20%20%20The%20**convex%20linear%20shrinkage**%20estimator%20mixes%20the%20sample%20matrix%20with%0A%20%20%20%20%20%20%20%20the%20identity%3A%0A%0A%20%20%20%20%20%20%20%20%24%24%5Chat%7BC%7D(%5Clambda)%20%3D%20%5Clambda%20%5Ccdot%20%5Chat%7BC%7D_%7B%5Ctext%7BEWMA%7D%7D%20%2B%20(1%20-%20%5Clambda)%20%5Ccdot%20I_n%24%24%0A%0A%20%20%20%20%20%20%20%20This%20pulls%20all%20eigenvalues%20toward%201%2C%20reducing%20variance%20at%20the%20cost%20of%20a%0A%20%20%20%20%20%20%20%20small%20bias.%20%20Ledoit%20%26%20Wolf%20(2004)%20showed%20that%20the%20optimal%20%24%5Clambda%5E*%24%0A%20%20%20%20%20%20%20%20minimises%20the%20expected%20Frobenius%20loss%20and%20has%20a%20closed-form%20expression%0A%20%20%20%20%20%20%20%20depending%20on%20%24n%24%2C%20%24T%24%2C%20and%20the%20spectral%20structure%20of%20the%20data.%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Why%20Basanos%20uses%20a%20fixed%20%CE%BB%20instead%20of%20optimal%20shrinkage%0A%0A%20%20%20%20%20%20%20%20The%20Basanos%20optimizer%20uses%20shrinkage%20to%20**regularise%20a%20linear%20solver**%0A%20%20%20%20%20%20%20%20(the%20system%20%24C%20x%20%3D%20%5Cmu%24%20must%20be%20well-posed%20at%20every%20timestamp)%2C%20not%20to%0A%20%20%20%20%20%20%20%20estimate%20a%20covariance%20matrix%20for%20portfolio%20optimisation.%20%20In%20this%20context%3A%0A%0A%20%20%20%20%20%20%20%20-%20A%20fixed%2C%20user-controlled%20%CE%BB%20is%20simpler%20and%20more%20predictable.%0A%20%20%20%20%20%20%20%20-%20The%20EWMA%20lookback%20already%20provides%20implicit%20regularisation.%0A%20%20%20%20%20%20%20%20-%20Optimal%20shrinkage%20minimises%20Frobenius%20loss%2C%20not%20position%20stability.%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Interpreting%20%60cfg.shrink%60%20(%3D%20%CE%BB)%0A%0A%20%20%20%20%20%20%20%20%7C%20%60cfg.shrink%60%20%7C%20Effect%20%7C%0A%20%20%20%20%20%20%20%20%7C%3A---%3A%7C%3A---%7C%0A%20%20%20%20%20%20%20%20%7C%20%601.0%60%20%7C%20No%20shrinkage%20%E2%80%94%20raw%20EWMA%20correlation%20used%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%600.5%60%20%7C%20Equal%20mix%20of%20EWMA%20correlation%20and%20identity%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%600.0%60%20%7C%20Full%20shrinkage%20%E2%80%94%20identity%20only%20(assets%20treated%20as%20uncorrelated)%20%7C%0A%0A%20%20%20%20%20%20%20%20**Rule%20of%20thumb%3A**%20start%20with%20%24%5Clambda%20%5Capprox%201%20-%20n%20%2F%20(2T)%24%2C%20then%20tune%0A%20%20%20%20%20%20%20%20on%20held-out%20data%20by%20sweeping%20%CE%BB%20and%20measuring%20out-of-sample%20Sharpe%20ratio.%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%0Adef%20cell_04()%3A%0A%20%20%20%20%22%22%22Render%20separator.%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%0Adef%20cell_05()%3A%0A%20%20%20%20%22%22%22Generate%20synthetic%20prices%20and%20signals%20(reused%20across%20all%20experiments).%22%22%22%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(42)%0A%20%20%20%20_assets%20%3D%20%5B%22AAPL%22%2C%20%22GOOGL%22%2C%20%22MSFT%22%2C%20%22AMZN%22%2C%20%22TSLA%22%2C%20%22META%22%5D%0A%20%20%20%20_n%20%3D%20750%20%20%23%20~3%20years%20of%20daily%20data%0A%20%20%20%20_start%20%3D%20pl.date(2021%2C%201%2C%201)%0A%20%20%20%20_end%20%3D%20_start%20%2B%20pl.duration(days%3D_n%20-%201)%0A%20%20%20%20_dates%20%3D%20pl.date_range(_start%2C%20_end%2C%20interval%3D%221d%22%2C%20eager%3DTrue)%0A%0A%20%20%20%20_drift%20%3D%20%5B0.0003%2C%200.0002%2C%200.0004%2C%200.0001%2C%200.0005%2C%200.0002%5D%0A%20%20%20%20_sigma%20%3D%20%5B0.018%2C%200.022%2C%200.020%2C%200.025%2C%200.030%2C%200.024%5D%0A%20%20%20%20_s0%20%3D%20%5B150.0%2C%202800.0%2C%20300.0%2C%203300.0%2C%20700.0%2C%20200.0%5D%0A%0A%20%20%20%20_prices_cols%3A%20dict%5Bstr%2C%20object%5D%20%3D%20%7B%22date%22%3A%20_dates%7D%0A%20%20%20%20for%20_i%2C%20_a%20in%20enumerate(_assets)%3A%0A%20%20%20%20%20%20%20%20_log_ret%20%3D%20_rng.normal(_drift%5B_i%5D%2C%20_sigma%5B_i%5D%2C%20_n)%0A%20%20%20%20%20%20%20%20_prices_cols%5B_a%5D%20%3D%20_s0%5B_i%5D%20*%20np.exp(np.cumsum(_log_ret))%0A%0A%20%20%20%20prices%20%3D%20pl.DataFrame(_prices_cols)%0A%0A%20%20%20%20%23%20Momentum%20signal%3A%20tanh(50%20*%20(MA5%20-%20MA20)%20%2F%20price)%0A%20%20%20%20_mu_cols%3A%20dict%5Bstr%2C%20object%5D%20%3D%20%7B%22date%22%3A%20_dates%7D%0A%20%20%20%20for%20_a%20in%20_assets%3A%0A%20%20%20%20%20%20%20%20_p%20%3D%20prices%5B_a%5D.to_numpy()%0A%20%20%20%20%20%20%20%20_ma5%20%3D%20np.convolve(_p%2C%20np.ones(5)%20%2F%205%2C%20mode%3D%22same%22)%20%2F%20_p%20-%201.0%0A%20%20%20%20%20%20%20%20_ma20%20%3D%20np.convolve(_p%2C%20np.ones(20)%20%2F%2020%2C%20mode%3D%22same%22)%20%2F%20_p%20-%201.0%0A%20%20%20%20%20%20%20%20_mu_cols%5B_a%5D%20%3D%20np.tanh(50.0%20*%20(_ma5%20-%20_ma20))%0A%0A%20%20%20%20mu%20%3D%20pl.DataFrame(_mu_cols)%0A%20%20%20%20return%20mu%2C%20prices%0A%0A%0A%40app.cell%0Adef%20cell_06()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20Sharpe%20and%20turnover%20vs.%20shrinkage%20sweep.%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%20%F0%9F%8E%9A%EF%B8%8F%20Sharpe%20Ratio%20and%20Turnover%20vs.%20Shrinkage%20Intensity%0A%0A%20%20%20%20%20%20%20%20The%20charts%20below%20sweep%20%24%5Clambda%24%20from%200.0%20(full%20shrinkage)%20to%201.0%20(no%0A%20%20%20%20%20%20%20%20shrinkage)%20in%20steps%20of%200.05%2C%20computing%20the%20annualised%20Sharpe%20ratio%20and%0A%20%20%20%20%20%20%20%20mean%20daily%20turnover%20at%20each%20level%20for%20two%20lookback%20regimes%3A%0A%0A%20%20%20%20%20%20%20%20-%20**Short%20lookback**%20(%60corr%3D20%60)%20%E2%80%94%20high%20concentration%20ratio%2C%20sample%20matrix%20is%20noisy%0A%20%20%20%20%20%20%20%20-%20**Long%20lookback**%20(%60corr%3D120%60)%20%E2%80%94%20low%20concentration%20ratio%2C%20sample%20matrix%20is%20more%20reliable%0A%0A%20%20%20%20%20%20%20%20Use%20the%20interactive%20controls%20below%20to%20choose%20%60vola%60%20and%20%60clip%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%0Adef%20cell_07()%3A%0A%20%20%20%20%22%22%22Create%20controls%20for%20the%20Sharpe%20sweep.%22%22%22%0A%20%20%20%20vola_sweep%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D4%2C%0A%20%20%20%20%20%20%20%20stop%3D32%2C%0A%20%20%20%20%20%20%20%20value%3D16%2C%0A%20%20%20%20%20%20%20%20step%3D2%2C%0A%20%20%20%20%20%20%20%20label%3D%22vola%20(volatility%20lookback%2C%20days)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20clip_sweep%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D1.0%2C%0A%20%20%20%20%20%20%20%20stop%3D6.0%2C%0A%20%20%20%20%20%20%20%20value%3D3.5%2C%0A%20%20%20%20%20%20%20%20step%3D0.5%2C%0A%20%20%20%20%20%20%20%20label%3D%22clip%20(vol-adjusted%20return%20clipping%20threshold)%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(%5Bvola_sweep%2C%20clip_sweep%5D)%0A%20%20%20%20return%20clip_sweep%2C%20vola_sweep%0A%0A%0A%40app.cell%0Adef%20cell_08(clip_sweep%2C%20mu%2C%20prices%2C%20vola_sweep)%3A%0A%20%20%20%20%22%22%22Sweep%20lambda%20and%20compute%20Sharpe%20ratio%20and%20mean%20daily%20turnover%20for%20short%20and%20long%20lookbacks.%22%22%22%0A%20%20%20%20_lambdas%20%3D%20np.arange(0.0%2C%201.05%2C%200.05).round(2)%0A%20%20%20%20_results%3A%20dict%5Bstr%2C%20list%5Bfloat%5D%5D%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22lambda%22%3A%20list(_lambdas)%2C%0A%20%20%20%20%20%20%20%20%22short_corr%22%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%22long_corr%22%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%22turnover_short%22%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%22turnover_long%22%3A%20%5B%5D%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20for%20_lam%20in%20_lambdas%3A%0A%20%20%20%20%20%20%20%20for%20_corr%2C%20_sharpe_key%2C%20_to_key%20in%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20(20%2C%20%22short_corr%22%2C%20%22turnover_short%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(120%2C%20%22long_corr%22%2C%20%22turnover_long%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_eff_corr%20%3D%20max(_corr%2C%20vola_sweep.value)%0A%20%20%20%20%20%20%20%20%20%20%20%20_cfg%20%3D%20BasanosConfig(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vola%3Dvola_sweep.value%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20corr%3D_eff_corr%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clip%3Dclip_sweep.value%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shrink%3Dfloat(_lam)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20aum%3D1_000_000%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_eng%20%3D%20BasanosEngine(prices%3Dprices%2C%20mu%3Dmu%2C%20cfg%3D_cfg)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_port%20%3D%20_eng.portfolio%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_sharpe%20%3D%20float(_port.stats.sharpe(periods%3D252).get(%22returns%22%2C%20float(%22nan%22)))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_turnover%20%3D%20float(_port.turnover%5B%22turnover%22%5D.mean()%20or%20float(%22nan%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20except%20Exception%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_sharpe%20%3D%20float(%22nan%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_turnover%20%3D%20float(%22nan%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20_results%5B_sharpe_key%5D.append(_sharpe)%0A%20%20%20%20%20%20%20%20%20%20%20%20_results%5B_to_key%5D.append(_turnover)%0A%0A%20%20%20%20sweep_df%20%3D%20pl.DataFrame(_results)%0A%20%20%20%20return%20(sweep_df%2C)%0A%0A%0A%40app.cell%0Adef%20cell_09(sweep_df)%3A%0A%20%20%20%20%22%22%22Render%20the%20Sharpe%20vs.%20lambda%20chart.%22%22%22%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%3Dsweep_df%5B%22lambda%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dsweep_df%5B%22short_corr%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Short%20lookback%20(corr%3D20)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%23e74c3c%22%2C%20%22width%22%3A%202%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%206%7D%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%3Dsweep_df%5B%22lambda%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dsweep_df%5B%22long_corr%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Long%20lookback%20(corr%3D120)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%232980b9%22%2C%20%22width%22%3A%202%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%206%7D%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%22Annualised%20Sharpe%20Ratio%20vs.%20Shrinkage%20Retention%20Weight%20(%CE%BB)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22%CE%BB%20%3D%20cfg.shrink%20%20(0%20%3D%20full%20shrinkage%2C%201%20%3D%20no%20shrinkage)%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Sharpe%20ratio%20(annualised)%22%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22orientation%22%3A%20%22h%22%2C%20%22yanchor%22%3A%20%22bottom%22%2C%20%22y%22%3A%201.02%2C%20%22xanchor%22%3A%20%22right%22%2C%20%22x%22%3A%201%7D%2C%0A%20%20%20%20%20%20%20%20height%3D450%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20cell_09a(sweep_df)%3A%0A%20%20%20%20%22%22%22Render%20the%20Mean%20Daily%20Turnover%20(%25%20AUM)%20vs.%20lambda%20chart.%22%22%22%0A%20%20%20%20_fig_to%20%3D%20go.Figure()%0A%20%20%20%20_fig_to.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%3Dsweep_df%5B%22lambda%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D(pl.Series(sweep_df%5B%22turnover_short%22%5D.to_list())%20*%20100).to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Short%20lookback%20(corr%3D20)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%23e74c3c%22%2C%20%22width%22%3A%202%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%206%7D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig_to.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%3Dsweep_df%5B%22lambda%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D(pl.Series(sweep_df%5B%22turnover_long%22%5D.to_list())%20*%20100).to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Long%20lookback%20(corr%3D120)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20%22%232980b9%22%2C%20%22width%22%3A%202%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3D%7B%22size%22%3A%206%7D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_fig_to.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Mean%20Daily%20Turnover%20(%25%20AUM)%20vs.%20Shrinkage%20Retention%20Weight%20(%CE%BB)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22%CE%BB%20%3D%20cfg.shrink%20%20(0%20%3D%20full%20shrinkage%2C%201%20%3D%20no%20shrinkage)%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Mean%20daily%20turnover%20(%25%20AUM)%22%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22orientation%22%3A%20%22h%22%2C%20%22yanchor%22%3A%20%22bottom%22%2C%20%22y%22%3A%201.02%2C%20%22xanchor%22%3A%20%22right%22%2C%20%22x%22%3A%201%7D%2C%0A%20%20%20%20%20%20%20%20height%3D450%2C%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%23%23%23%20%F0%9F%94%84%20Turnover%20vs.%20Shrinkage%20Intensity%0A%0A%20%20%20%20%20%20%20%20Lower%20%CE%BB%20(more%20shrinkage)%20tends%20to%20reduce%20turnover%20by%20dampening%20the%0A%20%20%20%20%20%20%20%20optimizer's%20sensitivity%20to%20noisy%20correlation%20estimates%2C%20producing%20more%0A%20%20%20%20%20%20%20%20stable%20positions.%20%20Higher%20%CE%BB%20allows%20the%20optimizer%20to%20exploit%20richer%0A%20%20%20%20%20%20%20%20correlation%20structure%2C%20which%20can%20increase%20turnover%20%E2%80%94%20especially%20with%0A%20%20%20%20%20%20%20%20short%20lookbacks%20where%20the%20sample%20matrix%20is%20noisier.%0A%0A%20%20%20%20%20%20%20%20The%20**position-change%20std%20dev**%20(accessible%20via%20%60portfolio.turnover_summary()%60)%0A%20%20%20%20%20%20%20%20complements%20mean%20turnover%3A%20a%20high%20ratio%20of%20std%20dev%20to%20mean%20signals%20regime%0A%20%20%20%20%20%20%20%20switches%20or%20spikes%20in%20trading%20activity%20that%20would%20amplify%20transaction%20costs%0A%20%20%20%20%20%20%20%20in%20live%20trading.%20%20The%20interactive%20panel%20below%20also%20shows%20all%20three%20turnover%0A%20%20%20%20%20%20%20%20metrics%20for%20the%20currently%20selected%20configuration.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5Bmo.ui.plotly(_fig_to)%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20cell_10()%3A%0A%20%20%20%20%22%22%22Render%20separator.%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%0Adef%20cell_11()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20condition%20number%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%20%F0%9F%93%8A%20Matrix%20Condition%20Number%20vs.%20%CE%BB%0A%0A%20%20%20%20%20%20%20%20The%20**condition%20number**%20%24%5Ckappa%20%3D%20%5Clambda_%7B%5Cmax%7D%20%2F%20%5Clambda_%7B%5Cmin%7D%24%20measures%0A%20%20%20%20%20%20%20%20how%20close%20a%20matrix%20is%20to%20singular.%20%20High%20condition%20numbers%20(%3E%201000)%20indicate%0A%20%20%20%20%20%20%20%20that%20the%20linear%20system%20%24C%20x%20%3D%20%5Cmu%24%20is%20ill-posed%20and%20solutions%20are%20dominated%0A%20%20%20%20%20%20%20%20by%20numerical%20noise%20rather%20than%20the%20signal.%0A%0A%20%20%20%20%20%20%20%20The%20chart%20below%20shows%20%24%5Ckappa%24%20as%20a%20function%20of%20%CE%BB%20for%20sample%20EWMA%0A%20%20%20%20%20%20%20%20correlation%20matrices%20with%20varying%20portfolio%20sizes.%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%0Adef%20cell_12(prices)%3A%0A%20%20%20%20%22%22%22Compute%20condition%20numbers%20for%20a%20range%20of%20lambda%20values%20and%20portfolio%20sizes.%22%22%22%0A%20%20%20%20_lambdas_cond%20%3D%20np.arange(0.0%2C%201.01%2C%200.02).round(2)%0A%20%20%20%20_asset_subsets%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%222%20assets%22%3A%20%5B%22AAPL%22%2C%20%22GOOGL%22%5D%2C%0A%20%20%20%20%20%20%20%20%224%20assets%22%3A%20%5B%22AAPL%22%2C%20%22GOOGL%22%2C%20%22MSFT%22%2C%20%22AMZN%22%5D%2C%0A%20%20%20%20%20%20%20%20%226%20assets%22%3A%20%5B%22AAPL%22%2C%20%22GOOGL%22%2C%20%22MSFT%22%2C%20%22AMZN%22%2C%20%22TSLA%22%2C%20%22META%22%5D%2C%0A%20%20%20%20%7D%0A%20%20%20%20_cond_results%3A%20dict%5Bstr%2C%20list%5D%20%3D%20%7B%22lambda%22%3A%20list(_lambdas_cond)%7D%0A%0A%20%20%20%20for%20_label%2C%20_subset%20in%20_asset_subsets.items()%3A%0A%20%20%20%20%20%20%20%20_conds%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%23%20Build%20a%20simple%20sample%20correlation%20matrix%20for%20the%20subset%0A%20%20%20%20%20%20%20%20_data%20%3D%20prices.select(_subset).to_numpy().astype(float)%0A%20%20%20%20%20%20%20%20_log_ret%20%3D%20np.diff(np.log(_data)%2C%20axis%3D0)%0A%20%20%20%20%20%20%20%20%23%20Use%20last%2040%20rows%20as%20%22sample%22%20(short%20lookback%20scenario)%0A%20%20%20%20%20%20%20%20_sample%20%3D%20_log_ret%5B-40%3A%5D%0A%20%20%20%20%20%20%20%20_corr%20%3D%20np.corrcoef(_sample.T)%0A%20%20%20%20%20%20%20%20for%20_lam%20in%20_lambdas_cond%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_shrunk%20%3D%20shrink2id(_corr%2C%20lamb%3Dfloat(_lam))%0A%20%20%20%20%20%20%20%20%20%20%20%20_eigvals%20%3D%20np.linalg.eigvalsh(_shrunk)%0A%20%20%20%20%20%20%20%20%20%20%20%20_kappa%20%3D%20_eigvals%5B-1%5D%20%2F%20max(_eigvals%5B0%5D%2C%201e-14)%0A%20%20%20%20%20%20%20%20%20%20%20%20_conds.append(float(_kappa))%0A%20%20%20%20%20%20%20%20_cond_results%5B_label%5D%20%3D%20_conds%0A%0A%20%20%20%20cond_df%20%3D%20pl.DataFrame(_cond_results)%0A%20%20%20%20return%20(cond_df%2C)%0A%0A%0A%40app.cell%0Adef%20cell_13(cond_df)%3A%0A%20%20%20%20%22%22%22Render%20the%20condition%20number%20chart.%22%22%22%0A%20%20%20%20_colors%20%3D%20%7B%222%20assets%22%3A%20%22%2327ae60%22%2C%20%224%20assets%22%3A%20%22%23e67e22%22%2C%20%226%20assets%22%3A%20%22%238e44ad%22%7D%0A%20%20%20%20_fig2%20%3D%20go.Figure()%0A%20%20%20%20for%20_col%20in%20%5B%222%20assets%22%2C%20%224%20assets%22%2C%20%226%20assets%22%5D%3A%0A%20%20%20%20%20%20%20%20_fig2.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%3Dcond_df%5B%22lambda%22%5D.to_list()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3Dcond_df%5B_col%5D.to_list()%2C%0A%20%20%20%20%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%20%20%20%20%20name%3D_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22color%22%3A%20_colors%5B_col%5D%2C%20%22width%22%3A%202%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20_fig2.add_hline(%0A%20%20%20%20%20%20%20%20y%3D1000%2C%0A%20%20%20%20%20%20%20%20line_dash%3D%22dash%22%2C%0A%20%20%20%20%20%20%20%20line_color%3D%22red%22%2C%0A%20%20%20%20%20%20%20%20annotation_text%3D%22%CE%BA%20%3D%201000%20(ill-conditioned%20threshold)%22%2C%0A%20%20%20%20%20%20%20%20annotation_position%3D%22top%20left%22%2C%0A%20%20%20%20)%0A%20%20%20%20_fig2.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Condition%20Number%20%CE%BA%20vs.%20Shrinkage%20Retention%20Weight%20(%CE%BB)%20%20%5Bcorr%20lookback%20%3D%2040%20days%5D%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22%CE%BB%20%3D%20cfg.shrink%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Condition%20number%20%CE%BA%20(log%20scale)%22%2C%0A%20%20%20%20%20%20%20%20yaxis_type%3D%22log%22%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22orientation%22%3A%20%22h%22%2C%20%22yanchor%22%3A%20%22bottom%22%2C%20%22y%22%3A%201.02%2C%20%22xanchor%22%3A%20%22right%22%2C%20%22x%22%3A%201%7D%2C%0A%20%20%20%20%20%20%20%20height%3D450%2C%0A%20%20%20%20)%0A%20%20%20%20mo.ui.plotly(_fig2)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20cell_14()%3A%0A%20%20%20%20%22%22%22Render%20separator.%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%0Adef%20cell_15()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20interactive%20parameter-sensitivity%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%20%F0%9F%97%BA%EF%B8%8F%20Interactive%20Parameter%20Sensitivity%0A%0A%20%20%20%20%20%20%20%20Explore%20the%20**joint%20effect**%20of%20%60shrink%60%20(%CE%BB)%20alongside%20the%20other%0A%20%20%20%20%20%20%20%20optimizer%20parameters%20on%20portfolio%20Sharpe%20ratio.%20%20This%20helps%20build%0A%20%20%20%20%20%20%20%20intuition%20for%20which%20combinations%20of%20lookback%20and%20shrinkage%20work%0A%20%20%20%20%20%20%20%20well%20for%20your%20specific%20dataset.%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%0Adef%20cell_16()%3A%0A%20%20%20%20%22%22%22Create%20interactive%20controls%20for%20sensitivity%20exploration.%22%22%22%0A%20%20%20%20vola_sens%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D4%2C%0A%20%20%20%20%20%20%20%20stop%3D32%2C%0A%20%20%20%20%20%20%20%20value%3D16%2C%0A%20%20%20%20%20%20%20%20step%3D2%2C%0A%20%20%20%20%20%20%20%20label%3D%22vola%20(days)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20corr_sens%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D4%2C%0A%20%20%20%20%20%20%20%20stop%3D128%2C%0A%20%20%20%20%20%20%20%20value%3D32%2C%0A%20%20%20%20%20%20%20%20step%3D4%2C%0A%20%20%20%20%20%20%20%20label%3D%22corr%20(days)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20clip_sens%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D1.0%2C%0A%20%20%20%20%20%20%20%20stop%3D6.0%2C%0A%20%20%20%20%20%20%20%20value%3D3.5%2C%0A%20%20%20%20%20%20%20%20step%3D0.5%2C%0A%20%20%20%20%20%20%20%20label%3D%22clip%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20shrink_sens%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D0.0%2C%0A%20%20%20%20%20%20%20%20stop%3D1.0%2C%0A%20%20%20%20%20%20%20%20value%3D0.5%2C%0A%20%20%20%20%20%20%20%20step%3D0.05%2C%0A%20%20%20%20%20%20%20%20label%3D%22shrink%20(%CE%BB)%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(%5Bvola_sens%2C%20corr_sens%2C%20clip_sens%2C%20shrink_sens%5D)%0A%20%20%20%20return%20clip_sens%2C%20corr_sens%2C%20shrink_sens%2C%20vola_sens%0A%0A%0A%40app.cell%0Adef%20cell_17(clip_sens%2C%20corr_sens%2C%20mu%2C%20prices%2C%20shrink_sens%2C%20vola_sens)%3A%0A%20%20%20%20%22%22%22Build%20engine%20from%20sensitivity%20controls%20and%20display%20key%20metrics.%22%22%22%0A%20%20%20%20_eff_corr_s%20%3D%20max(corr_sens.value%2C%20vola_sens.value)%0A%20%20%20%20_cfg_s%20%3D%20BasanosConfig(%0A%20%20%20%20%20%20%20%20vola%3Dvola_sens.value%2C%0A%20%20%20%20%20%20%20%20corr%3D_eff_corr_s%2C%0A%20%20%20%20%20%20%20%20clip%3Dclip_sens.value%2C%0A%20%20%20%20%20%20%20%20shrink%3Dshrink_sens.value%2C%0A%20%20%20%20%20%20%20%20aum%3D1_000_000%2C%0A%20%20%20%20)%0A%20%20%20%20_eng_s%20%3D%20BasanosEngine(prices%3Dprices%2C%20mu%3Dmu%2C%20cfg%3D_cfg_s)%0A%20%20%20%20port_s%20%3D%20_eng_s.portfolio%0A%20%20%20%20_n_assets%20%3D%20len(_eng_s.assets)%0A%20%20%20%20_concentration%20%3D%20_n_assets%20%2F%20_eff_corr_s%0A%20%20%20%20_sharpe_s%20%3D%20float(port_s.stats.sharpe(periods%3D252).get(%22returns%22%2C%20float(%22nan%22)))%0A%20%20%20%20_vol_s%20%3D%20float(port_s.stats.volatility(periods%3D252).get(%22returns%22%2C%20float(%22nan%22)))%0A%0A%20%20%20%20_concentration_msg%20%3D%20(%0A%20%20%20%20%20%20%20%20%22%E2%9A%A0%EF%B8%8F%20High%20concentration%20ratio%20(n%2FT%20%3E%200.3)%3A%20consider%20reducing%20%CE%BB%20for%20better%20regularisation.%22%0A%20%20%20%20%20%20%20%20if%20_concentration%20%3E%200.3%0A%20%20%20%20%20%20%20%20else%20%22%E2%9C%85%20Concentration%20ratio%20is%20within%20a%20manageable%20range.%22%0A%20%20%20%20)%0A%20%20%20%20_corr_raised_msg%20%3D%20%22%E2%9A%A0%EF%B8%8F%20%60corr%60%20was%20raised%20to%20match%20%60vola%60.%22%20if%20_eff_corr_s%20%3E%20corr_sens.value%20else%20%22%22%0A%20%20%20%20_to_summary%20%3D%20port_s.turnover_summary()%0A%20%20%20%20_mean_daily_to%20%3D%20float(_to_summary.filter(pl.col(%22metric%22)%20%3D%3D%20%22mean_daily_turnover%22)%5B%22value%22%5D%5B0%5D)%0A%20%20%20%20_mean_weekly_to%20%3D%20float(_to_summary.filter(pl.col(%22metric%22)%20%3D%3D%20%22mean_weekly_turnover%22)%5B%22value%22%5D%5B0%5D)%0A%20%20%20%20_to_std%20%3D%20float(_to_summary.filter(pl.col(%22metric%22)%20%3D%3D%20%22turnover_std%22)%5B%22value%22%5D%5B0%5D)%0A%20%20%20%20mo.callout(%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20**Active%20configuration%3A**%0A%20%20%20%20%20%20%20%20%20%20%20%20%60BasanosConfig(vola%3D%7B_cfg_s.vola%7D%2C%20corr%3D%7B_cfg_s.corr%7D%2C%20clip%3D%7B_cfg_s.clip%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20shrink%3D%7B_cfg_s.shrink%7D%2C%20aum%3D%7B_cfg_s.aum%3A%2C.0f%7D)%60%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Metric%20%7C%20Value%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C--------%7C-------%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Number%20of%20assets%20*n*%20%7C%20%7B_n_assets%7D%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Concentration%20ratio%20*n%2FT*%20%7C%20%7B_concentration%3A.3f%7D%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Annualised%20Sharpe%20%7C%20**%7B_sharpe_s%3A.3f%7D**%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Annualised%20volatility%20%7C%20%7B_vol_s%3A.4f%7D%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Mean%20daily%20turnover%20(%25%20AUM)%20%7C%20%7B_mean_daily_to%20*%20100%3A.4f%7D%20%25%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Mean%20weekly%20turnover%20(%25%20AUM)%20%7C%20%7B_mean_weekly_to%20*%20100%3A.4f%7D%20%25%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7C%20Turnover%20std%20dev%20(%25%20AUM)%20%7C%20%7B_to_std%20*%20100%3A.4f%7D%20%25%20%7C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B_concentration_msg%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B_corr_raised_msg%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20kind%3D%22info%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(port_s%2C)%0A%0A%0A%40app.cell%0Adef%20cell_18(port_s)%3A%0A%20%20%20%20%22%22%22Show%20the%20NAV%20chart%20for%20the%20selected%20configuration.%22%22%22%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%20Performance%20(NAV)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.plotly(port_s.plots.snapshot())%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%0Adef%20cell_19()%3A%0A%20%20%20%20%22%22%22Render%20separator.%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%0Adef%20cell_20()%3A%0A%20%20%20%20%22%22%22Render%20practical%20recommendations.%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%20%F0%9F%92%A1%20Practical%20Recommendations%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20When%20to%20prefer%20**strong%20shrinkage**%20(low%20%CE%BB%2C%20e.g.%200.2%20%E2%80%93%200.5)%0A%0A%20%20%20%20%20%20%20%20-%20Portfolio%20has%20**many%20assets**%20(n%20%3E%2015)%20and%20a%20**short%20lookback**%0A%20%20%20%20%20%20%20%20%20%20(%60corr%60%20%3C%2050%20days)%3A%20the%20EWMA%20matrix%20is%20noisy%20and%20the%20condition%20number%0A%20%20%20%20%20%20%20%20%20%20will%20be%20high%20without%20regularisation.%0A%20%20%20%20%20%20%20%20-%20During%20**crisis%20%2F%20high-correlation%20regimes**%3A%20off-diagonal%20correlations%0A%20%20%20%20%20%20%20%20%20%20spike%20and%20the%20sample%20matrix%20becomes%20nearly%20rank-deficient.%0A%20%20%20%20%20%20%20%20-%20When%20**position%20stability**%20is%20the%20priority%3A%20heavy%20shrinkage%20damps%0A%20%20%20%20%20%20%20%20%20%20the%20optimizer's%20sensitivity%20to%20noisy%20correlation%20estimates%2C%20reducing%0A%20%20%20%20%20%20%20%20%20%20turnover.%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20When%20to%20prefer%20**light%20shrinkage**%20(high%20%CE%BB%2C%20e.g.%200.7%20%E2%80%93%200.95)%0A%0A%20%20%20%20%20%20%20%20-%20Portfolio%20has%20**few%20assets**%20(n%20%3C%208)%20with%20a%20**long%20lookback**%0A%20%20%20%20%20%20%20%20%20%20(%60corr%60%20%3E%20100%20days)%3A%20the%20concentration%20ratio%20is%20low%20and%20the%20EWMA%0A%20%20%20%20%20%20%20%20%20%20matrix%20is%20reliable.%0A%20%20%20%20%20%20%20%20-%20When%20**diversification%20signals**%20are%20strong%3A%20if%20genuine%20off-diagonal%0A%20%20%20%20%20%20%20%20%20%20correlation%20structure%20exists%20that%20the%20optimizer%20should%20exploit%2C%20heavy%0A%20%20%20%20%20%20%20%20%20%20shrinkage%20discards%20this%20information.%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Quick-start%20heuristic%0A%0A%20%20%20%20%20%20%20%20%24%24%5Clambda_%7B%5Ctext%7Bstart%7D%7D%20%5Capprox%201%20-%20%5Cfrac%7Bn%7D%7B2T%7D%24%24%0A%0A%20%20%20%20%20%20%20%20where%20%24n%24%20%3D%20number%20of%20assets%20and%20%24T%24%20%3D%20%60cfg.corr%60.%20This%20approximates%20the%0A%20%20%20%20%20%20%20%20Ledoit%E2%80%93Wolf%20optimal%20intensity%20and%20provides%20a%20sensible%20starting%20point.%0A%20%20%20%20%20%20%20%20Always%20validate%20on%20out-of-sample%20data%20by%20sweeping%20%CE%BB%20and%20measuring%0A%20%20%20%20%20%20%20%20held-out%20Sharpe%20ratio%20(see%20the%20sweep%20chart%20at%20the%20top%20of%20this%20notebook).%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20References%0A%0A%20%20%20%20%20%20%20%20-%20Ledoit%2C%20O.%2C%20%26%20Wolf%2C%20M.%20(2004).%20*A%20well-conditioned%20estimator%20for%0A%20%20%20%20%20%20%20%20%20%20large-dimensional%20covariance%20matrices.*%20Journal%20of%20Multivariate%0A%20%20%20%20%20%20%20%20%20%20Analysis%2C%2088(2)%2C%20365%E2%80%93411.%0A%20%20%20%20%20%20%20%20%20%20https%3A%2F%2Fdoi.org%2F10.1016%2FS0047-259X(03)00096-4%0A%20%20%20%20%20%20%20%20-%20Chen%2C%20Y.%2C%20Wiesel%2C%20A.%2C%20Eldar%2C%20Y.%20C.%2C%20%26%20Hero%2C%20A.%20O.%20(2010).%0A%20%20%20%20%20%20%20%20%20%20*Shrinkage%20algorithms%20for%20MMSE%20covariance%20estimation.*%20IEEE%0A%20%20%20%20%20%20%20%20%20%20Transactions%20on%20Signal%20Processing%2C%2058(10)%2C%205016%E2%80%935029.%0A%20%20%20%20%20%20%20%20%20%20https%3A%2F%2Fdoi.org%2F10.1109%2FTSP.2010.2053029%0A%20%20%20%20%20%20%20%20-%20Marchenko%2C%20V.%20A.%2C%20%26%20Pastur%2C%20L.%20A.%20(1967).%20*Distribution%20of%0A%20%20%20%20%20%20%20%20%20%20eigenvalues%20for%20some%20sets%20of%20random%20matrices.*%20Mathematics%20of%20the%0A%20%20%20%20%20%20%20%20%20%20USSR-Sbornik%2C%201(4)%2C%20457%E2%80%93483.%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
bfc1c8ebf44aac0e3b46ffac11972705