
跑一个量化策略需要的不只是策略本身——还需要一套支撑它运行、监控它状态、在出问题时及时告警的工具链。这篇文章分享我的完整工具栈,从策略执行到告警通知。
整体架构
策略层(Python)
↓ 交易指令
Binance API
↓ 执行结果
状态文件 / CF KV
↓ 指标
Prometheus + node_exporter
↓ 存储
Grafana 可视化
↓ 告警规则
Alertmanager → Telegram
策略执行层
技术栈
- 语言:Python 3.11
- Binance SDK:
python-binance - 定时任务:APScheduler 或系统 cron
- 依赖管理:
requirements.txt+ venv
目录结构
quant/
├── strategy/
│ ├── main.py # 主策略逻辑(信号生成 + 下单)
│ ├── signals.py # 指标计算(技术指标库)
│ └── risk.py # 仓位管理、止损逻辑
├── exchange/
│ └── binance_client.py # Binance API 封装
├── monitor/
│ └── exporter.py # 状态指标写入 Prometheus 格式
├── config/
│ └── settings.py # 配置(从环境变量读取)
└── run.py # 入口
关键代码:状态指标暴露
策略运行时,把关键指标写成 Prometheus textfile 格式,供 node_exporter 抓取:
# monitor/exporter.py
import os
import time
METRICS_FILE = "/var/lib/node_exporter/textfile_collector/quant.prom"
def write_metrics(data: dict):
"""
data 示例:
{
"pnl_total": 12.5, # 累计收益率 %
"pnl_today": 0.8, # 今日收益率 %
"position": 1, # 1=多, -1=空, 0=空仓
"last_signal_ts": 1776200000, # 最后信号时间戳
"last_run_ts": 1776235000, # 策略最后运行时间
}
"""
lines = [
'# HELP quant_pnl_total 累计收益率(百分比)',
'# TYPE quant_pnl_total gauge',
f'quant_pnl_total {data["pnl_total"]}',
'',
'# HELP quant_pnl_today 今日收益率(百分比)',
'# TYPE quant_pnl_today gauge',
f'quant_pnl_today {data["pnl_today"]}',
'',
'# HELP quant_position 当前持仓方向 (1=多,-1=空,0=空仓)',
'# TYPE quant_position gauge',
f'quant_position {data["position"]}',
'',
'# HELP quant_last_signal_timestamp 最后信号时间',
'# TYPE quant_last_signal_timestamp gauge',
f'quant_last_signal_timestamp {data["last_signal_ts"]}',
'',
'# HELP quant_last_run_timestamp 策略最后运行时间',
'# TYPE quant_last_run_timestamp gauge',
f'quant_last_run_timestamp {int(time.time())}',
'',
]
tmp = METRICS_FILE + ".tmp"
with open(tmp, "w") as f:
f.write("\n".join(lines))
os.rename(tmp, METRICS_FILE)
服务器配置
选择
量化策略对服务器的核心要求:
- 稳定:不能随意宕机,24/7 运行
- 延迟低:离 Binance 服务器近(新加坡或东京),下单延迟更低
- 独立:不和其他高负载任务共享
我用 AWS 新加坡节点(aws-sg),Binance 主服务器在新加坡,下单延迟 1-5ms。
systemd 守护进程
不要用 nohup 跑策略,用 systemd:
# /etc/systemd/system/quant-strategy.service
[Unit]
Description=Quant Strategy
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/quant
ExecStart=/home/ubuntu/quant/venv/bin/python run.py
Restart=always
RestartSec=10
EnvironmentFile=/home/ubuntu/quant/.env
[Install]
WantedBy=multi-user.target
systemctl enable quant-strategy
systemctl start quant-strategy
systemctl status quant-strategy
策略崩溃会自动重启,重启间隔 10 秒。
环境变量管理
API Key 放 .env 文件,不提交到 Git:
# .env(只有 600 权限)
BINANCE_API_KEY=xxxx
BINANCE_API_SECRET=xxxx
TELEGRAM_BOT_TOKEN=xxxx
TELEGRAM_CHAT_ID=xxxx
# settings.py
from dotenv import load_dotenv
import os
load_dotenv()
BINANCE_API_KEY = os.environ["BINANCE_API_KEY"]
BINANCE_API_SECRET = os.environ["BINANCE_API_SECRET"]
Prometheus 监控配置
在 prometheus.yml 添加策略服务器的 node_exporter:
scrape_configs:
- job_name: node-remote-linux
static_configs:
- targets:
- 你的策略服务器IP:9100
node_exporter 默认会自动采集 /var/lib/node_exporter/textfile_collector/*.prom 里的指标,不需要额外配置。
Grafana Dashboard
量化策略的核心监控面板包含:
收益区(上方)
- 累计收益率时序曲线
- 今日收益 Stat 卡片
- 当前持仓方向(多/空/空仓)
风险区(中间)
- 最大回撤(Max Drawdown)
- 近 30 日日收益柱状图
- 夏普比率(年化)
健康区(下方)
- 策略最后运行时间(距现在多久)
- 最后信号时间(距现在多久)
- 心跳状态(绿色=正常,红色=异常)
关键面板:策略心跳
# Grafana PromQL
(time() - quant_last_run_timestamp) / 60
这个查询显示策略最后运行距现在多少分钟。配合阈值颜色:
- < 65 分钟:绿色(正常,小时级策略)
- 65-120 分钟:黄色(轻微延迟)
120 分钟:红色(策略可能挂了)
告警配置
Alertmanager + Telegram
在 alerts.yml 里定义告警规则:
groups:
- name: quant-alerts
rules:
# 策略心跳超时
- alert: QuantHeartbeatTimeout
expr: (time() - quant_last_run_timestamp) > 7200
for: 5m
labels:
severity: critical
annotations:
summary: "量化策略心跳超时"
description: "策略超过 2 小时未运行,请检查服务器状态"
# 今日大幅亏损
- alert: QuantLargeLoss
expr: quant_pnl_today < -3
for: 1m
labels:
severity: warning
annotations:
summary: "今日亏损超过 3%"
description: "当日收益率 {{ $value }}%,请关注"
Telegram 告警模板(在 alertmanager.yml 里配置):
receivers:
- name: telegram
telegram_configs:
- bot_token: "你的BOT_TOKEN"
chat_id: 你的CHAT_ID
message: |
🚨 {{ .GroupLabels.alertname }}
{{ range .Alerts }}
{{ .Annotations.summary }}
{{ .Annotations.description }}
{{ end }}
在策略代码里直接推送告警
除了 Alertmanager,策略代码里也可以直接推 Telegram:
import requests
def send_telegram(message: str):
bot_token = os.environ["TELEGRAM_BOT_TOKEN"]
chat_id = os.environ["TELEGRAM_CHAT_ID"]
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
requests.post(url, json={"chat_id": chat_id, "text": message})
# 下单后推送
send_telegram(f"📊 信号:{direction}\n价格:{price}\n仓位:{size}")
总结:工具选型逻辑
| 工具 | 替代方案 | 选这个的原因 |
|---|---|---|
| Python | Go、JavaScript | 量化生态最丰富(pandas、ta-lib 等) |
| Binance python-binance | 自己封装 REST | 官方 SDK,省去重复造轮子 |
| systemd | supervisor、PM2 | 系统自带,稳定,日志集中管理 |
| Prometheus + node_exporter | InfluxDB + Telegraf | 已有监控栈,复用,不引入新组件 |
| Alertmanager | 自己写告警脚本 | 支持规则、静默、分组,功能完整 |
| Telegram | 邮件、钉钉 | 手机推送及时,API 简单 |
→ 查看 北极星策略介绍 → 查看 Binance API 从零到第一笔下单 → 查看 Prometheus + Grafana VPS 监控搭建
📷 封面图 · Flux Schnell AI 生成 · panshi.io 品牌风格