#!/usr/bin/env python3
"""Reproduce the aligned backtest from market_prices_raw.csv."""
import csv, math
from datetime import date, datetime, timedelta
from collections import defaultdict
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

raw=defaultdict(dict)
with open("market_prices_raw.csv",newline="",encoding="utf-8") as f:
    for r in csv.DictReader(f):
        raw[r["asset"]][date.fromisoformat(r["date"])]=float(r["adjusted_close"])
end=min(max(s) for s in raw.values())
try: start=end.replace(year=end.year-3)
except ValueError: start=end.replace(year=end.year-3,day=28)
calendar=[]; d=start
while d<=end: calendar.append(d); d+=timedelta(days=1)
aligned={}
for asset,s in raw.items():
    vals=[]; prev=None
    for d in calendar:
        if d in s: prev=s[d]
        if prev is None:
            prior=[x for x in s if x<=d]
            prev=s[max(prior)]
        vals.append(prev)
    aligned[asset]=vals
metrics=[]
for asset,vals in aligned.items():
    a=np.asarray(vals,float); ret=a[1:]/a[:-1]-1
    wealth=a/a[0]; peaks=np.maximum.accumulate(wealth)
    years=(end-start).days/365.2425
    metrics.append({
      "asset":asset,"total_return":a[-1]/a[0]-1,
      "cagr":(a[-1]/a[0])**(1/years)-1,
      "annualized_volatility":np.std(ret,ddof=1)*np.sqrt(365),
      "max_drawdown":np.min(wealth/peaks-1)})
with open("reproduced_metrics.csv","w",newline="",encoding="utf-8") as f:
    w=csv.DictWriter(f,fieldnames=list(metrics[0])); w.writeheader(); w.writerows(metrics)
colors={"NVIDIA":"#0072B2","Bitcoin":"#E69F00","Gold (spot)":"#CC79A7","S&P 500 (SPY)":"#009E73"}
dates=[datetime.combine(d,datetime.min.time()) for d in calendar]
fig,ax=plt.subplots(figsize=(10,5.5))
for asset,vals in aligned.items():
    ax.plot(dates,100*np.asarray(vals)/vals[0],label=asset,color=colors[asset])
ax.set(title="Three-year growth of 100",ylabel="Growth of 100")
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=6))
ax.legend(frameon=False); fig.tight_layout()
fig.savefig("reproduced_curves.png",dpi=200)
