大部分网格策略文章都在讨论“网格密度设多少?”“用等差还是等比?”——这些还停留在“几何图形”的初级层面。真正的进阶策略在讨论两件事:存货管理、微观价格。
一、为什么大部分网格策略不值得收藏?
如果你只会在 100 元买、101 元卖,那你只是一个被动的“流动性提供者”。一旦行情从 100 跌到 80,手里积压的满仓筹码,就是亏损的根源。
值得收藏的 Python 策略必须具备“自我保护机制”。
今天要讲的 AS 模型(Avellaneda-Stoikov),就是给你的网格装上一个根据仓位自动变形的“大脑”。
二、拆解 AS 模型:这一行公式值千金
很多教程一上来就扔微分方程,那是劝退。我们只看对动态网格最有用的那个 偏移公式:
r = s - q × γ × σ²
别被字母吓到,我们拆解一下,告诉你实战中怎么用:
- s (Mid Price):当前市场的买一卖一中间价,这是基准。
- q (Inventory Pressure) —— 核心变量!这是策略的【压力感应器】。
普通人理解:我现在手里有多少货。
做市商理解:我现在有多慌?
实战技巧(归一化):不能直接把持仓数量(比如 10000 手)代入公式。需要定义一个“满仓阈值”:q = 当前持仓 / 满仓阈值
当q=0.1:策略很淡定,挂单几乎不偏。
当q=0.9:策略极度焦虑。这种焦虑通过公式瞬间转化为【价格屠刀】——大幅砍低买一卖一,宁可亏损也要把货甩出去。这就是 AS 模型的智慧:它把“库存风险”数字化成了“价格优势”。 - σ² (Variance):市场波动率的平方。波动越大,就要越怂(偏移越多)。
- γ (Risk Aversion) —— 灵魂参数!风险厌恶系数,这是你需要填的参数:
γ 设得小(如 0.1):头铁,适合震荡市。
γ 设得大(如 10.0):胆小,适合单边风险大的市场。
公式的物理含义算出 r(保留价格)后,你的网格挂单中心不再是 s,而是 r。当你有库存时,你的所有买单和卖单都要向下平移:
- 卖单变低了 → 更容易成交 → 加速去库存
- 买单变低了 → 更难成交 → 防止接飞刀
三、实战:Python 代码怎么写?
可以直接在本地 IDE 中运行的核心 Python 策略逻辑类:
import numpy as np
import pandas as pd
class AS_Grid_Logic:
def __init__(self, risk_gamma=0.5, max_pos=1000):
self.risk_gamma = risk_gamma # 风险厌恶系数(需要回测调优)
self.max_pos = max_pos # 最大允许持仓(用于归一化)
def get_dynamic_grid(self, mid_price, current_pos, volatility, atr):
"""
输入:
mid_price: 当前盘口买一卖一均价
current_pos: 当前持仓数量(绝对值)
volatility: 波动率(工程上可用 std 或 atr 近似)
atr: 平均真实波幅
"""
# 1. 归一化持仓 q (-1.0 ~ 1.0)
if self.max_pos == 0:
return mid_price, mid_price
q = current_pos / self.max_pos
# 2. AS 模型核心:计算偏移量(Spread Shift)
shift = q * self.risk_gamma * (volatility ** 2)
# 3. 计算保留价格(Reservation Price)
reservation_price = mid_price - shift
# 4. 计算网格半宽
half_spread = atr * 0.5
# 5. 生成最终挂单
bid_price = reservation_price - half_spread
ask_price = reservation_price + half_spread
return bid_price, ask_price
# 模拟运行
logic = AS_Grid_Logic(risk_gamma=1.5)
bid, ask = logic.get_dynamic_grid(mid_price=100, current_pos=1000, volatility=2.0, atr=1.0)
print(f"市场价: 100")
print(f"AS 模型挂买单: {bid:.2f} (大幅下移,防止接盘)")
print(f"AS 模型挂卖单: {ask:.2f} (大幅下移,急于止损)")
四、进阶:那些书本上没写的“坑”
如果直接拿上面的代码去跑实盘,可能还是会亏。因为还有两个工程级的坑,通常只有付费课程才会讲:
【坑一】死于费率(Maker 变 Taker)
AS 模型计算出的价格是毫秒级跳变的。如果代码频繁撤单重挂,由于网络延迟,极大概率会误吃单(Taker)。
Taker 费率(通常 0.05%)会瞬间吃光网格利润。
对策:
- 设置最小调整阈值:只有当计算出的 r 变动超过 0.1% 再改单。
- 确保账户有 Maker 返佣,否则别碰高频网格。
【坑二】死于“逆向选择”(Adverse Selection)
当你算出要“降价甩卖”时,往往市场已经大跌了。
“Python 这么慢,怎么可能跑赢做市商?”
真相是:你跑不赢 Citadel,但你可以跑赢用 HTTP 轮询的普通散户。
如果你的数据源慢了 500ms,你的“防御”指令还没发出去,旧的买单就已经被砸穿了。
这就是为什么量化实战中,数据源的速度比语言的速度更重要。 AS 模型是脑子,数据源是神经,缺一不可。
五、数据层选择:为什么低延迟数据源是动态网格的“神经”
在 AS 模型这种对库存变化极度敏感的策略中,数据的实时性和准确性直接决定了防御动作是否有效。市场上一类数据源能够满足动态网格对数据质量的苛刻要求:
| 数据源类型 | 代表 | 特点 | 适用性 |
|---|---|---|---|
| 顶级机构 | Bloomberg, Polygon | 数据质量极高,零延迟 | 价格昂贵(Polygon 专业版 $200/月),对个人开发者 ROI 低 |
| 高性价比聚合商 | TickDB | 统一接口,覆盖全球主要市场;针对国内优化,低延迟;包月计费,不限调用次数 | 适合个人/中小团队,既能满足动态网格对速度的需求,又成本可控 |
| 免费/爬虫接口 | Yahoo Finance | 免费 | 延迟 15-20 分钟,无法用于实时防御性网格 |
TickDB 的定位非常清晰:提供统一的 REST/WebSocket 接口,真正实现“一个账号,全市场覆盖”。一套 API 即可同时获取股票、外汇、贵金属、指数、加密货币等多市场数据,极大降低跨资产策略的集成复杂度。
1. 覆盖全球主流市场,一套接口全搞定
| 资产类别 | 数量 | 示例代码 |
|---|---|---|
| 美股 | 4,023 只 | AAPL.US |
| 港股 | 2,881 只 | 00700.HK |
| A股 | 6,023 只 | 600519.SH |
| 外汇/贵金属 | 1,207 个 | EURUSD, XAUUSD |
| 指数 | 12,708 只 | SPX, HSI |
| 数字货币 | 875 种 | BTCUSDT |
总计超过 27,000 个交易标的,涵盖网格策略可能涉及的所有相关市场。
2. 对开发者友好,像 Stripe 一样丝滑
| 设计特点 | 说明 | 开发者收益 |
|---|---|---|
| 结构清晰 | 文档按功能分类(行情快照、K线、深度等) | 无需在几百页 PDF 里翻找,快速定位所需接口 |
| 多市场统一 | 所有资产返回同一套 JSON 结构,last_price、timestamp 等字段命名一致 |
一套解析逻辑通吃所有市场,告别if market 分支 |
| 双接入方式 | REST API 用于快照,WebSocket 用于实时流 | 示例代码复制即用,不必自己补全工程细节 |
| 可执行错误码 | 错误码附带处理建议,例如 2002 提示“交易品种不存在” | 调试时一眼看出问题所在,不必对照文档猜含义 |
3. 对 AI 友好,让 AI 替你调接口
TickDB 开源了一个 Skill,支持 AI 大模型直接调用行情数据。复制以下指令到支持 Skill 的 AI(如 claude code):
读取 https://github.com/TickDB/tickdb-unified-realtime-marketdata-api/blob/main/SKILL/SKILL.md 并安装为 Skill(名称:tickdb-market-data),然后查询黄金实时价格。
AI 会自动完成 API 调用,返回实时价格。整个过程无需阅读一行文档,无需写一行代码。这种设计让动态网格的底层数据接入变得更加轻量。
六、总结:你的进化路线
读完这篇,应该建立起这样的认知体系:
- 入门级:死板网格。靠天吃饭,震荡赚,单边亏。
- 进阶级(本文):AS 模型思维。引入存货管理,让网格随仓位“变形”,自带止损属性。
- 工程化落地:解决延迟和费率问题,利用低延迟数据源构建实时管道,在概率的缝隙中寻找收益。
收藏建议:别光收藏不练。把代码复制下来,先把 γ 参数设为 0,看看是不是回到了普通网格;再设为 2.0,观察挂单怎么跑。亲手调试过的参数,才是你的 Alpha。

