第二十五章:套利策略的自动化部署
说实话,很多做套利的朋友,策略逻辑写得漂亮,回测曲线也好看。但一到实盘,就栽在「部署」这两个字上。
我见过最夸张的一次——有个团队写了三个月的跨品种套利策略,上线第一天晚上服务器宕机了,没人知道。第二天早上起来一看,亏了二十多万。你说冤不冤?
所以这一章,咱们就聊聊怎么把套利策略稳稳当当地跑起来。不是那种「装个Python就能跑」的简单教程,而是真正生产级别的部署方案。
25.1 服务器环境配置
25.1.1 选型建议
我个人习惯用Linux服务器跑套利策略。为什么?稳定、资源占用低、Cron原生支持。
配置方面,我建议至少:
- CPU:4核以上(跨品种套利计算量大)
- 内存:8GB起步(行情数据缓存很吃内存)
- 磁盘:SSD 100GB以上(日志和数据库写入频繁)
- 网络:BGP多线,延迟越低越好
25.1.2 基础环境搭建
嗯,这里我直接给一套我常用的初始化脚本:
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装Python 3.10
sudo apt install python3.10 python3.10-venv -y
# 安装系统依赖
sudo apt install build-essential libssl-dev libffi-dev -y
# 创建虚拟环境
python3.10 -m venv /opt/arbitrage_env
source /opt/arbitrage_env/bin/activate
# 安装核心库
pip install pandas numpy ccxt sqlalchemy psycopg2-binary
pip install requests websocket-client schedule
你想想看,为什么一定要用虚拟环境?因为不同策略可能依赖不同版本的库。我曾经因为升级了pandas版本,导致一个老策略的数据处理逻辑全崩了。从那以后,每个策略我都单独建虚拟环境。
25.2 定时任务(Cron)
25.2.1 为什么用Cron
套利策略的触发时机很关键。有的策略需要每分钟检查一次价差,有的只需要每天收盘后做一次调仓。Cron就是干这个的——定时执行你的Python脚本。
说白了,Cron就是Linux系统自带的「闹钟」。你告诉它「每天下午3点跑这个脚本」,它就会准时执行。
25.2.2 实战配置
先看看我的Cron配置模板:
# 编辑crontab
crontab -e
# 每分钟检查一次价差(高频套利)
* * * * * /opt/arbitrage_env/bin/python /opt/strategies/spread_monitor.py >> /var/log/arbitrage/spread.log 2>&1
# 每小时做一次持仓检查
0 * * * * /opt/arbitrage_env/bin/python /opt/strategies/position_check.py >> /var/log/arbitrage/position.log 2>&1
# 每天收盘后做一次结算(下午3点)
0 15 * * 1-5 /opt/arbitrage_env/bin/python /opt/strategies/settlement.py >> /var/log/arbitrage/settlement.log 2>&1
python script.py,结果发现找不到模块。一定要用绝对路径指定Python解释器!
我曾经犯过一个低级错误——在Cron里用了相对路径,结果脚本一直没跑起来。排查了整整两天才发现是路径问题。嗯,从那以后我所有Cron任务都用绝对路径。
25.2.3 日志重定向
你看上面的配置,每个任务后面都跟了 >> /var/log/arbitrage/xxx.log 2>&1。这行代码的意思是:
>>:把输出追加到日志文件(不覆盖)2>&1:把错误信息也重定向到同一个文件
为什么要这么做?因为Cron默认不会保存输出。如果脚本报错了,你连错误信息都看不到。我建议所有生产环境的Cron任务都加上日志重定向。
25.3 日志监控
25.3.1 日志分级
日志不是随便写的。我一般分三个级别:
| 级别 | 用途 | 示例 |
|---|---|---|
| INFO | 记录正常操作 | 「价差检查完成,当前价差0.23%」 |
| WARNING | 记录异常但不影响运行 | 「交易所API响应延迟超过500ms」 |
| ERROR | 记录需要人工干预的错误 | 「下单失败:余额不足」 |
我建议在Python脚本里用logging模块,而不是print。为什么?因为logging可以控制输出级别、格式化时间戳、还能同时输出到文件和终端。
import logging
import logging.handlers
# 配置日志
logger = logging.getLogger('arbitrage')
logger.setLevel(logging.INFO)
# 文件日志(每天轮转)
file_handler = logging.handlers.TimedRotatingFileHandler(
'/var/log/arbitrage/strategy.log',
when='midnight',
backupCount=30
)
file_handler.setLevel(logging.INFO)
# 终端日志
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
# 格式化
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 使用示例
logger.info('策略启动成功')
logger.warning('交易所A响应延迟偏高')
logger.error('下单失败:余额不足')
25.3.2 日志轮转
日志文件会越来越大。如果不做轮转,一个月下来可能几十个GB。上面代码里的 TimedRotatingFileHandler 就是干这个的——每天生成一个新日志文件,保留最近30天的。
我建议保留至少30天的日志。为什么?因为有些问题可能过了两周才暴露出来,你需要回溯历史日志才能定位。
25.4 异常报警机制
25.4.1 报警分级
不是所有异常都需要报警。我一般分三级:
- P0(紧急):策略停止运行、资金异常、连续亏损超过阈值 → 电话/短信通知
- P1(重要):交易所API异常、网络波动、价差异常 → 微信/钉钉通知
- P2(一般):日志轮转失败、非关键数据缺失 → 邮件通知,次日查看
25.4.2 实现方案
我常用的报警方式有两种:
方案一:钉钉/企业微信机器人
import requests
import json
def send_dingtalk_alert(message, level='INFO'):
webhook_url = 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN'
data = {
"msgtype": "text",
"text": {
"content": f"[{level}] 套利策略报警\n{message}"
}
}
headers = {'Content-Type': 'application/json'}
response = requests.post(webhook_url, data=json.dumps(data), headers=headers)
return response.ok
方案二:短信报警(重要报警用)
def send_sms_alert(message):
# 使用阿里云短信服务
import aliyunsdkcore.client
import aliyunsdkdysmsapi.request.v20170525
# 配置你的AccessKey
client = AcsClient('your-access-key', 'your-access-secret', 'cn-hangzhou')
request = SendSmsRequest.SendSmsRequest()
request.set_PhoneNumbers('13800138000')
request.set_SignName('量化报警')
request.set_TemplateCode('SMS_123456789')
request.set_TemplateParam(json.dumps({"message": message}))
response = client.do_action_with_exception(request)
return response
25.5 知识体系总览
下面这张图,是我对套利策略自动化部署的整体理解:
你看这个结构,从策略脚本到Cron调度,再到执行环境、监控报警,最后落到存储。每一层都环环相扣。少了任何一层,整个系统都不够健壮。
25.6 避坑指南
最后,分享几个我踩过的坑:
- 不要用root跑策略:我曾经用root跑策略,结果一个bug把系统文件删了。现在所有策略都用普通用户运行。
- Cron的PATH问题:Cron的环境变量很少。我习惯在脚本开头手动设置PATH。
- 日志磁盘写满:有一次日志文件把磁盘写满了,策略直接崩溃。从那以后我加了磁盘使用率监控。
- 报警不要只依赖一种方式:钉钉可能宕机,短信可能延迟。我建议至少两种报警渠道。
嗯,自动化部署这件事,说白了就是「把人的不确定性降到最低」。机器不会累,不会忘,不会情绪化。但前提是——你得把环境配好、任务设好、日志管好、报警搭好。
这一套下来,你的套利策略才能真正做到「无人值守,安心睡觉」。