用 AKShare 拉到第一只 A 股数据,并亲手发现"复权"这个回测造假重灾区
一个能重复使用的数据环境,和一次亲手实验:你会看到同一只茅台、同一天,两种"收盘价"给出完全相反的涨跌信号——并理解为什么。以后你的每一个策略、每一个 Agent 的数据入口,都建立在这节课的地基上。
你的 Mac 默认 python3 是 3.8(太旧),我用 python3.10 在工作区里建了一个虚拟环境 .venv,并装好了 akshare 1.18.64(实测通过)。
它是项目专属的"隔离 Python 包间":这个项目的库装在里面,不污染系统,也不和别的项目抢版本。你以后每个量化项目都应有自己的 .venv。用 python3.10 -m venv .venv 创建,source .venv/bin/activate 进入。
打开终端,进入工作区,激活环境:
cd "~/AI Project/Quant Learning"
source .venv/bin/activate # 命令行前面出现 (.venv) 即成功
工作区里已有我写好的脚本 scripts/first_data.py(欢迎先读一遍源码,每一行都有注释)。运行它:
python scripts/first_data.py
你会看到(这是我在你机器上的真实运行结果):
拉到 242 个交易日的数据,每个交易日有这些字段:
['日期', '股票代码', '开盘', '收盘', '最高', '最低', '成交量',
'成交额', '振幅', '涨跌幅', '涨跌额', '换手率']
一行 ak.stock_zh_a_hist(symbol="600519", period="daily", ...) 就完成了数据对接——这就是 AKShare 的价值:免费、免注册、一个函数拿到东方财富的日线数据。返回的正是你熟悉的 pandas DataFrame,你的数据分析技能从这里直接接管。
脚本还做了一件事:同时拉取不复权(adjust="")和前复权(adjust="qfq")两个版本,并找出它们"走势分歧最大"的一天。结果:
日期 不复权收盘 前复权收盘 不复权涨跌幅% 前复权涨跌幅%
2024-06-18 1521.5 1387.16 -1.30 -1.42
2024-06-19 1501.0 1397.54 -1.35 +0.75 ← 分歧!
2024-06-20 1500.1 1396.64 -0.06 -0.06
2024-06-19 是茅台的除权除息日:每股约 30.88 元的现金分红从股价中扣除。不复权价格因此"凭空跳水"约 2%,显示 -1.35%;但股东其实拿到了分红,真实收益是 +0.75%。前复权把除权前的历史价格整体向下平移,让走势连续、涨跌真实。
| 类型 | adjust 参数 | 做法 | 用途 |
|---|---|---|---|
| 不复权 | "" | 原始成交价 | 看当时真实报价、计算涨跌停价 |
| 前复权 | "qfq" | 以最新价为基准,向前调整历史 | 策略回测、技术分析的标准选择 |
| 后复权 | "hfq" | 以上市日为基准,向后调整至今 | 看长期真实累计收益 |
如果你的回测用不复权数据:除权日的假跳水会被均线、动量等策略误判为"暴跌",触发错误卖出;反过来,有些"神奇策略"的高收益,其实是吃到了复权口径错误的红利。网上大量晒收益的策略,死因就在这里。记住默认动作:回测用前复权,并在代码注释里写明口径。
| 库 | 特点 | 何时用 |
|---|---|---|
| AKShare | 免费免注册,接口极全(行情/宏观/新闻/公告) | 日常主力,本课程默认 |
| Tushare Pro | 规范稳定,需 token,高级接口要积分 | 需要长期稳定数据时 |
| BaoStock | 免费免注册,分钟级 K 线完善 | 分钟线备用源 |
接口礼仪(重要):这些免费库本质上是帮你爬取各财经网站,调用太频繁会被临时封 IP。纪律:批量拉取时每次间隔 0.3 秒以上;数据落地存 CSV/数据库(脚本已把茅台数据存到 data/600519_qfq_2024.csv),不重复拉同一份数据。这也是第 6 课"异动监控 Agent"轮询设计时的核心约束。
凭记忆作答——答错比答对更能加固记忆。
把脚本里的 SYMBOL 改成你持有或关注的一只股票(注意:上交所 6 开头、深交所 0/3 开头,只填 6 位数字),重跑脚本。看看它今年有没有除权日?如果有,想想第 1 课的问题:除权日"跳水"那天买入的人,当天能止损吗?
第 3 课 · 让 LLM 读懂政策与新闻:用 AKShare 拉取新闻/公告文本,写你的第一个"情绪打分" Prompt——Agent 辅助决策的第一步。
有任何不清楚的地方(比如复权的计算细节、DataFrame 操作),直接问我——我是你的老师。