from reportlab.platypus import SimpleDocTemplate,Paragraph,Spacer,Table,TableStyle,KeepTogether
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet,ParagraphStyle
from reportlab.lib.enums import TA_LEFT
from reportlab.lib.units import cm
from pathlib import Path
import json
p=Path(__file__).resolve().parent
styles=getSampleStyleSheet();styles.add(ParagraphStyle(name='TitleX',parent=styles['Title'],fontSize=22,leading=27,textColor=colors.HexColor('#10243d'),spaceAfter=18));styles.add(ParagraphStyle(name='BodyX',parent=styles['BodyText'],fontSize=10.2,leading=15,spaceAfter=10));styles.add(ParagraphStyle(name='HeadX',parent=styles['Heading2'],textColor=colors.HexColor('#156a73'),spaceBefore=14,spaceAfter=8))
doc=SimpleDocTemplate(str(p/'Informe_Metodologico.pdf'),pagesize=(595,842),leftMargin=50,rightMargin=50,topMargin=55,bottomMargin=55)
s=[]
def a(t,sty='BodyX'):s.append(Paragraph(t,styles[sty]))
a('Financial Risk Lab','TitleX');a('Informe técnico | Nahuel Iván López | Proyecto 03')
a('Objetivo','HeadX');a('Evaluar históricamente la rentabilidad y el riesgo de una cartera diversificada de ETF estadounidenses, frente a SPY. El análisis es descriptivo y retrospectivo; no pretende anticipar retornos futuros.')
a('Universo y fuente','HeadX');a('SPY (40%), QQQ (20%), IEF (25%) y GLD (15%). Cotizaciones diarias ajustadas por eventos corporativos obtenidas con yfinance/Yahoo Finance, desde enero de 2019 hasta el 8 de octubre de 2026, sujetas a disponibilidad. La comparación utiliza fechas comunes y excluye observaciones incompletas.')
a('Construcción del backtest','HeadX');a('Capital inicial normalizado a 100. Se calculan retornos simples diarios. Los pesos evolucionan con el rendimiento de cada ETF y se rebalancean al cierre de mes. Se descuenta un costo supuesto de 5 puntos básicos por dólar negociado. SPY se mantiene como benchmark buy-and-hold. No se modelan impuestos, spreads observados, slippage ni efectos cambiarios.')
a('Indicadores','HeadX');a('Retorno anualizado geométrico: (valor final / inicial)^(252 / sesiones) - 1. Volatilidad anualizada: desviación estándar muestral de retornos diarios multiplicada por raíz de 252. Máximo drawdown: mínima caída relativa respecto del máximo previo. VaR histórico al 95%: negativo del percentil 5 de retornos diarios. CVaR al 95%: pérdida media en retornos iguales o inferiores a ese percentil. Sharpe aproximado sin tasa libre de riesgo: media diaria por 252 dividida por volatilidad anualizada.')
a('Interpretación y límites','HeadX');a('VaR no es la peor pérdida posible y depende de la distribución histórica observada. CVaR resume la cola histórica, pero no cubre eventos futuros desconocidos. Una cartera de menor volatilidad no necesariamente maximiza retornos. El ETF IEF tiene riesgo de duración y de tasa de interés; no es un activo libre de riesgo. El desempeño pasado no garantiza resultados futuros.')
f=p/'resultados.json'
if f.exists():
 j=json.loads(f.read_text());a('Resultados calculados','HeadX');a('Ventana observada: '+j['periodo_inicio']+' a '+j['periodo_fin']+'.')
 data=[['Indicador','Cartera','SPY']]
 for key,label in [('rendimiento_anualizado','Rentabilidad anualizada'),('volatilidad_anualizada','Volatilidad anualizada'),('max_drawdown','Máximo drawdown'),('var_95_diario','VaR 95% diario'),('cvar_95_diario','CVaR 95% diario')]:data.append([label,f"{j['cartera'][key]*100:.2f}%",f"{j['benchmark_spy'][key]*100:.2f}%"])
 t=Table(data,colWidths=[235,115,115]);t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,0),colors.HexColor('#d9f0ef')),('GRID',(0,0),(-1,-1),.3,colors.grey),('PADDING',(0,0),(-1,-1),8)]));s.append(t)
else:
 a('Estado de resultados','HeadX');a('El entorno no permitió obtener las cotizaciones reales. No se incluyen cifras no verificadas. Al ejecutar analisis.py con conexión a Internet se generan los CSV, resultados.json y las visualizaciones. Después ejecutar make_report.py para insertar métricas calculadas en este informe.')
a('Reproducibilidad','HeadX');a('Instalar requirements.txt, ejecutar python analisis.py y luego python make_report.py. Archivos de salida: precios_ajustados.csv, evolucion.csv, drawdown.csv, resultados.json. La fecha final efectiva depende de la última sesión de mercado disponible.')
a('Fuente: https://finance.yahoo.com/ | Código: analisis.py | Uso educativo y de portfolio.')
doc.build(s)
