%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.12%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22marimo%3D%3D0.23.9%22%2C%0A%23%20%20%20%20%20%22numpy%3D%3D2.4.6%22%2C%0A%23%20%20%20%20%20%22plotly%3D%3D6.8.0%22%2C%0A%23%20%20%20%20%20%22polars%3D%3D1.41.2%22%2C%0A%23%20%20%20%20%20%22jquantstats%3D%3D0.9.6%22%2C%0A%23%20%20%20%20%20%22tinycta%3D%3D0.13.2%22%0A%23%20%5D%0A%23%20%2F%2F%2F%0A%0A%22%22%22Experiment%205%3A%20Advanced%20CTA%20strategy%20with%20correlation-based%20optimization.%0A%0AThis%20module%20implements%20a%20sophisticated%20trend-following%20strategy%20that%0Aincorporates%20dynamic%20conditional%20correlation%20(DCC)%20and%20matrix%20optimization%0Atechniques%20to%20improve%20portfolio%20construction%20and%20risk%20management.%0A%22%22%22%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.9%22%0Aapp%20%3D%20marimo.App()%0A%0Awith%20app.setup%3A%0A%20%20%20%20import%20sys%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20from%20jquantstats%20import%20Portfolio%0A%20%20%20%20from%20tinycta.linalg%20import%20inv_a_norm%2C%20solve%0A%20%20%20%20from%20tinycta.osc%20import%20osc%0A%20%20%20%20from%20tinycta.signal%20import%20shrink2id%0A%20%20%20%20from%20tinycta.util%20import%20vol_adj%0A%0A%20%20%20%20sys.path.insert(0%2C%20str(Path(__file__).parent))%0A%0A%20%20%20%20from%20preamble%20import%20date_col%2C%20load_prices%0A%0A%20%20%20%20prices%20%3D%20load_prices(__file__)%0A%20%20%20%20prices_only%20%3D%20prices.drop(date_col)%0A%20%20%20%20assets%20%3D%20prices_only.columns%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20CTA%205.0%20-%20Optimization%202.0%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20f(price%3A%20%22pl.Expr%22%2C%20fast%3D32%2C%20slow%3D96%2C%20vola%3D32%2C%20clip%3D4.2)%20-%3E%20%22pl.Expr%22%3A%0A%20%20%20%20%22%22%22Return%20the%20tanh%20oscillator%20of%20vol-adjusted%20cumulative%20price.%22%22%22%0A%20%20%20%20return%20osc(vol_adj(price%2C%20vola%3Dvola%2C%20clip%3Dclip%2C%20min_samples%3D300).cum_sum()%2C%20fast%3Dfast%2C%20slow%3Dslow).tanh()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20fast%20%3D%20mo.ui.slider(4%2C%20192%2C%20step%3D4%2C%20value%3D32%2C%20label%3D%22Fast%20Moving%20Average%22)%0A%20%20%20%20slow%20%3D%20mo.ui.slider(4%2C%20192%2C%20step%3D4%2C%20value%3D96%2C%20label%3D%22Slow%20Moving%20Average%22)%0A%20%20%20%20vola%20%3D%20mo.ui.slider(4%2C%20192%2C%20step%3D4%2C%20value%3D32%2C%20label%3D%22Volatility%22)%0A%20%20%20%20winsor%20%3D%20mo.ui.slider(1.0%2C%206.0%2C%20step%3D0.1%2C%20value%3D4.2%2C%20label%3D%22Winsorizing%22)%0A%20%20%20%20corr%20%3D%20mo.ui.slider(50%2C%20500%2C%20step%3D10%2C%20value%3D200%2C%20label%3D%22Correlation%22)%0A%20%20%20%20shrinkage%20%3D%20mo.ui.slider(0.0%2C%201.0%2C%20step%3D0.05%2C%20value%3D0.5%2C%20label%3D%22Shrinkage%22)%0A%0A%20%20%20%20mo.vstack(%5Bfast%2C%20slow%2C%20vola%2C%20winsor%2C%20corr%2C%20shrinkage%5D)%0A%20%20%20%20return%20corr%2C%20shrinkage%2C%20vola%2C%20winsor%0A%0A%0A%40app.cell%0Adef%20_(corr%2C%20shrinkage%2C%20vola%2C%20winsor)%3A%0A%20%20%20%20n_assets%20%3D%20len(assets)%0A%20%20%20%20n_rows%20%3D%20len(prices_only)%0A%20%20%20%20correlation%20%3D%20corr.value%0A%0A%20%20%20%20returns_adj%20%3D%20prices_only.select(vol_adj(pl.all()%2C%20vola%3Dvola.value%2C%20clip%3Dwinsor.value%2C%20min_samples%3D300))%0A%0A%20%20%20%20%23%20EWM%20correlation%20(DCC%20by%20Engle)%0A%20%20%20%20%23%20cov_t(i%2Cj)%20%3D%20ewm_t(r_i%20*%20r_j)%20-%20ewm_t(r_i)%20*%20ewm_t(r_j)%0A%20%20%20%20ewm_means_np%20%3D%20returns_adj.select(pl.all().ewm_mean(com%3Dcorrelation%2C%20min_samples%3Dint(correlation))).to_numpy()%0A%0A%20%20%20%20pair_indices%20%3D%20%5B(i%2C%20j)%20for%20i%20in%20range(n_assets)%20for%20j%20in%20range(i%2C%20n_assets)%5D%0A%20%20%20%20ewm_prod_np%20%3D%20returns_adj.select(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20(pl.col(assets%5Bi%5D)%20*%20pl.col(assets%5Bj%5D))%0A%20%20%20%20%20%20%20%20%20%20%20%20.fill_nan(None)%0A%20%20%20%20%20%20%20%20%20%20%20%20.ewm_mean(com%3Dcorrelation%2C%20min_samples%3Dint(correlation))%0A%20%20%20%20%20%20%20%20%20%20%20%20.alias(f%22p%7Bi%7D_%7Bj%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%2C%20j%20in%20pair_indices%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20).to_numpy()%0A%0A%20%20%20%20cov_np%20%3D%20np.full((n_rows%2C%20n_assets%2C%20n_assets)%2C%20np.nan)%0A%20%20%20%20for%20_k%2C%20(_i%2C%20_j)%20in%20enumerate(pair_indices)%3A%0A%20%20%20%20%20%20%20%20_cov%20%3D%20ewm_prod_np%5B%3A%2C%20_k%5D%20-%20ewm_means_np%5B%3A%2C%20_i%5D%20*%20ewm_means_np%5B%3A%2C%20_j%5D%0A%20%20%20%20%20%20%20%20cov_np%5B%3A%2C%20_i%2C%20_j%5D%20%3D%20_cov%0A%20%20%20%20%20%20%20%20cov_np%5B%3A%2C%20_j%2C%20_i%5D%20%3D%20_cov%0A%0A%20%20%20%20_var%20%3D%20cov_np%5B%3A%2C%20np.arange(n_assets)%2C%20np.arange(n_assets)%5D%0A%20%20%20%20with%20np.errstate(invalid%3D%22ignore%22%2C%20divide%3D%22ignore%22)%3A%0A%20%20%20%20%20%20%20%20_denom%20%3D%20np.sqrt(_var%5B%3A%2C%20%3A%2C%20None%5D%20*%20_var%5B%3A%2C%20None%2C%20%3A%5D)%0A%20%20%20%20%20%20%20%20cor_3d%20%3D%20cov_np%20%2F%20_denom%0A%20%20%20%20for%20_k%20in%20range(n_assets)%3A%0A%20%20%20%20%20%20%20%20cor_3d%5B_var%5B%3A%2C%20_k%5D%20%3E%200%2C%20_k%2C%20_k%5D%20%3D%201.0%0A%0A%20%20%20%20mu%20%3D%20prices_only.select(f(pl.all()%2C%20fast%3D32%2C%20slow%3D96%2C%20vola%3Dvola.value%2C%20clip%3Dwinsor.value)).to_numpy()%0A%20%20%20%20vo%20%3D%20prices_only.select(%0A%20%20%20%20%20%20%20%20pl.all().fill_nan(None).pct_change().ewm_std(com%3Dvola.value%2C%20min_samples%3Dint(vola.value))%0A%20%20%20%20).to_numpy()%0A%0A%20%20%20%20prices_np%20%3D%20prices_only.to_numpy()%0A%20%20%20%20pos_matrix%20%3D%20np.zeros((n_rows%2C%20n_assets))%0A%0A%20%20%20%20for%20_n%20in%20range(n_rows)%3A%0A%20%20%20%20%20%20%20%20_mask%20%3D%20np.isfinite(prices_np%5B_n%5D)%0A%20%20%20%20%20%20%20%20if%20_mask.sum()%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20_full_shrunk%20%3D%20shrink2id(cor_3d%5B_n%5D%2C%20lamb%3Dshrinkage.value)%0A%20%20%20%20%20%20%20%20_matrix%20%3D%20_full_shrunk%5B_mask%2C%20%3A%5D%5B%3A%2C%20_mask%5D%0A%20%20%20%20%20%20%20%20_expected_mu%20%3D%20np.nan_to_num(mu%5B_n%5D%5B_mask%5D)%0A%20%20%20%20%20%20%20%20_expected_vo%20%3D%20np.nan_to_num(vo%5B_n%5D%5B_mask%5D)%0A%20%20%20%20%20%20%20%20_norm%20%3D%20inv_a_norm(_expected_mu%2C%20_matrix)%0A%20%20%20%20%20%20%20%20if%20_norm%20%3D%3D%200%20or%20np.isnan(_norm)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20_risk_pos%20%3D%20solve(_matrix%2C%20_expected_mu)%20%2F%20_norm%0A%20%20%20%20%20%20%20%20pos_matrix%5B_n%2C%20_mask%5D%20%3D%20np.nan_to_num(1e6%20*%20_risk_pos%20%2F%20_expected_vo%2C%20nan%3D0.0)%0A%0A%20%20%20%20portfolio%20%3D%20Portfolio.from_cash_position(%0A%20%20%20%20%20%20%20%20prices%3Dprices%2C%0A%20%20%20%20%20%20%20%20cash_position%3Dpl.concat(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bprices.select(date_col)%2C%20pl.from_numpy(pos_matrix%2C%20schema%3Ddict.fromkeys(assets%2C%20pl.Float64))%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20how%3D%22horizontal%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20aum%3D1e8%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(portfolio%2C)%0A%0A%0A%40app.cell%0Adef%20_(portfolio)%3A%0A%20%20%20%20print(portfolio.stats.sharpe())%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Conclusions%0A%20%20%20%20*%20Dramatic%20relative%20improvements%20observable%20despite%20using%20the%20same%20signals%20as%20in%20previous%20Experiment.%0A%20%20%20%20*%20Main%20difference%20here%20is%20to%20take%20advantage%20of%20cross-correlations%20in%20the%20risk%20measurement.%0A%20%20%20%20*%20Possible%20to%20add%20constraints%20on%20individual%20assets%20or%20groups%20of%20them.%0A%20%20%20%20*%20Possible%20to%20reflect%20trading%20costs%20in%20objective%20with%20regularization%20terms%20(Ridge%2C%20Lars%2C%20Elastic%20Nets%2C%20...)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(portfolio)%3A%0A%20%20%20%20portfolio.plots.snapshot()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(portfolio)%3A%0A%20%20%20%20portfolio.stats.summary()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%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
138bd7a25e8e76400b41d5b254d37acb