3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常经典的多因子选股策略需求。在量化交易中,结合市盈率(PE)、**市净率(PB)和净资产收益率(ROE)**通常被称为“低估值高质量”策略。
以下是完整的策略代码。代码基于Python 3.5语法编写,可以直接在PTrade的回测或交易环境中运行。
import pandas as pd
import numpy as np
def initialize(context):
"""
初始化函数,设置策略参数
"""
# 1. 设置基准指数:沪深300
g.index_security = '000300.SS'
# 2. 设置持仓数量
g.stock_num = 10
# 3. 设置调仓标志,默认为False
g.rebalance_flag = False
# 设置回测参数(仅回测有效,实盘会忽略)
set_commission(commission_ratio=0.0003, min_commission=5.0, type="STOCK")
set_slippage(slippage=0.002)
def before_trading_start(context, data):
"""
盘前处理函数,每天开盘前运行
"""
# 获取当前日期
current_date = context.blotter.current_dt.date()
# 判断是否为月初(每月第一个交易日调仓)
# 获取未来几天的交易日,如果当前日期是本月第一个交易日,则标记为调仓日
# 这里使用一种简化的判断逻辑:获取过去20个交易日,判断月份是否发生变化
previous_date = get_trading_day(-1)
if previous_date.month != current_date.month:
g.rebalance_flag = True
else:
g.rebalance_flag = False
def handle_data(context, data):
"""
盘中运行函数
"""
# 如果是调仓日,则执行选股和交易逻辑
if g.rebalance_flag:
rebalance(context)
# 执行完后重置标志
g.rebalance_flag = False
def rebalance(context):
"""
核心调仓逻辑
"""
log.info("开始进行多因子选股调仓...")
# 1. 获取股票池(沪深300成分股)
# 注意:get_index_stocks在回测中默认取回测当日成分股
stocks = get_index_stocks(g.index_security)
# 2. 过滤掉 ST、停牌、退市的股票
# filter_stock_by_status 返回的是剔除后的列表
stocks = filter_stock_by_status(stocks, filter_type=["ST", "HALT", "DELISTING"])
if not stocks:
log.warning("股票池为空,跳过本次调仓")
return
# 3. 获取财务数据
# PTrade的get_fundamentals一次只能查一张表,所以需要分两次查询再合并
# 3.1 查询估值数据:PE(TTM) 和 PB
# pe_ttm: 市盈率TTM, pb: 市净率
df_val = get_fundamentals(
stocks,
table='valuation',
fields=['pe_ttm', 'pb']
)
# 3.2 查询盈利能力数据:ROE(TTM)
# roe_ttm: 净资产收益率TTM
df_prof = get_fundamentals(
stocks,
table='profit_ability',
fields=['roe_ttm']
)
# 4. 数据合并与清洗
if df_val is None or df_prof is None:
log.warning("获取财务数据失败")
return
# 将两个DataFrame合并,索引通常是股票代码
# 注意:PTrade返回的DataFrame索引通常是股票代码
df = pd.concat([df_val, df_prof], axis=1, join='inner')
# 去除包含空值的行
df = df.dropna()
# 过滤掉PE为负(亏损)的股票,通常亏损股的估值指标会失真
df = df[df['pe_ttm'] > 0]
if len(df) == 0:
log.warning("数据清洗后无股票可选")
return
# 5. 多因子打分 (Rank Scoring)
# 策略:低PE、低PB、高ROE
# 对PE进行排名,从小到大,名次越小越好
df['rank_pe'] = df['pe_ttm'].rank(ascending=True)
# 对PB进行排名,从小到大,名次越小越好
df['rank_pb'] = df['pb'].rank(ascending=True)
# 对ROE进行排名,从大到小,名次越小越好 (ascending=False)
df['rank_roe'] = df['roe_ttm'].rank(ascending=False)
# 计算总分(等权重相加)
df['total_score'] = df['rank_pe'] + df['rank_pb'] + df['rank_roe']
# 6. 选出总分最低(排名最靠前)的N只股票
df_sorted = df.sort_values(by='total_score', ascending=True)
target_stocks = df_sorted.head(g.stock_num).index.tolist()
log.info("选入股票: %s" % target_stocks)
# 7. 执行交易
adjust_position(context, target_stocks)
def adjust_position(context, target_stocks):
"""
交易执行函数
"""
# 获取当前持仓
current_positions = list(context.portfolio.positions.keys())
# 1. 卖出不在目标列表中的股票
for stock in current_positions:
if stock not in target_stocks:
# 检查是否停牌,停牌无法卖出
if check_limit(stock).get(stock) == 0: # 0表示既不涨停也不跌停,这里简单判断,严谨可用get_stock_status
# 强行平仓
order_target_value(stock, 0)
# 2. 买入目标股票
# 计算每只股票的目标资金分配(等权重)
if len(target_stocks) > 0:
# 获取当前账户总资产
total_value = context.portfolio.portfolio_value
# 预留一点现金防止手续费不够,乘以0.98
target_value_per_stock = (total_value * 0.98) / len(target_stocks)
for stock in target_stocks:
# 下单调整到目标金额
order_target_value(stock, target_value_per_stock)
数据获取 (get_fundamentals):
pe_ttm) 和市净率 (pb) 在 valuation 表中,而净资产收益率 (roe_ttm) 在 profit_ability 表中。pd.concat 将数据合并,这是处理多表因子的标准做法。因子排序 (rank):
rank(ascending=True):值越小,排名越靠前(得分越低)。适用于PE和PB。rank(ascending=False):值越大,排名越靠前(得分越低)。适用于ROE。调仓逻辑:
before_trading_start 中通过比较昨日和今日的月份来判断是否是月初。order_target_value 进行下单,这会自动计算需要买入或卖出的股数,非常适合等权重策略。风险控制:
filter_stock_by_status 剔除了ST、停牌和退市股票,防止买入无法交易或风险过大的标的。Q: 为什么使用 TTM (Trailing Twelve Months) 数据?
A: TTM 数据包含了最近12个月的财务数据,相比静态数据(仅看上一年报)更能反映公司当前的经营状况,且消除了季节性波动的影响。
Q: 如何修改选股数量?
A: 修改 initialize 函数中的 g.stock_num = 10,将 10 改为你想要的数量即可。
Q: 我想加入市值因子(小市值策略),怎么改?
A: 在 valuation 表中获取 total_value (总市值) 字段,对其进行 rank(ascending=True) 排名,并加入到 total_score 的计算中即可。
Q: 为什么代码中没有 import ptrade?
A: PTrade 平台的策略代码运行在特定的沙箱环境中,所有 API(如 get_fundamentals, order 等)都是内置的全局函数,无需导入,直接调用即可。
多因子选股是一种量化投资策略,它假设股票的收益可以由一组共同的“因子”来解释。通过寻找那些在历史上能够产生超额收益的因子(如低估值、高盈利、高动量等),并结合这些因子对股票进行打分或排序,从而构建投资组合。
这三个指标构成了一个经典的“高性价比”筛选体系: