def write_backtest_csv(result: BacktestResult, path: Path) -> None:
"""Write backtest results to a CSV file."""
with open(path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["=== TRADE LOG ==="])
writer.writerow([
"Date", "Ticker", "Direction", "Shares", "Price",
"Strategy", "Holding Period",
])
for t in result.trades:
writer.writerow([
t.date.isoformat(),
t.ticker,
t.direction.value,
t.shares,
f"{t.price:.2f}",
t.strategy_name,
t.holding_period.value if t.holding_period else "",
])
writer.writerow([])
writer.writerow(["=== SUMMARY ==="])
writer.writerow(["Metric", "Value"])
sv = result.starting_value
total_return = (result.final_value - sv) / sv if sv > 0 else 0
bh_return = (result.buy_and_hold_value - sv) / sv if sv > 0 else 0
writer.writerow(["Starting Value", f"${sv:.2f}"])
writer.writerow(["Final Value", f"${result.final_value:.2f}"])
writer.writerow(["Total Return", f"{total_return:.2%}"])
writer.writerow(["Buy & Hold Value", f"${result.buy_and_hold_value:.2f}"])
writer.writerow(["Buy & Hold Return", f"{bh_return:.2%}"])
writer.writerow(["Total Trades", len(result.trades)])
if result.split_date:
writer.writerow([])
writer.writerow(["=== OUT-OF-SAMPLE SPLIT ==="])
writer.writerow(["Split Date", result.split_date.isoformat()])
writer.writerow(["Train Return", f"{result.train_return:.2%}"])
writer.writerow(["Train B&H Return", f"{result.train_bh_return:.2%}"])
writer.writerow(["Train Trades", len(result.train_trades)])
writer.writerow(["Test Return", f"{result.test_return:.2%}"])
writer.writerow(["Test B&H Return", f"{result.test_bh_return:.2%}"])
writer.writerow(["Test Trades", len(result.test_trades)])