Files
All-in-one-Financial-Analysis/atlas-terminal/server/services/backtester.py
T
shawnkim1997 38c56a5a43 feat: deliver multi-asset analytics, OCR exchange selection, and heatmap UX
Add asset-type aware market/overview flows, portfolio OCR reverse-engineering with exchange overrides, and interactive index heatmap features. Update README with recent updates and wire backend/frontend APIs for FX matrix, exchange options, and improved portfolio editing flows.

Made-with: Cursor
2026-03-21 17:08:00 +00:00

48 lines
1.8 KiB
Python

"""Backtesting service for simple strategies."""
from __future__ import annotations
async def run_backtest(
ticker: str,
strategy: str,
start_date: str,
end_date: str,
initial_capital: float = 10000.0,
) -> dict:
"""Run a basic backtest for selected strategy."""
import yfinance as yf
import ta
df = yf.Ticker(ticker.upper()).history(start=start_date, end=end_date)
if df is None or df.empty:
return {"error": "No price data"}
if strategy == "sma_crossover":
df["sma50"] = ta.trend.sma_indicator(df["Close"], 50)
df["sma200"] = ta.trend.sma_indicator(df["Close"], 200)
df["signal"] = (df["sma50"] > df["sma200"]).astype(int)
elif strategy == "rsi_oversold":
df["rsi"] = ta.momentum.rsi(df["Close"], 14)
df["signal"] = 0
df.loc[df["rsi"] < 30, "signal"] = 1
df.loc[df["rsi"] > 70, "signal"] = 0
else:
df["signal"] = 1
df["returns"] = df["Close"].pct_change().fillna(0)
df["strategy_returns"] = (df["returns"] * df["signal"].shift(1)).fillna(0)
cumulative = (1 + df["strategy_returns"]).cumprod()
benchmark = (1 + df["returns"]).cumprod()
return {
"total_return_pct": round((float(cumulative.iloc[-1]) - 1) * 100, 2),
"benchmark_return_pct": round((float(benchmark.iloc[-1]) - 1) * 100, 2),
"alpha": round((float(cumulative.iloc[-1]) - float(benchmark.iloc[-1])) * 100, 2),
"max_drawdown_pct": round(float(((cumulative / cumulative.cummax()) - 1).min()) * 100, 2),
"sharpe_ratio": round(float(df["strategy_returns"].mean() / (df["strategy_returns"].std() + 1e-10) * (252 ** 0.5)), 2),
"equity_curve": [float(x) for x in cumulative.tolist()],
"benchmark_curve": [float(x) for x in benchmark.tolist()],
"dates": df.index.strftime("%Y-%m-%d").tolist(),
}