Python 量化入门实例
这一章我们直接用约 20 行 Python 代码跑通第一个完整的量化策略。
你会体验到量化交易的完整流程:获取数据、计算信号、可视化买卖点,先建立整体认知,原理和细节留到后面的章节再补。
双均线策略是什么
双均线策略(Moving Average Crossover)是最经典的量化入门策略,思想只有一句话:
当短期均线上穿长期均线时买入(金叉),下穿时卖出(死叉)。
均线是对过去 N 天收盘价取平均,能过滤掉日常波动、显出趋势。
短期均线比长期均线反应快,当短期均线从下方向上穿越长期均线,说明近期价格走强,趋势可能反转向上,这就是"金叉"买入信号;反之则是"死叉"卖出信号。
短期均线对价格更敏感,所以它总是围绕长期均线上下穿越,每次穿越就对应一次潜在的调仓机会。
提示:双均线是趋势跟踪策略,在趋势明显的行情中表现较好;在反复震荡的行情中会频繁发出假信号。没有在任何行情下都赚钱的策略,这是学习量化要建立的第一认知。
准备工作
本实例需要用到 4 个库,先安装(环境搭建详见前面的 Python 虚拟环境设置 与 Anaconda 环境搭建 两篇,任选其一即可):
pip install pandas numpy matplotlib yfinance
| 库 | 作用 |
|---|---|
| yfinance | 从 Yahoo Finance 获取股票、指数等金融历史数据 |
| pandas | 数据处理与分析,本实例用它计算均线和信号 |
| numpy | 数值计算基础库,pandas 的底层依赖 |
| matplotlib | 绘制走势图和买卖信号图 |
第一步:获取股票数据
我们以贵州茅台(A 股代码 600519,在 Yahoo Finance 中的代码为 600519.SS)为例,获取 2022 年 5 月到 2023 年 12 月的日线数据:
实例
# 股票代码:600519 为贵州茅台,.SS 后缀表示上海证券交易所
symbol = "600519.SS"
# 下载指定时间范围的日线数据
# multi_level_index=False 让返回的表格使用单层列名,便于初学者操作
data = yf.download(symbol, start="2022-05-01", end="2023-12-01",
progress=False, multi_level_index=False)
# 查看前 5 行:包含开盘价、最高价、最低价、收盘价、成交量
print(data.head())
输出结果如下所示:
Close High Low Open Volume
Date
2022-05-05 1587.689087 1616.210448 1580.757515 1581.639101 3366094
2022-05-06 1549.660645 1572.132020 1539.289240 1568.666234 2859618
2022-05-09 1514.224854 1538.424794 1502.124883 1538.424794 3035182
2022-05-10 1526.489136 1542.711757 1473.612320 1486.567923 4011919
2022-05-11 1528.053467 1545.753979 1514.224929 1516.817780 3031267
返回的是一张以日期为索引的表格(Pandas DataFrame),每一行是一个交易日,这就是量化最原始的"原料"。
注意:代码中默认使用复权后的价格计算均线,可以避免分红除权造成的价格跳空失真。数据获取的更多细节(参数、复权、A 股代码规则)将在获取金融数据一章详细展开。
第二步:计算均线并生成信号
用 pandas 的 rolling().mean() 计算滚动均线,再用条件判断生成买卖信号:
实例
# 计算短期(50 日)与长期(200 日)移动平均线
data["MA50"] = data["Close"].rolling(window=50).mean()
data["MA200"] = data["Close"].rolling(window=200).mean()
# 生成持仓信号:短期均线在长期均线上方记 1(持仓),否则记 -1(空仓)
data["Signal"] = np.where(data["MA50"] > data["MA200"], 1, -1)
# diff() 计算相邻两行信号之差:+2 表示刚发生金叉,-2 表示刚发生死叉
data["Position"] = data["Signal"].diff()
# 打印所有金叉(买入)与死叉(卖出)发生的日期
print("金叉(买入):", [str(d.date()) for d in data[data["Position"] == 2].index])
print("死叉(卖出):", [str(d.date()) for d in data[data["Position"] == -2].index])
输出结果如下所示:
金叉(买入): ['2023-02-27', '2023-07-25'] 死叉(卖出): ['2023-05-29']
策略在 2023 年 2 月底发出买入信号,5 月底卖出,7 月底再次买入。
短短几行代码,一个策略的"大脑"就完成了。把交易思路变成可计算的信号,这正是量化最核心的一步。
注意:均线计算需要足够的历史数据,200 日均线要求至少 200 行数据才会产生数值,所以前面的行会是 NaN(空值),这是正常现象。
第三步:可视化买卖点
把收盘价、两条均线和买卖信号画在一张图上,直观检验策略行为:
实例
plt.figure(figsize=(12, 6))
# 绘制收盘价与两条均线
plt.plot(data["Close"], label="Close Price", linewidth=1)
plt.plot(data["MA50"], label="MA50", linewidth=1.2)
plt.plot(data["MA200"], label="MA200", linewidth=1.2)
# 标记买点:金叉当日,绿色上三角
buy_points = data[data["Position"] == 2]
plt.scatter(buy_points.index, buy_points["MA50"],
marker="^", color="g", s=120, label="Buy Signal", zorder=3)
# 标记卖点:死叉当日,红色下三角
sell_points = data[data["Position"] == -2]
plt.scatter(sell_points.index, sell_points["MA50"],
marker="v", color="r", s=120, label="Sell Signal", zorder=3)
plt.title("Maotai (600519.SS) Dual Moving Average Strategy")
plt.xlabel("Date")
plt.ylabel("Price (CNY)")
plt.legend()
plt.show()
执行以上代码,输出的图表如下,绿色三角是买入信号,红色三角是卖出信号,点击图片放大查看:
可以看到,买点都出现在短期均线上穿长期均线之后,卖点出现在下穿之后,策略行为与我们定义的规则完全一致。
这个策略到底赚不赚钱
画出买卖点只是第一步,策略赚不赚钱需要严谨的回答。
这个问题要用回测来解答:把这套规则放到历史数据上模拟交易,计算年化收益、最大回撤、夏普比率等绩效指标,才能科学评估策略好坏。
提醒:千万不要因为策略在图上看起来很准就直接拿真金白银去交易。未经回测、未考虑交易成本、未经样本外验证的策略,实盘亏损是大概率事件。
更多常见量化策略
双均线只是量化世界的入门款。下表列出了常见的量化策略类型,帮你建立策略版图,其中的大部分思路都会在后续章节中实践:
| 策略类型 | 核心思想 | 典型做法 |
|---|---|---|
| 趋势跟踪 | 价格趋势一旦形成会延续一段时间 | 双均线、海龟交易法则、突破策略 |
| 均值回归 | 价格偏离均值过多后会回归平均水平 | 布林带、配对交易、统计套利 |
| 动量策略 | 过去表现强的资产在未来一段时间继续走强 | 按近期涨幅排序,买入强势组合 |
| 市场中性 | 同时做多与做空,剥离市场整体涨跌的影响 | 做多强势股、做空弱势股的组合 |
| 事件驱动 | 特定事件发生后价格有可预期的反应 | 监控财报、指数调样等事件进行交易 |
| 机器学习策略 | 从大量数据中学习模式,预测未来走势 | 回归、分类或深度学习模型 |
| 高频交易 | 利用极短时间内的小价差,快速大量交易 | 做市策略、跨交易所套利 |
策略的形式可以千变万化,但评价标准是统一的:必须经过充分的回测和风险管理检验。

点我分享笔记