%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%20polars%20as%20pl%0A%0A%20%20%20%20from%20basanos.math%20import%20BasanosConfig%2C%20BasanosEngine%0A%0A%0A%40app.cell%0Adef%20cell_01()%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%20%F0%9F%8F%81%20Basanos%20%E2%80%94%20End-to-End%20Worked%20Example%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20walks%20through%20the%20**complete%20Basanos%20workflow**%20from%20raw%20prices%0A%20%20%20%20%20%20%20%20to%20a%20self-contained%20HTML%20report%2C%20using%20a%20realistic%20synthetic%20dataset%20that%0A%20%20%20%20%20%20%20%20mimics%20eight%20diversified%20equity%20sectors.%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%20%7C%20Step%20%7C%20Topic%20%7C%0A%20%20%20%20%20%20%20%20%7C------%7C-------%7C%0A%20%20%20%20%20%20%20%20%7C%201%20%7C%20%F0%9F%93%88%20**Data%20preparation**%20%E2%80%94%20synthetic%20multi-sector%20equity%20prices%20and%20momentum%20signals%20%7C%0A%20%20%20%20%20%20%20%20%7C%202%20%7C%20%E2%9A%99%EF%B8%8F%20**Config%20selection**%20%E2%80%94%20choosing%20%60vola%60%2C%20%60corr%60%2C%20%60clip%60%2C%20and%20%60shrink%60%20with%20guidance%20%7C%0A%20%20%20%20%20%20%20%20%7C%203%20%7C%20%F0%9F%94%AC%20**Engine%20instantiation**%20%E2%80%94%20running%20%60BasanosEngine%60%20%7C%0A%20%20%20%20%20%20%20%20%7C%204%20%7C%20%F0%9F%93%84%20**HTML%20report%20generation**%20%E2%80%94%20one-call%20self-contained%20report%20%7C%0A%20%20%20%20%20%20%20%20%7C%205%20%7C%20%F0%9F%92%B8%20**Trading%20cost%20analysis**%20%E2%80%94%20Sharpe%20degradation%20across%20basis-point%20sweep%20%7C%0A%0A%20%20%20%20%20%20%20%20%3E%20**Public%20data%20only.**%20All%20data%20is%20generated%20deterministically%20from%20a%20fixed%20seed%20%E2%80%94%0A%20%20%20%20%20%20%20%20%3E%20no%20external%20data%20sources%2C%20API%20keys%2C%20or%20network%20access%20required.%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%22Introduce%20the%20data%20preparation%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%88%20Step%201%20%E2%80%94%20Data%20Preparation%0A%0A%20%20%20%20%20%20%20%20We%20generate%20**eight%20synthetic%20equity-like%20price%20series**%20representing%20broad%0A%20%20%20%20%20%20%20%20market%20sectors%20(Technology%2C%20Healthcare%2C%20Financials%2C%20Energy%2C%20Consumer%2C%0A%20%20%20%20%20%20%20%20Industrials%2C%20Materials%2C%20Utilities).%20%20The%20returns%20share%20a%20common%20market%20factor%0A%20%20%20%20%20%20%20%20(mimicking%20S%26P%20500%20beta%20exposure)%20plus%20idiosyncratic%20noise%2C%20producing%20a%0A%20%20%20%20%20%20%20%20realistic%20cross-sectional%20correlation%20structure.%0A%0A%20%20%20%20%20%20%20%20A%20**momentum%20signal**%20%24%5Cmu%20%5Cin%20%5B-1%2C%201%5D%24%20is%20derived%20from%20the%20difference%20between%0A%20%20%20%20%20%20%20%20a%20fast%20(5-day)%20and%20slow%20(60-day)%20exponentially%20weighted%20moving%20average%20of%0A%20%20%20%20%20%20%20%20log%20returns%2C%20rescaled%20through%20%24%5Ctanh%24%20to%20keep%20values%20bounded.%0A%0A%20%20%20%20%20%20%20%20The%20dataset%20spans%20**five%20years**%20of%20daily%20data%20(~1%20260%20rows)%20%E2%80%94%20enough%20history%0A%20%20%20%20%20%20%20%20for%20robust%20EWMA%20warmup%20and%20meaningful%20out-of-sample%20statistics.%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%22Generate%20synthetic%20multi-sector%20equity%20prices%20and%20momentum%20signals.%22%22%22%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(2024)%0A%0A%20%20%20%20_assets%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22Technology%22%2C%0A%20%20%20%20%20%20%20%20%22Healthcare%22%2C%0A%20%20%20%20%20%20%20%20%22Financials%22%2C%0A%20%20%20%20%20%20%20%20%22Energy%22%2C%0A%20%20%20%20%20%20%20%20%22Consumer%22%2C%0A%20%20%20%20%20%20%20%20%22Industrials%22%2C%0A%20%20%20%20%20%20%20%20%22Materials%22%2C%0A%20%20%20%20%20%20%20%20%22Utilities%22%2C%0A%20%20%20%20%5D%0A%20%20%20%20_n_assets%20%3D%20len(_assets)%0A%20%20%20%20_n_days%20%3D%201_260%20%20%23%20~5%20years%20of%20daily%20data%0A%0A%20%20%20%20_start%20%3D%20pl.date(2019%2C%201%2C%201)%0A%20%20%20%20_end%20%3D%20_start%20%2B%20pl.duration(days%3D_n_days%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%23%20Per-sector%20parameters%0A%20%20%20%20_annual_drift%20%3D%20np.array(%5B0.14%2C%200.10%2C%200.09%2C%200.06%2C%200.08%2C%200.09%2C%200.07%2C%200.05%5D)%0A%20%20%20%20_annual_vol%20%3D%20np.array(%5B0.22%2C%200.18%2C%200.20%2C%200.28%2C%200.17%2C%200.19%2C%200.24%2C%200.14%5D)%0A%20%20%20%20_betas%20%3D%20np.array(%5B1.3%2C%200.9%2C%201.1%2C%200.8%2C%200.95%2C%201.0%2C%201.1%2C%200.5%5D)%20%20%23%20market%20sensitivity%0A%20%20%20%20_s0%20%3D%20np.array(%5B100.0%5D%20*%20_n_assets)%0A%0A%20%20%20%20_daily_drift%20%3D%20_annual_drift%20%2F%20252%0A%20%20%20%20_daily_vol%20%3D%20_annual_vol%20%2F%20np.sqrt(252)%0A%0A%20%20%20%20%23%20Market%20factor%20(shared%20component%20%E2%86%92%20cross-sectional%20correlation)%0A%20%20%20%20_market_vol_daily%20%3D%200.012%0A%20%20%20%20_market_factor%20%3D%20_rng.normal(0.0%2C%20_market_vol_daily%2C%20_n_days)%0A%0A%20%20%20%20%23%20Idiosyncratic%20shocks%20(sector-specific)%0A%20%20%20%20_idio_shocks%20%3D%20_rng.normal(0.0%2C%201.0%2C%20(_n_days%2C%20_n_assets))%0A%0A%20%20%20%20%23%20Combine%3A%20r_i%20%3D%20drift_i%20%2B%20beta_i%20*%20market%20%2B%20idio_vol_i%20*%20epsilon_i%0A%20%20%20%20_idio_vol%20%3D%20np.sqrt(np.maximum(_daily_vol**2%20-%20(_betas%20*%20_market_vol_daily)%20**%202%2C%201e-6))%0A%20%20%20%20_log_returns%20%3D%20(%0A%20%20%20%20%20%20%20%20_daily_drift%5Bnp.newaxis%2C%20%3A%5D%0A%20%20%20%20%20%20%20%20%2B%20_betas%5Bnp.newaxis%2C%20%3A%5D%20*%20_market_factor%5B%3A%2C%20np.newaxis%5D%0A%20%20%20%20%20%20%20%20%2B%20_idio_vol%5Bnp.newaxis%2C%20%3A%5D%20*%20_idio_shocks%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Build%20price%20DataFrame%0A%20%20%20%20_price_paths%20%3D%20_s0%5Bnp.newaxis%2C%20%3A%5D%20*%20np.exp(np.cumsum(_log_returns%2C%20axis%3D0))%0A%20%20%20%20prices%20%3D%20pl.DataFrame(%7B%22date%22%3A%20_dates%2C%20**%7Ba%3A%20_price_paths%5B%3A%2C%20i%5D.tolist()%20for%20i%2C%20a%20in%20enumerate(_assets)%7D%7D)%0A%0A%20%20%20%20%23%20Momentum%20signal%3A%20tanh%20of%20fast-minus-slow%20EWMA%20log%20return%20spread%0A%20%20%20%20_alpha_fast%20%3D%202.0%20%2F%20(5%20%2B%201)%0A%20%20%20%20_alpha_slow%20%3D%202.0%20%2F%20(60%20%2B%201)%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_i%2C%20_a%20in%20enumerate(_assets)%3A%0A%20%20%20%20%20%20%20%20_lr%20%3D%20_log_returns%5B%3A%2C%20_i%5D%0A%20%20%20%20%20%20%20%20%23%20Vectorised%20EWMA%20using%20cumulative%20trick%20(approximate)%0A%20%20%20%20%20%20%20%20_ew_fast%20%3D%20np.zeros(_n_days)%0A%20%20%20%20%20%20%20%20_ew_slow%20%3D%20np.zeros(_n_days)%0A%20%20%20%20%20%20%20%20_ew_fast%5B0%5D%20%3D%20_lr%5B0%5D%0A%20%20%20%20%20%20%20%20_ew_slow%5B0%5D%20%3D%20_lr%5B0%5D%0A%20%20%20%20%20%20%20%20for%20_t%20in%20range(1%2C%20_n_days)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_ew_fast%5B_t%5D%20%3D%20_alpha_fast%20*%20_lr%5B_t%5D%20%2B%20(1%20-%20_alpha_fast)%20*%20_ew_fast%5B_t%20-%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20_ew_slow%5B_t%5D%20%3D%20_alpha_slow%20*%20_lr%5B_t%5D%20%2B%20(1%20-%20_alpha_slow)%20*%20_ew_slow%5B_t%20-%201%5D%0A%20%20%20%20%20%20%20%20_mu_cols%5B_a%5D%20%3D%20np.tanh(100.0%20*%20(_ew_fast%20-%20_ew_slow))%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_05(mu%2C%20prices)%3A%0A%20%20%20%20%22%22%22Preview%20the%20generated%20dataset.%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%20Price%20series%20(first%205%20rows)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(prices.head(5))%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*%7Bprices.height%3A%2C%7D%20daily%20rows%20%C3%97%20%7Bprices.width%20-%201%7D%20assets.%20%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Date%20column%20%60date%60%20is%20a%20Polars%20%60Date%60%20type.*%22%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%20mo.md(%22%23%23%23%20Momentum%20signals%20%C2%B5%20(first%205%20rows)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(mu.head(5))%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%20r%22*%24%5Cmu%20%5Cin%20%5B-1%2C%201%5D%24%20%E2%80%94%20fast%20EWMA%20vs.%20slow%20EWMA%20spread%20through%20%24%5Ctanh%24.%20%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Positive%20values%20indicate%20upward%20momentum.*%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%0Adef%20cell_06()%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_07()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20config%20selection%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%E2%9A%99%EF%B8%8F%20Step%202%20%E2%80%94%20Config%20Selection%0A%0A%20%20%20%20%20%20%20%20%60BasanosConfig%60%20has%20four%20key%20parameters.%20%20The%20table%20below%20summarises%20the%0A%20%20%20%20%20%20%20%20selection%20guidelines%20built%20into%20the%20library.%0A%0A%20%20%20%20%20%20%20%20%7C%20Parameter%20%7C%20Role%20%7C%20Guidance%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%20%60vola%60%20%7C%20EWMA%20lookback%20for%20per-asset%20volatility%20(days)%20%7C%2010%20%E2%80%93%2030%20for%20daily%20equity%20data%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60corr%60%20%7C%20EWMA%20lookback%20for%20correlation%20matrix%20(days%3B%20must%20be%20%E2%89%A5%20%60vola%60)%20%7C%2030%20%E2%80%93%2090%3B%20longer%20%E2%86%92%20smoother%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60clip%60%20%7C%20Clipping%20threshold%20for%20vol-adjusted%20returns%20(std%20devs)%20%7C%203%20%E2%80%93%205%3B%20tighter%20%E2%86%92%20reduces%20outlier%20impact%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60shrink%60%20%7C%20Shrinkage%20intensity%20towards%20identity%20%60%5B0%2C%201%5D%60%20%7C%20See%20guidance%20below%20%7C%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Shrinkage%20guidance%0A%0A%20%20%20%20%20%20%20%20The%20correct%20%60shrink%60%20value%20depends%20on%20the%20ratio%20of%20assets%20(%60n%60)%20to%20correlation%0A%20%20%20%20%20%20%20%20lookback%20(%60T%20%3D%20corr%60)%3A%0A%0A%20%20%20%20%20%20%20%20%7C%20Regime%20%7C%20Assets%20%60n%60%20%7C%20Lookback%20%60T%60%20%7C%20Recommended%20%60shrink%60%20%7C%0A%20%20%20%20%20%20%20%20%7C--------%7C-----------%7C-------------%7C----------------------%7C%0A%20%20%20%20%20%20%20%20%7C%20Many%20assets%2C%20short%20history%20%7C%20%3E%2020%20%7C%20%3C%2040%20%7C%20**0.3%20%E2%80%93%200.5**%20(strong%20regularisation)%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Balanced%20%7C%20~%2010%20%7C%20~%2060%20%7C%20**0.5%20%E2%80%93%200.7**%20%7C%0A%20%20%20%20%20%20%20%20%7C%20Few%20assets%2C%20long%20history%20%7C%20%3C%2010%20%7C%20%3E%20100%20%7C%20**0.7%20%E2%80%93%200.9**%20(light%20regularisation)%20%7C%0A%0A%20%20%20%20%20%20%20%20For%20this%20dataset%20we%20have%20**8%20assets**%20and%20will%20use%20%60corr%20%3D%2060%60%20%E2%86%92%20the%20*balanced*%0A%20%20%20%20%20%20%20%20regime%2C%20so%20%60shrink%20%3D%200.6%60%20is%20a%20reasonable%20starting%20point.%0A%0A%20%20%20%20%20%20%20%20Use%20the%20sliders%20to%20explore%20how%20each%20parameter%20affects%20the%20strategy.%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_08()%3A%0A%20%20%20%20%22%22%22Create%20interactive%20sliders%20for%20BasanosConfig%20parameters.%22%22%22%0A%20%20%20%20vola_slider%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%3D64%2C%0A%20%20%20%20%20%20%20%20value%3D16%2C%0A%20%20%20%20%20%20%20%20step%3D1%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%20corr_slider%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%3D60%2C%0A%20%20%20%20%20%20%20%20step%3D1%2C%0A%20%20%20%20%20%20%20%20label%3D%22corr%20(correlation%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_slider%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%3D4.0%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%20shrink_slider%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.6%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(shrinkage%20towards%20identity)%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_slider%2C%20corr_slider%2C%20clip_slider%2C%20shrink_slider%5D)%0A%20%20%20%20return%20clip_slider%2C%20corr_slider%2C%20shrink_slider%2C%20vola_slider%0A%0A%0A%40app.cell%0Adef%20cell_09(clip_slider%2C%20corr_slider%2C%20shrink_slider%2C%20vola_slider)%3A%0A%20%20%20%20%22%22%22Build%20BasanosConfig%20from%20slider%20values%20and%20display%20the%20active%20configuration.%22%22%22%0A%20%20%20%20_effective_corr%20%3D%20max(corr_slider.value%2C%20vola_slider.value)%0A%20%20%20%20_warn%20%3D%20_effective_corr%20%3E%20corr_slider.value%0A%0A%20%20%20%20%23%20Shrinkage%20regime%20note%0A%20%20%20%20_n_assets%20%3D%208%0A%20%20%20%20_corr_lookback%20%3D%20_effective_corr%0A%20%20%20%20if%20_n_assets%20%3E%2020%20and%20_corr_lookback%20%3C%2040%3A%0A%20%20%20%20%20%20%20%20_regime%20%3D%20%22many%20assets%20%2F%20short%20history%20%E2%86%92%20%60shrink%60%200.3%20%E2%80%93%200.5%20recommended%22%0A%20%20%20%20elif%20_n_assets%20%3C%2010%20and%20_corr_lookback%20%3E%20100%3A%0A%20%20%20%20%20%20%20%20_regime%20%3D%20%22few%20assets%20%2F%20long%20history%20%E2%86%92%20%60shrink%60%200.7%20%E2%80%93%200.9%20recommended%22%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_regime%20%3D%20%22balanced%20regime%20%E2%86%92%20%60shrink%60%200.5%20%E2%80%93%200.7%20recommended%22%0A%0A%20%20%20%20cfg%20%3D%20BasanosConfig(%0A%20%20%20%20%20%20%20%20vola%3Dvola_slider.value%2C%0A%20%20%20%20%20%20%20%20corr%3D_effective_corr%2C%0A%20%20%20%20%20%20%20%20clip%3Dclip_slider.value%2C%0A%20%20%20%20%20%20%20%20shrink%3Dshrink_slider.value%2C%0A%20%20%20%20%20%20%20%20aum%3D10_000_000%2C%0A%20%20%20%20)%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**%20%E2%80%94%20%7B_regime%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%60BasanosConfig(vola%3D%7Bcfg.vola%7D%2C%20corr%3D%7Bcfg.corr%7D%2C%20clip%3D%7Bcfg.clip%7D%2C%20shrink%3D%7Bcfg.shrink%7D%2C%20aum%3D%7Bcfg.aum%3A%2C.0f%7D)%60%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22%E2%9A%A0%EF%B8%8F%20%60corr%60%20was%20raised%20to%20match%20%60vola%60%20(constraint%3A%20corr%20%E2%89%A5%20vola).%22%20if%20_warn%20else%20%22%22%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(cfg%2C)%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%20engine%20instantiation%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%94%AC%20Step%203%20%E2%80%94%20Engine%20Instantiation%0A%0A%20%20%20%20%20%20%20%20%60BasanosEngine%60%20implements%20a%20vectorised%20three-step%20pipeline%20across%20all%0A%20%20%20%20%20%20%20%20timestamps%20in%20a%20single%20constructor%20call%3A%0A%0A%20%20%20%20%20%20%20%201.%20**Volatility%20adjustment**%20%E2%80%94%20log%20returns%20are%20normalised%20by%20an%20EWMA%0A%20%20%20%20%20%20%20%20%20%20%20volatility%20estimate%20and%20clipped%20at%20%60cfg.clip%60%20standard%20deviations.%0A%0A%20%20%20%20%20%20%20%202.%20**Correlation%20estimation**%20%E2%80%94%20an%20EWMA%20correlation%20matrix%20is%20computed%0A%20%20%20%20%20%20%20%20%20%20%20and%20regularised%20via%20linear%20shrinkage%20toward%20the%20identity%3A%0A%0A%20%20%20%20%20%20%20%20%20%20%20%24%24C_%5Ctext%7Bshrunk%7D%20%3D%20%5Clambda%20%5Ccdot%20C_%5Ctext%7BEWMA%7D%20%2B%20(1%20-%20%5Clambda)%20%5Ccdot%20I%2C%0A%20%20%20%20%20%20%20%20%20%20%20%5Cquad%20%5Clambda%20%3D%20%5Ctexttt%7Bcfg.shrink%7D%24%24%0A%0A%20%20%20%20%20%20%20%203.%20**Position%20solving**%20%E2%80%94%20for%20each%20timestamp%20the%20system%0A%20%20%20%20%20%20%20%20%20%20%20%24C_%5Ctext%7Bshrunk%7D%20%5Ccdot%20x%20%3D%20%5Cmu%24%20is%20solved%20and%20the%20risk%20position%20%24x%24%20is%0A%20%20%20%20%20%20%20%20%20%20%20normalised%2C%20then%20converted%20to%20a%20cash%20position%20by%20dividing%20by%20per-asset%0A%20%20%20%20%20%20%20%20%20%20%20EWMA%20volatility.%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(cfg%2C%20mu%2C%20prices)%3A%0A%20%20%20%20%22%22%22Instantiate%20BasanosEngine.%22%22%22%0A%20%20%20%20engine%20%3D%20BasanosEngine(prices%3Dprices%2C%20mu%3Dmu%2C%20cfg%3Dcfg)%0A%20%20%20%20portfolio%20%3D%20engine.portfolio%0A%20%20%20%20return%20engine%2C%20portfolio%0A%0A%0A%40app.cell%0Adef%20cell_13(engine)%3A%0A%20%20%20%20%22%22%22Show%20key%20engine%20outputs%3A%20position%20status%2C%20cash%20positions%2C%20and%20IC.%22%22%22%0A%20%20%20%20_status_counts%20%3D%20(%0A%20%20%20%20%20%20%20%20engine.position_status.group_by(%22status%22).agg(pl.len().alias(%22count%22)).sort(%22count%22%2C%20descending%3DTrue)%0A%20%20%20%20)%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%20Position%20status%20breakdown%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(_status_counts)%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%20%22*%60warmup%60%20%E2%80%94%20EWMA%20not%20yet%20converged%3B%20%60valid%60%20%E2%80%94%20position%20produced%20normally%3B%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%60zero_signal%60%20%E2%80%94%20signal%20was%20zero%3B%20%60degenerate%60%20%E2%80%94%20matrix%20ill-conditioned.*%22%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%20mo.md(%22%23%23%23%20Cash%20positions%20(last%205%20rows)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(engine.cash_position.tail(5))%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*%7Bengine.cash_position.height%3A%2C%7D%20rows%20%C3%97%20%7Blen(engine.assets)%7D%20assets.%20%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Values%20are%20in%20currency%20units%20(AUM-scaled).*%22%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%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%23%23%23%20Signal%20quality%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22-%20**IC%20mean**%3A%20%60%7Bengine.ic_mean%3A.4f%7D%60%20%7C%20**IC%20std**%3A%20%60%7Bengine.ic_std%3A.4f%7D%60%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22-%20**ICIR**%3A%20%60%7Bengine.icir%3A.4f%7D%60%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22-%20**Rank%20IC%20mean**%3A%20%60%7Bengine.rank_ic_mean%3A.4f%7D%60%20%7C%20**Rank%20IC%20std**%3A%20%60%7Bengine.rank_ic_std%3A.4f%7D%60%5Cn%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%0Adef%20cell_14(portfolio)%3A%0A%20%20%20%20%22%22%22Display%20key%20performance%20statistics.%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%20Statistics%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(portfolio.stats.summary())%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%20%22*Metrics%20are%20computed%20on%20the%20daily%20profit%20stream%20scaled%20by%20AUM.%20%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Sharpe%2C%20volatility%2C%20and%20VaR%20are%20annualised%20(%C3%97%E2%88%9A252).*%22%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%20mo.md(%22%23%23%23%20Turnover%20Summary%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(portfolio.turnover_summary())%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_15(portfolio)%3A%0A%20%20%20%20%22%22%22Render%20the%20performance%20snapshot%20(NAV%20%2B%20drawdown).%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(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%20Performance%20Dashboard%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20The%20upper%20panel%20shows%20cumulative%20NAV%20alongside%20the%20**tilt**%20component%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(static%20average%20allocation)%20and%20the%20**timing**%20component%20(dynamic%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20deviation%20from%20average).%20%20The%20lower%20panel%20shows%20the%20drawdown%20from%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20running%20high-water%20mark.%0A%20%20%20%20%20%20%20%20%20%20%20%20%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%20%20%20%20mo.ui.plotly(portfolio.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_16()%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_17()%3A%0A%20%20%20%20%22%22%22Introduce%20the%20HTML%20report%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%84%20Step%204%20%E2%80%94%20HTML%20Report%20Generation%0A%0A%20%20%20%20%20%20%20%20%60portfolio.report%60%20is%20a%20lazy%20facade%20that%20assembles%20a%20**self-contained%20HTML%0A%20%20%20%20%20%20%20%20report**%20containing%3A%0A%0A%20%20%20%20%20%20%20%20-%20Metadata%20(date%20range%2C%20asset%20list%2C%20AUM)%0A%20%20%20%20%20%20%20%20-%20All%20key%20statistics%20and%20turnover%20tables%0A%20%20%20%20%20%20%20%20-%20Eight%20interactive%20Plotly%20charts%20(NAV%2C%20rolling%20Sharpe%2C%20volatility%2C%20annual%0A%20%20%20%20%20%20%20%20%20%20Sharpe%2C%20monthly%20returns%20heatmap%2C%20correlation%20heatmap%2C%20lead%2Flag%20IR%2C%0A%20%20%20%20%20%20%20%20%20%20and%20trading%20cost%20impact)%0A%0A%20%20%20%20%20%20%20%20The%20report%20embeds%20Plotly%20from%20CDN%20and%20requires%20no%20additional%20dependencies%0A%20%20%20%20%20%20%20%20to%20open%20in%20any%20modern%20browser.%0A%0A%20%20%20%20%20%20%20%20%60%60%60python%0A%20%20%20%20%20%20%20%20%23%20Save%20to%20disk%0A%20%20%20%20%20%20%20%20saved_path%20%3D%20portfolio.report.save(%22basanos_report.html%22)%0A%0A%20%20%20%20%20%20%20%20%23%20Or%20get%20the%20HTML%20string%20(e.g.%20to%20serve%20via%20an%20API)%0A%20%20%20%20%20%20%20%20html_str%20%3D%20portfolio.report.to_html(title%3D%22My%20Strategy%20Report%22)%0A%20%20%20%20%20%20%20%20%60%60%60%0A%0A%20%20%20%20%20%20%20%20The%20cell%20below%20saves%20the%20report%20to%20a%20temporary%20path%20and%20confirms%20success.%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_18(portfolio)%3A%0A%20%20%20%20%22%22%22Generate%20and%20save%20the%20HTML%20report.%22%22%22%0A%20%20%20%20import%20tempfile%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20_tmp%20%3D%20Path(tempfile.mkdtemp())%20%2F%20%22basanos_report.html%22%0A%20%20%20%20_saved%20%3D%20portfolio.report.save(_tmp)%0A%20%20%20%20_size_kb%20%3D%20_saved.stat().st_size%20%2F%201_024%0A%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%E2%9C%85%20**Report%20saved%20successfully**%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20-%20**Path**%3A%20%60%7B_saved%7D%60%0A%20%20%20%20%20%20%20%20%20%20%20%20-%20**File%20size**%3A%20%60%7B_size_kb%3A%2C.1f%7D%20KB%60%0A%20%20%20%20%20%20%20%20%20%20%20%20-%20**Charts**%3A%20NAV%20%2B%20drawdown%2C%20rolling%20Sharpe%2C%20rolling%20volatility%2C%20annual%20Sharpe%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20monthly%20returns%20heatmap%2C%20correlation%20heatmap%2C%20lead%2Flag%20IR%2C%20trading%20cost%20impact%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20To%20save%20to%20a%20custom%20location%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%60%60python%0A%20%20%20%20%20%20%20%20%20%20%20%20portfolio.report.save(%22my_report.html%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%60%60%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%22success%22%2C%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%22Introduce%20the%20trading%20cost%20analysis%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%92%B8%20Step%205%20%E2%80%94%20Trading%20Cost%20Analysis%0A%0A%20%20%20%20%20%20%20%20High%20turnover%20strategies%20can%20erode%20edge%20when%20real-world%20trading%20costs%20are%0A%20%20%20%20%20%20%20%20applied.%20%20Basanos%20estimates%20cost%20impact%20via%20a%20**linear%20cost%20model**%3A%0A%0A%20%20%20%20%20%20%20%20%24%24%5Ctext%7Bdaily%20cost%7D%20%3D%20%5Ctext%7Bturnover%7D_t%20%5Ctimes%20%5Cfrac%7B%5Ctext%7Bcost%5C_bps%7D%7D%7B10%5C%2C000%7D%24%24%0A%0A%20%20%20%20%20%20%20%20where%20%24%5Ctext%7Bturnover%7D_t%24%20is%20the%20fraction%20of%20AUM%20traded%20on%20day%20%24t%24.%0A%0A%20%20%20%20%20%20%20%20%60portfolio.trading_cost_impact(max_bps)%60%20sweeps%20one-way%20costs%20from%200%20to%0A%20%20%20%20%20%20%20%20%60max_bps%60%20basis%20points%20and%20returns%20the%20net%20Sharpe%20at%20each%20level%20%E2%80%94%20making%20it%0A%20%20%20%20%20%20%20%20easy%20to%20see%20at%20what%20cost%20level%20the%20strategy's%20edge%20is%20fully%20consumed.%0A%0A%20%20%20%20%20%20%20%20Use%20the%20slider%20to%20set%20the%20maximum%20cost%20level%20to%20evaluate.%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_21()%3A%0A%20%20%20%20%22%22%22Create%20slider%20for%20maximum%20trading%20cost.%22%22%22%0A%20%20%20%20max_bps_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D5%2C%0A%20%20%20%20%20%20%20%20stop%3D50%2C%0A%20%20%20%20%20%20%20%20value%3D30%2C%0A%20%20%20%20%20%20%20%20step%3D5%2C%0A%20%20%20%20%20%20%20%20label%3D%22Maximum%20one-way%20trading%20cost%20to%20evaluate%20(bps)%3A%22%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20max_bps_slider%0A%20%20%20%20return%20(max_bps_slider%2C)%0A%0A%0A%40app.cell%0Adef%20cell_22(max_bps_slider%2C%20portfolio)%3A%0A%20%20%20%20%22%22%22Run%20and%20display%20the%20trading%20cost%20impact%20analysis.%22%22%22%0A%20%20%20%20_impact%20%3D%20portfolio.trading_cost_impact(max_bps%3Dmax_bps_slider.value)%0A%0A%20%20%20%20%23%20Find%20the%20breakeven%20cost%20(first%20level%20where%20Sharpe%20%E2%89%A4%200)%0A%20%20%20%20_breakeven%20%3D%20_impact.filter(pl.col(%22sharpe%22)%20%3C%3D%200).select(%22cost_bps%22).head(1)%0A%20%20%20%20_be_note%20%3D%20(%0A%20%20%20%20%20%20%20%20f%22The%20strategy's%20edge%20is%20**fully%20consumed%20at%20~%7B_breakeven%5B0%2C%200%5D%7D%20bps**%20one-way%20trading%20cost.%22%0A%20%20%20%20%20%20%20%20if%20_breakeven.height%20%3E%200%0A%20%20%20%20%20%20%20%20else%20%22The%20strategy%20retains%20positive%20Sharpe%20across%20the%20entire%20cost%20range%20evaluated.%22%0A%20%20%20%20)%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%20Trading%20Cost%20Impact%20Table%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(_impact)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22*%7B_be_note%7D%20%20One-way%20cost%20in%20basis%20points%20per%20unit%20of%20AUM%20traded.*%22)%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_23(portfolio)%3A%0A%20%20%20%20%22%22%22Render%20the%20trading%20cost%20impact%20chart.%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(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%23%20Sharpe%20vs.%20Trading%20Cost%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Each%20bar%20shows%20the%20annualised%20Sharpe%20ratio%20after%20deducting%20one-way%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trading%20costs%20at%20the%20given%20basis-point%20level.%20%20The%20height%20of%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20zero-cost%20bar%20(0%20bps)%20is%20the%20gross%20strategy%20Sharpe.%0A%20%20%20%20%20%20%20%20%20%20%20%20%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%20%20%20%20mo.ui.plotly(portfolio.plots.trading_cost_impact_plot())%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_24()%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_25()%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%20%F0%9F%8E%89%20Summary%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20demonstrated%20the%20complete%20**Basanos**%20workflow%20end-to-end%3A%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Data%20preparation**%20%E2%80%94%20realistic%20synthetic%20sector%20prices%20with%20shared%20market%0A%20%20%20%20%20%20%20%20factor%20and%20momentum%20signals%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Config%20selection**%20%E2%80%94%20%60BasanosConfig%60%20with%20shrinkage%20guidance%20table%20and%0A%20%20%20%20%20%20%20%20reactive%20parameter%20sliders%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Engine%20instantiation**%20%E2%80%94%20%60BasanosEngine%60%20computes%20correlation-adjusted%0A%20%20%20%20%20%20%20%20cash%20positions%20and%20IC%2FICIR%20signal%20quality%20metrics%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**HTML%20report%20generation**%20%E2%80%94%20one-call%20%60portfolio.report.save()%60%20producing%0A%20%20%20%20%20%20%20%20a%20self-contained%20browser%20report%20with%20eight%20interactive%20charts%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Trading%20cost%20analysis**%20%E2%80%94%20%60portfolio.trading_cost_impact()%60%20sweep%20showing%0A%20%20%20%20%20%20%20%20Sharpe%20degradation%20and%20the%20breakeven%20cost%20level%0A%0A%20%20%20%20%20%20%20%20---%0A%0A%20%20%20%20%20%20%20%20%23%23%23%20Next%20steps%0A%0A%20%20%20%20%20%20%20%20-%20Replace%20the%20synthetic%20data%20with%20real%20price%20data%20from%20a%20public%20source%0A%20%20%20%20%20%20%20%20%20%20(e.g.%20%60yfinance%60)%20and%20your%20own%20forecasting%20signal%0A%20%20%20%20%20%20%20%20-%20Switch%20to%20%60SlidingWindowConfig%60%20for%20the%20factor-model%20covariance%20mode%0A%20%20%20%20%20%20%20%20%20%20(see%20%60book%2Fmarimo%2Fnotebooks%2Fewm_benchmark.py%60)%0A%20%20%20%20%20%20%20%20-%20Tune%20%60shrink%60%20empirically%20using%20the%20interactive%20sweep%20in%0A%20%20%20%20%20%20%20%20%20%20%60book%2Fmarimo%2Fnotebooks%2Fshrinkage_guide.py%60%0A%20%20%20%20%20%20%20%20-%20Use%20%60portfolio.truncate()%60%20to%20analyse%20sub-periods%20in%20isolation%0A%20%20%20%20%20%20%20%20-%20See%20the%20%5Bbasanos%20repository%5D(https%3A%2F%2Fgithub.com%2FJebel-Quant%2Fbasanos)%20for%0A%20%20%20%20%20%20%20%20%20%20the%20full%20API%20reference%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
b3c20836ba571d8e5f52d23d18e78bca