aggiunta produzione csv per QUO
This commit is contained in:
@@ -125,6 +125,26 @@ def validate_returns_frame(df_returns: pd.DataFrame, threshold: float = 0.2):
|
|||||||
cols = ", ".join([f"{c} ({v:.0%})" for c, v in high_na.items()])
|
cols = ", ".join([f"{c} ({v:.0%})" for c, v in high_na.items()])
|
||||||
print(f"[warn] Colonne con >{threshold:.0%} di NaN prima del fill: {cols}")
|
print(f"[warn] Colonne con >{threshold:.0%} di NaN prima del fill: {cols}")
|
||||||
|
|
||||||
|
# ---------------------------------
|
||||||
|
# Utility per mappare Asset Class -> NEO
|
||||||
|
# ---------------------------------
|
||||||
|
def map_neo_asset_class(asset_class: str) -> str:
|
||||||
|
"""Mappa l'Asset Class in un valore compatibile NEO."""
|
||||||
|
if not asset_class:
|
||||||
|
return ""
|
||||||
|
value = asset_class.strip().lower()
|
||||||
|
if "azion" in value:
|
||||||
|
return "Equity"
|
||||||
|
if "obblig" in value:
|
||||||
|
return "Fixed Income"
|
||||||
|
if "immobil" in value:
|
||||||
|
return "Real Estate"
|
||||||
|
if "metalli" in value or "materie" in value:
|
||||||
|
return "Commodities"
|
||||||
|
if "cript" in value or "crypto" in value:
|
||||||
|
return "Crypto"
|
||||||
|
return asset_class
|
||||||
|
|
||||||
# ---------------------------------
|
# ---------------------------------
|
||||||
# Utility per R^2 sull’equity line
|
# Utility per R^2 sull’equity line
|
||||||
# ---------------------------------
|
# ---------------------------------
|
||||||
@@ -346,6 +366,8 @@ except SQLAlchemyError as e:
|
|||||||
# =========================
|
# =========================
|
||||||
template_path = os.path.join(INPUT_DIR, 'Template_Guardian.xls')
|
template_path = os.path.join(INPUT_DIR, 'Template_Guardian.xls')
|
||||||
template_df = pd.read_excel(template_path)
|
template_df = pd.read_excel(template_path)
|
||||||
|
template_neo_path = os.path.join(INPUT_DIR, 'Template NEO.csv')
|
||||||
|
template_neo_df = pd.read_csv(template_neo_path, sep=';', dtype=str).fillna("")
|
||||||
|
|
||||||
file_path = os.path.join(INPUT_DIR, 'Universo per ottimizzatore.xlsx')
|
file_path = os.path.join(INPUT_DIR, 'Universo per ottimizzatore.xlsx')
|
||||||
df = pd.read_excel(
|
df = pd.read_excel(
|
||||||
@@ -402,6 +424,8 @@ riskfree_rate = 0.02
|
|||||||
optimized_weights = pd.DataFrame()
|
optimized_weights = pd.DataFrame()
|
||||||
per_asset_metrics = {}
|
per_asset_metrics = {}
|
||||||
export_rows = []
|
export_rows = []
|
||||||
|
export_rows_neo = []
|
||||||
|
neo_portfolio_name = "VAR6_5Y"
|
||||||
|
|
||||||
for (years, target_vol), name in volatility_targets.items():
|
for (years, target_vol), name in volatility_targets.items():
|
||||||
period_start_date = end_date - pd.DateOffset(years=years)
|
period_start_date = end_date - pd.DateOffset(years=years)
|
||||||
@@ -537,6 +561,33 @@ for (years, target_vol), name in volatility_targets.items():
|
|||||||
output_df = results_full_df.reindex(columns=template_cols)
|
output_df = results_full_df.reindex(columns=template_cols)
|
||||||
export_rows.append(output_df)
|
export_rows.append(output_df)
|
||||||
|
|
||||||
|
# --- File CSV NEO (uno per portafoglio) ---
|
||||||
|
if name == neo_portfolio_name:
|
||||||
|
template_neo_cols = list(template_neo_df.columns)
|
||||||
|
if not template_neo_df.empty:
|
||||||
|
template_neo_defaults = template_neo_df.iloc[0].to_dict()
|
||||||
|
else:
|
||||||
|
template_neo_defaults = {col: "" for col in template_neo_cols}
|
||||||
|
neo_rows = []
|
||||||
|
for isin, weight in weights.items():
|
||||||
|
if weight > 0:
|
||||||
|
row = dict(template_neo_defaults)
|
||||||
|
row['Asset class'] = "Equity"
|
||||||
|
row['InstrumentType'] = row.get('InstrumentType') or "ISIN"
|
||||||
|
row['Instrument'] = isin
|
||||||
|
row['Currency'] = row.get('Currency') or "EUR"
|
||||||
|
row['Side'] = row.get('Side') or "Buy"
|
||||||
|
row['Quantity'] = round(float(weight * 0.95), 4)
|
||||||
|
row['Price'] = ""
|
||||||
|
neo_rows.append(row)
|
||||||
|
|
||||||
|
neo_full_df = pd.DataFrame(neo_rows, columns=template_neo_cols)
|
||||||
|
if neo_full_df.empty:
|
||||||
|
output_neo_df = pd.DataFrame(columns=template_neo_cols)
|
||||||
|
else:
|
||||||
|
output_neo_df = neo_full_df.reindex(columns=template_neo_cols)
|
||||||
|
export_rows_neo.append(output_neo_df)
|
||||||
|
|
||||||
# --- Pie chart asset allocation: salva in Output senza mostrare ---
|
# --- Pie chart asset allocation: salva in Output senza mostrare ---
|
||||||
asset_allocations = {asset: 0 for asset in asset_class_limits}
|
asset_allocations = {asset: 0 for asset in asset_class_limits}
|
||||||
for isin, weight in weights.items():
|
for isin, weight in weights.items():
|
||||||
@@ -689,3 +740,14 @@ with pd.ExcelWriter(combined_path, engine='openpyxl', mode='w') as writer:
|
|||||||
combined_df = template_df.copy()
|
combined_df = template_df.copy()
|
||||||
combined_df.to_excel(writer, sheet_name='Pesi Ottimizzati', index=False)
|
combined_df.to_excel(writer, sheet_name='Pesi Ottimizzati', index=False)
|
||||||
print(f"Pesi ottimizzati salvati in un unico file/sheet: '{combined_path}'.")
|
print(f"Pesi ottimizzati salvati in un unico file/sheet: '{combined_path}'.")
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# EXPORT CSV NEO
|
||||||
|
# =========================
|
||||||
|
neo_combined_path = os.path.join(OUTPUT_DIR, f"{date_tag} Pesi ottimizzati NEO.csv")
|
||||||
|
if export_rows_neo:
|
||||||
|
neo_combined_df = pd.concat(export_rows_neo, ignore_index=True)
|
||||||
|
else:
|
||||||
|
neo_combined_df = pd.DataFrame(columns=template_neo_df.columns)
|
||||||
|
neo_combined_df.to_csv(neo_combined_path, sep=';', index=False)
|
||||||
|
print(f"Pesi ottimizzati NEO salvati in un unico CSV: '{neo_combined_path}'.")
|
||||||
|
|||||||
Reference in New Issue
Block a user