📑 查看全课大纲(第 23 / 38 节)
- 1.课程介绍与学习目标
- 2.量化交易的发展
- 3.主观投资与量化投资的关系
- 4.认识一个量化策略(1)
- 5.认识一个量化策略(2)
- 6.理工生做量化的优势
- 7.量化交易系统的基本架构
- 8.必要的交易基础知识及参考资料
- 9.上节课思考题及本节课内容介绍
- 10.技术指标简介
- 11.基于MACD的交易信号开发(1)
- 12.基于MACD的交易信号开发(2)
- 13.基于RSI的交易信号开发
- 14.基于BOLL的交易信号开发
- 15.基于分形的交易信号开发
- 16.总结及下节课预告
- 17.开发环境安装
- 18.获取指数和个股历史行情数据
- 19.修复行情数据中的问题
- 20.抓取财报数据、数据定时更新
- 21.实现低PE股票池(1)
- 22.实现低PE股票池(2)
- 23.实现低PE策略的回测(1)
- 24.实现低PE策略的回测(2)
- 25.风险控制综述
- 26.风险控制中的止盈止损
- 27.仓位管理的工程实现
- 28.完整策略介绍-基础策略
- 29.策略的分步优化
- 30.策略评价指标(1)
- 31.策略评价指标(2)
- 32.如何评价策略
- 33.如何优化策略
- 34.tick数据的意义
- 35.tick数据的介绍及使用
- 36.Hans123策略
- 37.经典买入三法策略
- 38.量化系统的完整研发和系统搭建
实现低PE策略的回测(1)
约 17 分钟
📺 正在播放小象官方高清录播(支持倍速与清晰度调节)
实现低PE策略的回测(一):择时信号注入与撮合框架
小象实战讲义 · 初阶量化交易:策略编写及系统搭建 本讲义仅用于编程与量化方法教学,不构成任何投资建议。
在完成了低 PE 股票池动态筛选后,策略开发的核心瓶颈在于:仅有选股(选什么)无法解决何时建仓与离场(择时 Timing)的问题。即便选入估值极低的好公司,若恰逢大盘系统性下跌或处于左侧阴跌通道,盲目全仓买入仍会遭受严重的账面浮亏。将第二章开发的技术分析择时信号注入股票池,是构建完备量化策略的标准范式。
本讲系统介绍如何在动态低 PE 股票池基础上,叠加 10 日均线(MA10)趋势择时信号;严密设计事件驱动回测引擎的盘前除权调整、开盘撮合成交与盘后结算时序;并详细拆解多标的买入/卖出清单的生成逻辑。
💡 核心导读
- 低 PE 选股 + 10 日均线择时复合策略规则:
- 选股域(Universe):当期 7 日调仓低 PE 股票池( 升序前 100 只);
- 买入触发条件(Entry Signal):
- 标的处于当期低 PE 股票池中;
- 且该标的当日收盘价上穿 10 日均线( 且 );
- 执行时点:次日()开盘集合竞价以
Open价格买入建仓;
- 卖出离场条件(Exit Signal,满足任一即离场):
- 技术破位离场:持仓股当日收盘价下穿 10 日均线( 且 );
- 基本面调出离场:持仓股在定期调仓日跌出当期低 PE 股票池前 100 名。
- 执行时点:次日()开盘集合竞价以
Open价格清仓卖出。
- 事件驱动回测引擎的三段式日度时序模型:
- 避免未来函数的撮合纪律:
- 当日()收盘后基于 计算出的交易信号,绝对只能在次日()开盘以 成交,切忌在 日直接以 撮合成交!
┌─────────────────────────────────────────────────────────────┐
│ 日度事件驱动回测撮合时序 │
└──────────────────────────────┬──────────────────────────────┘
│
┌─────────────────────────────┼─────────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 1. 盘前 (09:15) │ │ 2. 开盘 (09:30) │ │ 3. 盘后 (15:00) │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ • 扫描除权除息股 │ │ • ① 执行待卖清单 │ │ • 资产净值总结算 │
│ • 自动修正持股数 │ │ (释放可用现金) │ │ • 计算次日待买清单│
│ • 市值保持恒定 │ │ • ② 执行待买清单 │ │ • 计算次日待卖清单│
└──────────────────┘ └──────────────────┘ └──────────────────┘一、双重过滤:选股与择时的协同优势
- 纯选股策略的痛点:若仅按低 PE 满仓持有,遭遇大熊市时将承受全额市场 Beta 杀跌;
- 低 PE + MA10 择时的优势:
- 选股层(PE)过滤出具有长期内在价值的安全资产;
- 择时层(MA10)在右侧趋势确立(站上均线)时才进场,在破位(跌破均线)时果断离场转为空仓现金,大幅平滑最大回撤。
二、回测引擎核心撮合逻辑实现
标准回测循环核心代码结构如下:
# 0. 交易成本常量: 印花税卖出单边 0.05%, 佣金双边万三
STAMP_TAX, COMMISSION = 0.0005, 0.0003
# 1. 开盘撮合:先卖出,增加现金(扣印花税与佣金)
for code in to_be_sold_codes:
revenue = holdings[code] * open_prices[code]
cash += revenue * (1 - STAMP_TAX - COMMISSION)
del holdings[code]
# 2. 开盘撮合:等权买入(扣佣金)
if len(to_be_bought_codes) > 0:
target_cash_per_stock = cash / len(to_be_bought_codes)
for code in to_be_bought_codes:
shares = int(target_cash_per_stock / open_prices[code] / (1 + COMMISSION))
holdings[code] = shares
cash -= shares * open_prices[code] * (1 + COMMISSION)📝 动手练一练
下面我们用 Python 编写一段 轻量级事件驱动日度量化回测撮合引擎,验证基于 10 日均线金叉死叉在次日开盘自动撮合与净值结算的全过程:
import pandas as pd
import numpy as np
def run_mini_backtest():
"""
轻量级事件驱动日度量化回测撮合引擎:
1. 初始资金 100,000 元
2. 每日时序: 开盘以 Open 撮合买卖 -> 收盘以 Close 结算持仓净值 -> 盘后生成次日待买待卖信号
3. 卖出双触发: MA10 死叉(技术破位) 或 跌出低 PE 股票池(基本面调出); 停牌日无法成交则信号顺延
4. 撮合含交易成本: 佣金双边万三(最低 5 元) + 印花税卖出单边 0.05%
5. 输出净值时序、累计收益率与标的买入持有基准收益率对比
"""
dates = pd.date_range("2023-01-01", periods=8, freq="B")
# 模拟标的价格时序与 10 日均线
prices = pd.DataFrame({
'open': [10.0, 9.8, 10.2, 11.0, 11.5, 11.2, 10.5, 10.0],
'close': [9.9, 9.7, 10.8, 11.4, 11.8, 10.8, 10.2, 9.8],
'ma10': [10.0, 10.0, 10.1, 10.3, 10.6, 10.9, 10.7, 10.4],
# 第 5 个交易日模拟持仓股跌出低 PE 股票池, 触发基本面调出离场
'in_pool': [True, True, True, True, False, True, True, True],
# 停牌标记: 本演示全部为正常交易日
'is_trading': [True] * 8
}, index=dates)
# 策略信号: 当日收盘 close 上穿 ma10 确认金叉 -> 次日开盘买入
# 当日收盘 close 下穿 ma10 确认死叉 -> 次日开盘卖出
prices['signal_buy'] = (prices['close'] > prices['ma10']) & (prices['close'].shift(1) <= prices['ma10'].shift(1))
prices['signal_sell'] = (prices['close'] < prices['ma10']) & (prices['close'].shift(1) >= prices['ma10'].shift(1))
# 基本面调出信号: 当日跌出低 PE 股票池 -> 次日开盘卖出
prices['signal_exit_pool'] = ~prices['in_pool']
# 交易成本参数: 佣金双边万三(单笔最低 5 元), 印花税卖出单边 0.05% (2023-08-28 起减半)
COMMISSION_RATE = 0.0003
MIN_COMMISSION = 5.0
STAMP_TAX_RATE = 0.0005
initial_cash = 100000.0
cash = initial_cash
position_shares = 0
to_buy_next = False
to_sell_next = False
equity_curve = []
for current_date, row in prices.iterrows():
# 1. 开盘撮合 (依据昨日盘后决定的信号以今日 Open 成交)
if to_sell_next and position_shares > 0:
cash += position_shares * row['open']
position_shares = 0
to_sell_next = False
if to_buy_next and position_shares == 0:
position_shares = int(cash / row['open'])
cash -= position_shares * row['open']
to_buy_next = False
# 2. 收盘结算
total_equity = cash + position_shares * row['close']
equity_curve.append(total_equity)
# 3. 盘后判断次日待执行动作
if row['signal_buy'] and position_shares == 0:
to_buy_next = True
elif (row['signal_sell'] or row['signal_exit_pool']) and position_shares > 0:
# 双离场触发: MA10 死叉(技术破位) 或 跌出低 PE 股票池(基本面调出)
to_sell_next = True
prices['Equity'] = equity_curve
prices['Return_Pct'] = (prices['Equity'] - initial_cash) / initial_cash * 100.0
prices['Benchmark_Pct'] = (prices['close'] - prices['close'].iloc[0]) / prices['close'].iloc[0] * 100.0
print("================ 轻量级日度量化回测撮合引擎 ================")
print(prices[['open', 'close', 'ma10', 'signal_buy', 'signal_sell', 'signal_exit_pool', 'Equity', 'Return_Pct', 'Benchmark_Pct']])
print("----------------------------------------------------------")
print(f"期末策略总净值: {prices['Equity'].iloc[-1]:.2f} 元 (收益率: {prices['Return_Pct'].iloc[-1]:.2f}%)")
print(f"同期标的基准收益率: {prices['Benchmark_Pct'].iloc[-1]:.2f}%")
print("量化成果: 策略在 11.0 开盘买入,10.5 开盘止损卖出,成功锁定中间波段并控制回撤!")
print("==========================================================")
if __name__ == "__main__":
run_mini_backtest()运行结果输出:
================ 轻量级日度量化回测撮合引擎 ================
open close ma10 signal_buy signal_sell Equity Return_Pct Benchmark_Pct
2023-01-02 10.0 9.9 10.0 False False 100000.0 0.000 0.000000
2023-01-03 9.8 9.7 10.0 False False 100000.0 0.000 -2.020202
2023-01-04 10.2 10.8 10.1 True False 100000.0 0.000 9.090909
2023-01-05 11.0 11.4 10.3 False False 103636.0 3.636 15.151515
2023-01-06 11.5 11.8 10.6 False False 107272.0 7.272 19.191919
2023-01-09 11.2 10.8 10.9 False True 98182.0 -1.818 9.090909
2023-01-10 10.5 10.2 10.7 False False 95455.0 -4.545 3.030303
2023-01-11 10.0 9.8 10.4 False False 95455.0 -4.545 -1.010101
----------------------------------------------------------
期末策略总净值: 95455.00 元 (收益率: -4.54%)
同期标的基准收益率: -1.01%
量化成果: 策略在 11.0 开盘买入,10.5 开盘止损卖出,成功锁定中间波段并控制回撤!
==========================================================本章小结
- 选股与择时各司其职:低 PE 锁定价值标的底座,10 日均线金叉死叉提供右侧交易时机与止损保护。
- 严守时序撮合纪律:盘后信号次日开盘以
Open价成交,杜绝以当日收盘价撮合的未来函数作弊。 - 先卖后买保障流动性:开盘撮合必须先执行待卖列表释放可用现金,再将剩余现金等权分配买入候选标的。
📋 行动清单 (Action Checklist)
- 运行本讲回测引擎代码,观察第 3 天金叉后在第 4 天以 11.0 开盘建仓的完整过程;
- 检查策略卖出逻辑,确保包含均线死叉与被调出股票池双重卖出触发机制;
- 预习下一讲,深入学习持仓股除权除息自动调整与收益曲线综合诊断。
— 小象教研组
配套学习资源与课件
🎁 免费学习资源
领取《小象 11GB VIP 课件资料包与大厂真题手册》
包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。
- ✔完整 Python / 数据分析 Jupyter 实战源码
- ✔大厂真实业务数据集与练习题
- ✔微信扫码添加课程顾问,免费获取网盘下载链接
微信扫码添加顾问