Skip to content

TRADELYBOX/backtest_api

Repository files navigation

TRADELYBOX — Backtest API

A drag-and-drop forex strategy backtesting engine built with FastAPI, PostgreSQL, and Cloudflare R2. Design trading strategies as visual block graphs and backtest them on historical OHLCV data — or let the AI Copilot generate strategies from natural language.

Live API: https://tradelybox-api.fly.dev
Docs: https://tradelybox-api.fly.dev/docs


Table of Contents


Features

  • 31 drag-and-drop blocks — indicators (SMA, EMA, RSI, MACD, Bollinger, ATR, Stochastic, ADX), ICT concepts (FVG, order blocks, BOS, CHoCH, liquidity sweeps), price action (engulfing, pin bar), comparators, logic gates, and action blocks (buy, sell, stop loss, take profit, position sizing)
  • Graph-based strategy engine — topological sort + bar-by-bar forex simulator with lots, pips, spread, intra-bar SL/TP, and support for long & short trades
  • 28 performance metrics — total return, Sharpe ratio, max drawdown, win rate, profit factor, consecutive wins/losses, and more
  • AI Copilot — describe a strategy in plain English and get a complete block canvas back (powered by Gemini 2.5 Flash)
  • 15 built-in strategy templates — trend following, mean reversion, ICT, scalping, and more
  • OHLCV data from Cloudflare R2 — monthly CSV files, multiple timeframes (M1 to W1)
  • Results persistence — save, retrieve, and compare backtest results in PostgreSQL

Tech Stack

Component Technology
Framework FastAPI 0.115.0
Database PostgreSQL (Neon)
ORM SQLAlchemy 2.x
Price Data Cloudflare R2 (S3-compatible)
AI Copilot Google Gemini 2.5 Flash
Data Processing Pandas, NumPy
Deployment Fly.io (Docker)
Python 3.10

Prerequisites

  • Python 3.10+
  • PostgreSQL database (or a Neon project)
  • Cloudflare R2 bucket with OHLCV CSV files
  • Google AI API key (for the Copilot feature — get one here)
  • (Optional) Docker & Fly.io CLI for deployment

Environment Variables

Create a .env file in the project root:

# ─── Database ─────────────────────────────────────────────────
DATABASE_URL=postgresql://user:password@host/database

# ─── Cloudflare R2 ────────────────────────────────────────────
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_BUCKET=your-bucket-name
R2_ACCESS_KEY_ID=your-r2-access-key
R2_SECRET_ACCESS_KEY=your-r2-secret-key

# ─── AI Copilot ───────────────────────────────────────────────
GEMINI_API_KEY=your-gemini-api-key

# ─── Optional ─────────────────────────────────────────────────
ENV=development          # "development" enables hot reload
PORT=8000                # local port (Docker uses 8080)

R2 File Structure

OHLCV data must be stored as monthly CSV files in R2 with this naming convention:

<symbol>_<timeframe>_<YYYY-MM>.csv

Examples: eurusd_d1_2024-08.csv, gbpusd_h1_2025-01.csv

Each CSV must have columns: timestamp (Unix ms), open, high, low, close, volume.


Local Development

# 1. Clone the repo
git clone git@github.com:TRADELYBOX/backtest_api.git
cd backtest_api

# 2. Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Set up environment variables
cp .env.example .env    # then fill in your values

# 5. Start the server
python main.py

The API will be available at http://localhost:8000 with interactive docs at /docs.


Docker

# Build the image
docker build -t tradelybox-api .

# Run the container
docker run -p 8080:8080 --env-file .env tradelybox-api

The Dockerfile uses python:3.10-slim, installs system deps (gcc, libpq-dev), and runs uvicorn on port 8080.


Deployment (Fly.io)

# 1. Install the Fly CLI
curl -L https://fly.io/install.sh | sh

# 2. Login
fly auth login

# 3. Launch (first time only — creates the app)
fly launch

# 4. Set secrets (environment variables)
fly secrets set DATABASE_URL="postgresql://..."
fly secrets set R2_ENDPOINT="https://..."
fly secrets set R2_BUCKET="your-bucket"
fly secrets set R2_ACCESS_KEY_ID="..."
fly secrets set R2_SECRET_ACCESS_KEY="..."
fly secrets set GEMINI_API_KEY="..."

# 5. Deploy
fly deploy

# 6. Check status
fly status
fly logs

Current config (fly.toml): app tradelybox-api, region cdg (Paris), 1 GB RAM, auto-stop enabled.


API Endpoints

Blocks — /api/blocks

Method Path Description
GET /api/blocks List all available block types (flat)
GET /api/blocks/categories List blocks grouped by category
POST /api/blocks/seed Seed/reset the block catalog (31 blocks)

Strategies — /api/strategies

Method Path Description
GET /api/strategies List strategies (filter by user_id, is_template, category)
POST /api/strategies Create a new strategy from canvas data
PUT /api/strategies/{id} Update a strategy
GET /api/strategies/{id}/canvas Get canvas data formatted for React Flow
POST /api/strategies/{id}/backtest Backtest a saved strategy

