#!/usr/bin/env python3 """ Leverage Decay Study — reproducibility script AEA Capital Research · Aydin Ali Recomputes every number in /research/leverage-decay.html from a CSV of daily adjusted closes. DATA SOURCE ----------- Daily adjusted closes were pulled from Massive Market Data (the same market-data provider cited across the AEA site) for the trailing ~12 months and stored, then aggregated with SQL. This script reproduces the identical arithmetic from a flat CSV so the analysis is auditable without an API key. INPUT ----- A CSV with columns: date,ticker,close (date = ISO or any pandas-parseable date; close = adjusted close) PAIRS (etf : underlying : stated daily leverage) ------------------------------------------------ NBIL:NBIS:2 TSLL:TSLA:2 NVDL:NVDA:2 AAPU:AAPL:2 MSFU:MSFT:2 TQQQ:QQQ:3 SOXL:SOXX:3 METHOD ------ For each pair, over the pair's common date window: und_ret = und_last / und_first - 1 target = leverage * und_ret etf_ret = etf_last / etf_first - 1 decay_gap = (etf_ret - target) # in return space und_vol = std(daily log returns) * sqrt(252) # annualized NBIL began trading in Oct 2025, so the NBIL/NBIS pair is measured over NBIL's shorter common window; every other pair spans the full ~12 months. USAGE ----- python leverage_decay.py closes.csv """ import sys import numpy as np import pandas as pd PAIRS = [ ("NBIL", "NBIS", 2), ("TSLL", "TSLA", 2), ("NVDL", "NVDA", 2), ("AAPU", "AAPL", 2), ("MSFU", "MSFT", 2), ("TQQQ", "QQQ", 3), ("SOXL", "SOXX", 3), ] def load(path): df = pd.read_csv(path, parse_dates=["date"]) df = df.sort_values("date") return df.pivot(index="date", columns="ticker", values="close") def annualized_vol(series): lr = np.log(series / series.shift(1)).dropna() return lr.std(ddof=0) * np.sqrt(252) * 100 def analyze(px): rows = [] for etf, und, lev in PAIRS: common = px[[etf, und]].dropna() if len(common) < 2: continue e, u = common[etf], common[und] und_ret = (u.iloc[-1] / u.iloc[0] - 1) * 100 etf_ret = (e.iloc[-1] / e.iloc[0] - 1) * 100 target = lev * und_ret rows.append({ "etf": etf, "lev": f"{lev}x", "underlying": und, "und_ret_%": round(und_ret, 2), "target_%": round(target, 2), "etf_ret_%": round(etf_ret, 2), "decay_gap_pp": round(etf_ret - target, 2), "und_ann_vol_%": round(annualized_vol(u), 1), "days": len(common), }) return pd.DataFrame(rows) if __name__ == "__main__": if len(sys.argv) != 2: print(__doc__) sys.exit(1) result = analyze(load(sys.argv[1])) pd.set_option("display.width", 160) print(result.to_string(index=False)) single = result[result["lev"] == "2x"]["decay_gap_pp"].mean() print(f"\nAvg decay gap, 2x single-stock funds: {single:.2f} pp") print(f"Avg decay gap, all {len(result)} funds: {result['decay_gap_pp'].mean():.2f} pp")