暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

均值回归策略

量化分析之路 2020-03-15
1450

(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 = context
self.account_name = account_name
self.upper_limit = upper_limit

def get_account_instance(self):
'''获取账户信息,例如账户的 账号密码 资金数量等
cash
portforlio_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:
pass
return controlled_stock_list

def 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.history
data = 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.05
position_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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论