用Python 构建网格交易策略
本文将探讨网格交易方法——一种简单但有效的技术,它不使用技术指标来预测趋势。这种方法是算法交易的绝佳选择

一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | 用AI学区块链开发
欢迎阅读今天的文章,我们将探讨网格交易方法——一种简单但有效的技术,它不使用技术指标来预测趋势。这种方法是算法交易的绝佳选择,我们的 Python 回测显示,在 5 分钟图上,两个月的数据显示,净值稳步增长。研究结果令人印象深刻,夏普比率接近 5.7。
网格交易入门
网格交易需要在价格图表上设置一个数值网格。每当价格穿过网格线时,我们同时开立多头仓位和空头仓位。每个开仓的止盈点都位于下一条网格线上。该策略在价格波动频繁的市场中表现优异,非常适合较短的时间周期。
现在,我们将用 Python 实现一个网格策略,并使用历史数据进行回测。
1、配置环境
首先,我们需要配置 Python 环境,导入所需的库并下载数据集。我们将使用 yfinance 获取欧元/美元汇率数据,使用 pandas 进行数据处理,使用 numpy 进行数值运算,并使用 pandas_ta 获取技术分析指标。
import yfinance as yf
import pandas as pd
import numpy as np
import pandas_ta as ta
# Download the EUR/USD data for the last 59 days with a 5-minute interval
dataF = yf.download("EURUSD=X", start=pd.Timestamp.today() - pd.DateOffset(days=59), end=pd.Timestamp.today(), interval='5m')
# yfinance (yf): A Python library to download historical market data from Yahoo Finance.
# pandas (pd): A powerful data manipulation and analysis library.
# numpy (np): A library for numerical operations.
# pandas_ta (ta): A technical analysis library for financial datasets.
2、创建网格
在此步骤中,我们将创建一个数值网格,用于指定入场点和出场点。该网格由价格图表上一系列等距的水平线组成。每当价格穿过其中一条网格线时,我们就会开立新仓。
grid_distance = 0.005
midprice = 1.065
def generate_grid(midprice, grid_distance, grid_range):
return np.arange(midprice - grid_range, midprice + grid_range, grid_distance)
grid = generate_grid(midprice=midprice, grid_distance=grid_distance, grid_range=0.1)
2.1 设置参数
- grid_distance = 0.005:设置每条网格线之间的间距,代表新仓位的价格增量。
- midprice = 1.065:这是网格建立的中心参考价格。可以设置为当前市场价格或其他参考价格。
重要提示:这些值必须根据市场、交易资产和当前分析进行调整。因此,每次从 Yfinance 查询数据时,数据都会更新,这些参数以及此策略中的其他参数也需要相应更新。
2.2 生成网格
- generate_grid 函数创建一系列值,范围从中间价 - grid_range 到中间价 + grid_range,间隔为 grid_distance。
- grid_range = 0.1:这定义了网格在中间价上下的总范围。
2.3 构建网格
网格数组包含我们考虑开仓的所有价格水平。这是我们网格交易策略的核心,使我们能够随着价格波动系统地入场和出场。
3、创建交易信号
在此步骤中,我们将根据已建立的网格生成交易信号。每当价格穿过网格线时,就会生成交易信号。这涉及迭代数据集中的每一行,并检查该区间的最高价或最低价是否与任何网格线相交。
signal = [0] * len(dataF)
i = 0
for index, row in dataF.iterrows():
for p in grid:
if min(row.Low, row.High) < p and max(row.Low, row.High) > p:
signal[i] = 1
i += 1
dataF["signal"] = signal
dataF[dataF["signal"] == 1]
3.1 初始化信号
signal = [0] *len(dataF):我们创建一个与数据集长度相同的零列表。此列表将存储我们的交易信号。
3.2 迭代数据
我们使用 dataF.iterrows() 循环遍历数据集中的每一行。
对于每一行,我们通过将行最高价和最低价的最小值和最大值与每条网格线进行比较来检查价格是否与任何网格线相交。
3.3 生成信号
如果与网格线相交(即最低价低于网格线,最高价高于网格线),我们将信号列表中的相应条目设置为 1。这表示在该时间间隔内产生了交易信号。
3.4 向 DataFrame 添加信号
- dataF["signal"] = signal:我们将信号列表作为新列添加到 DataFrame 中。
- dataF[dataF["signal"] == 1]:这会过滤 DataFrame,使其仅显示产生交易信号的行。
通过创建这些交易信号,我们可以确定价格穿过网格线的准确时间点,从而指示潜在的交易入场机会。这种系统性方法确保我们能够捕捉到定义网格内所有相关的价格变动。
4、准备回测
在此步骤中,我们通过计算平均真实波动幅度 (ATR) 并定义信号函数来准备回测数据集。ATR 是一个波动率指标,可以帮助我们设置动态止损和止盈位。
dfpl = dataF[:].copy()
def SIGNAL():
return dfpl.signal
dfpl['ATR'] = ta.atr(high=dfpl.High, low=dfpl.Low, close=dfpl.Close, length=16)
dfpl.dropna(inplace=True)
4.1 复制 DF
dfpl = dataF[:].copy():我们创建原始数据集的副本,以避免在回测过程中直接对其进行更改。这确保了原始数据保持不变。
4.2 定义信号函数
def SIGNAL():此函数从 DataFrame 返回信号列。它将在回测期间用于访问生成的交易信号。
4.3 计算平均真实波动幅度 (ATR)
dfpl['ATR'] = ta.atr(high=dfpl.High, low=dfpl.Low, close=dfpl.Close, length=16):我们使用 16 个间隔来计算 ATR。ATR 是衡量市场波动性的指标,有助于设置合适的止损和止盈价位。
high=dfpl.High, low=dfpl.Low, close=dfpl.Close:这些参数指定用于计算 ATR 的最高价、最低价和收盘价。
4.4 清理
dfpl.dropna(inplace=True):我们删除所有缺失值的行,以维护回测过程的完整性。此步骤对于获得准确可靠的回测结果至关重要。
ATR 提供了一种动态的波动性度量。通过计算 ATR 并定义信号函数,我们为回测框架配备了必要的工具,以评估网格交易策略的性能。
5、测试回测
在此步骤中,我们使用回测库实现我们的交易策略,并执行回测以评估其性能。我们定义一个自定义策略类并配置回测参数。
from backtesting import Strategy
from backtesting import Backtest
import backtesting
class MyStrat(Strategy):
mysize = 50
def init(self):
super().init()
self.signal1 = self.I(SIGNAL)
def next(self):
super().next()
slatr = 1.5 * grid_distance # Stop loss distance
TPSLRatio = 0.5 # Take profit to stop loss ratio
if self.signal1 == 1 and len(self.trades) <= 10000:
# Sell position
sl1 = self.data.Close[-1] + slatr
tp1 = self.data.Close[-1] - slatr * TPSLRatio
self.sell(sl=sl1, tp=tp1, size=self.mysize)
# Buy position
sl1 = self.data.Close[-1] - slatr
tp1 = self.data.Close[-1] + slatr * TPSLRatio
self.buy(sl=sl1, tp=tp1, size=self.mysize)
# Running the backtest
bt = Backtest(dfpl, MyStrat, cash=50, margin=1/100, hedging=True, exclusive_orders=False)
stat = bt.run()
stat
5.1 导入库
- from backtesting import Strategy, Backtest:从回测库中导入必要的类,以创建并执行我们的交易策略。
- import backtesting:导入回测库。
5.2 创建策略类
- class MyStrat(Strategy):我们通过扩展 Strategy 类来定义一个自定义策略类。
- mysize = 50:设置每笔交易的仓位规模。
5.3 初始化
- def init(self):初始化策略。
- self.signal1 = self.I(SIGNAL):使用先前定义的 SIGNAL 函数访问交易信号。
5.4 定义交易逻辑
- def next(self):概述执行交易的规则。
- slatr = 1.5 * grid_distance:根据网格间距确定止损距离。
- TPSLRatio = 0.5:确定止盈止损比率。
5.4 执行交易
- 如果触发信号 (self.signal1 == 1) 且交易数量小于或等于 10,000:
- 卖出仓位:— sl1 = self.data.Close[-1] + slatr:将止损设置在当前收盘价上方。— tp1 = self.data.Close[-1] — slatr * TPSLRatio:将止盈设置在当前收盘价下方。— self.sell(sl=sl1, tp=tp1, size=self.mysize):下达卖单。— 买入仓位:— sl1 = self.data.Close[-1] — slatr:将止损设置在当前收盘价下方。— tp1 = self.data.Close[-1] + slatr * TPSLRatio:将止盈设置在当前收盘价上方。— self.buy(sl=sl1, tp=tp1, size=self.mysize):下达买单。
5.5 运行回测
- bt = Backtest(dfpl, MyStrat, cash=50, margin=1/100, hedging=True, exclude_orders=False):设置回测参数。
- cash=50:初始可用现金金额。
- margin=1/100:杠杆率。
- hedging=True:允许对冲。
- exclusive_orders=False:允许重叠订单。
- stat = bt.run():执行回测并保存结果。
通过此回测,我们可以评估网格交易策略的表现。stat
对象提供了详细的指标和洞察,以评估策略的有效性。
6、结果