Backtests — /api/backtests

Method Path Description
POST /api/backtests/run Run a backtest with raw nodes + edges from canvas

Results — /api/results

Method Path Description
GET /api/results List results (filter by strategy_id, status)
GET /api/results/{id} Get full result with trades
GET /api/results/{id}/trades Get just the trade list
GET /api/results/{id}/equity Get just the equity curve
DELETE /api/results/{id} Delete a result

Prices — /api/prices

Method Path Description
GET /api/prices/ohlcv Fetch OHLCV data from R2
GET /api/prices/available-symbols List symbols available in R2
GET /api/prices/timeframes/{symbol} List timeframes for a symbol
GET /api/prices/date-range/{symbol}/{timeframe} Get available date range

Copilot — /api/copilot

Method Path Description
POST /api/copilot/generate Generate a strategy canvas from a natural-language prompt

Health

Method Path Description
GET /health Health check
GET /docs Swagger UI
GET /redoc ReDoc

Block Types

Data Blocks

Block Params Description
price field: close/open/high/low/volume Outputs a price series
constant value: number Outputs a constant value series

Indicator Blocks

Block Key Params Description
sma period Simple Moving Average
ema period Exponential Moving Average
rsi period Relative Strength Index
macd fast, slow, signal MACD (line, signal, histogram)
bollinger period, std_dev Bollinger Bands (upper, middle, lower)
atr period Average True Range
stochastic k_period, d_period Stochastic Oscillator (%K, %D)
adx period Average Directional Index

ICT / Smart Money Blocks

Block Key Params Description
fvg min_gap_pips Fair Value Gap detection
orderBlock lookback Order Block detection
bos lookback Break of Structure
choch lookback Change of Character
liquiditySweep lookback Liquidity Sweep detection
premiumDiscount lookback Premium/Discount zones
swingHighLow lookback Swing High/Low detection

Price Action Blocks

Block Params Description
engulfing Engulfing candle
pinBar Pin bar / hammer

Comparator Blocks

Block Params Description
greaterThan threshold A > B (or A > threshold)
lessThan threshold A < B (or A < threshold)
crossAbove threshold A crosses above B (or threshold)
crossBelow threshold A crosses below B (or threshold)

Logic Blocks

Block Description
and Logical AND of signals
or Logical OR of signals
not Invert a signal

Action Blocks

Block Params Description
buy Open a long trade on signal
sell Open a short trade on signal
stopLoss pips or price Set stop loss (pips or fixed price)
takeProfit pips or price Set take profit (pips or fixed price)
positionSize lots Set position size in lots

Note: Indicator blocks are self-contained — they auto-read the close price from OHLCV when no input is wired.


Database Seeding

Seed Blocks

Populates the block_templates table with all 31 block definitions:

# Via API
curl -X POST https://tradelybox-api.fly.dev/api/blocks/seed

# Or locally
curl -X POST http://localhost:8000/api/blocks/seed

Seed Strategy Templates

Populates the strategies table with 15 built-in templates:

python scripts/seed_templates.py

Make sure DATABASE_URL is set in your .env before running.


Example Requests

1. Run a Backtest (raw canvas)

curl -X POST https://tradelybox-api.fly.dev/api/backtests/run \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "rsi-1",
        "type": "indicator",
        "data": { "block_type": "rsi", "params": { "period": 14 } },
        "position": { "x": 100, "y": 100 }
      },
      {
        "id": "const-30",
        "type": "data_source",
        "data": { "block_type": "constant", "params": { "value": 30 } },
        "position": { "x": 100, "y": 250 }
      },
      {
        "id": "cross-1",
        "type": "comparator",
        "data": { "block_type": "crossAbove", "params": {} },
        "position": { "x": 350, "y": 175 }
      },
      {
        "id": "buy-1",
        "type": "action",
        "data": { "block_type": "buy", "params": {} },
        "position": { "x": 600, "y": 175 }
      }
    ],
    "edges": [
      { "id": "e1", "source": "rsi-1", "target": "cross-1", "sourceHandle": "rsi", "targetHandle": "a" },
      { "id": "e2", "source": "const-30", "target": "cross-1", "sourceHandle": "series", "targetHandle": "b" },
      { "id": "e3", "source": "cross-1", "target": "buy-1", "sourceHandle": "result", "targetHandle": "signal" }
    ],
    "symbol": "EURUSD",
    "timeframe": "d1",
    "start_date": "2024-08-01",
    "end_date": "2025-06-30",
    "initial_capital": 10000,
    "spread_pips": 1.0,
    "default_lot_size": 0.1,
    "max_open_trades": 3
  }'

2. Save a Strategy

