量化交易:财务选股RSRS择时的策略
哈喽,大家好,我是木头左!
引言
本文将介绍一种结合财务指标选股和RSRS(Risk-Adjusted Return to Strength Ratio)择时的策略,旨在帮助投资者在复杂的市场环境中做出更明智的决策。 感兴趣的朋友,可以在下方公号内回复:001,即可获取源码,共同交流!
策略原理
财务指标选股
财务指标选股是一种基于公司财务报表数据来评估股票价值的方法。常见的财务指标包括市盈率(PE)、市净率(PB)、净资产收益率(ROE)等。这些指标可以帮助投资者判断公司的盈利能力、资产状况和成长潜力。在本策略中,使用市净率(PB)和净资产收益率(ROE)作为选股的主要依据。
RSRS择时
RSRS择时是一种基于历史价格数据的技术分析方法,用于评估市场的风险和收益。RSRS通过计算价格序列的回归斜率来衡量市场趋势的强度。当斜率大于买入阈值时,认为市场风险在合理范围内,可以进行买入操作;当斜率小于卖出阈值时,认为市场风险过大,应保持空仓状态。
在聚宽平台运行Python代码
初始化函数
在聚宽平台上,首先需要导入所需的函数库,并在initialize
函数中设置策略的基本参数,如股票交易的手续费、基准指数等。
def initialize(context):
set_option('use_real_price', True)
set_parameter(context)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
run_daily(market_open, time='open', reference_security='000300.XSHG')
参数设置
在set_parameter
函数中,设置了RSRS指标中N和M的值,以及买入和卖出的阈值。此外,还计算了2005年1月5日至回测开始日期的RSRS斜率指标。
def set_parameter(context):
g.N = 18
g.M = 1100
g.init = True
g.stock_num = 10
g.security = '000300.XSHG'
set_benchmark(g.security)
g.days = 0
g.buy = 0.7
g.sell = -0.7
# ... 省略部分代码 ...
开盘前和开盘时运行函数
在before_market_open
和market_open
函数中,根据RSRS指标的计算结果来决定是否进行交易。如果RSRS指标大于买入阈值,则调用trade_func
函数进行交易;如果小于卖出阈值且持有股票,则卖出所有股票。
security = g.security
# 填入各个日期的RSRS斜率值
beta=0
r2=0
if g.init:
g.init = False
else:
#RSRS斜率指标定义
prices = attribute_history(security, g.N, '1d', ['high', 'low'])
highs = prices.high
lows = prices.low
X = sm.add_constant(lows)
model = sm.OLS(highs, X)
beta = model.fit().params[1]
g.ans.append(beta)
#计算r2
r2=model.fit().rsquared
g.ans_rightdev.append(r2)
# 计算标准化的RSRS指标
# 计算均值序列
section = g.ans[-g.M:]
# 计算均值序列
mu = np.mean(section)
# 计算标准化RSRS指标序列
sigma = np.std(section)
zscore = (section[-1]-mu)/sigma
#计算右偏RSRS标准分
zscore_rightdev= zscore*beta*r2
# 如果上一时间点的RSRS斜率大于买入阈值, 则全仓买入
if zscore_rightdev > g.buy:
# 记录这次买入
log.info("市场风险在合理范围")
#满足条件运行交易
trade_func(context)
# 如果上一时间点的RSRS斜率小于卖出阈值, 则空仓卖出
elif (zscore_rightdev < g.sell) and (len(list(context.portfolio.positions.keys())) > 0):
# 记录这次卖出
log.info("市场风险过大,保持空仓状态")
# 卖出所有股票,使这只股票的最终持有量为0
for s in list(context.portfolio.positions.keys()):
order_target(s, 0)
策略选股买卖部分
在trade_func
函数中,首先获取股票池,然后根据市净率(PB)和净资产收益率(ROE)进行筛选和打分,最后根据得分选取前10只股票进行买入或卖出操作。
def trade_func(context):
#获取股票池
df = get_fundamentals(query(valuation.code,valuation.pb_ratio,indicator.roe))
#进行pb,roe大于0筛选
df = df[(df['roe']>0) & (df['pb_ratio']>0)].sort('pb_ratio')
#以股票名词作为index
df.index = df['code'].values
#取roe倒数
df['1/roe'] = 1/df['roe']
#获取综合得分
df['point'] = df[['pb_ratio','1/roe']].rank().T.apply(f_sum)
#按得分进行排序,取指定数量的股票
df = df.sort('point')[:g.stock_num]
pool = df.index
log.info('总共选出%s只股票'%len(pool))
#得到每只股票应该分配的资金
cash = context.portfolio.total_value/len(pool)
#获取已经持仓列表
hold_stock = list(context.portfolio.positions.keys())
#卖出不在持仓中的股票
for s in hold_stock:
if s not in pool:
order_target(s,0)
#买入股票
for s in pool:
order_target_value(s,cash)
回测效果
通过在聚宽平台上运行上述策略,得到了以下回测效果:
从回测结果可以看出,该策略收益实在不怎么样,后续反向优化。
策略的缺点
- 适用性 :在高波动性或快速变化的市场中,RSRS策略可能难以适应,导致投资组合表现不佳。
- 交易成本 :为了降低交易成本,应合理控制交易频率,或者通过设置较长的交易周期或采用定期再平衡的方式来减少交易次数。
市场有风险,交易需谨慎。感兴趣的朋友,可以在下方公号内回复:001,即可获取源码,共同交流!
我是木头左,感谢各位童鞋的点赞、收藏,我们下期更精彩!