Skip to content

Commit 813119c

Browse files
committed
fixed update portfolio
1 parent dc33d76 commit 813119c

3 files changed

Lines changed: 249 additions & 92 deletions

File tree

run_daily_update_portfolio.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
# run_daily_update_portfolio.py
1+
# run_daily_update_portfolio.py - Ultra Semplificato
22
import logging
33
import os
44
from datetime import datetime
55

6-
from scripts import config
7-
from scripts.portfolio import Portfolio, get_portfolio_names
6+
from scripts.portfolio import get_portfolio_names, Portfolio
87

98
# Setup logging
109
os.makedirs("logs", exist_ok=True)
@@ -30,20 +29,16 @@ def main():
3029
logging.info(f"📊 Aggiornamento portfolio: {name}")
3130

3231
try:
33-
pf = Portfolio(name, today)
34-
35-
# Aggiorna ogni posizione
36-
for pos in pf._positions.values():
37-
pos.current_price = pf._get_current_price(pos.ticker)
38-
pos._save_to_db()
39-
40-
# Aggiorna snapshot
41-
pf._update_snapshot()
32+
# Carica portfolio (ultima data disponibile)
33+
pf = Portfolio(name)
34+
35+
# Una sola riga fa tutto!
36+
pf.update_to_date(today)
4237

4338
logging.info(
4439
f"✅ Portfolio {name} aggiornato: "
45-
f"valore={pf.get_total_value():,.2f}, "
46-
f"cash={pf.get_cash_balance():,.2f}, "
40+
f"valore={pf.get_total_value():,.2f}, "
41+
f"cash={pf.get_cash_balance():,.2f}, "
4742
f"posizioni={pf.get_positions_count()}"
4843
)
4944

@@ -55,4 +50,4 @@ def main():
5550
raise
5651

5752
if __name__ == "__main__":
58-
main()
53+
main()

run_weekly_report.py

Lines changed: 202 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,227 @@
1-
# run_weekly_report.py
1+
# run_weekly_report.py - Versione Semplificata
22
"""
3-
Entry Point: Report Settimanale Portfolio
4-
=========================================
3+
Entry Point: Report Settimanale Portfolio (VERSIONE SEMPLIFICATA)
4+
================================================================
55
6-
Genera report settimanale completo usando il RiskManager refactored.
7-
Schedulato per esecuzione automatica ogni venerdì.
6+
Workflow semplice e diretto:
7+
1. Genera segnali da tutte le strategie disponibili
8+
2. Applica risk management per validare/raffinare i segnali
9+
3. Apre Google Sheet esistente nel drive
10+
4. Pulisce e scrive N+1 fogli:
11+
- 1 foglio per strategia con segnali validati
12+
- 1 foglio con snapshot portfolio della settimana
13+
5. Fine!
814
9-
NUOVO WORKFLOW:
10-
1. Carica portfolio "demo"
11-
2. Genera segnali da tutte le strategie (moving_average, rsi, breakout)
12-
3. Valida segnali con risk manager (position sizing, cash limits, concentration)
13-
4. Scrive Google Sheets organizzati:
14-
- Portfolio_Overview: Metriche aggregate + storico
15-
- Active_Positions: Dettaglio posizioni correnti
16-
- Strategy_*: Segnali per ogni strategia con validazione
17-
- Execution_Summary: Dashboard per decisioni weekend
18-
19-
OUTPUT: Google Sheet aggiornato pronto per review weekend
15+
Niente classi complesse, solo funzioni dirette.
2016
"""
2117

2218
import logging
2319
import os
2420
import sys
25-
from datetime import datetime
26-
27-
# Assicura che la cartella logs/ esista
28-
os.makedirs("logs", exist_ok=True)
21+
from datetime import datetime, timedelta
22+
import pandas as pd
2923

3024
# Setup logging
25+
os.makedirs("logs", exist_ok=True)
3126
logging.basicConfig(
3227
level=logging.INFO,
3328
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
3429
handlers=[
3530
logging.FileHandler("logs/run_weekly_report.log", encoding='utf-8'),
36-
logging.StreamHandler(sys.stdout) # Aggiungi anche output console
31+
logging.StreamHandler(sys.stdout)
3732
]
3833
)
3934

4035
logger = logging.getLogger(__name__)
4136

4237

