%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%20basanos%20demo%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%93%8A%20Basanos%20%E2%80%94%20Portfolio%20Optimization%20%26%20Analytics%0A%0A%20%20%20%20%20%20%20%20**Basanos**%20computes%20**correlation-adjusted%20risk%20positions**%20from%20price%20data%0A%20%20%20%20%20%20%20%20and%20expected-return%20signals.%20It%20estimates%20time-varying%20EWMA%20correlations%2C%0A%20%20%20%20%20%20%20%20applies%20shrinkage%20towards%20the%20identity%20matrix%2C%20and%20solves%20a%20normalized%0A%20%20%20%20%20%20%20%20linear%20system%20per%20timestamp%20to%20produce%20stable%2C%20scale-invariant%20positions%20%E2%80%94%0A%20%20%20%20%20%20%20%20implementing%20a%20*first%20hurdle*%20for%20expected%20returns.%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%88%20**Synthetic%20market%20data**%20%E2%80%94%20four%20equity-like%20price%20series%20and%20momentum%20signals%0A%20%20%20%20%20%20%20%202.%20%E2%9A%99%EF%B8%8F%20**Interactive%20configuration**%20%E2%80%94%20reactive%20sliders%20for%20%60BasanosConfig%60%20parameters%0A%20%20%20%20%20%20%20%203.%20%F0%9F%94%AC%20**Optimization**%20%E2%80%94%20%60BasanosEngine%60%20computes%20correlation-adjusted%20cash%20positions%0A%20%20%20%20%20%20%20%204.%20%F0%9F%93%89%20**Portfolio%20analytics**%20%E2%80%94%20NAV%2C%20drawdown%2C%20tilt%2Ftiming%20decomposition%2C%20statistics%0A%20%20%20%20%20%20%20%205.%20%F0%9F%8E%A8%20**Visualisations**%20%E2%80%94%20performance%20dashboard%2C%20lead%2Flag%20IR%2C%20and%20correlation%20heatmap%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%20horizontal%20rule%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%20synthetic%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%20%F0%9F%93%88%20Synthetic%20Market%20Data%0A%0A%20%20%20%20%20%20%20%20We%20generate%20four%20synthetic%20equity-like%20price%20series%20%E2%80%94%20**AAPL**%2C%20**GOOGL**%2C%0A%20%20%20%20%20%20%20%20**MSFT**%2C%20and%20**AMZN**%20%E2%80%94%20over%20three%20years%20of%20daily%20data%20using%20geometric%0A%20%20%20%20%20%20%20%20Brownian%20motion.%20A%20fixed%20random%20seed%20(%6042%60)%20ensures%20reproducibility.%0A%0A%20%20%20%20%20%20%20%20The%20expected-return%20signals%20%24%5Cmu%20%5Cin%20%5B-1%2C%201%5D%24%20are%20constructed%20from%20a%20simple%0A%20%20%20%20%20%20%20%20price-momentum%20rule%3A%20the%20difference%20between%20a%205-day%20and%2020-day%20moving%20average%2C%0A%20%20%20%20%20%20%20%20passed%20through%20%24%5Ctanh%24%20to%20keep%20values%20bounded.%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%20prices%20and%20expected-return%20signals%20with%20a%20fixed%20seed.%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%5D%0A%20%20%20%20_n%20%3D%20750%20%20%23%20roughly%203%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%23%20Geometric%20Brownian%20motion%3A%20different%20drift%20%2F%20vol%20per%20asset%0A%20%20%20%20_drift%20%3D%20%5B0.0003%2C%200.0002%2C%200.0004%2C%200.0001%5D%0A%20%20%20%20_sigma%20%3D%20%5B0.018%2C%200.022%2C%200.020%2C%200.025%5D%0A%20%20%20%20_s0%20%3D%20%5B150.0%2C%202800.0%2C%20300.0%2C%203300.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_05(mu%2C%20prices)%3A%0A%20%20%20%20%22%22%22Show%20a%20preview%20of%20the%20prices%20and%20signals%20DataFrames.%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%20data%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(%22%23%23%23%20Expected-return%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%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%20configuration%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%20Configuration%0A%0A%20%20%20%20%20%20%20%20Adjust%20the%20%60BasanosConfig%60%20parameters%20using%20the%20sliders%20below.%0A%20%20%20%20%20%20%20%20The%20optimizer%20and%20all%20downstream%20analytics%20**update%20reactively**%20whenever%0A%20%20%20%20%20%20%20%20you%20move%20a%20slider.%0A%0A%20%20%20%20%20%20%20%20%7C%20Parameter%20%7C%20Constraint%20%7C%20Description%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%20%60%3E%200%60%20%7C%20EWMA%20lookback%20for%20volatility%20estimation%20(days)%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60corr%60%20%7C%20%60%E2%89%A5%20vola%60%20%7C%20EWMA%20lookback%20for%20correlation%20estimation%20(days)%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60clip%60%20%7C%20%60%3E%200%60%20%7C%20Clipping%20threshold%20for%20vol-adjusted%20returns%20%7C%0A%20%20%20%20%20%20%20%20%7C%20%60shrink%60%20%7C%20%60%5B0%2C%201%5D%60%20%7C%20Shrinkage%20intensity%20towards%20identity%20%E2%80%94%20%600%60%20%3D%20none%2C%20%601%60%20%3D%20full%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%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%3D32%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%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%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.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(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%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%3D1_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**%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%20optimization%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%20Optimization%0A%0A%20%20%20%20%20%20%20%20%60BasanosEngine%60%20implements%20a%20three-step%20pipeline%20per%20timestamp%3A%0A%0A%20%20%20%20%20%20%20%201.%20**Volatility%20adjustment**%20%E2%80%94%20log%20returns%20are%20normalized%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%20shrunk%20towards%20the%20identity%20matrix%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%20%5Cquad%20%5Clambda%20%3D%20%5Ctext%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%2C%20solve%20%24C_%5Ctext%7Bshrunk%7D%20%5Ccdot%20x%20%3D%20%5Cmu%24%0A%20%20%20%20%20%20%20%20%20%20%20and%20normalize%20by%20the%20inverse-matrix%20norm%20of%20%24%5Cmu%24.%20Positions%20are%20then%20scaled%0A%20%20%20%20%20%20%20%20%20%20%20by%20EWMA%20volatility%20and%20a%20running%20profit-variance%20estimate.%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%22Run%20BasanosEngine%20and%20extract%20cash%20positions%20and%20portfolio.%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%22Display%20the%20computed%20cash%20positions%20(last%205%20rows).%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%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%7D%20rows%20%C3%97%20%7Blen(engine.assets)%7D%20assets.%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%5D%0A%20%20%20%20)%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%20portfolio%20analytics%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%89%20Portfolio%20Analytics%0A%0A%20%20%20%20%20%20%20%20The%20%60Portfolio%60%20object%20exposes%20a%20rich%20set%20of%20computed%20properties%20for%0A%20%20%20%20%20%20%20%20evaluating%20strategy%20performance.%20All%20values%20update%20reactively%20as%20you%0A%20%20%20%20%20%20%20%20adjust%20the%20configuration%20sliders%20above.%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(portfolio)%3A%0A%20%20%20%20%22%22%22Display%20the%20full%20statistics%20summary%20table.%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%20Statistics%20Summary%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%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.*%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_16b(portfolio)%3A%0A%20%20%20%20%22%22%22Display%20the%20turnover%20summary%20table.%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%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%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22*%60mean_daily_turnover%60%20and%20%60mean_weekly_turnover%60%20are%20one-way%20turnover%20as%20a%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22fraction%20of%20AUM.%20%20%60turnover_std%60%20is%20the%20standard%20deviation%20of%20daily%20turnover%20%E2%80%94%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%20high%20value%20relative%20to%20the%20mean%20indicates%20regime%20switches%20or%20unstable%20positions.*%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_17(portfolio)%3A%0A%20%20%20%20%22%22%22Display%20the%20tilt%20%2F%20timing%20decomposition%20(last%206%20rows).%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%20Tilt%20%2F%20Timing%20Decomposition%20(last%206%20rows)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20**Portfolio**%20%E2%80%94%20total%20accumulated%20NAV%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20**Tilt**%20%E2%80%94%20static%20average%20allocation%20(constant%20weights%20over%20time)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20**Timing**%20%E2%80%94%20dynamic%20deviation%20from%20the%20average%20weight%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.table(portfolio.tilt_timing_decomp.tail(6))%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_18(portfolio)%3A%0A%20%20%20%20%22%22%22Display%20the%20monthly%20returns%20table.%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%20Monthly%20Returns%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(portfolio.monthly.select(%5B%22year%22%2C%20%22month_name%22%2C%20%22returns%22%2C%20%22profit%22%2C%20%22NAV_accumulated%22%5D))%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%22Introduce%20the%20visualisations%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%8E%A8%20Visualisations%0A%0A%20%20%20%20%20%20%20%20All%20charts%20are%20interactive%20Plotly%20figures%20%E2%80%94%20hover%20for%20tooltips%2C%20click%0A%20%20%20%20%20%20%20%20legend%20items%20to%20toggle%20traces%2C%20and%20use%20the%20range-selector%20buttons%20for%0A%20%20%20%20%20%20%20%20quick%20zoom%20presets.%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(portfolio)%3A%0A%20%20%20%20%22%22%22Render%20the%20performance%20snapshot%20dashboard%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%20Three%20overlaid%20NAV%20curves%20show%20the%20total%20portfolio%20alongside%20its%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20**tilt**%20(static%20average)%20and%20**timing**%20(dynamic%20deviation)%20components.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20The%20lower%20panel%20shows%20the%20drawdown%20as%20a%20percentage%20of%20the%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_22(portfolio)%3A%0A%20%20%20%20%22%22%22Render%20the%20lead%20%2F%20lag%20information-ratio%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%20Lead%20%2F%20Lag%20Information%20Ratio%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Each%20bar%20shows%20the%20annualised%20Sharpe%20ratio%20when%20positions%20are%20shifted%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20by%20a%20given%20number%20of%20days.%20A%20genuine%20signal%20should%20peak%20at%20**lag%200**%20and%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20decay%20positively%3B%20negative%20lags%20test%20for%20look-ahead%20bias%20(should%20be%20flat).%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.lead_lag_ir_plot(start%3D-5%2C%20end%3D10))%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%20asset%20%2B%20portfolio%20correlation%20heatmap.%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%20Correlation%20Heatmap%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Pairwise%20Pearson%20correlation%20of%20asset%20log-returns%2C%20with%20the%20portfolio%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20profit%20series%20appended%20as%20an%20additional%20column.%20Helps%20identify%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20concentration%20risk%20and%20diversification%20properties.%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.correlation_heatmap())%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%20Conclusion%0A%0A%20%20%20%20%20%20%20%20This%20notebook%20walked%20through%20the%20full%20**basanos**%20workflow%3A%0A%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Synthetic%20data**%20%E2%80%94%20GBM%20price%20series%20and%20momentum-based%20signals%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Interactive%20configuration**%20%E2%80%94%20reactive%20%60BasanosConfig%60%20sliders%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Optimization**%20%E2%80%94%20%60BasanosEngine%60%20generates%20correlation-adjusted%20positions%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Analytics**%20%E2%80%94%20statistics%20summary%2C%20tilt%2Ftiming%20decomposition%2C%20monthly%20returns%0A%20%20%20%20%20%20%20%20%E2%9C%85%20**Visualisations**%20%E2%80%94%20performance%20dashboard%2C%20lead%2Flag%20IR%2C%20and%20correlation%20heatmap%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%20and%20a%20forecasting%20signal%0A%20%20%20%20%20%20%20%20-%20Tune%20%60vola%60%2C%20%60corr%60%2C%20%60clip%60%2C%20and%20%60shrink%60%20for%20your%20specific%20market%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-%20Explore%20%60Portfolio.smoothed_holding()%60%20to%20reduce%20portfolio%20turnover%0A%20%20%20%20%20%20%20%20-%20See%20the%20%5Bbasanos%20repository%5D(https%3A%2F%2Fgithub.com%2FJebel-Quant%2Fbasanos)%20for%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
5a580582f10dac31b14b64e9f525f85d