### Summary:
- **Duration:** The strategy was evaluated over a period of 57 days and 21 hours, offering a thorough assessment timeframe.
- **Exposure Time:** 99.14%, meaning the strategy was nearly always active in the market.
### Performance Metrics:
- **Final Equity:** $136.02, up from the initial $50.
- **Equity Peak:** $156.59, indicating potential for greater gains.
- **Return:** 172.04%, showing substantial profitability.
- **Buy & Hold Return:** 4.23%, highlighting the strategy's superior performance over a passive approach.
- **Annualized Return:** 37364.62%, extremely high due to the brief backtesting period.
- **Annualized Volatility:** 46309.60%, suggesting significant risk and frequent trading activity.
### Risk-Adjusted Metrics:
- **Sharpe Ratio:** 0.81, indicating moderate returns adjusted for risk.
- **Sortino Ratio:** 1089.28, reflecting excellent management of downside risk.
- **Calmar Ratio:** 2194.58, demonstrating high returns relative to the maximum drawdown.
### Drawdown:
- **Max Drawdown:** -17.03%, a notable but manageable drop.
- **Avg Drawdown:** -1.16%, relatively modest.
- **Max Drawdown Duration:** Almost 10 days, representing the longest recovery time.
- **Avg Drawdown Duration:** Under 7 hours, suggesting quick recoveries.
### Trading Activity:
- **Number of Trades:** 1698, indicating high trading frequency due to the grid strategy.
- **Win Rate:** 73.03%, a very high success rate.
- **Best Trade:** 0.87%, reflecting consistent small gains.
- **Worst Trade:** -0.85%, indicating controlled losses.
- **Avg Trade:** 0.10%, showing the cumulative effect of many small trades.
原文链接:Building A Simple Grid Trading Strategy With Python
DefiPlot翻译整理,转载请标明出处
免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。