
这篇教程解决一个具体问题:怎么让量化策略的数据更新和策略运行全自动,不用每天手动操作。跟着做完,你会在云服务器上配好一套 crontab 定时任务:每天收盘后自动下载当天股票数据 → 更新数据库 → 运行策略 → 把信号推送到你手机。配好之后连续一个多月我没碰过它,每天下午 5 点信号准时到。
先交代下我的情况:我做的是股票中低频策略,日线级别,每天收盘后跑一次,输出第二天的调仓信号。
这个活儿的性质决定了它非常适合自动化——流程固定、时间固定、频率固定。但我之前是怎么干的呢?
每天下午 4 点半,定个闹钟,打开电脑,手动双击运行脚本。
听起来还行?那你试试坚持一年。出差怎么办?开会怎么办?忘了怎么办?
上个月我出差三天,第三天晚上才想起来数据没更新、策略没跑。打开一看,错过了一次调仓信号,那个信号第二天涨了 4%。
那天晚上我在酒店里,咬着牙把整套东西搬到了腾讯云轻量应用服务器上,用 crontab 配了定时任务。
结果这一个多月:我没管过它一次。 每天下午 5 点 05 分,微信准时收到当天的策略信号。人在外面浪,机器在云服务器上打工。
这才是量化该有的样子。
先说清楚一件事:Windows 也有任务计划程序,Mac 也有 launchd,本地的定时任务技术上完全可行。
但"可行"和"靠谱"是两码事。
我之前在 Windows 上用过任务计划程序跑这个流程,三个月里翻过四次车:一次是系统更新重启后任务莫名其妙没触发;一次是电脑睡眠了任务直接跳过;一次是我妈来家里把电脑关机了;还有一次更离谱——任务跑了,但电脑连的 Wi-Fi 断了,脚本下载数据失败,静默退出,我压根不知道那天没跑成。
本地定时任务的根本问题:电脑不一定开着,开着不一定联网,联网了任务失败了也没人通知你。
云服务器把这三个问题全解决了:
腾讯云轻量应用服务器 2 核 2G 就够(这个活儿不重,下载数据+跑个日线策略),一天不到一块钱。
自动化之前,得先有一个能手动跑通的流程。我的流程拆成两个脚本:
第一个脚本 update_data.py:用 akshare 下载当天数据,追加到本地数据库
import akshare as ak
import sqlite3
from datetime import datetime
def update():
today = datetime.now().strftime("%Y-%m-%d")
conn = sqlite3.connect("/home/ubuntu/quant/data/stocks.db")
# 获取我的自选股列表(实际是从配置文件读)
symbols = ["600519", "000001", "300750"]
for symbol in symbols:
df = ak.stock_zh_a_hist(symbol=symbol, period="daily",
start_date=today.replace("-", ""),
end_date=today.replace("-", ""), adjust="qfq")
if not df.empty:
df.to_sql("daily_data", conn, if_exists="append", index=False)
print(f"{symbol} 更新 {len(df)} 条")
conn.close()
if __name__ == "__main__":
update()第二个脚本 run_strategy.py:读数据、跑策略、输出信号、推送微信
import subprocess
# ... 策略逻辑省略 ...
# 算出信号后,推送到微信(用的Server酱,免费够用)
def push_wechat(title, content):
# Server酱的API,替换成你自己的SendKey
key = "你的SendKey"
subprocess.run(["curl", f"https://sctapi.ftqq.com/{key}.send",
"-d", f"title={title}", "-d", f"desp={content}"])手动跑两遍,确认没问题了,再上定时任务。永远不要定时一个没手动验证过的脚本,这是铁律。
登录云服务器,输入:
crontab -e第一次用会让你选编辑器,选 nano 或 vim 都行。然后写入:
# 每个交易日17:00更新数据(先按周一到周五跑,节假日后面处理)
0 17 * * 1-5 /home/ubuntu/venv/bin/python /home/ubuntu/quant/update_data.py >> /home/ubuntu/quant/logs/update.log 2>&1
# 17:05运行策略并推送信号
5 17 * * 1-5 /home/ubuntu/venv/bin/python /home/ubuntu/quant/run_strategy.py >> /home/ubuntu/quant/logs/strategy.log 2>&1保存退出。就这么点东西,定时任务就配好了。
但这里面的门道,每一个都是我趟出来的,逐条说:
1. 必须用绝对路径
/home/ubuntu/venv/bin/python 而不是 python。crontab 执行环境和你 SSH 登录的环境不一样,它没有你的 PATH,直接写 python 会报 command not found。这是新手第一大坑。
2. 必须重定向日志
>> xxx.log 2>&1 这一坨的意思是:把标准输出和错误输出都追加到日志文件。不配这个,脚本跑没跑、成没成、报什么错,你全都不知道,定时任务就变成了黑盒。
3. 时间留够间隔
数据更新 17:00,策略 17:05,中间隔 5 分钟。akshare 下载速度不慢,但给上游数据源的延迟留点余量——收盘后数据不是立刻就有,我一般等 1 小时以上。
4. 为什么按周一到周五跑而不是每天
周六周日跑会下载到空数据,虽然脚本里做了 if not df.empty 判断不会出错,但日志里一堆空跑记录很烦。法定节假日的问题后面讲。
验证配置生效:
crontab -l # 列出当前定时任务配好的第二天,我特意等到下午 5 点 10 分,打开微信——没有消息。
第一反应是策略出错了,上去翻日志:
cat /home/ubuntu/quant/logs/update.log日志文件压根不存在。
这说明任务根本没执行。问题出在哪?查了一圈,答案是另一个经典大坑:
云服务器默认时区/时间不对。
date我一看,服务器显示的是 UTC 时间,比北京时间慢 8 小时。我在 crontab 里写的"17:00",服务器理解成 UTC 的 17:00,也就是北京时间凌晨 1 点。
修复很简单:
sudo timedatectl set-timezone Asia/Shanghai
date # 再确认一下,显示 CST 就对了改完之后,第三天下午 5 点 05 分,微信准时收到了策略信号。
那一刻我在地铁上,看着手机上的调仓信号,心里就一句话:这班加得值。
所以记住:配 crontab 之前,先 date 看时区。 这 5 秒钟能省你一小时排查。
跑顺了之后,我又陆续加了三个东西,都是实用向的:
1. 节假日判断
周一到周五不代表交易日,碰到国庆、春节,脚本会白跑。我在 update_data.py 开头加了个交易日判断,用 akshare 的交易日历:
import akshare as ak
from datetime import datetime
def is_trading_day():
today = datetime.now().strftime("%Y-%m-%d")
cal = ak.tool_trade_date_hist_sina()
return today in cal["trade_date"].astype(str).values
if not is_trading_day():
print("非交易日,退出")
exit(0)2. 失败告警
脚本开头 try,失败的时候 except 里也推一条微信:"今天数据更新失败了,原因:xxx"。自动化系统最重要的不是成功时多安静,而是失败时必须叫唤。
3. 日志轮转
日志一直追加下去,一年后就是个几百 M 的文件。用系统自带的 logrotate,或者简单粗暴一点,每月在 crontab 里加一条清理:
0 0 1 * * find /home/ubuntu/quant/logs -name "*.log" -size +10M -delete现在这套系统跑了一个多月,我的日常变成:
数据始终是最新的,策略一天不落,失败会主动告警。我在云服务器上花的唯一时间,就是那次踩坑排查时区。
维度 | 本地手动/本地定时 | 云服务器 crontab |
|---|---|---|
每天操作 | 开电脑手动跑,5分钟 | 零操作 |
出差/忘跑 | 直接断档 | 不存在 |
电脑睡眠/关机 | 任务跳过 | 7×24在线 |
失败通知 | 没有,默默失败 | 微信告警 |
数据一致性 | 看心情 | 每天准时更新 |
成本 | 电费+每天5分钟 | 一天不到一块钱 |
做量化的人总爱琢磨策略怎么优化,但我越来越觉得,先把基础设施自动化,是性价比最高的优化。策略从年化 15% 提到 18% 可能要半年,而把"每天手动跑脚本"自动化掉只要一个晚上,还杜绝了人为疏漏。
给不同朋友:
放心冲。机器值夜班,你睡你的觉。
Q:crontab 定时任务不执行怎么排查?
按顺序查四项:第一,date 确认服务器时区是不是 Asia/Shanghai(最常见的坑);第二,crontab 里命令是否用了绝对路径(包括 python 解释器本身);第三,是否配置了 >> 日志 2>&1 输出重定向,看日志文件有没有内容;第四,systemctl status cron 确认 cron 服务本身在运行。
Q:crontab 里的环境变量和我 SSH 登录时不一样吗?
对,这是 crontab 最经典的坑。cron 任务的执行环境非常精简,没有你 shell 里的 PATH 和虚拟环境配置。所以脚本里要用绝对路径调用 python(如 /home/ubuntu/venv/bin/python),脚本内部如果需要环境变量也要自己 export。
Q:云服务器跑定时任务需要什么配置?
每天跑数据更新加日线策略这种轻量任务,2 核 2G 的腾讯云轻量应用服务器足够,一天不到一块钱。只有当你要下载全市场分钟级数据或跑大型回测时才需要升配置。
Q:定时任务失败了怎么通知我?
在脚本里加 try-except,失败时调用微信推送接口(如 Server酱)发告警消息。自动化系统的核心原则是:成功可以安静,失败必须叫唤,否则和没自动化一样。
Q:怎么让定时任务只在交易日执行?
crontab 只能按"周一到周五"粗筛,法定节假日要在脚本里判断:用 akshare 的交易日历接口(tool_trade_date_hist_sina),脚本开头先判断今天是不是交易日,不是就直接退出。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。