免责声明:本文基于个人使用体验,与任何厂商无商业关系。内容仅供技术交流参考,不构成投资建议。
一、前言
网格策略是一种经典的量化交易策略,原理简单、逻辑清晰,很适合量化新手练手。
2026年了,用Python实现网格策略有很多选择。今天分享一下我用不同工具实现网格策略的经验。
二、网格策略原理
1. 基本逻辑
网格策略的核心思想是:在价格波动区间内,按固定间隔设置买卖点。
价格 ↑
│ ─────────── 卖出5 (平多/开空)
│ ─────────── 卖出4
│ ─────────── 卖出3
│ ─────────── 卖出2
│ ─────────── 卖出1
│ ─────────── 基准价格
│ ─────────── 买入1
│ ─────────── 买入2
│ ─────────── 买入3
│ ─────────── 买入4
│ ─────────── 买入5 (开多/平空)
价格 ↓
2. 策略参数
| 基准价格 | 网格中心价格 |
| 网格间距 | 相邻网格的价格差 |
| 网格数量 | 上下各多少格 |
| 每格手数 | 每次交易的手数 |
3. 适用场景
- 震荡行情(效果好)
- 趋势行情(可能亏损)
- 波动率稳定的品种
三、TqSdk实现
1. 基础版本
from tqsdk import TqApi, TqAuth, TqBacktest
from datetime import date
# 策略参数
SYMBOL = "SHFE.rb2505"
BASE_PRICE = 3600 # 基准价格
GRID_SIZE = 20 # 网格间距
GRID_COUNT = 10 # 单边网格数量
LOTS_PER_GRID = 1 # 每格手数
api = TqApi(
backtest=TqBacktest(start_dt=date(2025, 1, 1), end_dt=date(2025, 6, 30)),
auth=TqAuth("账户", "密码")
)
quote = api.get_quote(SYMBOL)
position = api.get_position(SYMBOL)
# 计算网格价格
grid_prices = []
for i in range(–GRID_COUNT, GRID_COUNT + 1):
grid_prices.append(BASE_PRICE + i * GRID_SIZE)
# 记录已触发的网格
triggered_grids = set()
while True:
api.wait_update()
if api.is_changing(quote, "last_price"):
current_price = quote.last_price
for i, grid_price in enumerate(grid_prices):
grid_id = i – GRID_COUNT # -10到+10
# 跳过已触发的网格
if grid_id in triggered_grids:
continue
# 价格下穿网格线,买入
if grid_id < 0 and current_price <= grid_price:
api.insert_order(SYMBOL, "BUY", "OPEN", LOTS_PER_GRID, limit_price=grid_price)
triggered_grids.add(grid_id)
print(f"买入信号: 网格{grid_id}, 价格{grid_price}")
# 价格上穿网格线,卖出
if grid_id > 0 and current_price >= grid_price:
if position.pos_long >= LOTS_PER_GRID:
api.insert_order(SYMBOL, "SELL", "CLOSE", LOTS_PER_GRID, limit_price=grid_price)
triggered_grids.add(grid_id)
print(f"卖出信号: 网格{grid_id}, 价格{grid_price}")
2. 改进版本
class GridStrategy:
"""网格策略类"""
def __init__(self, api, symbol, base_price, grid_size, grid_count, lots):
self.api = api
self.symbol = symbol
self.base_price = base_price
self.grid_size = grid_size
self.grid_count = grid_count
self.lots = lots
self.quote = api.get_quote(symbol)
self.position = api.get_position(symbol)
# 初始化网格状态
self.grids = {}
for i in range(–grid_count, grid_count + 1):
price = base_price + i * grid_size
self.grids[i] = {
'price': price,
'triggered': False,
'direction': 'BUY' if i < 0 else 'SELL'
}
def on_tick(self):
current_price = self.quote.last_price
for grid_id, grid in self.grids.items():
if grid['triggered']:
continue
if grid['direction'] == 'BUY' and current_price <= grid['price']:
self._buy(grid_id, grid['price'])
elif grid['direction'] == 'SELL' and current_price >= grid['price']:
self._sell(grid_id, grid['price'])
def _buy(self, grid_id, price):
self.api.insert_order(self.symbol, "BUY", "OPEN", self.lots, limit_price=price)
self.grids[grid_id]['triggered'] = True
print(f"开多: 网格{grid_id}, 价格{price}")
def _sell(self, grid_id, price):
if self.position.pos_long >= self.lots:
self.api.insert_order(self.symbol, "SELL", "CLOSE", self.lots, limit_price=price)
self.grids[grid_id]['triggered'] = True
print(f"平多: 网格{grid_id}, 价格{price}")
# 使用示例
api = TqApi(auth=TqAuth("账户", "密码"))
strategy = GridStrategy(api, "SHFE.rb2505", 3600, 20, 10, 1)
while True:
api.wait_update()
if api.is_changing(strategy.quote):
strategy.on_tick()
四、VnPy实现
VnPy使用策略模板的方式:
from vnpy_ctastrategy import CtaTemplate
class GridStrategy(CtaTemplate):
"""VnPy网格策略"""
# 参数
base_price = 3600.0
grid_size = 20.0
grid_count = 10
lots_per_grid = 1
# 变量
triggered_grids = []
parameters = ["base_price", "grid_size", "grid_count", "lots_per_grid"]
variables = ["triggered_grids"]
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
super().__init__(cta_engine, strategy_name, vt_symbol, setting)
self._init_grids()
def _init_grids(self):
"""初始化网格"""
self.buy_grids = []
self.sell_grids = []
for i in range(1, self.grid_count + 1):
self.buy_grids.append(self.base_price – i * self.grid_size)
self.sell_grids.append(self.base_price + i * self.grid_size)
def on_tick(self, tick):
"""Tick数据回调"""
current_price = tick.last_price
# 检查买入网格
for price in self.buy_grids:
if price not in self.triggered_grids:
if current_price <= price:
self.buy(price, self.lots_per_grid)
self.triggered_grids.append(price)
# 检查卖出网格
for price in self.sell_grids:
if price not in self.triggered_grids:
if current_price >= price and self.pos > 0:
self.sell(price, self.lots_per_grid)
self.triggered_grids.append(price)
def on_bar(self, bar):
"""K线回调"""
pass # 网格策略主要用Tick
五、代码对比
对比表格
| 代码量 | 较少 | 较多 |
| 复杂度 | 简单 | 中等 |
| 灵活性 | 高 | 需遵循模板 |
| 实时性 | 好 | 好 |
| 学习成本 | 低 | 中 |
代码风格差异
TqSdk:脚本式,数据驱动
while True:
api.wait_update()
if api.is_changing(quote):
# 策略逻辑
VnPy:面向对象,回调驱动
class MyStrategy(CtaTemplate):
def on_tick(self, tick):
# 策略逻辑
六、网格策略优化
1. 动态基准价格
def update_base_price(klines, lookback=100):
"""使用近期均价作为基准"""
return klines['close'].iloc[–lookback:].mean()
# 定期更新基准价格
if api.is_changing(klines):
BASE_PRICE = update_base_price(klines)
# 重新计算网格…
2. 自适应网格间距
def calculate_grid_size(klines, atr_period=14, multiplier=0.5):
"""基于ATR计算网格间距"""
high = klines['high']
low = klines['low']
close = klines['close']
tr = pd.concat([
high – low,
abs(high – close.shift(1)),
abs(low – close.shift(1))
], axis=1).max(axis=1)
atr = tr.rolling(atr_period).mean().iloc[–1]
return atr * multiplier
3. 风控增强
class GridStrategyWithRisk(GridStrategy):
"""带风控的网格策略"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.max_position = 10 # 最大持仓
self.max_loss = 5000 # 最大亏损
def on_tick(self):
# 检查风控
if self.position.pos_long >= self.max_position:
print("达到最大持仓,暂停买入")
return
account = self.api.get_account()
if account.float_profit < –self.max_loss:
print("达到止损线,平仓")
self._close_all()
return
# 正常网格逻辑
super().on_tick()
def _close_all(self):
if self.position.pos_long > 0:
self.api.insert_order(self.symbol, "SELL", "CLOSE", self.position.pos_long)
七、回测结果分析
关键指标
def analyze_grid_result(trades):
"""分析网格策略回测结果"""
# 交易统计
total_trades = len(trades)
win_trades = len([t for t in trades if t['pnl'] > 0])
# 盈亏统计
total_pnl = sum(t['pnl'] for t in trades)
max_drawdown = calculate_max_drawdown(trades)
print(f"总交易次数: {total_trades}")
print(f"胜率: {win_trades/total_trades:.1%}")
print(f"总盈亏: {total_pnl:.0f}")
print(f"最大回撤: {max_drawdown:.0f}")
网格策略特点
- 优点:逻辑简单,震荡行情收益稳定
- 缺点:趋势行情可能大幅亏损
八、我的使用经验
作为一个从业二十年的期货量化交易者,分享几点网格策略的经验:
1. 品种选择
网格策略适合波动率稳定、有明显区间的品种。我通常选择:
- 螺纹钢
- 豆粕
- 橡胶
2. 参数设置
- 网格间距:根据ATR设置,不要太小(手续费吃掉利润)
- 网格数量:不要太多,控制最大持仓
- 每格手数:根据资金量设置,留足保证金
3. 工具选择
我用TqSdk实现网格策略,主要因为:
- 代码简洁,逻辑清晰
- Tick数据实时推送
- API容易理解
VnPy的策略模板更规范,适合大型项目。但对于网格这种简单策略,TqSdk够用了。
这只是我个人的选择,每个人需求不同,建议多试用。
九、总结
2026年实现期货网格策略的要点:
网格策略虽然简单,但实际运用中有很多细节。建议先在回测和模拟盘充分验证。
本文仅作为技术介绍,不代表对任何工具的推荐。实际使用请自行评估。
声明:本文基于个人学习经验整理,仅供技术交流参考,不构成任何投资建议。




