Backtest Trading Strategies with AI Assistance
Run and customize 85+ trading strategy backtests with your AI. Clone the open-source framework, modify strategies with natural language, or run on cloud compute via the Projects API.
This guide covers running and building trading strategy backtests with AI assistance. We provide an open-source framework with 85+ strategies. Your AI can run them as-is, customize parameters, or build entirely new strategies from scratch.
Two ways to execute:
- Local: Clone the repo and run on your machine
- Cloud: Use the Projects API to run on managed infrastructure
Both use the same framework and the same AI workflow.
Prerequisites
- A Trading Studio API key (tradingstudio.finance, Settings, API Keys)
- Python 3.9+
- A CLI-based AI tool: Claude Code, Cursor, Windsurf, or similar
Quick start: run an existing strategy
git clone https://github.com/ceta-research/backtests
cd backtests
pip install -r requirements.txt
export TS_API_KEY="ts_your_key_here"
python low-pe/backtest.py --exchange NYSE,NASDAQ
This runs a Low P/E value strategy on US stocks from 2000 to present. The framework fetches data from the API, generates buy/sell signals, simulates trades with transaction costs, and prints performance metrics (CAGR, Sharpe, max drawdown, Calmar ratio, and more).
Every strategy supports the same CLI flags:
# Run on specific exchanges
python qarp/backtest.py --exchange BSE,NSE
# Use a preset (india, us, europe, global)
python piotroski/backtest.py --preset india
# Change rebalancing frequency
python low-pe/backtest.py --preset us --frequency monthly
# Disable transaction costs for comparison
python low-pe/backtest.py --preset us --no-costs
# Save results to JSON
python low-pe/backtest.py --preset us --output results.json
What the framework provides
The backtests repo includes shared infrastructure and ready-to-run strategies.
Shared modules:
| File | Purpose |
|---|---|
cr_client.py |
API client. Handles submit, poll, presigned URL download. |
metrics.py |
25+ metrics: CAGR, Sharpe, Sortino, Calmar, VaR, CVaR, alpha, beta, up/down capture |
costs.py |
Transaction cost models (size-tiered by market cap, flat rate) |
data_utils.py |
Price lookups, rebalance date generation, data loading |
cli_utils.py |
CLI argument parsing, exchange presets, regional risk-free rates |
Example strategies: Low P/E, QARP, Piotroski F-Score, Magic Formula, Dividend Growth, GARP, and many more.
Each strategy directory contains:
backtest.py- full historical backtestscreen.py- current stock screener (what would the strategy buy today)README.md- strategy documentationresults/- pre-computed results as JSON
Customize strategies with AI
Tell your AI to read the strategy code and modify it. CLI tools like Claude Code, Cursor, and Windsurf can read the framework files directly and understand the structure.
Change signal criteria:
"Read low-pe/backtest.py. Change the P/E filter from < 15 to < 12 and add a ROE > 15% requirement."Switch universes:
"Run the QARP strategy on Indian stocks instead of US. Use --preset india."Add new filters:
"Modify piotroski/backtest.py to exclude financial sector stocks."Compare parameter variations:
"Run the Low P/E strategy three times: top 10, top 20, and top 30 holdings. Save each result and show me a comparison table."
The AI reads the code, makes the changes, runs the backtest, and shows results. If a query fails or results look wrong, it can debug by inspecting intermediate data.
Build a new strategy from scratch
Every strategy follows the same pattern. Give your AI this context:
I'm building a new backtesting strategy using the ceta-research/backtests framework.
Framework files I have:
- cr_client.py: CetaResearch().query(sql) handles API authentication and polling
- metrics.py: compute_metrics(period_returns, benchmark_returns, periods_per_year) returns 25+ metrics
- costs.py: tiered_cost(market_cap) returns one-way cost by size; apply_costs(return, entry_cost, exit_cost)
- data_utils.py: get_prices(con, symbols, date), generate_rebalance_dates(start, end, frequency)
- cli_utils.py: add_common_args(parser) adds --exchange, --preset, --frequency, etc.
Data source: Trading Studio API (FMP financial data in DuckDB).
Tables: fmp.financial_ratios_ttm, fmp.key_metrics_ttm, fmp.stock_eod, fmp.profile, fmp.company_screener
Strategy pattern:
1. Parse CLI args
2. Fetch data via cr_client, load into local DuckDB
3. Generate rebalance dates (monthly/quarterly)
4. On each rebalance: screen stocks, rank, pick top N
5. Get entry/exit prices, calculate period returns with costs
6. Compute metrics vs benchmark (equal-weight universe)
My strategy: [describe your strategy]
The AI generates a complete backtest.py following the established pattern. It can also create a screen.py and README.md for the strategy.
Run on cloud compute
For larger backtests (multi-exchange, long history, parameter sweeps), run on Trading Studio infrastructure instead of locally.
Option A: Run from GitHub
The fastest path. Point the API at a public repo and specify which file to run:
import os
import requests
import time
API_KEY = os.environ["TS_API_KEY"]
BASE = "https://tradingstudio.finance/api/v1"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
# Submit
resp = requests.post(f"{BASE}/code-executions/run-from-repo",
headers=HEADERS,
json={
"repoUrl": "https://github.com/ceta-research/backtests",
"entryPath": "low-pe/backtest.py",
"compute": {
"cpuCount": 2,
"ramMb": 4096,
"timeoutSeconds": 600
}
})
task_id = resp.json()["taskId"]
print(f"Submitted: task {task_id}")
# Poll
while True:
status = requests.get(f"{BASE}/code-executions/{task_id}",
headers=HEADERS).json()
if status["status"] == "completed":
print(status.get("stdout", ""))
break
elif status["status"] == "failed":
print(f"Error: {status.get('errorMessage')}")
break
time.sleep(3)
Option B: Create a project
For strategies you're actively developing. Create a project, upload files, run, tweak, re-run.
import os
import requests
import time
API_KEY = os.environ["TS_API_KEY"]
BASE = "https://tradingstudio.finance/api/v1"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
# Create project
project = requests.post(f"{BASE}/projects",
headers=HEADERS,
json={"name": "My Strategy", "language": "python"}).json()
project_id = project["id"]
# Upload your strategy file
with open("my_strategy.py") as f:
code = f.read()
requests.put(f"{BASE}/projects/{project_id}/files",
headers=HEADERS,
json={"path": "main.py", "content": code})
# Run
run = requests.post(f"{BASE}/projects/{project_id}/run",
headers=HEADERS,
json={
"cpuCount": 2,
"ramMb": 4096,
"timeoutSeconds": 600
})
task_id = run.json()["taskId"]
# Poll for results
while True:
result = requests.get(f"{BASE}/projects/{project_id}/runs/{task_id}",
headers=HEADERS).json()
if result["status"] == "completed":
print(result.get("stdout", ""))
break
elif result["status"] == "failed":
print(f"Error: {result.get('errorMessage')}")
break
time.sleep(3)
Option C: Import from GitHub
Import an entire repo as a project, then modify and re-run:
project = requests.post(f"{BASE}/projects/import-git",
headers=HEADERS,
json={
"url": "https://github.com/ceta-research/backtests",
"name": "My Backtests"
}).json()
The project gets all the framework files. You can then modify individual files and run different strategies.
Validation
Before trusting backtest results, check for common pitfalls:
Same-bar entry bias. If your strategy enters and exits on the same price bar it computed signals from, returns will be inflated. The framework uses next-day close execution by default.
Transaction costs. Always run with costs enabled (the default). The framework applies size-tiered costs: 0.1% for large caps, 0.3% for mid caps, 0.5% for small caps.
Benchmark comparison. Every backtest compares against an equal-weight benchmark of the same universe. A strategy with 12% CAGR sounds good until you see the benchmark returned 11%.
Data coverage. Check that your universe has enough stocks. Ask the AI: "How many stocks passed the filter on each rebalance date? Show me a count over time."
Which guide should I use?
| Guide 1 (SQL) | Guide 2 (API) | Guide 3 (Backtesting) | |
|---|---|---|---|
| Tools | Any AI chatbot | CLI AI tools | CLI AI tools |
| Setup | None | API key + Python | API key + Python + backtests repo |
| What it does | Generate SQL queries | Fetch data programmatically | Run full strategy backtests |
| Best for | Quick lookups, data exploration | Scripting, pipelines, notebooks | Strategy research, signal testing |
Start with Guide 1 for data exploration, Guide 2 for building data pipelines, and this guide when you're ready to test trading strategies.
Resources
- Backtests framework: github.com/ceta-research/backtests
- Methodology: github.com/ceta-research/backtests/blob/main/METHODOLOGY.md