(1)均值回归策略思想:
比如一个行业 汽车电子或者半导体行业有50只股票。在大盘整体上涨或者下跌过程中。大盘对他们的影响应该是比较类似的。有一个均值。剩下的就是公司本身的因素。头部溢价稀缺性等等。
如果有一部分公司最近的股价表现得特别好,另一部分公司的股价表现的特别差
那么就可以认为表现好的会回调一下,表现差的会反弹一下 如下图 超过均线的卖出 低于均线的买入

操作方法
以20天时间为窗口 操作频率一周一次 选出某行业中 前20天上涨幅度最少的20-40只股票均仓(0.02)买入。第二周继续选出上周上涨幅度最少的20只股票均仓买入。每个股票的仓位不超过0.05
问题
反转周期不确定,也可能强者恒强 上涨的一直涨 下跌的一直跌
解决方法
对不同的周期都进行回测 10,15,20,50天等
代码分为两个部分,
(1)仓位控制器 有可能 某一直股票 连续几周都是上涨幅度 都在最小的20只内 但是为了控制单支股票的持仓比例 会设置当某只股票的持仓超过0.05之后 不在买入。即创建一个空列表 获取账户持仓信息是 当某个股票的持仓超过总体仓位的0.05 放入该空列表 下单买入前判断 想买的股票是否在该列表内
class PositionController:'''用于检测当前持仓仓位并且控制单支股票的持仓上线'''def __init__(self,context,account_name,upper_limit):'''初始化'''self.context = contextself.account_name = account_nameself.upper_limit = upper_limitdef get_account_instance(self):'''获取账户信息,例如账户的 账号密码 资金数量等cashportforlio_value'''self.account_instance = self.context.get_account(self.account_name)def get_position_situation(self):'''获取账户持仓 get positions 返回的是一个字典 key 为代码 value为持仓情况'''self.position_situation = self.account_instance.get_positions()def controller_position(self):'''仓位控制 position分别获取每个股票的的持仓信息amount 数量available_amount 可卖出数量profit 盈利cost 成本value 市值(随市场变化)'''controlled_stock_list = [] # 存放持仓 达到 上限的股票for stock in self.position_situation.keys():stock_position = self.account_instance.get_position(stock)if stock_position.value / self.account_instance.portfolio_value > self.upper_limit:self.account_instance.order_pct_to(stock,self.upper_limit)controlled_stock_list.append(stock)else:passreturn controlled_stock_listdef run(self):self.get_account_instance()self.get_position_situation()controlled_stock_list = self.controller_position()log.info( controlled_stock_list)return controlled_stock_list
(2)买入策略
每周选出前20天上涨幅度最小的20只股票。即用昨日的收盘价/20天前的收盘价。均仓买入(0.02)
start = '2013-06-01' # 回测起始时间end = '2014-01-01' # 回测结束时间universe = DynamicUniverse('A') # 证券池,支持股票、基金、期货、指数四种资产benchmark = 'HS300' # 策略参考标准freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测refresh_rate = Weekly(1) # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟# 配置账户信息,支持多资产多账户accounts = {'fantasy_account': AccountConfig(account_type='security', capital_base=10000000)}def initialize(context):context.window = 20 #往前回测窗口 20天context.stock_num = 20 #购买沪深300表现最差的20只股票# 每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次def handle_data(context):universe = context.get_universe(exclude_halt = True) #获取当天可以交易的股票池 返回一个列表 作为参数传给context.historydata = context.history(universe, 'closePrice', context.window, freq='1d', rtype='frame', style = 'ast')# log.info(data)data = data['closePrice'] #获取全A股过去20天的收盘价#计算动量momentum = data.iloc[-1]/data.iloc[0]#根据动量大小排序momentum.sort_values(ascending = True ,inplace = True)buy_list = list(momentum[:20].index)log.info(buy_list)# # 获取因子PE的的历史数据集,截止到前一个交易日# hist = context.history(symbol=context.get_universe(exclude_halt=True), attribute='PE', time_range=1, style='tas')[previous_date]# # 将因子值从小到大排序,并取前100支股票作为目标持仓# signal = hist['PE'].order(ascending=True)# target_position = signal[:100].index# 获取当前账户信息account = context.get_account('fantasy_account')positions = account.get_positions()# 卖出不在持仓目标范围内的股票,并进行仓位控制器 单支股票不超过0.05position_controller = PositionController(context,'fantasy_account',0.05)controlled_stock_list = position_controller.run()for stock in positions:if stock not in buy_list:account.order_to(stock, 0)# 根据目标持仓权重,逐一委托下单for stock in buy_list:if stock not in controlled_stock_list:account.order_pct(stock, 0.02)
跑了一下回测 在13到 15年模型较好用 18年之后表现一般



文章转载自量化分析之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




