Make strategy whitelist configurable

This commit is contained in:
fredmaloggia
2025-11-18 12:58:58 +01:00
parent 86223b0bc9
commit 2201ed9d5b
2 changed files with 48 additions and 47 deletions

View File

@@ -31,5 +31,11 @@
"base_capital_per_strategy": 100.0,
"min_trade_notional": 0.01,
"risk_parity_lookback": 60
},
"equity_log": {
"strategy_whitelist": [
"Equal_Weight",
"Risk_Parity"
]
}
}

View File

@@ -20,6 +20,13 @@ import pandas as pd
import numpy as np
import os
from shared_utils import (
detect_column,
load_config,
read_connection_txt,
require_section,
)
# =============================================================================
# PATH & OUTPUT
# =============================================================================
@@ -38,53 +45,35 @@ SP_NAME_DEFAULT = "opt_RendimentoGiornaliero1_ALL"
SP_N_DEFAULT = 1305
PTF_CURR_DEFAULT = "EUR"
# prova a leggere il file di configurazione condiviso; se manca si usano i default
CONFIG = None
try:
CONFIG = load_config()
DB_CONFIG = require_section(CONFIG, "db")
except Exception as exc: # pragma: no cover - best effort
print(f"[WARN] Config non disponibile ({exc}); uso i default interni.")
DB_CONFIG = {}
else:
SP_NAME_DEFAULT = str(DB_CONFIG.get("stored_proc", SP_NAME_DEFAULT))
SP_N_DEFAULT = int(DB_CONFIG.get("n_bars", SP_N_DEFAULT))
PTF_CURR_DEFAULT = str(DB_CONFIG.get("ptf_curr", PTF_CURR_DEFAULT))
# Strategie valide (tutto il resto viene ignorato)
VALID_STRATEGIES = ["Equal_Weight", "Risk_Parity"]
# "Aggressiva_Crypto" è stata rimossa perché non deve più essere processata
DEFAULT_STRATEGIES = ["Equal_Weight", "Risk_Parity"]
VALID_STRATEGIES = DEFAULT_STRATEGIES
# =============================================================================
# CONNESSIONE DB
# =============================================================================
def read_connection_txt(path: Path) -> str:
import pyodbc
params = {}
for line in path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or "=" not in line or line.startswith("#"):
continue
k, v = line.split("=", 1)
params[k.strip().lower()] = v.strip()
try: # opzionale: sezione dedicata nel config per personalizzare la whitelist
EQUITY_CFG = CONFIG.get("equity_log", {}) if CONFIG else {}
except NameError: # pragma: no cover - CONFIG non definito se load_config fallisce
EQUITY_CFG = {}
username = params.get("username")
password = params.get("password")
host = params.get("host")
port = params.get("port", "1433")
database = params.get("database")
if not all([username, password, host, database]):
raise ValueError("connection.txt incompleto: servono username/password/host/database.")
installed = [d for d in pyodbc.drivers()]
driver_q = (
"ODBC+Driver+18+for+SQL+Server"
if "ODBC Driver 18 for SQL Server" in installed
else "ODBC+Driver+17+for+SQL+Server"
)
return f"mssql+pyodbc://{username}:{password}@{host}:{port}/{database}?driver={driver_q}"
# =============================================================================
# UTILS
# =============================================================================
def _pick(df: pd.DataFrame, candidates):
low = {c.lower(): c for c in df.columns}
for c in candidates:
if c.lower() in low:
return low[c.lower()]
for col in df.columns:
lc = col.lower()
if any(tok.lower() in lc for tok in candidates):
return col
return None
if EQUITY_CFG:
raw_whitelist = EQUITY_CFG.get("strategy_whitelist")
if raw_whitelist:
whitelist = [str(x).strip() for x in raw_whitelist if str(x).strip()]
if whitelist:
VALID_STRATEGIES = whitelist
# =============================================================================
# FETCH RENDIMENTI DAL DB
@@ -113,9 +102,9 @@ def fetch_returns_from_db(isins, start_date, end_date) -> pd.DataFrame:
if df.empty:
continue
col_date = _pick(df, ["Date", "Data", "Datetime", "Timestamp", "Time"])
col_ret = _pick(df, ["Ret", "Return", "Rendimento", "Rend", "Ret_%", "RET"])
col_px = _pick(df, ["Close", "AdjClose", "Price", "Px", "Last", "Prezzo", "Chiusura"])
col_date = detect_column(df, ["Date", "Data", "Datetime", "Timestamp", "Time"])
col_ret = detect_column(df, ["Ret", "Return", "Rendimento", "Rend", "Ret_%", "RET"])
col_px = detect_column(df, ["Close", "AdjClose", "Price", "Px", "Last", "Prezzo", "Chiusura"])
if not col_date:
continue
@@ -270,7 +259,13 @@ def main():
# === filtro whitelist: solo strategie volute ===
audit["Strategy"] = audit["Strategy"].astype(str)
before = len(audit)
audit = audit[audit["Strategy"].isin(VALID_STRATEGIES)]
removed = before - len(audit)
if removed > 0:
print(
f"[INFO] Filtrate {removed} righe con strategie non incluse in {VALID_STRATEGIES}."
)
if audit.empty:
raise SystemExit(f"Nessuna riga con strategie in {VALID_STRATEGIES} nell'audit log.")