Compare live vs backtest returns for a symphony¶
"""
Compare live vs backtest returns for a symphony
"""
from composer import ComposerClient
from dotenv import load_dotenv
import os
load_dotenv()
# Initialize client
client = ComposerClient(
api_key=os.getenv("COMPOSER_API_KEY"),
api_secret=os.getenv("COMPOSER_API_SECRET"),
)
all_accounts = client.accounts.list()
first_account = all_accounts.accounts[0]
all_symphonies = client.portfolio.get_symphony_stats_meta(first_account.account_uuid)
first_symphony = all_symphonies.symphonies[0]
# Get live returns
live_returns = client.portfolio.get_symphony_value_history(
first_account.account_uuid, first_symphony.id
)
# Get the date range from live returns
live_dates_list = sorted(live_returns.dates.keys())
start_date = live_dates_list[0]
end_date = live_dates_list[-1]
# Get initial capital from first live return
initial_capital = live_returns.dates[live_dates_list[0]].series
# Get backtest returns with matching date range and capital
backtest_returns = client.user_symphony.backtest_symphony_v2(
first_symphony.id,
start_date=start_date,
end_date=end_date,
capital=initial_capital,
)
# Find the symphony ID in the backtest dvm_capital
symphony_id = first_symphony.id
# Build comparable backtest series (using deposit_adjusted_series equivalent)
backtest_series = {}
if backtest_returns.dvm_capital:
for date, series_dict in backtest_returns.dvm_capital.items():
if symphony_id in series_dict:
backtest_series[date] = series_dict[symphony_id]
# Find overlapping dates
live_dates = set(live_returns.dates.keys())
backtest_dates = set(backtest_series.keys())
overlapping_dates = sorted(live_dates & backtest_dates)
print(f"Live returns: {len(live_returns.dates)} days ({min(live_dates)} to {max(live_dates)})")
print(
f"Backtest returns: {len(backtest_series)} days ({min(backtest_dates)} to {max(backtest_dates)})"
)
print(f"Overlapping dates: {len(overlapping_dates)}")
# Compare overlapping dates
if overlapping_dates:
print("\n--- Deviation Analysis ---")
deviations = []
for date in overlapping_dates:
live_value = live_returns.dates[date].deposit_adjusted_series
backtest_value = backtest_series[date]
if backtest_value > 0:
deviation_pct = ((live_value - backtest_value) / backtest_value) * 100
else:
deviation_pct = 0
deviations.append(
{
"date": date,
"live": live_value,
"backtest": backtest_value,
"deviation_pct": deviation_pct,
}
)
# Summary statistics
avg_deviation = sum(d["deviation_pct"] for d in deviations) / len(deviations)
max_deviation = max(deviations, key=lambda x: abs(x["deviation_pct"]))
# Cumulative difference (% change from first to last)
first_live = deviations[0]["live"]
last_live = deviations[-1]["live"]
first_backtest = deviations[0]["backtest"]
last_backtest = deviations[-1]["backtest"]
live_pct_change = ((last_live - first_live) / first_live) * 100
backtest_pct_change = ((last_backtest - first_backtest) / first_backtest) * 100
cumulative_diff_pct = live_pct_change - backtest_pct_change
print(f"Average deviation: {avg_deviation:.2f}%")
print(f"Live % change: {live_pct_change:+.2f}% (${first_live:,.2f} -> ${last_live:,.2f})")
print(
f"Backtest % change: {backtest_pct_change:+.2f}% (${first_backtest:,.2f} -> ${last_backtest:,.2f})"
)
print(f"Cumulative difference: {cumulative_diff_pct:+.2f}%")
print(f"Max deviation: {max_deviation['deviation_pct']:.2f}% on {max_deviation['date']}")
print(f" Live: ${max_deviation['live']:,.2f}, Backtest: ${max_deviation['backtest']:,.2f}")
# Show first few comparisons
print("\nFirst 5 comparisons:")
for d in deviations[:5]:
print(
f" {d['date']}: Live=${d['live']:,.2f}, Backtest=${d['backtest']:,.2f}, Deviation={d['deviation_pct']:+.2f}%"
)
else:
print("\nNo overlapping dates found.")
print("Live returns may be from a different period than backtest.")
Output:
Live returns: 5 days (2026-02-09 to 2026-02-13)
Backtest returns: 5 days (2026-02-09 to 2026-02-13)
Overlapping dates: 5
--- Deviation Analysis ---
Average deviation: 0.11%
Live % change: -6.76% ($12,990.00 -> $12,111.55)
Backtest % change: -6.32% ($12,926.46 -> $12,109.49)
Cumulative difference: -0.44%
Max deviation: 0.49% on 2026-02-09
Live: $12,990.00, Backtest: $12,926.46
First 5 comparisons:
2026-02-09: Live=$12,990.00, Backtest=$12,926.46, Deviation=+0.49%
2026-02-10: Live=$12,748.05, Backtest=$12,746.57, Deviation=+0.01%
2026-02-11: Live=$12,842.90, Backtest=$12,841.51, Deviation=+0.01%
2026-02-12: Live=$12,059.14, Backtest=$12,057.03, Deviation=+0.02%
2026-02-13: Live=$12,111.55, Backtest=$12,109.49, Deviation=+0.02%