diff --git a/portfolios.yml b/portfolios.yml new file mode 100644 index 0000000..c956df9 --- /dev/null +++ b/portfolios.yml @@ -0,0 +1,10 @@ +# Config LIVE del paper trader a portafoglio. Seleziona UN portafoglio attivo +# (definito in scripts/portfolios/_defs.py) e ne fa l'override dei parametri operativi. +active: PORT06 # default raccomandato: master + shape +overrides: + total_capital: 1000 + weighting: cap # equal | cap | inverse_vol | cluster_rp | manual + caps: {PAIRS: 0.33} + leverage: 2 # sobrio per il live reale + rebalance: 1D + poll_seconds: 60 diff --git a/src/portfolio/base.py b/src/portfolio/base.py index 892e887..8e0a0e8 100644 --- a/src/portfolio/base.py +++ b/src/portfolio/base.py @@ -77,3 +77,18 @@ class Portfolio: risk = {sid: float(rc[k] / pv * 100) if pv > 0 else 0.0 for k, sid in enumerate(self.sleeve_ids)} return PortfolioResult(self.code, w, full, oos, yearly_returns(port_dr), risk) + + +def load_active_portfolio(config_path) -> "Portfolio": + """Carica il portafoglio attivo da portfolios.yml applicando gli override.""" + import yaml + from pathlib import Path + from scripts.portfolios._defs import PORTFOLIOS + + cfg = yaml.safe_load(Path(config_path).read_text()) + p = PORTFOLIOS[cfg["active"]] + ov = cfg.get("overrides", {}) + for k in ("total_capital", "weighting", "caps", "leverage", "rebalance", "vol_lookback"): + if k in ov and ov[k] is not None: + setattr(p, k, ov[k]) + return p diff --git a/tests/portfolio/test_config.py b/tests/portfolio/test_config.py new file mode 100644 index 0000000..da3de5c --- /dev/null +++ b/tests/portfolio/test_config.py @@ -0,0 +1,10 @@ +from src.portfolio.base import load_active_portfolio + + +def test_load_active_applies_overrides(tmp_path): + cfg = tmp_path / "portfolios.yml" + cfg.write_text("active: PORT06\noverrides:\n leverage: 2\n total_capital: 500\n") + p = load_active_portfolio(cfg) + assert p.code == "PORT06" + assert p.leverage == 2.0 + assert p.total_capital == 500