Python 量化入门实例

这一章我们直接用约 20 行 Python 代码跑通第一个完整的量化策略。

你会体验到量化交易的完整流程:获取数据、计算信号、可视化买卖点,先建立整体认知,原理和细节留到后面的章节再补。


双均线策略是什么

双均线策略(Moving Average Crossover)是最经典的量化入门策略,思想只有一句话:

当短期均线上穿长期均线时买入(金叉),下穿时卖出(死叉)。

均线是对过去 N 天收盘价取平均,能过滤掉日常波动、显出趋势。

短期均线比长期均线反应快,当短期均线从下方向上穿越长期均线,说明近期价格走强,趋势可能反转向上,这就是"金叉"买入信号;反之则是"死叉"卖出信号。

价格 时间 金叉 · 买入 死叉 · 卖出 LEGEND 短期均线(MA50) 长期均线(MA200) 买点(金叉) 卖点(死叉)

短期均线对价格更敏感,所以它总是围绕长期均线上下穿越,每次穿越就对应一次潜在的调仓机会。

提示:双均线是趋势跟踪策略,在趋势明显的行情中表现较好;在反复震荡的行情中会频繁发出假信号。没有在任何行情下都赚钱的策略,这是学习量化要建立的第一认知。


准备工作

本实例需要用到 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 月的日线数据:

实例

import yfinance as yf

# 股票代码: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() 计算滚动均线,再用条件判断生成买卖信号:

实例

import numpy as np

# 计算短期(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(空值),这是正常现象。


第三步:可视化买卖点

把收盘价、两条均线和买卖信号画在一张图上,直观检验策略行为:

实例

import matplotlib.pyplot as plt

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()

执行以上代码,输出的图表如下,绿色三角是买入信号,红色三角是卖出信号,点击图片放大查看:

可以看到,买点都出现在短期均线上穿长期均线之后,卖点出现在下穿之后,策略行为与我们定义的规则完全一致。


这个策略到底赚不赚钱

画出买卖点只是第一步,策略赚不赚钱需要严谨的回答。

这个问题要用回测来解答:把这套规则放到历史数据上模拟交易,计算年化收益、最大回撤、夏普比率等绩效指标,才能科学评估策略好坏。

提醒:千万不要因为策略在图上看起来很准就直接拿真金白银去交易。未经回测、未考虑交易成本、未经样本外验证的策略,实盘亏损是大概率事件。


更多常见量化策略

双均线只是量化世界的入门款。下表列出了常见的量化策略类型,帮你建立策略版图,其中的大部分思路都会在后续章节中实践:

策略类型 核心思想 典型做法
趋势跟踪 价格趋势一旦形成会延续一段时间 双均线、海龟交易法则、突破策略
均值回归 价格偏离均值过多后会回归平均水平 布林带、配对交易、统计套利
动量策略 过去表现强的资产在未来一段时间继续走强 按近期涨幅排序,买入强势组合
市场中性 同时做多与做空,剥离市场整体涨跌的影响 做多强势股、做空弱势股的组合
事件驱动 特定事件发生后价格有可预期的反应 监控财报、指数调样等事件进行交易
机器学习策略 从大量数据中学习模式,预测未来走势 回归、分类或深度学习模型
高频交易 利用极短时间内的小价差,快速大量交易 做市策略、跨交易所套利

策略的形式可以千变万化,但评价标准是统一的:必须经过充分的回测和风险管理检验。