文章目录
一、BigQuant的重要模块说明
1.回测模块
二、基于技术指标的策略实现
1.库函数导入与全局变量初始化
2.每日逻辑函数编写
策略1: MACD金叉+MA多头买入
策略2: 利用MA指标进行择股
3.策略结果展示
策略1: MACD金叉+MA多头买入
策略2: MA择股
三、基于QP优化的策略实现
1.基于经典QP的handle函数
2.增加限制条件使股票具有多样性:
3.融合技术指标的QP策略:
4.策略结果展示
策略1:经典基于QP优化策略
策略2:限制股票权重的QP优化策略
策略3:融合技术指标的QP优化策略
前言
提示:本文主要介绍了BigQuant的简单使用,并复现了基于技术指标的策略与基于QP优化的策略。
提示:以下是本篇文章正文内容,下面案例可供参考
一、BigQuant的重要模块说明
1.回测模块
m=M.trade.v2(instruments=instruments,start_date=start_date,end_date=end_date,initialize=initialize,handle_data=handle_data,order_price_field_buy='open',order_price_field_sell='open',capital_base=1000000
)
说明1: instrument为初始选股池
说明2:start_date为回测开始时间
说明3:end_date为回测结束时间
说明4:capital_base初始资产
说明5:handle_data是我们自己需要自定义的函数,该函数每天执行一次
def handle_data(context,data):##技术指标所需要的最大天数max_need_period=26if context.trading_day_index<26:returnif (context.trading_day_index)%20!=0:return print(context.trading_day_index)##记录筛选后的股票和股票数目stock_selected=[]stock_count=0for stock in stock_list: sid=context.symbol(stock)prices = data.history(sid,'price',26,'1d')##是否符合MA指标ma_short=data.history(sid,'price',context.ma_short_period,'1d').mean()ma_long=data.history(sid,'price',context.ma_long_period,'1d').mean()if ma_short>ma_long and data.can_trade(sid) and stock_count<10:stock_selected.append(stock)stock_count+=1##是否符合MACD指标try:macd, signal, hist = talib.MACD(np.array(prices), context.macd_short_period,context.macd_long_period, context.macd_dea)if macd[-1] - signal[-1] > 0 and macd[-2] - signal[-2] < 0 and stock_count<10:if cur_position == 0 and data.can_trade(sid):stock_selected.append(stock)stock_count+=1except:passif stock_count==10:breakcash=context.portfolio.cash per_stock=1/len(stock_selected)for stock in stock_selected:sid=context.symbol(stock)price=data.current(sid,'price')context.order_target_percent(sid,per_stock)
二、基于技术指标的策略实现
1.库函数导入与全局变量初始化
其中stocks是初始选股池,我们可以自行定义
import pandas as pd
import talib as tadf=pd.read_csv('stocks.csv')stock_list=[row['stock'] for index,row in df.iterrows()]
2.每日逻辑函数编写
策略1: MACD金叉+MA多头买入
说明:1)每20日进行一次调仓
2)最多买入10只股票
#选股池
instruments=stock_list#回测时间
start_date='2019-01-03'
end_date='2021-01-22'def initialize(context):##买入卖出均为0.3%,最少5元context.set_commission(PerOrder(buy_cost=0.0003,sell_cost=0.0003,min_cost=5))##macd参数设置 dif短线:12 dif长线:26 dea:9context.macd_short_period=12context.macd_long_period=26context.macd_dea=9#ma参数设置:ma短线5 ma长线20context.ma_short_period=5context.ma_long_period=20##每天执行一次
def handle_data(context,data):##技术指标所需要的最大天数max_need_period=26if context.trading_day_index<26:returnif (context.trading_day_index)%20!=0:return print(context.trading_day_index)##记录筛选后的股票和股票树木stock_selected=[]stock_count=0for stock in stock_list: sid=context.symbol(stock)prices = data.history(sid,'price',26,'1d')##是否符合MA指标ma_short=data.history(sid,'price',context.ma_short_period,'1d').mean()ma_long=data.history(sid,'price',context.ma_long_period,'1d').mean()if ma_short>ma_long and data.can_trade(sid) and stock_count<10:stock_selected.append(stock)stock_count+=1##是否符合MACD指标try:macd, signal, hist = talib.MACD(np.array(prices), context.macd_short_period,context.macd_long_period, context.macd_dea)if macd[-1] - signal[-1] > 0 and macd[-2] - signal[-2] < 0 and stock_count<10:if cur_position == 0 and data.can_trade(sid):stock_selected.append(stock)stock_count+=1except:passif stock_count==10:breakcash=context.portfolio.cash per_stock=1/len(stock_selected)for stock in stock_selected:sid=context.symbol(stock)price=data.current(sid,'price')context.order_target_percent(sid,per_stock)
策略2: 利用MA指标进行择股
说明:1)每20日进行一次调仓
2)ma3>ma5且ma5>ma10且ma10>ma15时买入股票
3)最多买入5只股票
def handle_data(context,data):##技术指标所需要的最大天数max_need_period=26if context.trading_day_index<26:returnif (context.trading_day_index)%20!=0:return print(context.trading_day_index)##记录筛选后的股票和股票树木stock_selected=[]stock_count=0for stock in stock_list: sid=context.symbol(stock)prices = data.history(sid,'price',26,'1d')##是否符合MA指标ma_3=data.history(sid,'price',3,'1d').mean()ma_5=data.history(sid,'price',5,'1d').mean()ma_10=data.history(sid,'price',10,'1d').mean()ma_15=data.history(sid,'price',15,'1d').mean()if ma_3>ma_5 and ma_5>ma_10 and ma_10>ma_15 and data.can_trade(sid) and stock_count<5:stock_selected.append(stock)stock_count+=1##是否符合MACD指标if stock_count==5:breakcash=context.portfolio.cash per_stock=1/len(stock_selected)for stock in stock_selected:sid=context.symbol(stock)price=data.current(sid,'price')context.order_target_percent(sid,per_stock)
3.策略结果展示
策略1: MACD金叉+MA多头买入
策略2: MA择股
三、基于QP优化的策略实现
1.基于经典QP的handle函数
说明:构造优化问题缺点比较明显,最后最优权重会集中在某一支股票,不利于风险分散
def handle_data(context,data):##技术指标所需要的最大天数if context.trading_day_index<100:returnif (context.trading_day_index)%20!=0:return print(context.trading_day_index)price_df=pd.DataFrame()stock_num=120count=0for stock in instruments:count+=1sid=context.symbol(stock)prices = data.history(sid,'price',5,'1d')price_df=pd.concat([price_df,prices],axis=1)price_df.fillna(0,inplace=True)if(count==stock_num):break## 120,5price_np=price_df.to_numpy().T##cov##(120,120)cov_df= pd.DataFrame(np.cov(price_np))P=matrix(cov_df.to_numpy())q=-matrix(np.mean(price_np,axis=1),(stock_num,1))##Ax=bA=matrix(1.,(1,stock_num))b=matrix(1.)##GX<=hG = -matrix(np.eye(stock_num)) h = opt.matrix(0.0, (stock_num,1))##solver:solvers.options['show_progress'] = Falsesol = solvers.qp(P,q,G,h,A,b)weight=list(sol['x'])stock_selected_list=[]sum_weight=0.0cur=0for stock in stock_list: sid=context.symbol(stock)if data.can_trade(sid):stock_selected_list.append(stock)sum_weight+=weight[cur]else:weight[cur]=0cur+=1cur=0for stock in stock_list:if weight[cur]!=0:sid=context.symbol(stock)price=data.current(sid,'price')context.order_target_percent(sid,weight[cur]/sum_weight)cur+=1
2.增加限制条件使股票具有多样性:
方法:修改QP约束中的G矩阵与h矩阵
##GX<=htemp_df1= pd.DataFrame(-np.eye(stock_num))temp_df2= pd.DataFrame(np.eye(stock_num))G_df=pd.concat([temp_df1,temp_df2],axis=0)G = matrix(G_df.to_numpy()) ##xi<=0.2temp_list=[]for i in range(stock_num):temp_list.append([0.0])for i in range(stock_num):temp_list.append([0.2])h = opt.matrix(np.array(temp_list))
3.融合技术指标的QP策略:
说明:1)按5日的数据构造协方差矩阵与收益均值矩阵
2)每20日进行一次调仓
3)如果满足ma3>ma5且ma5>ma10且ma10>ma15权重翻倍
def handle_data(context,data):##技术指标所需要的最大天数if context.trading_day_index<100:returnif (context.trading_day_index)%20!=0:return print(context.trading_day_index)price_df=pd.DataFrame()stock_num=120count=0for stock in instruments:count+=1sid=context.symbol(stock)prices = data.history(sid,'price',5,'1d')price_df=pd.concat([price_df,prices],axis=1)price_df.fillna(0,inplace=True)if(count==stock_num):break## 120,5price_np=price_df.to_numpy().T##cov##(120,120)cov_df= pd.DataFrame(np.cov(price_np))P=matrix(cov_df.to_numpy())q=-matrix(np.mean(price_np,axis=1),(stock_num,1))##Ax=bA=matrix(1.,(1,stock_num))b=matrix(1.)##GX<=htemp_df1= pd.DataFrame(-np.eye(stock_num))temp_df2= pd.DataFrame(np.eye(stock_num))G_df=pd.concat([temp_df1,temp_df2],axis=0)G = matrix(G_df.to_numpy()) ##xi<=0.2temp_list=[]for i in range(stock_num):temp_list.append([0.0])##每只权重不超过0.2for i in range(stock_num):temp_list.append([0.2])h = opt.matrix(np.array(temp_list))##solver:solvers.options['show_progress'] = Falsesol = solvers.qp(P,q,G,h,A,b)weight=list(sol['x'])stock_selected_list=[]sum_weight=0.0cur=0for stock in stock_list: sid=context.symbol(stock)if data.can_trade(sid):stock_selected_list.append(stock)sid=context.symbol(stock)##融入技术指标,如果满足条件,,权重加倍ma_3=data.history(sid,'price',3,'1d').mean()ma_5=data.history(sid,'price',5,'1d').mean()ma_10=data.history(sid,'price',10,'1d').mean()ma_15=data.history(sid,'price',15,'1d').mean()sum_weight+=weight[cur]if ma_3>ma_5 and ma_5>ma_10 and ma_10>ma_15:sum_weight+=weight[cur]*2weight[cur]*=2else:weight[cur]=0cur+=1cur=0for stock in stock_list:if weight[cur]!=0:sid=context.symbol(stock)price=data.current(sid,'price')context.order_target_percent(sid,weight[cur]/sum_weight)cur+=1
4.策略结果展示
策略1:经典基于QP优化策略
策略2:限制股票权重的QP优化策略
策略3:融合技术指标的QP优化策略