一个简单的指数增强策略实现

        首先,指数增强策略的概念:指数增强策略是指基金经理在构建投资组合时,运用“指数跟踪”与“主动管理”相结合的方式获取超额收益的投资策略,而相对于单纯的“指数”,指数增强策略的关键点是管理人的“主动管理”能力。简单而言,就是让产品走势与指数保持一致的同时,依托管理人的管理能力,让组合的涨幅尽可能地高于指数而跌幅小于指数。指数增强策略获取的是阿尔法+贝塔收益。

        假如目前指数增强的指数是沪深300,需要在沪深300指数中寻找能够超过指数表现的个股。首先可以将沪深300个股权重初始化为0.7,然后根据个股是否:1、MACD金叉;2、MACD死叉来判断个股是否为强势股/弱势股,并把强势股的权重从0.7更新到1.1,把弱势股的权重从0.7降低到0.3,来达到指数增强的目的。基于QMT平台,代码如下:

#coding:gbk
'''
回测模型示例

本策略以0.7为初始权重跟踪指数标的沪深300中权重大于0.35%的成份股.
个股所占的百分比为(0.7*成份股权重)*100%.然后根据个股是否:
1、macd金叉;2、macd死叉
来判定个股是否为强势股/弱势股,并对其把权重由0.7调至1.1或0.3'''
#在指数(例如HS300)日线下运行
import numpy as np
import talib

def init(ContextInfo):
	#设置股票池
	stock300 =ContextInfo.get_stock_list_in_sector('沪深300')
	ContextInfo.stock300_weight = {}
	stock300_symbol = []
	stock300_weightlist = [] 
	ContextInfo.index_code = ContextInfo.stockcode+"."+ContextInfo.market
	print(ContextInfo.index_code)
	for key in stock300:
		# 保留权重大于0.35%的成份股
		
		if (ContextInfo.get_weight_in_index(ContextInfo.index_code, key) / 100) > 0.0035:
			stock300_symbol.append(key)
			ContextInfo.stock300_weight[key] = ContextInfo.get_weight_in_index(ContextInfo.index_code, key) / 100
			stock300_weightlist.append(ContextInfo.get_weight_in_index(ContextInfo.index_code, key) / 100)
	print('选择的成分股权重总和为: ', np.sum(stock300_weightlist)) 
	ContextInfo.set_universe(stock300_symbol)
	
	#print ContextInfo.stock300_weight
	# 资产配置的初始权重,配比为0.3-0.7-1.1
	ContextInfo.ratio = 0.7

	#账号
	ContextInfo.accountid = "testS"

def handlebar(ContextInfo):
	buy_sum = 0
	sell_sum = 0
	index  = ContextInfo.barpos
	realtimetag = ContextInfo.get_bar_timetag(index)
	print(timetag_to_datetime(realtimetag, '%Y%m%d %H:%M:%S'))
	dict_close=ContextInfo.get_history_data(35,'1d','close',3)
	#持仓市值
	holdvalue = 0
	#持仓
	holdings=get_holdings(ContextInfo.accountid,"STOCK")
	#剩余资金
	surpluscapital=get_avaliablecost(ContextInfo.accountid,"STOCK")
	for stock in ContextInfo.stock300_weight:
		if  stock  in holdings:
			if len(dict_close[stock]) == 35:
				holdvalue += dict_close[stock][-2] * holdings[stock]
	
	for stock in ContextInfo.stock300_weight:
		# 若没有仓位则按照初始权重开仓
		if  stock not in holdings and stock in list(dict_close.keys()):
			if len(dict_close[stock]) == 35:
				pre_close = dict_close[stock][-1]
				buy_num = int(ContextInfo.stock300_weight[stock] * ( holdvalue + surpluscapital ) *ContextInfo.ratio / pre_close /100)
				order_shares(stock,buy_num*100,'fix',pre_close,ContextInfo,ContextInfo.accountid)
				buy_sum += 1
				#print "买入",stock,buy_num
		elif stock in list(dict_close.keys()):
			if len(dict_close[stock]) == 35:
				recent_date = np.array(dict_close[stock])

				macd = talib.MACD(recent_date)[0][-1]
				macd_pre = talib.MACD(recent_date)[0][-2]

				pre_close = dict_close[stock][-1]
				buytarget_num = int(ContextInfo.stock300_weight[stock] * ( holdvalue + surpluscapital ) * (ContextInfo.ratio + 0.4)/ pre_close /100)
				selltarget_num = int(ContextInfo.stock300_weight[stock] * ( holdvalue + surpluscapital ) *(ContextInfo.ratio - 0.4)/ pre_close /100)
				# 获取过去5天的价格数据,若连续上涨则为强势股,调仓到(权重+0.4)的仓位
				if macd_pre < 0 and macd > 0 and holdings[stock] < buytarget_num:
					buy_num = buytarget_num - holdings[stock]
					order_shares(stock,buy_num*100,'fix',pre_close,ContextInfo,ContextInfo.accountid)
					buy_sum += 1
					#print "买入",stock,buy_num
				# 获取过去5天的价格数据,若连续下跌则为弱势股,调仓到(权重-0.4)的仓位
				elif macd_pre > 0 and macd < 0 and holdings[stock] > selltarget_num:
					sell_num = holdings[stock] - selltarget_num
					order_shares(stock,(-1.0)*sell_num*100,'fix',pre_close,ContextInfo,ContextInfo.accountid)
					sell_sum += 1
					#print "卖出",stock,sell_num
	if not ContextInfo.do_back_test:
		ContextInfo.paint('buy_num', buy_sum, -1, 0)
		ContextInfo.paint('sell_num', sell_sum, -1, 0)
					
def get_holdings(accountid,datatype):
	holdinglist={}
	resultlist=get_trade_detail_data(accountid,datatype,"POSITION")
	for obj in resultlist:
		holdinglist[obj.m_strInstrumentID+"."+obj.m_strExchangeID]=obj.m_nVolume/100
	return holdinglist

def get_avaliablecost(accountid,datatype):
	result=0
	resultlist=get_trade_detail_data(accountid,datatype,"ACCOUNT")
	for obj in resultlist:
		 result=obj.m_dAvailable
	return result

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值