Backtest Strategy
Type:
backtest_strategyβ’ Category:flowβ’ Tags:backtest,trading,strategy,finance,risk,walk-forward,optimization
Descriptionβ
High-performance strategy backtesting with comprehensive statistics
Parametersβ
| Name | Type | Description | Required | Default |
|---|---|---|---|---|
data | string | OHLC data from upstream worker (e.g., {{workers[1].[result]}}) | yes | |
signals | string | Trading signals with time and action (long/short/close) | yes | |
initial_capital | number | Starting capital | no | 10000 |
commission | number | Commission per trade (0.001 = 0.1%) | no | 0.001 |
slippage | number | Slippage (0.0005 = 0.05%) | no | 0.0005 |
time_field | string | Timestamp field name. Supports Unix timestamps (seconds/ms), ISO strings, or datetime objects. | no | "time" |
open_field | string | Open price field name. Used for entry price when signal triggers at bar open. | no | "open" |
high_field | string | High price field name. Used for take profit hit detection - the highest price in each bar determines if TP was triggered. | no | "high" |
low_field | string | Low price field name. Used for stop loss hit detection - the lowest price in each bar determines if SL was triggered. | no | "low" |
close_field | string | Close price field name. Used for position valuation, trailing stop updates, and exits at bar close. | no | "close" |
ai_optimize | boolean | π€ AI Find Best Strategy - Automatically analyze data volatility and test all parameter combinations to find optimal settings. No configuration needed! | no | false |
ai_optimize_target | string | Metric to optimize for | no | "sharpe_ratio" |
ai_sl_tp_type | string | SL/TP calculation type: percent (% of price), fixed (price units/pips), atr (ATR multiples) | no | "percent" |
ai_show_trades_for | number | Show detailed trades for which result (1-N). Change this to see trades for different top results. | no | 1 |
ai_top_results_count | number | How many top results to include in output (1-50). More results = more data to compare. | no | 10 |
position_size_type | string | How to calculate position size | no | "percent" |
position_size | number | Position size value (0.1 = 10% for percent type) | no | 0.1 |
stop_loss_type | string | Stop loss calculation method | no | "percent" |
stop_loss_value | number | Stop loss value (2.0 = 2% for percent type) | no | 2 |
take_profit_type | string | Take profit calculation method | no | "percent" |
take_profit_value | number | Take profit value (4.0 = 4% for percent type, or 3.0 = 1:3 RR) | no | 4 |
trailing_stop | boolean | Enable trailing stop | no | false |
trailing_stop_value | number | Trailing stop distance in % | no | 1 |
analysis_blocks | number | Split data into N blocks for consistency analysis (0=disabled, recommended: 4, 6, or 12) | no | 0 |
max_hold_duration | string | Max position hold time (e.g., '30m', '2h', '1d'). Leave empty to disable. | no | "" |
close_at_time | string | Close all positions at specific time daily (e.g., '16:00', '8pm'). Leave empty to disable. | no | "" |
close_at_time_offset | number | UTC offset in hours for time settings (e.g., -5 for EST, 1 for CET) | no | 0 |
trading_window_start | string | Only open positions after this time (e.g., '9:30', '9am'). Leave empty for no restriction. | no | "" |
trading_window_end | string | Only open positions before this time (e.g., '15:30', '3pm'). Leave empty for no restriction. | no | "" |
optimize_sl | string | Stop loss range to optimize (e.g., '1-5:0.5' or '1,2,3,4'). Leave empty for no optimization. | no | "" |
optimize_tp | string | Take profit range to optimize (e.g., '2-10:1' or '2,4,6,8'). Leave empty for no optimization. | no | "" |
optimize_size | string | Position size range to optimize (e.g., '0.05-0.2:0.05'). Leave empty for no optimization. | no | "" |
optimize_target | string | Metric to optimize for when running parameter optimization | no | "total_return" |
Helpβ
Backtest Strategy
A high-performance, license-free backtesting engine for evaluating trading strategies. Built with pure numpy for maximum speed - no GPL dependencies (unlike vectorbt/backtrader).
β‘ Key Advantagesβ
Performanceβ
- Vectorized numpy operations - processes 100k+ bars in milliseconds
- O(1) signal lookup using hashmap for instant bar matching
- Memory optimized with
__slots__and contiguous arrays - No external dependencies - only numpy (BSD) and pandas (BSD)
License-Safeβ
- 100% BSD/MIT licensed - safe for commercial use
- No GPL contamination - unlike vectorbt, backtrader, zipline
- No attribution required - use freely in paid products
Unique Featuresβ
- Block Analysis - Walk-forward validation with consistency scoring
- Trading Window - Restrict entry times (market hours only)
- Time-Based Exits - Auto-close at specific times or after duration
- Flexible Field Mapping - Works with any OHLC data format
Complete Risk Managementβ
- Multiple position sizing methods (percent, fixed, risk-based)
- Stop loss & take profit (percent, ATR, fixed, R:R ratio)
- Trailing stops with customizable distance
- Commission and slippage modeling
Professional Statisticsβ
- Risk-adjusted returns (Sharpe, Sortino, Calmar)
- Drawdown analysis (max DD, duration, recovery)
- Trade breakdown by direction and exit reason
- Equity & drawdown curves for visualization
π₯ Inputsβ
OHLC Dataβ
Connect data with time, open, high, low, close fields.
Sources: postgres_sql, fetch_ohlc, fetch_csv, or any worker returning OHLC data.
Use the field dropdowns to select the correct columns from your data:
time_field: Timestamp column (Unix seconds/ms, ISO string, or datetime)open_field: Entry price when signal triggers at bar openhigh_field: Used for take profit hit detection (highest price in bar)low_field: Used for stop loss hit detection (lowest price in bar)close_field: Position valuation, trailing stops, and bar close exits
Signalsβ
List of trading signals with:
- time: Timestamp (Unix, ISO string, or datetime)
- action:
"long","short", or"close" - size (optional): Override position size for this signal
π° Position Sizingβ
| Type | Description | Example |
|---|---|---|
percent | Use X% of capital per trade | 0.1 = 10% of capital |
fixed | Fixed dollar amount | 1000 = $1000 per trade |
risk_based | Size based on stop loss distance | 0.02 = risk 2% per trade |
Risk-based sizing automatically calculates position size so that if stopped out, you lose exactly X% of capital. Professional money management!
π‘οΈ Risk Managementβ
Stop Loss Typesβ
| Type | Description | Example |
|---|---|---|
percent | Distance as % of entry price | 2.0 = 2% below entry |
atr | Multiple of ATR(14) | 1.5 = 1.5x ATR |
fixed | Fixed price distance | 5.0 = $5 from entry |
Take Profit Typesβ
| Type | Description | Example |
|---|---|---|
percent | Distance as % of entry price | 4.0 = 4% above entry |
atr | Multiple of ATR(14) | 3.0 = 3x ATR |
rr_ratio | Risk:Reward ratio | 3.0 = 1:3 (3x stop distance) |
fixed | Fixed price distance | 10.0 = $10 from entry |
Trailing Stopβ
When enabled, stop loss follows price movement:
- Long: Stop moves up as price rises (never down)
- Short: Stop moves down as price falls (never up)
- Distance:
trailing_stop_valuein percent
β° Time-Based Rulesβ
Max Hold Durationβ
Close positions after a specific time period:
max_hold_duration: "30m" β 30 minutes
max_hold_duration: "2h" β 2 hours
max_hold_duration: "1d" β 1 day
Use cases: Scalping, momentum strategies, avoiding overnight gaps
Close At Timeβ
Close all positions at a specific time daily:
close_at_time: "16:00" β 4:00 PM
close_at_time: "8pm" β 8:00 PM
close_at_time_offset: -5 β EST timezone
Use cases: Day trading, avoiding after-hours, market close exits
Trading Windowβ
Only allow new positions during specific hours:
trading_window_start: "9:30" β Market open
trading_window_end: "15:30" β 30 min before close
close_at_time_offset: -5 β EST timezone
Examples:
| Market | Start | End | Offset |
|---|---|---|---|
| US Stocks | 9:30 | 16:00 | -5 |
| US Futures | 18:00 | 17:00 | -5 |
| London Forex | 8:00 | 16:00 | 0 |
| Asian Session | 0:00 | 9:00 | 9 |
Note: Overnight windows are supported (end < start).
π€ AI Find Best Strategyβ
One-click optimization! Let AI automatically find the best parameters for your strategy.
How to Useβ
- Configure only:
data,signals, OHLC field mappings,initial_capital,commission,slippage - Check the "π€ AI Find Best Strategy" checkbox
- Select your optimization target (sharpe_ratio recommended)
- Run the backtest
That's it! All other parameters will be hidden - AI determines everything automatically!
What AI Doesβ
-
Analyzes your data's volatility:
- Average bar price change %
- 95th percentile price change
- Detects timeframe (tick/intraday/hourly/daily)
- Adjusts parameters based on volatility
-
Auto-determines parameter types:
- Stop Loss Type:
percent(universal) - Take Profit Type:
percent(universal) - Position Size Type:
percent(universal)
- Stop Loss Type:
-
Calculates smart ranges based on volatility:
Parameter How Range is Calculated Stop Loss 0.5x to 3x average bar change Take Profit 1x to 5x average bar change Position Size 5% - 25% of capital Trailing Stop Disabled, tight, normal, wide (based on volatility) Max Hold Duration Based on detected timeframe (5min-2weeks) -
Tests all combinations (up to 600) and finds optimal settings
-
π Recursive Search - If best result is unprofitable, AI automatically:
- Expands parameter ranges (tighter AND wider)
- Increases granularity (more test values)
- Tries up to 3 additional searches
- Compares results and returns the best
-
Runs full backtest with optimal parameters to get detailed trade data for charting
π Recursive Search (Auto-Retry)β
If the best strategy found is losing money or has negative Sharpe ratio, AI doesn't give up! It automatically expands the search with wider parameter ranges:
| Attempt | SL/TP Range Expansion | Test Values |
|---|---|---|
| Initial | 1.0x (baseline) | 5-7 values |
| Retry 1 | 1.5x wider + tighter | 7-9 values |
| Retry 2 | 2.0x wider + tighter | 9-11 values |
| Retry 3 | 2.5x wider + tighter | 11-13 values |
Trigger conditions:
total_return < 0%(losing money)sharpe_ratio < 0(negative risk-adjusted return)sharpe_ratio < 0.3ANDreturn < 2%(poor results)
Output includes:
"recursive_search": {
"performed": true,
"depth": 2,
"max_depth": 3,
"reason": "Searched 2 additional time(s) for better parameters",
"improved": true
}
Recommendations will show:
π AI performed 2 additional search(es) with expanded parameter rangesβ οΈ Strategy remains unprofitable even after exhaustive search. Consider revising signal logic.
π Verify Top 10 Resultsβ
Want to verify that calculations are correct for any of the top 10 results? Use the ai_show_trades_for parameter!
How to use:
- Run AI optimization normally
- Look at
top_10array - you'll see 10 best results with different parameters - Change
ai_show_trades_forto any number 1-10 - Re-run the worker
- Now
trades,trades_summary,equity_curve,drawdown_curvewill show data for that specific result
Example workflow:
Step 1: ai_show_trades_for = 1 (default)
β See trades for best result (#1)
Step 2: ai_show_trades_for = 5
β See trades for 5th best result
β Compare equity curve, verify calculations
Step 3: ai_show_trades_for = 10
β See trades for 10th result
β Understand why it ranked lower
Output includes info about which result is shown:
"showing_trades_for": {
"rank": 5,
"parameters": {
"stop_loss": 1.2,
"take_profit": 3.6,
"position_size": 0.15,
"trailing_stop": true
},
"results": {
"total_return_pct": 8.5,
"sharpe_ratio": 0.85,
"win_rate": 52.3,
"total_trades": 127
},
"note": "Change 'ai_show_trades_for' parameter (1-10) to see trades for different top results"
}
This allows you to:
- β Verify calculations are correct for each strategy
- β Compare equity curves between different parameter sets
- β Visualize trades on chart for any top 10 result
- β Understand why certain parameters rank higher/lower
AI Outputβ
- data_analysis: Full volatility analysis with detected timeframe
- auto_determined_types: Explains why AI chose percent types
- best_parameters: Optimal settings ready to use (copy-paste!)
- best_results: Summary statistics for optimal configuration
initial_capital: Starting capitalfinal_capital: Ending capital after all tradestotal_return_pct: Percentage returntotal_return_value: Absolute return in currencymax_drawdown_pct: Maximum drawdown as percentagemax_drawdown_value: Maximum drawdown in currency
- recommendations: Actionable insights about your strategy
- top_10: Top 10 performing parameter combinations (with all metrics)
- trades: Full list of all trades with entry/exit details for charting
- trades_summary: Breakdown of trades by type and exit reason
- equity_curve: Equity over time for charting
- drawdown_curve: Drawdown over time for charting
- ranges_tested: Shows what ranges AI tested based on volatility
- statistics: Distribution of results across all tests
- recursive_search: Info about recursive search attempts
Trade Details (for charting)β
Each trade in the trades array includes:
| Field | Description |
|---|---|
entry_time | When position was opened (ISO timestamp) |
exit_time | When position was closed (ISO timestamp) |
direction | long or short |
entry_price | Price at entry |
exit_price | Price at exit |
stop_loss | Stop loss price level |
take_profit | Take profit price level |
size | Position size / lots |
profit | Profit/loss in currency |
profit_pct | Profit/loss as percentage |
exit_reason | stop_loss, take_profit, signal, trailing_stop, max_duration |
bars_held | Number of bars position was held |
commission | Commission paid for this trade |
Example Outputβ
{
"ai_optimization": true,
"message": "π€ AI analyzed 280 combinations based on your data's volatility...",
"best_parameters": {
"stop_loss_value": 0.9,
"take_profit_value": 2.7,
"position_size": 0.15,
"trailing_stop": true,
"rr_ratio": 3.0
},
"trades": [
{
"entry_time": "2024-01-15T09:30:00+00:00",
"exit_time": "2024-01-15T14:22:00+00:00",
"direction": "long",
"entry_price": 150.25,
"exit_price": 154.31,
"stop_loss": 148.90,
"take_profit": 154.31,
"size": 66,
"profit": 267.96,
"profit_pct": 2.7,
"exit_reason": "take_profit",
"bars_held": 58
}
],
"trades_summary": {
"total_trades": 127,
"winning_trades": 74,
"losing_trades": 53,
"exits_by_tp": 48,
"exits_by_sl": 45,
"exits_by_trailing": 26
},
"equity_curve": [...],
"drawdown_curve": [...]
}
π Manual Parameter Optimizationβ
For advanced users who want full control over parameter ranges.
How to Useβ
Fill in the optimization range fields:
optimize_sl: Stop loss values to testoptimize_tp: Take profit values to testoptimize_size: Position size values to test (optional)
Range Formatβ
| Format | Example | Result |
|---|---|---|
| Single value | 2 | [2.0] |
| List | 1,2,3,4 | [1.0, 2.0, 3.0, 4.0] |
| Range | 1-5 | [1.0, 2.0, 3.0, 4.0, 5.0] |
| Range with step | 1-5:0.5 | [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0] |
Examplesβ
Test SL from 1% to 3%, TP from 2% to 6%:
optimize_sl: "1-3:0.5" β [1.0, 1.5, 2.0, 2.5, 3.0]
optimize_tp: "2-6:1" β [2.0, 3.0, 4.0, 5.0, 6.0]
optimize_target: "sharpe_ratio"
This tests 5 Γ 5 = 25 combinations.
Test specific values:
optimize_sl: "1,1.5,2,2.5,3"
optimize_tp: "3,4,5,6"
optimize_size: "0.05,0.1,0.15,0.2"
This tests 5 Γ 4 Γ 4 = 80 combinations.
Optimization Targetsβ
| Target | Description |
|---|---|
total_return | (Default) Maximum profit |
sharpe_ratio | Best risk-adjusted return |
profit_factor | Highest gross profit / gross loss |
win_rate | Highest winning percentage |
expectancy | Best expected value per trade |
sortino_ratio | Best downside risk-adjusted return |
Outputβ
The optimization returns:
- best_parameters: Optimal SL, TP, position size, and R:R ratio
- best_results: Performance metrics for best combination
- top_10: Top 10 performing combinations
- heatmap: Data for SL vs TP heatmap visualization
- statistics: Distribution of results across all tests
Limitsβ
Maximum 1000 combinations per optimization to prevent excessive computation.
π Block Analysis (Walk-Forward Validation)β
Divide your backtest into N blocks to validate strategy consistency. This helps detect overfitting - a robust strategy should perform similarly across all periods.
analysis_blocks: 6 β Split data into 6 equal periods
Why Use Block Analysis?β
- Detect overfitting: Strategy that works only in one period is likely curve-fitted
- Validate robustness: Consistent profits across all blocks = reliable strategy
- Walk-forward simulation: Each block is like a forward test
Consistency Score (0-100)β
| Score | Rating | Meaning |
|---|---|---|
| 80-100 | β Excellent | Strategy works consistently across all periods |
| 60-80 | β Good | Minor variations, generally reliable |
| 40-60 | β οΈ Moderate | Notable differences, needs review |
| 20-40 | β Poor | Likely overfitted to specific periods |
| 0-20 | π« Very Poor | Strategy fails in multiple periods |
Block Outputβ
Each block includes:
- Start/end dates
- Total return & trades
- Win rate & profit factor
- Sharpe ratio
π Output Metricsβ
Summary Statisticsβ
| Metric | Description |
|---|---|
total_return | Total profit/loss in currency |
total_return_pct | Total return as percentage |
annual_return | Annualized return |
sharpe_ratio | Risk-adjusted return (volatility) |
sortino_ratio | Risk-adjusted return (downside only) |
calmar_ratio | Return / Max Drawdown |
Risk Metricsβ
| Metric | Description |
|---|---|
max_drawdown | Largest peak-to-trough decline |
max_drawdown_duration | Longest recovery period |
volatility | Annualized standard deviation |
win_rate | Percentage of winning trades |
profit_factor | Gross profit / Gross loss |
expectancy | Average expected profit per trade |
Trade Analysisβ
| Field | Description |
|---|---|
total_trades | Number of completed trades |
avg_win / avg_loss | Average winning/losing trade |
best_trade / worst_trade | Extremes |
avg_bars_held | Average holding period |
statistics_by_direction | Separate stats for long/short |
exit_analysis | Breakdown by exit reason |
Visualizationsβ
| Output | Description |
|---|---|
equity_curve | Capital over time (for charting) |
drawdown_curve | Drawdown over time |
trades | Full trade list with details |
π§ Complete Parameter Referenceβ
Requiredβ
| Parameter | Type | Description |
|---|---|---|
data | string | OHLC data from upstream worker |
signals | string | Trading signals array |
Capital & Sizingβ
| Parameter | Default | Description |
|---|---|---|
initial_capital | 10000 | Starting capital |
position_size_type | percent | percent, fixed, or risk_based |
position_size | 0.1 | Size value (0.1 = 10% for percent) |
Costsβ
| Parameter | Default | Description |
|---|---|---|
commission | 0.001 | Per-trade commission (0.1%) |
slippage | 0.0005 | Slippage (0.05%) |
Risk Managementβ
| Parameter | Default | Description |
|---|---|---|
stop_loss_type | percent | percent, atr, or fixed |
stop_loss_value | 2.0 | Stop loss distance |
take_profit_type | percent | percent, atr, rr_ratio, or fixed |
take_profit_value | 4.0 | Take profit distance |
trailing_stop | false | Enable trailing stop |
trailing_stop_value | 1.0 | Trailing distance (%) |
Time Rulesβ
| Parameter | Default | Description |
|---|---|---|
max_hold_duration | "" | Max hold time (30m, 2h, 1d) |
close_at_time | "" | Daily close time (16:00, 8pm) |
close_at_time_offset | 0 | UTC offset in hours |
trading_window_start | "" | Entry window start (9:30) |
trading_window_end | "" | Entry window end (15:30) |
Advancedβ
| Parameter | Default | Description |
|---|---|---|
time_field | time | Timestamp field name |
open_field | open | Open price field |
high_field | high | High price field |
low_field | low | Low price field |
close_field | close | Close price field |
analysis_blocks | 0 | Block analysis (4, 6, or 12) |
AI Optimizationβ
| Parameter | Default | Description |
|---|---|---|
ai_optimize | false | π€ Enable AI auto-optimization |
ai_optimize_target | sharpe_ratio | Metric for AI to optimize |
ai_sl_tp_type | percent | SL/TP type: percent (%), fixed (pips/price), atr (ATRΓ) |
ai_top_results_count | 10 | How many top results to include (1-50) |
ai_show_trades_for | 1 | Show trades for which result (1-N). Change to verify different results! |
Manual Optimizationβ
| Parameter | Default | Description |
|---|---|---|
optimize_sl | "" | SL range (e.g., "1-3:0.5" or "1,2,3") |
optimize_tp | "" | TP range (e.g., "2-6:1" or "2,4,6") |
optimize_size | "" | Position size range (e.g., "0.05-0.2:0.05") |
optimize_target | total_return | Metric to maximize |