This repository implements and extends the academic Dynamic Grid Trading (DGT) strategy into a flexible research and backtesting framework.
The strategy is inspired by the paper:
"Dynamic Grid Trading Strategy: From Zero Expectation to Market Outperformance"
by Kai-Yuan Chen, Kai-Hsin Chen, and Jyh-Shing Roger Jang (arXiv:2506.11921).
The main objective of this project is to provide a robust environment for testing, comparing, and optimizing multiple Dynamic Grid Trading strategies on historical market data. Users can define custom ranges of the two key grid parameters β grid size and number of grid levels β and automatically evaluate every parameter combination to identify the most effective configurations.
Building upon the original DGT approach, I introduced a market regime filtering mechanism to improve strategy robustness. Since grid trading strategies are designed to capture price oscillations and generally perform better in range-bound markets than in strong trending environments, I integrated statistical regime detection based on both the Augmented Dickey-Fuller (ADF) test and the Hurst exponent. This allows the strategy to dynamically identify market conditions and avoid initiating grid positions during unfavorable trending periods.
The framework includes a complete backtesting pipeline with portfolio tracking, performance metrics, parameter comparison, and visualization tools, enabling systematic analysis of how different grid configurations behave across various market regimes.
A future extension could integrate the strategy into a live trading environment (e.g., on dYdX), but live execution is not currently implemented in this repository.
The primary objective of this project is to bridge the gap between academic theory and institutional-grade execution. While the original DGT paper proves that a dynamic reset mechanism can outperform static grid systems and buy-and-hold benchmarks in ideal settings, transitioning this strategy to live cryptocurrency markets requires a rigorous backtester, statistical market regime filters, and low-latency execution logic.
We are transforming this repository into a complete quantitative trading pipeline optimized for dYdX Chain (v4), focusing on capital efficiency, risk-adjusted returns, and safety.
The transition from academic code to live trading is structured into three main phases:
flowchart TD
%% Define styles
classDef phase1 fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,color:#01579b;
classDef phase2 fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#1b5e20;
classDef phase3 fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#e65100;
classDef core fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c;
subgraph AcademicCore["Academic Foundation"]
A["DGT Strategy Core Logic"]:::core
end
subgraph Phase1["Phase 1: Rigorous Backtesting"]
B["Historical CSV Data (1m)"]:::phase1
C["DGT Backtest Engine"]:::phase1
D["Slippage & Latency Simulator"]:::phase1
E["dYdX Fee Structure Model"]:::phase1
end
subgraph Phase2["Phase 2: Market Filtering"]
F["Augmented Dickey-Fuller (ADF)"]:::phase2
G["Hurst Exponent (H)"]:::phase2
H["Regime Decision Engine"]:::phase2
end
subgraph Phase3["Phase 3: Live Execution (dYdX)"]
I["dYdX v4 API Connector"]:::phase3
J["WebSocket Orderbook Sync"]:::phase3
K["Active Order Manager"]:::phase3
L["Risk Controls & Circuit Breakers"]:::phase3
end
A --> C
B --> C
C --> D
C --> E
F --> H
G --> H
H -->|Regime Signal| K
D & E --> M["Key Metrics (Sharpe, MaxDD, Win Rate)"]:::phase1
L --> K
K --> M
To establish a realistic baseline, we are upgrading the simple backtester to simulate live market mechanics:
- dYdX Fee Modeling: Incorporating the tiered Maker/Taker fee schedules on dYdX.
- Slippage & Market Impact: Modeling execution slippage using historical bid-ask spreads and order book depth to ensure large orders do not overestimate performance.
- Execution Delays: Simulating latency (API roundtrips, node execution, and network delay) to test if dynamic grid resets are front-run or suffer from price degradation.
Traditional grid strategies fail during prolonged, strong trending phases. We are introducing a statistical regime filter to active trading pairs:
- Augmented Dickey-Fuller (ADF) Test: Evaluates whether a asset's price series is stationary (mean-reverting) or has a unit root (trending).
-
Hurst Exponent (
$H$ ): Measures the long-term memory and persistence of price time series.-
$H < 0.5$ : Mean-reverting regime (Optimal for Grid Trading). -
$H = 0.5$ : Random walk / Brownian motion. -
$H > 0.5$ : Trending regime (Grid trading is halted or parameters are dynamically widened).
-
N.B.: Customizing Filters: The trading thresholds can be configured in the
config.pyfile. If any threshold is exceeded, the strategy automatically refrains from opening new positions. Lower threshold values make the trading conditions more restrictive, requiring stronger market signals before any trade is executed.
- Decision Engine: Automatically halts grid generation or dynamically scales grid boundaries based on real-time ADF and Hurst calculations.
Developing a secure, low-latency execution wrapper targeting the Cosmos-based dYdX Chain (v4):
- API & WebSocket Client: Establishing streaming connections to monitor order-books, account balances, and position fills in real-time.
- Smart Order Router: Handling fast grid resets, dynamic level adjustments, and order placement via asynchronous threads.
- Risk Management: Multi-layered risk framework featuring automatic margin liquidation warnings, max-drawdown circuit breakers, and asset-specific risk limits.
To support this expansion, we use the following technologies:
| Category | Component / Library | Purpose |
|---|---|---|
| Strategy & Logic | Python 3.10+ | Core development runtime environment |
| Statistical Analysis | statsmodels |
Performing ADF stationarity checks |
numpy & scipy |
Mathematical modeling, variance ratio tests, and Hurst exponent calculations | |
| Data Processing | pandas |
Large-scale timeseries manipulation and cleaning |
| Exchange Integration | dydx-v4-client |
Live execution, order creation, and private websocket endpoints |
asyncio & aiohttp |
Async event-loop handling for real-time WebSocket tick streams | |
| Plotting & Analytics | matplotlib & seaborn |
Visualizing equity curves, drawdown profile, and regime transition boundaries |
A strategy is only as good as its risk metrics. We evaluate all backtest iterations and live performance against the following key metrics:
-
Sharpe Ratio (Annualized): Measures the return per unit of total risk. Target:
$> 1.8$ on historical data. -
Sortino Ratio: Focuses strictly on downside risk rather than total volatility, protecting against asymmetric drawdown risk. Target:
$> 2.2$ . -
Maximum Drawdown (Max DD): The maximum peak-to-trough drop in portfolio value. We actively optimize parameters to keep Max DD
$< 15%$ . - Win Rate (Per Grid Segment): The percentage of closed grid segments that yield a positive net return after accounting for all taker/maker fees.
- Profit Factor: The ratio of gross profits to gross losses.
- Calmar Ratio: Annualized rate of return divided by the maximum drawdown over the same period; key for tracking structural tail risk.
- Execution Slippage Leakage: Comparing expected fill prices to actual fill prices to quantify latency costs.
Dynamic-Grid-Trading/
βββ src/
β βββ config.py # Core strategy configuration parameters
β βββ grid_logic.py # Math formulas, reset bounds, and settlement logic
β βββ dgt_backtest.py # Main backtest loop & metrics calculator
β β
β βββ filters/ # Phase 2: Statistical market regime filtering
β β βββ __init__.py
β β βββ adf_test.py # Augmented Dickey-Fuller stationarity implementation
β β βββ hurst_exp.py # Hurst exponent calculation (persistence analysis)
β β
β βββ execution/ (no yet implemented!) # Phase 3: Live execution engine for dYdX
β βββ __init__.py
β βββ dydx_client.py # REST and WebSockets wrapper for dYdX v4 Chain
β βββ order_manager.py# Active grid order placement & fail-safe tracker
β
βββ requirements.txt # Updated Python library dependencies
βββ README.md # Project documentation (this file)
βββ fetch_candlestick.py # Historical candlestick download utility
To optimize backtesting speed and avoid hitting API rate limits or downloading redundant historical files, the system implements a persistent, serverless local database.
We chose SQLite as the local database solution for several key architectural reasons:
- Zero Configuration: A serverless database that stores everything in a single local file (
data/market_data.db) without requiring any daemon process or Docker containers. - Persistence: Stored permanently on the host system, surviving kernel restarts, Python environment resets, and machine restarts.
- Index-backed Speeds: A compound primary key on
(symbol, interval, open_time_ms)facilitates sub-millisecond query filtering. - Pandas Native: Seamless reading and writing of query results directly to and from pandas DataFrames.
The download utility in fetch_candlestick.py integrates this local database to provide an intelligent cache-aside logic:
- Cache Inspection: The requested time frame is partitioned into discrete 1000-candle chunks. The script queries the database for existing records within each chunk.
- Gap Filtering: The scheduler filters out chunks that are already fully cached, targeting only the missing time gaps for API downloading.
- Deduplicated Upsert: Newly fetched candles are merged using
INSERT OR REPLACEstatements to avoid duplicates while retaining historical consistency. - Legacy CSV Export: Once cached, the entire continuous dataset is queried from SQLite and written to the configured CSV (e.g.,
BTCUSDT_spot_1m.csv) to keep the backtest engine backward-compatible.
Clone the repository and install the project in a Python virtual environment:
git clone https://github.com/mathiasmoka/Dynamic-Grid-Trading.git
cd Dynamic-Grid-Trading
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtNote
If you have an error message with the command python3 -m venv venv, remove the virtual environement with the following command: rm -rf venv and then try python3 -m venv venv
Set up your parameters inside src/config.py, specifying the currency pair, time frame, grid settings, and dYdX API keys.
Run the updated DGT backtester:
python -m src.dgt_backtestAt the end of the backtest, a brief summary of some metrics is provided in the terminal.
After running the backtest, a CSV file named BTCUSDT_spot_grid_strategy_backtest_results containing the backtest results, is generated in the local directory.
N.B.: If you run a new backtest, it will overwrite this file. If you want to save it, rename it to avoid overwriting, or download it.
To compare visually the different strategies of the backtest, you can open the HTML dashboard.
It is a static HTML file, which uses the content of the BTCUSDT_spot_grid_strategy_backtest_results.
After running a new backtest, make sure to refresh the dashboard page to view the updated results.
N.B.: the x-axis is the Grid size.
In a backtest, each strategy corresponds to a different combination of parameters tested on the same historical data. For the Dynamic Grid Trading (DGT) strategy, we mainly vary the grid size (the percentage distance between grid levels) and the number of grid levels (controlled by grid_numbers_half). These parameters determine how frequently trades are triggered and how the strategy reacts to price movements. A smaller grid size creates more frequent trades with smaller gains per trade, while a larger grid size reduces trading frequency but captures larger price movements. The number of grid levels controls the width and granularity of the grid, influencing risk exposure and the ability to handle larger market fluctuations. Each parameter combination is evaluated independently to compare profitability, return, and risk-adjusted performance.
N.B: the grid sizes and the numbers of grid levels included in the backtest are 100% customizable in the config.py file.
If you use this codebase or build upon these concepts, please credit the original authors of the strategy:
@article{chen2025dynamic,
title={Dynamic Grid Trading Strategy: From Zero Expectation to Market Outperformance},
author={Chen, Kai-Yuan and Chen, Kai-Hsin and Jang, Jyh-Shing Roger},
journal={arXiv preprint arXiv:2506.11921},
year={2025},
url={https://arxiv.org/abs/2506.11921}
}