4338
def main():
44-
"""Entry point principale per generazione report settimanale."""
45-
pass
46-
#start_time = datetime.now()
47-
#logger.info("=" * 60)
48-
#logger.info("🚀 AVVIO GENERAZIONE REPORT SETTIMANALE")
49-
#logger.info("=" * 60)
50-
#logger.info(f"Timestamp: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
51-
#
52-
#try:
53-
# # Import dopo setup logging per catturare eventuali errori di import
54-
# from scripts.reports import generate_weekly_report
55-
#
56-
# # Genera report per portfolio demo
57-
# result = generate_weekly_report(
58-
# portfolio_name="demo",
59-
# date=None # Usa data corrente
60-
# )
61-
#
62-
# if result['success']:
63-
# # SUCCESS
64-
# duration = datetime.now() - start_time
65-
# logger.info("=" * 60)
66-
# logger.info("✅ REPORT GENERATO CON SUCCESSO!")
67-
# logger.info("=" * 60)
68-
# logger.info(f"Portfolio: {result['portfolio_name']}")
69-
# logger.info(f"Data: {result['date']}")
70-
# logger.info(f"Fogli scritti: {', '.join(result['sheets_written'])}")
71-
# logger.info(f"Segnali totali: {result['total_signals']}")
72-
# logger.info(f"Ordini approvati: {result['approved_orders']}")
73-
# logger.info(f"Valore portfolio: €{result['portfolio_summary']['Total_Value']:,.2f}")
74-
# logger.info(f"Cash disponibile: €{result['portfolio_summary']['Cash_Balance']:,.2f}")
75-
# logger.info(f"Posizioni attive: {result['portfolio_summary']['Positions_Count']}")
76-
# logger.info(f"Durata esecuzione: {duration.total_seconds():.1f} secondi")
77-
# logger.info("=" * 60)
78-
# logger.info("📊 REPORT PRONTO PER REVIEW WEEKEND")
79-
# logger.info("=" * 60)
80-
#
81-
# else:
82-
# # ERROR
83-
# logger.error("=" * 60)
84-
# logger.error("❌ ERRORE NELLA GENERAZIONE DEL REPORT")
85-
# logger.error("=" * 60)
86-
# logger.error(f"Errore: {result.get('error', 'Errore sconosciuto')}")
87-
# logger.error("=" * 60)
88-
# raise Exception(f"Report generation failed: {result.get('error')}")
89-
#
90-
#except ImportError as e:
91-
# logger.error(f"❌ Errore import moduli: {e}")
92-
# logger.error("Verificare che tutti i moduli siano disponibili")
93-
# raise
94-
#
95-
#except Exception as e:
96-
# logger.exception(f"❌ Errore critico durante la generazione del report: {e}")
97-
# raise
98-
#
39+
"""Entry point per generazione report settimanale semplificato."""
40+
start_time = datetime.now()
41+
today = start_time.strftime("%Y-%m-%d")
42+
43+
logger.info("=" * 60)
44+
logger.info("🚀 AVVIO REPORT SETTIMANALE SEMPLIFICATO")
45+
logger.info("=" * 60)
46+
47+
try:
48+
# Import dopo logging setup
49+
from scripts import database, portfolio, strategies, risk_manager, google_services
50+
from scripts import config
51+
52+
# 1. CARICA PORTFOLIO
53+
logger.info("📊 Caricamento portfolio 'demo'...")
54+
pf = portfolio.Portfolio("demo", today)
55+
logger.info(f"Portfolio caricato: valore={pf.get_total_value():,.2f}€, cash={pf.get_cash_balance():,.2f}€")
56+
57+
# 2. CARICA DATI UNIVERSE (ultima settimana)
58+
week_ago = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
59+
logger.info(f"📈 Caricamento dati universe dal {week_ago} al {today}...")
60+
df = database.get_universe_data(start_date=week_ago, end_date=today)
61+
logger.info(f"Dati caricati: {len(df)} righe, {df['ticker'].nunique()} ticker")
62+
63+
# 3. GENERA SEGNALI PER OGNI STRATEGIA
64+
strategies_list = [
65+
("Moving_Average", strategies.moving_average_crossover),
66+
("RSI_Strategy", strategies.rsi_strategy),
67+
("Breakout_Strategy", strategies.breakout_strategy)
68+
]
69+
70+
signals_data = {}
71+
for strategy_name, strategy_fn in strategies_list:
72+
logger.info(f"🎯 Generazione segnali: {strategy_name}")
73+
74+
# Genera e raffina segnali
75+
signals = risk_manager.generate_signals(strategy_fn, df, today, pf)
76+
77+
# Converti in DataFrame per Google Sheets
78+
signals_df = _convert_signals_to_dataframe(signals, strategy_name)
79+
signals_data[strategy_name] = signals_df
80+
81+
buy_count = len(signals.get("BUY", {}))
82+
sell_count = len(signals.get("SELL", {}))
83+
hold_count = len(signals.get("HOLD", {}))
84+
logger.info(f"Segnali {strategy_name}: BUY={buy_count}, SELL={sell_count}, HOLD={hold_count}")
85+
86+
# 4. GENERA SNAPSHOT PORTFOLIO SETTIMANALE
87+
logger.info("📸 Generazione snapshot portfolio settimanale...")
88+
portfolio_df = _generate_portfolio_snapshots(pf, week_ago, today)
89+
90+
# 5. SCRIVI GOOGLE SHEETS
91+
logger.info("📝 Scrittura Google Sheets...")
92+
sheet_url = _write_to_google_sheets(signals_data, portfolio_df, today)
93+
94+
# SUCCESS
95+
duration = datetime.now() - start_time
96+
logger.info("=" * 60)
97+
logger.info("✅ REPORT GENERATO CON SUCCESSO!")
98+
logger.info("=" * 60)
99+
logger.info(f"Durata: {duration.total_seconds():.1f} secondi")
100+
logger.info(f"Google Sheet: {sheet_url}")
101+
logger.info("📊 REPORT PRONTO PER REVIEW!")
102+
logger.info("=" * 60)
103+
104+
except Exception as e:
105+
logger.exception(f"❌ Errore critico: {e}")
106+
raise
107+
108+
109+
def _convert_signals_to_dataframe(signals: dict, strategy_name: str) -> pd.DataFrame:
110+
"""Converte dict segnali in DataFrame per Google Sheets."""
111+
rows = []
112+
113+
# BUY signals
114+
for ticker, data in signals.get("BUY", {}).items():
115+
rows.append({
116+
"Ticker": ticker,
117+
"Signal": "BUY",
118+
"Strategy": strategy_name,
119+
"Size": data.get("size", 0),
120+
"Price": data.get("price", 0),
121+
"Stop_Loss": data.get("stop", 0),
122+
"Risk_Amount": data.get("risk", 0),
123+
"Notes": f"Size: {data.get('size', 0)} shares"
124+
})
125+
126+
# SELL signals
127+
for ticker, data in signals.get("SELL", {}).items():
128+
rows.append({
129+
"Ticker": ticker,
130+
"Signal": "SELL",
131+
"Strategy": strategy_name,
132+
"Size": data.get("quantity", 0),
133+
"Price": data.get("price", 0),
134+
"Stop_Loss": "",
135+
"Risk_Amount": "",
136+
"Notes": data.get("reason", "Strategy sell")
137+
})
138+
139+
# HOLD signals
140+
for ticker, data in signals.get("HOLD", {}).items():
141+
rows.append({
142+
"Ticker": ticker,
143+
"Signal": "HOLD",
144+
"Strategy": strategy_name,
145+
"Size": "",
146+
"Price": "",
147+
"Stop_Loss": "",
148+
"Risk_Amount": "",
149+
"Notes": data.get("reason", "Keep position")
150+
})
151+
152+
return pd.DataFrame(rows)
153+
154+
155+
def _generate_portfolio_snapshots(pf, start_date: str, end_date: str) -> pd.DataFrame:
156+
"""Genera snapshots portfolio per la settimana."""
157+
from scripts import database
158+
159+
# Query snapshot della settimana
160+
query = """
161+
SELECT date, total_value, cash_balance, positions_count,
162+
total_return_pct, max_drawdown_pct, volatility_pct, sharpe_ratio
163+
FROM portfolio_snapshots
164+
WHERE portfolio_name = %s AND date BETWEEN %s AND %s
165+
ORDER BY date
166+
"""
167+
168+
rows, columns = database.execute_query(query, (pf.name, start_date, end_date))
169+
df = pd.DataFrame(rows, columns=columns)
170+
171+
# Converti date in stringhe per Google Sheets
172+
if not df.empty and 'date' in df.columns:
173+
df['date'] = df['date'].astype(str)
174+
175+
return df
176+
177+
178+
def _write_to_google_sheets(signals_data: dict, portfolio_df: pd.DataFrame, date: str) -> str:
179+
"""Scrive tutti i dati su Google Sheets e ritorna URL."""
180+
from scripts import google_services, config
181+
182+
client = google_services.get_gsheet_client()
183+
184+
# Apri/crea spreadsheet per la settimana
185+
sheet_name = f"Weekly_Report_{date}"
186+
187+
try:
188+
# Prova ad aprire sheet esistente nella cartella
189+
# (questo richiede di implementare una funzione per cercare nella cartella)
190+
# Per ora creiamo sempre nuovo sheet
191+
spreadsheet = client.create(sheet_name)
192+
193+
# Sposta nella cartella corretta se definita
194+
if hasattr(config, 'WEEKLY_REPORTS_FOLDER_ID'):
195+
# Codice per spostare il file nella cartella...
196+
pass
197+
198+
except Exception as e:
199+
logger.warning(f"Creazione nuovo sheet fallita: {e}")
200+
# Fallback: usa sheet di test
201+
spreadsheet = client.open_by_key(config.TEST_SHEET_ID)
202+
203+
# Pulisci tutti i worksheet esistenti (tranne il primo)
204+
worksheets = spreadsheet.worksheets()
205+
for ws in worksheets[1:]: # Mantieni il primo
206+
spreadsheet.del_worksheet(ws)
207+
208+
# Rinomina il primo worksheet
209+
main_ws = worksheets[0]
210+
main_ws.update_title("Portfolio_Snapshot")
211+
212+
# Scrivi snapshot portfolio
213+
if not portfolio_df.empty:
214+
main_ws.update([portfolio_df.columns.tolist()] + portfolio_df.values.tolist())
215+
216+
# Crea worksheet per ogni strategia
217+
for strategy_name, signals_df in signals_data.items():
218+
ws = spreadsheet.add_worksheet(title=strategy_name, rows=100, cols=10)
219+
if not signals_df.empty:
220+
ws.update([signals_df.columns.tolist()] + signals_df.values.tolist())
221+
222+
logger.info(f"Google Sheet scritto: {spreadsheet.title}")
223+
return spreadsheet.url
224+
99225

100226
if __name__ == "__main__":
101227
main()

0 commit comments

Comments
 (0)