Complete documentation for the RLX Backtester Python API
RLX requires a valid license key for production use. Get your license at rlxbt.com/pricing.
| Plan | Max Bars | RL | Intrabar | Multi-Strategy | Price |
|---|---|---|---|---|---|
| Starter | 500K | ❌ | ❌ | ❌ | $29/mo |
| Pro | Unlimited | ✅ | ✅ | ✅ | $79/mo |
| Institutional | Unlimited | ✅ | ✅ | ✅ | $499/mo |
The main entry point for running backtests. Manages portfolio, executes trades, and calculates metrics.
engine = rlx.TradingEngine(
initial_capital=100000.0, # Starting capital
commission=0.0, # Commission rate (0.1 = 0.1%)
slippage=0.0, # Slippage per trade
contract_size=1.0, # Size of one contract
enable_dynamic_tp_sl=True, # Enable TP/SL from signals
exit_controller=None, # ExitController instance
license_key="rlx_pro_xxx" # License key (production)
)Runs backtest using pre-calculated signals in the data.
Parameters:
data — DataFrame with OHLCV and signal column signal_column — Column name with signals (1/-1/0) Returns:BacktestResult
Runs backtest using a strategy object that generates signals.
Parameters:
strategy — Strategy instance with generate_signals method data — DataFrame or list of Bar objects High-precision backtest with intrabar resolution for accurate TP/SL.
Parameters:
main_data — Main timeframe data (e.g., 1H) intrabar_data — Higher resolution data (e.g., 1M) Run multiple strategies as a portfolio.
Returns:MultiStrategyResult
Advanced exit management beyond simple TP/SL. Supports time-based, session-based, and drawdown-based exits.
from rlxbt import ExitController, ExitRules
# Create exit rules
rules = ExitRules(
hold_bars=10, # Close after 10 bars
max_hold_minutes=60, # Or after 60 minutes
exit_at_night=True, # Close at night
night_start_hour=22, # Night starts 22:00 UTC
night_end_hour=6, # Night ends 06:00 UTC
max_drawdown_percent=5.0, # Close if DD > 5%
min_profit_percent=2.0 # Close if profit > 2%
)
# Create controller and attach to engine
controller = ExitController(rules)
engine.set_exit_controller(controller)| Parameter | Type | Description |
|---|---|---|
| hold_bars | int? | Max bars to hold position |
| max_hold_minutes | int? | Max time in minutes |
| exit_at_night | bool? | Close during night hours |
| night_start_hour | int? | Night start (UTC). Default: 22 |
| night_end_hour | int? | Night end (UTC). Default: 6 |
| max_drawdown_percent | float? | Force exit on drawdown % |
| min_profit_percent | float? | Force exit on profit % |
| custom_rules | Dict[str, float]? | Custom key-value rules for extension |
# Simple time-based exit
rules = ExitRules.hold_bars_only(bars=10)
# Day trading preset (includes night exit and drawdown protection)
rules = ExitRules.day_trading_rules(hold_bars=50, max_hold_minutes=240)Most backtesters only see OHLC values, making it impossible to know if price hit stop-loss or take-profit first. RLX solves this with intrabar analysis.
Bar: Open=100, High=105, Low=95, Close=102 Position: Long at 100, SL=96, TP=104
Traditional Backtest
Can't determine order — High or Low first?
RLX Intrabar
Uses 1M data to determine exact sequence
# Load main timeframe (signals generated here)
main_df = pd.read_csv("BTCUSDT_1h.csv")
# Load intrabar data (execution happens here)
intrabar_df = pd.read_csv("BTCUSDT_1m.csv")
# Run with intrabar precision
result = engine.run_intrabar_backtest(
strategy=my_strategy,
main_data=main_df,
intrabar_data=intrabar_df
)Represents a single OHLCV candle in the market data.
bar = rlx.Bar(
timestamp=1609459200, # Unix timestamp
open=100.0, # Open price
high=105.0, # High price
low=98.0, # Low price
close=103.0, # Close price
volume=1000.0 # Volume
)A trading signal with optional Take Profit and Stop Loss levels for precise position management.
signal = rlx.EnhancedSignal(
signal=1, # 1 = Long, -1 = Short, 0 = Flat
take_profit=105.0, # Optional TP price level
stop_loss=95.0 # Optional SL price level
)signal = 1Long position — buy and hold
signal = -1Short position — sell and hold
signal = 0Flat — close any position
Contains comprehensive results from a backtest simulation.
| Attribute | Type | Description |
|---|---|---|
| initial_capital | float | Starting capital |
| final_capital | float | Ending portfolio value |
| total_return | float | Percentage return (e.g., 0.15 for 15%) |
| total_trades | int | Number of completed trades |
| winning_trades | int | Number of profitable trades |
| losing_trades | int | Number of losing trades |
| equity_curve | List[float] | Portfolio value at each bar |
| equity_curve_timestamps | List[int] | Unix timestamps for equity curve |
| trades | List[TradeResult] | Detailed history of all trades |
| metrics | Dict[str, float] | Performance metrics (Sharpe, Drawdown, etc.) |
| trade_analysis | Dict[str, float] | Trade statistics (avg_win, avg_loss) |
| total_commission | float | Total fees paid |
| drawdown_series | List[DrawdownPoint] | Drawdown at each timestamp |
| daily_returns | List[DailyReturn] | Daily return breakdown |
Details of a single completed trade.
entry_timeintUnix timestamp of entry
exit_timeintUnix timestamp of exit
entry_pricefloatPrice at entry
exit_pricefloatPrice at exit
sidestr"long" or "short"
pnlfloatProfit/Loss in quote currency
returnsfloatPercentage return of the trade
quantityfloatNumber of contracts traded
contract_sizefloatSize of one contract
commission_amountfloatCommission paid for this trade
exit_reasonExitReasonWhy the trade was closed
take_profitOptional[float]Take profit level if set
stop_lossOptional[float]Stop loss level if set
directionint1 for long, -1 for short
profitfloatAlias for pnl
commissionfloatAlias for commission_amount
Enum representing the reason for closing a position.
NoneNo exit
TakeProfitTP level hit
StopLossSL level hit
SignalStrategy signal
EndOfDataBacktest finished
MaxBarsReachedHold limit exceeded
MaxTimeReachedTime limit exceeded
NightExitNight session
MaxDrawdownDD limit exceeded
MinProfitReachedProfit target hit
Result object returned by run_multi_strategy.
| Attribute | Type | Description |
|---|---|---|
| strategies | List[StrategyResult] | Individual results for each strategy |
| portfolio_result | BacktestResult | Combined portfolio performance |
# Run multiple strategies as a portfolio
result = engine.run_multi_strategy(
strategies=[strategy_a, strategy_b, strategy_c],
data=market_data,
strategy_names=["Momentum", "Mean Reversion", "Breakout"],
allocation_weights=[0.4, 0.3, 0.3] # Must sum to 1.0
)
# Access individual strategy results
for strat in result.strategies:
print(f"{strat.name}: {strat.total_return:.2%}")
# Access combined portfolio
print(f"Portfolio Return: {result.portfolio_result.total_return:.2%}") RLX calculates 30+ institutional-grade metrics. Access via result.metrics.
| Metric | Description |
|---|---|
| total_return | Total percentage return over the backtest period |
| annual_return | Annualized return (CAGR) |
| total_trades | Total number of completed trades |
| winning_trades | Number of profitable trades |
| losing_trades | Number of losing trades |
| win_rate | Percentage of winning trades |
| profit_factor | Gross profit / Gross loss |
| avg_win | Average profit on winning trades |
| avg_loss | Average loss on losing trades |
| largest_win | Largest single winning trade |
| largest_loss | Largest single losing trade |
| avg_trade | Average P&L per trade |
| expectancy | Expected value per trade |
# From BacktestResult
result = engine.run_with_signals(data)
# Access basic metrics
print(f"Sharpe Ratio: {result.metrics['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {result.metrics['max_drawdown']:.2%}")
print(f"Win Rate: {result.metrics['win_rate']:.2%}")
# From DashboardResult (more detailed)
dashboard = generator.generate_dashboard(result, data)
metrics = dashboard.performance_metrics
print(f"Sortino Ratio: {metrics.sortino_ratio:.2f}")
print(f"VaR 95%: {metrics.var_95:.2%}")
print(f"Omega Ratio: {metrics.omega_ratio:.2f}")
print(f"Kelly Criterion: {metrics.kelly_criterion:.2%}") Train your own trading agents using popular RL libraries like Stable-Baselines3, Ray RLlib, or custom implementations. The RLEnvironment wraps the TradingEngine and handles state observation, action execution, and reward calculation.
env = rlx.RLEnvironment(
initial_capital=100000.0, # Starting capital
commission=0.0, # Commission rate per trade
slippage=0.0, # Slippage per trade
window_size=20, # Number of past bars in observation
exit_controller=None # Optional ExitController instance
)| Parameter | Type | Default | Description |
|---|---|---|---|
| initial_capital | float | 100000.0 | Starting capital |
| commission | float | 0.0 | Commission rate per trade |
| slippage | float | 0.0 | Slippage per trade |
| window_size | int | 20 | Past bars in observation |
| exit_controller | ExitController? | None | Custom exit logic |
Loads historical market data into the environment.
Parameters:
data — A pandas DataFrame containing OHLCV data Resets the environment to the beginning of the data or a random starting point.
Returns:
(observation, info) — Tuple of initial state vector and info dict Executes an action in the environment and advances one time step.
Parameters:
action (int) — The action to take (0, 1, or 2) Returns:
(observation, reward, done, truncated, info)Close position if open
Open/flip to long
Open/flip to short
The observation vector is a flattened list containing market data and account state:
Total Dimension:(window_size × 5) + 3
Example: window_size=20 → 20×5 + 3 = 103 features
import rlx
import pandas as pd
# Load market data
df = pd.read_csv("BTCUSDT_1h.csv")
# Create environment
env = rlx.RLEnvironment(
initial_capital=100000.0,
window_size=10
)
env.load_data(df)
# Training loop
obs, info = env.reset()
done = False
while not done:
action = 1 # Example: Always go Long
obs, reward, done, truncated, info = env.step(action)
print(f"Reward: {reward:.2f}%, Portfolio: ${info['portfolio_value']:.2f}") For proper risk management, configure exit rules through an ExitController:
import rlx
# Define exit rules
rules = rlx.ExitRules(
hold_bars=12, # Max 12 bars in position
max_drawdown_percent=3.0, # Stop loss at 3% drawdown
min_profit_percent=1.5, # Take profit at 1.5%
)
# Create exit controller
exit_controller = rlx.ExitController(rules)
# Create environment with exit rules
env = rlx.RLEnvironment(
initial_capital=100000.0,
commission=0.001, # 0.1% commission
slippage=0.0,
window_size=20,
exit_controller=exit_controller
)
env.load_data(df)Real benchmark (BTCUSDT 1h, PPO agent, 100K training steps):
| Configuration | Test Return | Sharpe | Max DD | Trades |
|---|---|---|---|---|
| No Rules (baseline) | -14.01% | -0.0480 | 50.37% | 106 |
| Conservative (2% SL) | -12.14% | -0.0012 | 42.90% | 5,914 |
| Aggressive (5% SL) ⭐ | +28.50% | 0.0407 | 17.84% | 767 |
Proper exit rules dramatically improve RL agent performance by:
The GraphAnalyzer converts backtest results into a directed graph of trades, features, and patterns. This enables advanced analysis such as finding winning streaks, loss recovery patterns, and correlation clusters — just like institutional hedge funds do.
import json
# Convert backtest result to JSON
result_json = json.dumps(result.__dict__, default=lambda o: o.__dict__)
# Create analyzer
analyzer = rlx.GraphAnalyzer(backtest_result_json=result_json)Note: The constructor takes a JSON string representation of a BacktestResult. This allows the graph to be constructed from serialized data as well.
Searches the graph for patterns matching a specific query language.
Parameters:
query (str) — Pattern definition string (e.g., "WinningStreak → WinningStreak") Returns:
List[PatternMatch]Automatically searches for common institutional trading patterns.
Returns:
List[PatternMatch]Winning Streaks
3+ consecutive wins
Loss Recovery
Loss → larger Win
ML Signals
High confidence signals
Volatility Regime
Regime adaptation
Correlation Clusters
Related trade groups
Generates a human-readable text report summarizing the patterns found in the backtest.
Returns:
str — The report textProvides a detailed, human-readable explanation of a specific pattern ID found by the analyzer.
Parameters:
pattern_id (str) — The ID of the pattern to explain Returns:
strExports the entire graph structure (nodes and edges) to a JSON string for visualization.
Returns:
str — JSON stringimport rlx
import json
# Run backtest
engine = rlx.TradingEngine(initial_capital=100000)
result = engine.execute_backtest(strategy, data)
# Convert result to JSON
result_json = json.dumps(result.__dict__, default=lambda o: o.__dict__)
# Create analyzer
analyzer = rlx.GraphAnalyzer(result_json)
# Find institutional patterns
patterns = analyzer.find_hedge_fund_patterns()
print(f"Found {len(patterns)} patterns")
# Generate report
report = analyzer.generate_pattern_report()
print(report)
# Explain specific pattern
if patterns:
explanation = analyzer.explain_pattern(patterns[0].id)
print(explanation)
# Export for visualization
graph_json = analyzer.export_graph()
with open("trade_graph.json", "w") as f:
f.write(graph_json)=== TRADE PATTERN ANALYSIS REPORT ===
📊 Backtest Summary:
Total Trades: 156
Win Rate: 58.3%
Profit Factor: 1.87
🔥 Winning Streaks Detected: 12
Longest Streak: 7 trades
Average Streak Length: 3.2 trades
Best Streak P&L: +$4,230.50
🔄 Loss Recovery Patterns: 8
Recovery Rate: 87.5%
Average Recovery P&L: +$890.25
📈 Correlation Clusters: 3
Cluster 1: BTC momentum trades (23 trades)
Cluster 2: Mean reversion plays (18 trades)
Cluster 3: Breakout entries (12 trades)
💡 Key Insights:
• Strategy performs best during high volatility
• Average 2.3 bars between cluster trades
• 73% of losses recovered within 3 trades
The RLX Backtester includes a powerful built-in dashboard for visualizing backtest results, analyzing trades, and inspecting performance metrics.
The DashboardGenerator class processes backtest results and generates data structures for visualization.
generator = rlx.DashboardGenerator(
initial_capital=100000.0, # Starting capital
commission=0.0, # Commission rate
slippage=0.0, # Slippage per trade
use_intrabar_resolution=False, # Process intrabar data
contract_size=1.0 # Contract size
) Processes raw backtest results into a structured DashboardResult.
Exports the full dashboard data to a JSON file.
Launches a local web server to visualize results in an interactive dashboard.
Exports all trades to a CSV file with extended statistics.
Contains all processed data for visualization.
| Attribute | Type | Description |
|---|---|---|
| backtest_result | BacktestResult | Original backtest results |
| extended_trades | List[ExtendedTradeInfo] | Trades with additional analytics |
| performance_metrics | PerformanceMetrics | All calculated metrics |
| equity_curve | List[EquityPoint] | Equity over time |
| drawdown_curve | List[DrawdownPoint] | Drawdown over time |
| monthly_returns | List[MonthlyReturn] | Returns by month |
| trade_statistics | TradeStatistics | Aggregated trade stats |
Extended trade information with MFE/MAE and intrabar data.
trade_idintopen_timeintclose_timeintentry_pricefloatexit_pricefloatsidestrprofitfloatreturnsfloatexit_reasonstrduration_barsintprice_changefloatprice_change_pctfloatmax_favorable_excursionfloatMaximum profit during trade (MFE)
max_adverse_excursionfloatMaximum drawdown during trade (MAE)
intrabar_dataList[IntrabarPoint]?entry_bar_ohlcBarOHLC?exit_bar_ohlcBarOHLC?take_profitfloat?stop_lossfloat?High-resolution price data within a trade.
timestampintpricefloatunrealized_pnlfloatprice_change_from_entryfloatprice_change_pct_from_entryfloatSingle point on the equity curve.
timestampintequityfloatreturnsfloatcumulative_returnsfloatSingle point on the drawdown curve.
timestampintdrawdownfloatdrawdown_pctfloatpeak_equityfloatcurrent_equityfloatMonthly performance breakdown.
yearintmonthint (1-12)return_pctfloattrades_countintAggregated trade statistics.
| Attribute | Type | Description |
|---|---|---|
| total_trades | int | Total trades |
| winning_trades | int | Profitable trades |
| losing_trades | int | Losing trades |
| win_rate | float | Win percentage |
| avg_win | float | Average winning trade |
| avg_loss | float | Average losing trade |
| avg_trade | float | Average trade P&L |
| largest_win | float | Biggest winner |
| largest_loss | float | Biggest loser |
| max_consecutive_wins | int | Longest win streak |
| max_consecutive_losses | int | Longest loss streak |
| avg_trade_duration | float | Average duration (seconds) |
| avg_bars_in_trade | float | Average bars per trade |
| expectancy | float | Expected value per trade |
| kelly_criterion | float | Optimal position size |
When the dashboard server is running (via plot()), it exposes a REST API for programmatic access.
Base URL:http://localhost:8000
| Endpoint | Description |
|---|---|
| GET /api/health | Check server status and uptime |
| GET /api/dashboard-data | Full dashboard dataset |
| GET /api/trades | List all trades (supports filters: side, limit, offset) |
| GET /api/trades/:trade_id | Detailed info for specific trade |
| GET /api/performance-metrics | All calculated metrics |
| GET /api/equity-curve | Equity curve data points |
| GET /api/monthly-returns | Monthly return statistics |
import requests
response = requests.get("http://localhost:8000/api/performance-metrics")
metrics = response.json()['data']
print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {metrics['max_drawdown']:.2%}")