
这篇教程解决的问题:在云服务器上搭一个属于自己的A股分钟线数据库,每天自动采集、自动入库、随时可查可回测。做完你会得到:一台装着MySQL的云服务器、一套我实际在用的分钟线表结构、每天定时跑的采集脚本,以及最重要的——一份真实的硬盘容量测算(大家最关心的"一年要多少硬盘",文末FAQ有明确答案)。我用的是腾讯云轻量应用服务器2核4G、60G系统盘,存全市场分钟线绰绰有余。
我做A股量化两年多,数据这块一直是个心病。之前的方式说出来都是泪:本地一堆CSV文件,按日期分文件夹,找一只股票半年的分钟线要翻半天目录,pandas读个几十兆的CSV风扇就开始起飞。
两个月前,我第N次因为"CSV文件命名规则不统一"写了个查找脚本的时候,突然觉得自己特别蠢:我一个写代码的,为什么要用文件夹管理数据?
于是决定搭个正经数据库。本以为MySQL运维很复杂,结果一个晚上搭起来,用到现在两个月,我只想说:早知道这么爽,我一年前就该干这事。
先交代一下我的旧方案有多烂,估计很多朋友能照镜子。
我本地"数据文件夹"的真实状况:akshare下载的分钟线,一个交易日一个CSV,两年下来4万多个文件,Finder打开文件夹要转圈10秒;同一只股票的数据散在几百个文件里,回测前要写个合并脚本跑5分钟;有一次误删了一个月份的文件夹,哭着重新下载,akshare限流,下了三个晚上。最崩溃的是笔记本256G的硬盘,数据加缓存吃了60多G,系统天天报"磁盘空间不足"。
这套"文件管理系统"的尽头,就是数据库。这个道理我懂,只是一直懒得动——直到硬盘报警那天。
上上个月某个周三晚上,腾讯云控制台,轻量应用服务器,2核4G、Ubuntu 22.04。数据库吃内存和磁盘IO,4G内存对MySQL是舒服线。价格一天不到一块钱。
SSH连上,装MySQL:
sudo apt update && sudo apt install -y mysql-server
sudo mysql_secure_installation第二条是安全初始化向导,设root密码、删掉匿名用户、禁远程root登录,跟着提示按几个Y就完了。装完验证:
sudo systemctl status mysql绿色的 active (running) 跳出来,MySQL就在机房里跑起来了。全程10分钟。
说个对比:三年前我在自己Windows电脑上装MySQL,安装向导卡住、服务起不来、3306端口被占用,搞了一晚上最后用的还是别人打包的绿色版。这次在干净的Ubuntu上,两行命令,10分钟。Linux服务器装数据库的友好度,跟桌面系统完全不是一个物种。
这是全文最值钱的部分,直接抄我的。分钟线表:
CREATE DATABASE quant DEFAULT CHARSET utf8mb4;
USE quant;
CREATE TABLE min_bar (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
ts_code VARCHAR(12) NOT NULL COMMENT '股票代码',
trade_time DATETIME NOT NULL COMMENT '分钟时间',
open DECIMAL(10,3),
high DECIMAL(10,3),
low DECIMAL(10,3),
close DECIMAL(10,3),
vol BIGINT COMMENT '成交量(股)',
amount DECIMAL(18,2) COMMENT '成交额(元)',
UNIQUE KEY uk_code_time (ts_code, trade_time),
KEY idx_time (trade_time)
) ENGINE=InnoDB;设计要点说三个:
(ts_code, trade_time) 联合唯一索引——防止重复入库,重复采集直接 INSERT IGNORE,天然幂等;这个结构我跑了两个月,单表目前3000多万行,常用查询都是毫秒级。
采集用akshare,核心逻辑(精简版,可直接跑):
import akshare as ak
import pymysql
from datetime import date
conn = pymysql.connect(host="localhost", user="quant",
password="你的密码", database="quant")
cur = conn.cursor()
def save_minute(ts_code):
df = ak.stock_zh_a_minute(symbol=ts_code, period="1",
adjust="qfq")
rows = [(ts_code, r.day, r.open, r.high, r.low,
r.close, r.volume, r.amount)
for r in df.itertuples()]
cur.executemany(
"INSERT IGNORE INTO min_bar"
"(ts_code,trade_time,open,high,low,close,vol,amount)"
" VALUES (%s,%s,%s,%s,%s,%s,%s,%s)", rows)
conn.commit()
# 示例:采集自选股列表
for code in ["sh600519", "sz300750", "sh510300"]:
save_minute(code)如您需求,可以到腾讯官网购买体验:
腾讯云国内官网云服务器大促活动:https://cloud.tencent.com/act/pro/featured-202607?fromSource=gwzcw.17760458.17760458.17760458
腾讯云国际站云服务器促销活动:https://www.tencentcloud.com/act/pro/promo?fromSource=intl.17760459.17760459.17760459
然后crontab挂个定时,交易日15:30自动跑:
30 15 * * 1-5 /usr/bin/python3 /root/collect.py >> /root/collect.log 2>&1从那天起,每天下午3点半,我的数据库就自动"吃饭",我什么都没干。两个月了,一次没漏。
翻车环节。
搭好第二周,我一时兴起想导全市场5000只股票的日线历史数据进去,写了个循环猛插。插到大概800只的时候,数据库直接挂了——systemctl status 一看,MySQL进程没了。
查日志 /var/log/mysql/error.log,真相大白:OOM,内存爆了。MySQL默认配置是给大机器用的,innodb_buffer_pool_size 默认值在这台4G内存的机器上根本不合适,大批量写入直接把内存吃光,被系统杀掉了。
解决办法,改配置 /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
innodb_buffer_pool_size = 1G
max_connections = 100sudo systemctl restart mysql,重新跑导入,稳如老狗,全市场日线一次性导完。
所以给大家的铁律:轻量服务器上跑MySQL,装完第一件事就是改buffer_pool_size,4G内存的机器给1G是正解。别信默认值,默认值不是给咱们这种小机器准备的。
现在我的回测流程是这样的:
SELECT trade_time, close FROM min_bar
WHERE ts_code='sh600519'
AND trade_time BETWEEN '2026-06-01' AND '2026-08-01';0.3秒,数据出来,pandas一接,开始回测。
以前干同样的事:找到正确的文件夹→确认文件命名→读几十个CSV→concat→清洗列名,5分钟起步,还经常因为某天的文件缺列报错。
数据在库里、在云上,还有个意外之喜:我在外面用iPad都能连上去查数(开了SSH隧道,安全),上次在朋友家聊到一个策略想法,当场掏出手机查了十分钟数据验证——那种"数据随身带"的感觉,用CSV时代想都不敢想。
挑几个刺:
不影响核心体验。
维度 | 本地CSV文件夹 | 云服务器+MySQL |
|---|---|---|
查一段数据 | 找文件+合并,5分钟 | 一条SQL,0.3秒 |
数据文件 | 4万多个CSV,Finder转圈 | 一张表,干干净净 |
防重复/防丢 | 全靠自觉,误删过一整月 | 唯一索引,天然幂等 |
随时随地查 | 数据绑死在笔记本 | iPad都能连 |
硬盘焦虑 | 256G天天报警 | 60G几年用不完 |
成本 | 我的时间和眼泪 | 一天不到一块钱 |
一句话:量化玩家的数据,就该有个正经的家。
还在用CSV的朋友,放心冲,一个晚上搭起来,我上面的表结构和脚本直接抄。纯新手建议先只采十几只自选股跑一周,熟悉流程再扩到全市场;老鸟注意两件事:装完先改 innodb_buffer_pool_size,采集脚本加重试告警。这两点记住,基本不会翻车。
如您需求,可以到腾讯官网购买体验:
腾讯云国内官网云服务器大促活动:https://cloud.tencent.com/act/pro/featured-202607?fromSource=gwzcw.17760458.17760458.17760458
腾讯云国际站云服务器促销活动:https://www.tencentcloud.com/act/pro/promo?fromSource=intl.17760459.17760459.17760459
Q:MySQL存A股分钟线一年要多少硬盘?
给你实测数字:一行分钟线记录约60-80字节(含索引),一只股票一年约6万条分钟线,即约4-5MB。存100只股票一年约500MB,全市场5000只一年约20-25G。轻量服务器60G系统盘存全市场两年没问题,存自选股组合更是几年用不完。
Q:云服务器上跑MySQL,2核4G够用吗?
够,但必须改配置:把 innodb_buffer_pool_size 调到1G左右。默认值不适合小内存机器,大批量写入会OOM把数据库搞崩——这是我实测踩过的坑,改完之后全市场数据导入都稳。
Q:云服务器上的MySQL能被自己本地电脑远程连吗?
能,但强烈建议不要直接开放3306端口到公网,用SSH隧道连接(ssh -L 3307:localhost:3306 服务器IP),安全性和便利性兼得。公网暴露数据库端口等于把家门钥匙挂门口。
Q:用akshare在云服务器上采集A股数据会被封IP吗?
正常频率采集不会。分钟线采集一次全市场约几分钟,数据接口都能承受。注意两点:循环里加0.3-0.5秒sleep、失败加重试,别写暴力并发循环,就不会有问题。
Q:分钟线数据用什么表结构最合理?
核心就两点:(股票代码, 时间) 建联合唯一索引防重复,时间列单独建索引方便截面查询。价格用DECIMAL别用FLOAT,避免浮点精度污染回测。我文中的表结构单表3000万行查询毫秒级,可直接抄。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。