curl -X POST https://tradelybox-api.fly.dev/api/strategies \
  -H "Content-Type: application/json" \
  -d '{
    "name": "RSI Oversold Bounce",
    "symbol": "EURUSD",
    "timeframe": "h1",
    "user_id": 1,
    "canvas_data": {
      "blocks": [
        { "id": "rsi-1", "type": "indicator", "position": { "x": 100, "y": 100 }, "data": { "block_type": "rsi", "params": { "period": 14 } } },
        { "id": "const-1", "type": "data_source", "position": { "x": 100, "y": 250 }, "data": { "block_type": "constant", "params": { "value": 30 } } },
        { "id": "cross-1", "type": "comparator", "position": { "x": 350, "y": 175 }, "data": { "block_type": "crossAbove", "params": {} } },
        { "id": "buy-1", "type": "action", "position": { "x": 600, "y": 175 }, "data": { "block_type": "buy", "params": {} } }
      ],
      "connections": [
        { "id": "e1", "source": "rsi-1", "target": "cross-1", "sourceHandle": "rsi", "targetHandle": "a" },
        { "id": "e2", "source": "const-1", "target": "cross-1", "sourceHandle": "series", "targetHandle": "b" },
        { "id": "e3", "source": "cross-1", "target": "buy-1", "sourceHandle": "result", "targetHandle": "signal" }
      ]
    }
  }'

3. Backtest a Saved Strategy

curl -X POST https://tradelybox-api.fly.dev/api/strategies/1/backtest \
  -H "Content-Type: application/json" \
  -d '{
    "start_date": "2024-08-01",
    "end_date": "2025-06-30",
    "initial_capital": 10000,
    "spread_pips": 1.5,
    "default_lot_size": 0.1,
    "max_open_trades": 1
  }'

4. AI Copilot — Generate a Strategy

curl -X POST https://tradelybox-api.fly.dev/api/copilot/generate \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Buy when RSI crosses above 30 with a 50 pip stop loss and 100 pip take profit",
    "symbol": "EURUSD",
    "timeframe": "h1"
  }'

5. Fetch OHLCV Data

curl "https://tradelybox-api.fly.dev/api/prices/ohlcv?symbol=EURUSD&timeframe=d1&start_date=2024-08-01&end_date=2024-12-31"

Project Structure

backtest_api/
├── main.py                          # FastAPI app entry point
├── requirements.txt                 # Python dependencies
├── Dockerfile                       # Docker image (python:3.10-slim)
├── fly.toml                         # Fly.io deployment config
├── .env                             # Environment variables (not committed)
│
├── app/
│   ├── database.py                  # SQLAlchemy engine & session
│   │
│   ├── models/                      # SQLAlchemy ORM models
│   │   ├── blocks.py                # BlockTemplate (block catalog)
│   │   ├── strategies.py            # Strategy (user strategies + templates)
│   │   ├── results.py               # BacktestResult (saved results)
│   │   └── user.py                  # User model (placeholder)
│   │
│   ├── schemas/                     # Pydantic request/response schemas
│   │   ├── backtests.py             # BacktestRequest, BacktestResponse, metrics
│   │   ├── blocks.py                # Block schemas
│   │   ├── strategies.py            # StrategyCreate, CanvasData, StrategyBacktestRequest
│   │   └── strategy_templates.py    # Template schemas
│   │
│   ├── routers/                     # API route handlers
│   │   ├── blocks.py                # /api/blocks — seed & list blocks
│   │   ├── strategies.py            # /api/strategies — CRUD, canvas, backtest
│   │   ├── backtests.py             # /api/backtests — run raw backtests
│   │   ├── results.py               # /api/results — result persistence
│   │   ├── prices.py                # /api/prices — OHLCV from R2
│   │   └── copilot.py               # /api/copilot — AI strategy generation
│   │
│   └── functions/                   # Core business logic
│       ├── block_registry.py        # 31 block execution functions
│       ├── default_blocks.py        # Block catalog definitions (for seeding)
│       └── engine.py                # StrategyEngine (graph) + ForexSimulator
│
└── scripts/
    ├── seed_blocks.py               # Seed block catalog
    ├── seed_templates.py            # Seed 15 strategy templates
    └── cleanup_database.py          # DB cleanup utilities

Backtest Metrics Reference

Every backtest response includes these 28 metrics:

Metric Description
total_return Absolute P&L in account currency
total_return_pct Percentage return
sharpe_ratio Risk-adjusted return
max_drawdown Max peak-to-trough drawdown ($)
max_drawdown_pct Max drawdown as percentage
win_rate % of winning trades
total_trades Total closed trades
winning_trades Number of winners
losing_trades Number of losers
profit_factor Gross profit / gross loss
avg_trade_pnl Average trade P&L ($)
avg_trade_pips Average trade P&L (pips)
best_trade Best single trade ($)
worst_trade Worst single trade ($)
avg_win Average winning trade ($)
avg_loss Average losing trade ($)
max_consecutive_wins Longest winning streak
max_consecutive_losses Longest losing streak
long_trades Number of long trades
short_trades Number of short trades
long_win_rate Win rate for longs
short_win_rate Win rate for shorts
sl_exits Trades closed by stop loss
tp_exits Trades closed by take profit
signal_exits Trades closed by opposing signal
initial_capital Starting capital
final_equity Ending equity

License

Private — TRADELYBOX © 2025

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors