基于BigQuant的量化策略实现

文章目录

一、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=26
    
    if context.trading_day_index<26:
        return
    
    if (context.trading_day_index)%20!=0:
        return 
    
    print(context.trading_day_index)
    
    ##记录筛选后的股票和股票数目
    stock_selected=[]
    stock_count=0
    
    for 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+=1
        except:
            pass
                
        if stock_count==10:
            break
            
    cash=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 ta

df=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:9
    
    context.macd_short_period=12
    context.macd_long_period=26
    context.macd_dea=9
    
    #ma参数设置:ma短线5 ma长线20
    context.ma_short_period=5
    context.ma_long_period=20


##每天执行一次
def handle_data(context,data):
    
    ##技术指标所需要的最大天数
    max_need_period=26
    
    if context.trading_day_index<26:
        return
    
    if (context.trading_day_index)%20!=0:
        return 
    
    print(context.trading_day_index)
    
    ##记录筛选后的股票和股票树木
    stock_selected=[]
    stock_count=0
    
    for 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+=1
        except:
            pass
                
        if stock_count==10:
            break
            
    cash=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=26
    
    if context.trading_day_index<26:
        return
    
    if (context.trading_day_index)%20!=0:
        return 
    
    print(context.trading_day_index)
    
    ##记录筛选后的股票和股票树木
    stock_selected=[]
    stock_count=0
    
    for 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:
            break
            
    cash=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多头买入

基于BigQuant的量化策略实现_第1张图片

策略2: MA择股

基于BigQuant的量化策略实现_第2张图片

 

三、基于QP优化的策略实现

1.基于经典QP的handle函数

说明:构造优化问题缺点比较明显,最后最优权重会集中在某一支股票,不利于风险分散

def handle_data(context,data):
    
    ##技术指标所需要的最大天数
    
    if context.trading_day_index<100:
        return
    
    if (context.trading_day_index)%20!=0:
        return 
    
    print(context.trading_day_index)
    
    price_df=pd.DataFrame()
    
    stock_num=120
    count=0
    
    for stock in instruments:
        count+=1
        sid=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,5
    price_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=b
    A=matrix(1.,(1,stock_num))
    b=matrix(1.)
    
    
    ##GX<=h
    G = -matrix(np.eye(stock_num)) 
    h = opt.matrix(0.0, (stock_num,1))
  
    
    ##solver:
    solvers.options['show_progress'] = False
    sol = solvers.qp(P,q,G,h,A,b)
    weight=list(sol['x'])

    stock_selected_list=[]
    sum_weight=0.0
    cur=0
    for 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]=0
        cur+=1
    
    cur=0
    for 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<=h
    temp_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.2
    temp_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:
        return
    
    if (context.trading_day_index)%20!=0:
        return 
    
    print(context.trading_day_index)
    
    price_df=pd.DataFrame()
    
    stock_num=120
    count=0
    
    for stock in instruments:
        count+=1
        sid=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,5
    price_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=b
    A=matrix(1.,(1,stock_num))
    b=matrix(1.)
    
    
    ##GX<=h
    temp_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.2
    temp_list=[]
    for i in range(stock_num):
        temp_list.append([0.0])
        
    ##每只权重不超过0.2
    for i in range(stock_num):
        temp_list.append([0.2])
    h = opt.matrix(np.array(temp_list))
  
    
    ##solver:
    solvers.options['show_progress'] = False
    sol = solvers.qp(P,q,G,h,A,b)
    weight=list(sol['x'])

    stock_selected_list=[]
    sum_weight=0.0
    cur=0
    for 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]*2
                    weight[cur]*=2
        else:
            weight[cur]=0
        cur+=1
    
    cur=0
    for 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优化策略

基于BigQuant的量化策略实现_第3张图片

 

策略2:限制股票权重的QP优化策略

基于BigQuant的量化策略实现_第4张图片

 

策略3:融合技术指标的QP优化策略

基于BigQuant的量化策略实现_第5张图片

 

 

你可能感兴趣的:(量化投资,深度学习,机器学习,数据挖掘)