第二章:环境搭建——Python量化生态与工具选型
说实话,搭建量化回测环境这件事,我踩过的坑比写过的策略还多。刚开始做因子研究那会儿,我天真地以为装个Anaconda就能搞定一切。结果呢?数据存得乱七八糟,回测跑得比乌龟还慢,最后连自己都搞不清哪个版本是对的。
这一章,我就把这几年的经验掰开揉碎讲给你听。咱们从Python生态说起,再到数据库选型,最后聊聊回测框架。嗯,跟着我的节奏走,保证你少走弯路。
2.1 Python量化三件套:pandas、numpy、matplotlib
这三样东西,说白了就是量化分析的左膀右臂。我个人的习惯是,不管做什么项目,先把这三个库的版本锁死。为什么?因为版本不兼容导致的bug,我曾经排查了整整两天。
2.1.1 pandas——数据处理的灵魂
pandas在量化里的地位,就像地基之于高楼。你想想看,日线数据、分钟数据、因子值、收益率……哪样离得开DataFrame?
我个人最常用的几个操作:
- 数据读取:read_csv、read_sql,注意dtype参数一定要指定,否则日期和浮点数会搞混
- 时间序列处理:resample、shift、pct_change,这三个函数能解决80%的因子计算需求
- 合并与对齐:merge、join,多因子分析时特别重要
避坑指南:我曾经在merge时忘记指定how参数,结果左连接变成了内连接,丢掉了整整三年的数据。从那以后,我写merge必写how='left'。
import pandas as pd
import numpy as np
# 读取日线数据,指定日期列和数据类型
df = pd.read_csv('stock_data.csv',
parse_dates=['trade_date'],
dtype={'close': np.float64, 'volume': np.int64})
# 计算5日收益率
df['ret_5d'] = df.groupby('stock_code')['close'].pct_change(5)
# 按日期和股票代码排序
df.sort_values(['trade_date', 'stock_code'], inplace=True)
2.1.2 numpy——速度的保证
numpy的向量化运算,说白了就是让Python跑出C语言的速度。我在做因子标准化时,如果数据量超过10万行,用pandas的apply会慢到怀疑人生。换成numpy的向量化操作,速度能快100倍。
记住这几个核心操作:
- np.where:条件筛选,比pandas的loc快得多
- np.nanmean/np.nanstd:处理缺失值的均值、标准差
- np.corrcoef:计算相关系数矩阵,因子分析必备
小技巧:做因子中性化处理时,先用numpy做矩阵运算,再转回pandas的DataFrame。这样既保留了速度,又方便后续分析。
2.1.3 matplotlib——可视化利器
很多人觉得matplotlib画图丑,其实是你没用对。我习惯用matplotlib + seaborn的组合,一个负责底层控制,一个负责美化样式。
回测中最常用的几张图:
- 净值曲线:看策略整体表现
- 回撤曲线:看风险控制能力
- 因子收益分布:看因子是否有效
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体,避免乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 画净值曲线
plt.figure(figsize=(12, 6))
plt.plot(nav.index, nav.values, linewidth=2, color='steelblue')
plt.title('策略净值曲线')
plt.xlabel('日期')
plt.ylabel('净值')
plt.grid(True, alpha=0.3)
plt.show()
2.2 数据库选型:MySQL vs ClickHouse
数据库选型这个问题,我纠结了整整一个月。当时手上有500G的日线数据,用MySQL存得下,但查询慢得像蜗牛。换ClickHouse呢?学习成本又高。
后来我想明白了:没有最好的数据库,只有最合适的场景。
| 对比维度 | MySQL | ClickHouse |
|---|---|---|
| 数据量 | 适合百万级 | 适合亿级 |
| 查询速度 | 秒级 | 毫秒级 |
| 写入速度 | 一般 | 极快(列式存储) |
| 学习成本 | 低 | 中 |
| 适用场景 | 小规模回测、策略管理 | 大规模因子库、高频数据 |
注意:ClickHouse不支持事务,也不适合频繁的更新操作。如果你需要频繁修改历史数据,MySQL更合适。
我个人建议:初期用MySQL,数据量超过1亿行再迁移到ClickHouse。别一上来就搞ClickHouse,学习曲线太陡,容易劝退。
2.3 回测框架选型:Backtrader vs Zipline
回测框架的选择,直接决定了你后面写策略的效率。我用过Zipline,也用过Backtrader,最后长期用的是Backtrader。为什么?
Zipline的问题在于:数据格式太死板。它强制要求用特定的数据格式,如果你有自己的数据源,适配起来很痛苦。我当年为了把A股数据塞进Zipline,写了整整一周的转换脚本。
Backtrader就好多了:
- 数据灵活:支持CSV、pandas DataFrame、数据库等多种数据源
- 策略编写简单:继承Strategy类,重写next方法就行
- 回测速度快:纯Python实现,但性能足够
- 文档完善:社区活跃,遇到问题容易找到答案
import backtrader as bt
class MyStrategy(bt.Strategy):
def __init__(self):
self.sma = bt.indicators.SimpleMovingAverage(
self.data.close, period=20)
def next(self):
if self.data.close[0] > self.sma[0]:
self.buy(size=100)
elif self.data.close[0] < self.sma[0]:
self.sell(size=100)
# 运行回测
cerebro = bt.Cerebro()
cerebro.addstrategy(MyStrategy)
cerebro.adddata(data)
cerebro.run()
我的建议:如果你是新手,直接选Backtrader。等你有了一定经验,再考虑Zipline或者其他框架。别在框架选型上浪费太多时间,策略本身才是核心。
2.4 本章知识体系总览
下面这张图,是我花了一个晚上画的。它把本章的核心知识点串在了一起,你保存下来,以后搭建环境时对照着看。
这张图你看懂了吗?三个模块之间是相互依赖的。Python生态是基础,数据库是数据仓库,回测框架是执行引擎。缺一个,整个系统就跑不起来。
最后说一句:环境搭建这件事,别追求完美。先让一个简单的策略跑起来,再慢慢优化。我见过太多人,环境搭了一个月,策略一行没写。记住:完成比完美重要。