手把手用 abupy 完成第一次量化策略回测
学习如何用 abupy 框架完成量化回测全流程。从环境搭建到数据获取,从编写双均线策略到跑通回测,帮你理解年化收益、最大回撤、夏普比率等核心指标,让交易决策有据可依。

手把手用 abupy 完成第一次量化策略回测
开篇
你是不是也遇到过这种尴尬:看某个技术指标说"金叉买入、死叉卖出"觉得有道理,但真拿自己的钱去试又心虚?或者自己写了几十行回测代码,结果发现连手续费和滑点都没算,收益数据纯属自欺欺人?
量化交易听起来门槛很高,核心逻辑其实就三步:获取数据 → 定义规则 → 验证结果。今天带你用 18K+ 星的开源量化框架 abupy(GitHub: bbfamily/abu),30 分钟走完这个完整闭环,完成第一个真正有参考价值的策略回测。
前置条件
开始前确认满足以下条件:
- 已安装 Python 3.7+(强烈推荐用 Anaconda,量化依赖包它基本都能预编译好)
- 了解 Python 基础语法(变量、列表、函数、if/for)
- 对股票市场有基本认知(知道 K 线、均线、收盘价是什么即可)
没接触过量化完全没关系,跟着做就行,abupy 封装得很友好。
环境安装
量化项目依赖 numpy、pandas、scipy 等科学计算库,这些库经常有 C 扩展和版本冲突。conda 的二进制预编译方案能帮你省掉 90% 的环境折磨。
打开终端(Windows 用 Anaconda Prompt,Mac/Linux 用普通终端):
bash
## 1. 创建专属的量化环境(避免污染全局 Python)
conda create -n quant python=3.8
conda activate quant
## 2. 安装 abupy
pip install abupy
## 3. 验证安装
python -c "import abupy; print('abupy 安装成功')"
能正常打印就说明环境 OK 了。abupy 首次运行时会自动初始化本地缓存目录(通常在 ~/.abupy/ 或项目同级),耐心等几十秒完成数据目录创建。
第一步:获取历史行情数据
量化第一步永远是拿到干净的数据。abupy 内置了多个数据源,A 股、美股、港股、期货、加密货币都能拉。
历史数据清洗是个大坑:除权除息、停牌复牌、数据缺失时对齐到交易日…… abupy 已经帮你处理好了这些脏活,直接调用就能拿到规整的 DataFrame。
python
from abupy import ABuSymbolPd
## 获取腾讯控股(港股)近一年的日 K 线数据
symbol = 'hk00700'
kl_data = ABuSymbolPd.make_kl_df(symbol, n_folds=1)
if kl_data is not None:
print(f'成功获取 {len(kl_data)} 条数据')
print(kl_data.tail())
make_kl_df 是 abupy 最核心的数据接口。n_folds=1 表示 1 年数据,可按需改成 2、3、5。返回的是一个带时间索引的 pandas DataFrame,每行包含 open/close/high/low/volume 等字段——这就是后续所有分析的原材料。
第二步:编写你的第一个择时策略
光看数据没意义,我们要验证一个策略到底能不能赚钱。
今天做一个最经典的双均线策略:10 日均线向上突破 30 日均线(金叉)时买入,跌破时(死叉)卖出。
逻辑清晰、参数直观、容易理解失效原因。等你熟悉了回测框架,再换更复杂的因子就顺理成章了。
在 abupy 中,策略以因子(Factor)形式存在。买入因子继承 AbuFactorBuyXD,卖出因子继承 AbuFactorSellXD,框架会在每个交易日自动调用 fit_day 方法判断是否触发信号。
python
from abupy import AbuFactorBuyXD, AbuFactorSellXD
import numpy as np
class MaCrossBuy(AbuFactorBuyXD):
"""10日均线上穿30日均线时买入"""
def fit_day(self, today, orders):
short = self.kl_pd.close_price.rolling(10).mean().dropna()
long = self.kl_pd.close_price.rolling(30).mean().dropna()
# 取交集部分计算金叉
common_idx = short.index.intersection(long.index)
if len(common_idx) < 2:
return False
s_cur, s_pre = short.loc[common_idx[-1]], short.loc[common_idx[-2]]
l_cur, l_pre = long.loc[common_idx[-1]], long.loc[common_idx[-2]]
# 昨日短均线在下,今日在上 → 金叉
if s_pre <= l_pre and s_cur > l_cur:
self.buy_today = True
return True
return False
class MaCrossSell(AbuFactorSellXD):
"""10日均线下穿30日均线时卖出"""
def fit_day(self, today, orders, pick_times):
short = self.kl_pd.close_price.rolling(10).mean().dropna()
long = self.kl_pd.close_price.rolling(30).mean().dropna()
common_idx = short.index.intersection(long.index)
if len(common_idx) < 2:
return False
s_cur, s_pre = short.loc[common_idx[-1]], short.loc[common_idx[-2]]
l_cur, l_pre = long.loc[common_idx[-1]], long.loc[common_idx[-2]]
if s_pre >= l_pre and s_cur < l_cur:
return True
return False
关键说明:
fit_day里的self.kl_pd是当前标的的完整 K 线数据,today是当前交易日信息- 金叉判断用前一日和当日的大小关系变化,避免用到未来数据
- 返回 True 即触发信号,框架会自动记录订单
第三步:配置并执行回测
因子写好了,接下来告诉 abupy 用什么标的、多少本金、回测多长时间。
python
from abupy import AbuPickTimeWorker, AbuBenchmark, AbuCapital, AbuMetricsBase
## 设定基准(用上证指数做对比)
benchmark = AbuBenchmark(benchmark='sz000001')
## 初始资金 100 万
capital = AbuCapital(1000000, benchmark)
## 组装因子
buy_factors = [{'class': MaCrossBuy}]
sell_factors = [{'class': MaCrossSell}]
## 执行回测
worker = AbuPickTimeWorker(
capital=capital,
benchmark=benchmark,
buy_factors=buy_factors,
sell_factors=sell_factors,
choice_symbols=['hk00700']
)
worker.fit()
## 计算指标
metrics = AbuMetricsBase(worker.orders, worker.action_flags, benchmark, capital)
metrics.fit_metrics()
metrics.plot_returns_cmp(only_show_returns=True)
这段代码跑完后,你会看到一张对比图:策略收益曲线 vs 基准线。metrics.fit_metrics() 会自动算出年化收益率、最大回撤、夏普比率等核心数值。
几个关键参数的意义:
AbuCapital(1000000, benchmark):设定初始本金,abupy 会据此计算仓位大小choice_symbols:可传入多只标的,框架会自动并行回测plot_returns_cmp():可视化对比,一眼看出策略是否跑赢大盘
第四步:读懂回测指标
回测跑完不是结束,而是开始。你需要判断这个策略到底靠不靠谱。
- 年化收益率:折算成一年的平均收益。单纯看这个数字没用,必须对比同时期大盘。
- 最大回撤:策略运行期间从最高点到最低点的最大跌幅。这代表你心理最难受的时候能亏多少,直接决定你能否拿得住。
- 夏普比率:收益与风险的比值。低于 1 说明性价比不高,超过 1.5 才算优秀。
- 胜率:赚钱交易次数占比。但高胜率不等于赚钱,关键还要看盈亏比。
警惕过拟合: 如果某一组参数回测收益极高,但在另一只股票或另一时间段就崩盘,说明策略只是凑巧拟合了历史数据,不具备泛化能力。真正好的策略应该在多个标的、多段时间上表现稳定。
常见问题与踩坑提醒
首次运行卡住或下载慢
abupy 初始化时会创建缓存目录并下载历史数据,可能需要几分钟。网络不好时可设置代理,耐心等待进度完成,不要强制中断。
回测结果好得不像真的
很多新手会犯的错误:未来函数。比如买入信号用到了当天的收盘价,但实盘开盘时你根本拿不到。abupy 的 fit_day 机制在设计时已尽量避免此问题,但自定义因子时务必严格只用已发生数据。
手续费和滑点没算
默认回测可能不计交易成本,这会严重虚高收益。实际部署前务必在配置中开启佣金(A 股通常万分之三加印花税)和滑点模拟。
总结与下一步
今天我们完整过了一遍量化交易的闭环:
- 搭建 Python + abupy 环境
- 用
make_kl_df拉取历史 K 线 - 编写均线交叉因子并执行回测
- 读取核心指标判断策略有效性
接下来建议你:
- 换标的验证:把港股换成 A 股(如
sz000001)或美股(usTSLA),看策略在不同市场的稳定性 - 加过滤条件:在买入信号中叠加成交量阈值,比如只有放量突破时才进场
- 阅读官方教程:abupy 的
abupy_lecture目录有完整的 Jupyter Notebook,从止损策略、仓位管理到机器学习选股都有,跟着敲一遍就能进阶
量化不是写个神奇代码就能稳赚,它的真正价值在于让你的交易决策有据可依、有数据可查。先用 abupy 把流程跑通,再慢慢打磨策略,这才是正确的姿势。有问题随时在评论区交流,我看到都会回。