111-羊驼策略
由qxiao创建,最终由qxiao 被浏览 303 用户
策略介绍
- 美国《旧金山纪事报》曾做过大猩猩选股实验,让大猩猩独写有股票代码的纸板投标,投中一个代码就意味着选中一只股票,用此方法让大猩猩挑选出5只股票。然后,用大猩猩挑选的股票组合与《华尔街日报》8位知名分析师精心计算分析挑选的5只股票相比较,在持有一段时间之后,大猩猩随机抽取购买的股票票面价值超过操盘手的股票。2014年,甘肃卫视的《马上知道》节目也向观众展示了用羊驼来选股,即每天卖掉持有的股票中收益率最差的一只,然后让羊驼随机选入一只股票来买。结果得到了很可观的收益率。 根据这种情况,人们开始尝试使用羊驼来选股,本文档介绍根据每天持有收益率最靠前的股票来选股的策略。
- 在本策略中,起始时随机等权重买入30只股票。在每个调仓期(本例以22个交易日调仓),按照持仓收益率从小到大对持仓中的30只股票进行排序,然后从持仓中选出收益率前最差的6只股票卖出,同时再等权随机买入6只股票。
策略流程
1.选股: 剔除全市场中ST或者上市时间不足270个交易日的全部股票,然后随机从股票池中等权重买入30只股票
2.打分:对股票按照构造的收益率打分
3.仓位:按照持仓中收益率最差的6只股票卖出,同时等权随机买入6只股票
4.回测:设置调仓周期为22个交易日,按日回测,买卖点均为开盘价,回测周期为2009年1月1日至2021年12月31日,初始资金为100万元
策略实现
输入特征
- 由于是随机选取股票,因此不需要额外输入表达式特征,在过滤条件中加入筛选。
\
BigTrader初始化函数
context.total_stock_nums = 30 # 总持仓股票数30只
context.sell_stock_nums = 6 # 每次调仓期卖出6只,卖出后同理会随机买入6只
context.index = 0 # context是全局变量,可添加属性以便在各个函数之间传递
- 上述代码是在交易引擎的初始化函数中设置回测的持仓数量和每期调仓股数和K线序号
\
# 首日建仓,等权随机买入股票
if context.index == 1:
# 从传入的数据 context.data 中读取今天的信号数据
target_instruments = list(today_df["instrument"])
# 随机抽取10只股票
random_elements = random.sample(target_instruments, context.total_stock_nums)
target_instruments = list(random_elements)
# 等权买入10只股票
for i in target_instruments:
context.order_target_percent(i, 1 / context.total_stock_nums)
-
上述代码里,我们用了一个if条件判断是否是回测第一天,如果是第一天那么随机选择出30只股票,然后等权买入。随机筛选我们用到了random.sample这个函数
我们通过context.rebalance_period.is_signal_date这个函数判断当前是否调仓期,如果进入调仓期,就进入调仓逻辑。
BigTrader调仓逻辑
# 下一个交易日是调仓日,则运行调仓的逻辑,即卖出持仓收益最低的6只股票,再随机抽取6只股票,等权买入
if context.rebalance_period.is_signal_date(data.current_dt.date()):
return
print('当前是调仓期:',data.current_dt.strftime("%Y-%m-%d"))
# 构建一个组合股票名称和持仓收益率的字典
stock_ret = {}
hold_instruments = set(context.get_account_positions().keys())
# 对于持仓中的每一只股票来说
for ins in hold_instruments:
# 获取它的成本价
stock_cost = context.get_position(ins).cost_price
# 获取它的当前市场价
stock_market_price = context.get_position(ins).last_price
# 计算涨跌幅
if stock_cost != 0:
return_pct = (stock_market_price - stock_cost) / stock_cost
else:
return_pct = 0
stock_ret[ins] = return_pct
# 使用 sorted() 函数和 lambda 表达式按值升序排序
sorted_items = sorted(stock_ret.items(), key=lambda item: item[1], reverse=False)
sorted_dict = dict(sorted_items)
# 按收益率降序排序选择要卖出的股票
stock_to_sell = list(sorted_dict.keys())[:context.sell_stock_nums]
# 卖出
for instrument in stock_to_sell:
context.order_target_percent(instrument, 0)
- 调仓逻辑是我们先对持仓里的每一只股票获取其成本价和最新价,然后计算持仓里30只股票的实际持仓收益率,然后按收益率降序排序,最终根据排序结果选择出收益最差的6只股票,再进行卖出。卖出以后,我们在全市场再随机选择出6只股票进行等权重买入。
# 随机等权重再买入
target_instruments = list(today_df["instrument"])
random_elements = random.sample(target_instruments, context.sell_stock_nums)
stock_to_buy = list(random_elements)
for instrument in stock_to_buy:
context.order_target_percent(instrument, 1 / context.total_stock_nums)
- 本质上讲,羊驼策略是动量因子起作用,其走势与动量因子的表现相关性较高,从下列回测结果看出在牛市阶段羊驼策略表现比较亮眼。长期来看是一个正收益系统策略,小伙伴在运行的时候每次结果可能略有差异,因为该策略在选股时有一定的随机性。
策略代码
直接点击下文的”克隆策略“按钮即可复制本策略源码到开发环境。
https://bigquant.com/codesharev3/954d12f3-becd-43fd-9a70-dabeff9a5b44
\