Ricequant 平台入门--回测第一个量化交易策略

一、如何使用ricequant 平台进行落单和回测

def init(context):

    context.s1 = "000001.XSHE"
    update_universe([context.s1])
    
def handle_bar(context, bar_dict):
     
    MA_short= bar_dict[context.s1].mavg(20,frequency='day')
    MA_long = bar_dict[context.s1].mavg(50,frequency ='day')

    curPosition =context.portfolio.positions[context.s1].quantity
    shares = context.portfolio.cash/bar_dict[context.s1].close

        如上是上一篇教程写的简单的一个交易策略,接下来我们的目标是建立起交易落单的逻辑,以便于我们使用历史数据进行回测。金叉的交易思路我们在上一篇教程中已经分析,如果短期均线从底部突破长期均线,是买入信号,我们把思路转化为python代码。

    if MA_short > MA_long and curPosition == 0:
       order_shares(context.s1,shares)    

      在这里我们接触到了新的api,就是落单功能order_shares,这里有两个参数,第一个是股票代码,第二个代表买多少share,如果数值为负数就代表卖出。在这个例子里,我们满仓买入。

       Ricequant提供了强大而灵活的各种order的方法,除了最基本的order_shares之外,还可以使用order_target_value,order_lot,order_percent等等。在上面这个例子中,满仓买入我们使用order_target_percent会更加方便,在这里传入的第二个参数不再是购买(卖出)的数量,而是购买(卖出)后该股票占到投资组合的百分比,0代表0%,1代表100%。

  if MA_short > MA_long and curPosition == 0:  
       order_target_percent(context.s1,1) 

        如果短期均线从顶部跌破,那么出现一个清仓的信号。

    if MA_short < MA_long and curPosition != 0:      
        order_target_percent(context.s1,0)

       在进行回测前,我们还有最后一个步骤要完成,只要是交易策略不免会涉及到手续费,印花税和滑点费用。目前ricequant的默认设置如下

  • 固定印花税: 0.1%,

  • 手续费: 0.08% - 可以用context.commission手动修改(废弃)

  • 滑点: 0.246% - 可以用context.slippage手动修改(废弃)

第一个完整回测策略:

def init(context):
    context.s1 = "000001.XSHE"
    context.slippage = 0.05
    update_universe([context.s1])
    
    
def handle_bar(context, bar_dict):
     
    MA_short= bar_dict[context.s1].mavg(20,frequency ='day')
    MA_long = bar_dict[context.s1].mavg(50,frequency ='day')

    curPosition =context.portfolio.positions[context.s1].quantity
    shares = context.portfolio.cash/bar_dict[context.s1].close
    
    if MA_short > MA_long and curPosition == 0:  
       order_target_percent(context.s1,1) 
       
    if MA_short < MA_long and curPosition != 0:
       order_target_percent(context.s1,0)

        除了策略表现以外,我们经常希望直观的看到一些历史数据以图表的方式展现出来,以上面金叉策略为例,我们想画出短均线,长均线和股票价格,可是直观地看出产生金叉的时候是不是一个交易的好的信号。

        这时候就可以使用Ricequant的plot 功能来实现,在上述策略中的handle_bar function下面加入这几行代码

plot('close', bar_dict[context.s1].close) 
plot('short_avg',MA_short)
plot('long_avg',MA_long)

        这段code的意义是在每个handle_bar的时间切片上绘制下该时间的数值,这个数值可以是bar_dict当中存储的股票价格,也可以是任意我们赋值的参数,比如当前的N日均价,或者当天的某个技术指标(之后的教程中会降到),等等。

二、如何解读回测结果数据

      Ricequant的回测结果中,我们比较关心的回测数据主要是

1.回测收益 & 基准收益

      这是最直观的收益对比。其他风险数据相似的情况下,回测收益相对基准收益越高,策略表现越好。

2.Beta

      Beta 主要是衡量策略相对于大盘的系统风险性。比较优秀稳健的量化策略通常追求较低的beta值,降低策略的系统风险。也就是说无论大盘是熊是牛都能保证稳定的收益。

      降低策略的beta值有几种方法,1)在策略中加入对冲部分 2)在只能做单边的情况下,增加股票数量,选择相关性较低的一篮子股票。

3.最大回撤和波动率

      这两个数据主要是体现策略的风险性。波动率越高,最大回撤越高,策略的风险性就越大。最大回撤的数值尤为重要,如果看到过大的最大回撤,通常要考虑策略的可行性,增加止损或者其他有效的仓位控制方式。

4.夏普比率

      Sharpe Ratio,和Sortino Ratio一样,是把风险和收益综合起来的数据,可以看成是一种考虑风险因素之后的调整收益率 。夏普指数越高,相当于每多承担一份风险,获得的额外收益越高。这是我们在策略调试中,综合衡量评定一个策略价值的重要标准。

三、如何使用ricequant中的回测历史功能来优化策略

    为何需要查看回测历史?

  • 参数优化:设计交易策略中,常常会需要做一些参数的优化。比如我们写的金叉策略中,根据回测时间段的长度的不同和思路的差别,最优长短均线的设置就是需要不断优化测试,trial and error的策略参数。
  • 市场行情选择:某类交易策略表现和市场行情关系较大,我们希望能分别观察它们在熊市和牛市,在risk on 和 risk off 市场中的不同表现,从而把策略选择和市场动向结合起来。

     为了让大家更方便的看到同一策略使用不同参数和不同时间段的回测表现,我们开发了查看回测历史的功能,在每一个策略下面,都能看到所有的历史回测表现。

     比如我们可以选择在14-15年的牛市段和13-14年的熊市段分别运行金叉这样的动量策略

     当然值得注意的是,不管是参数优化还是市场行情相关,我们在优化策略的时候仍然需要以理论框架为出发点,不然单纯追求回报率,很容易造成历史数据过度拟合的情况。

四、文中涉及到的知识点

1.order_lots - 指定手数交易(股票专用)

order_lots(id_or_ins, amount, style=OrderType)

指定手数发送买/卖单。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。

参数

参数 类型 注释
id_or_ins str或instrument对象 order_book_id或symbol或instrument对象,用户必须指定
amount float 多少手的数目。正数表示买入,负数表示卖出,用户必须指定
style OrderType 订单类型,默认是市价单。目前支持的订单类型有:
  • style=MarketOrder
  • style=LimitOrder(limit_price)

范例

  • 买入20手的平安银行股票,并且发送市价单:
order_lots('000001.XSHE', 20)
  • 买入10手平安银行股票,并且发送限价单,价格为¥10:
order_lots('000001.XSHE', 10, style=LimitOrder(10))

2.plot - 画图

plot(series_name, value)

plot函数可以将时间序列的数据传给页面进行绘图,结果是以时间为横轴,value为纵轴的曲线。

参数

参数 类型 注释
series_name str 绘制曲线的名称,用户必须填写
value float 当前日期的曲线的点的值,用户必须填写

范例

 # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
    # TODO: 开始编写你的算法吧!

    plot('close', bar_dict['000001.XSHE'].close)
    plot('high', bar_dict['000001.XSHE'].high)
    plot('low', bar_dict['000001.XSHE'].low)
    plot('open', bar_dict['000001.XSHE'].open)

以上代码画图的结果截图:

 

3.order_percent - 一定比例下单(股票专用)

order_percent(id_or_ins, percent, style=OrderType)

       发送一个等于目前投资组合价值(市场价值和目前现金的总和)一定百分比的买/卖单,正数代表买,负数代表卖(暂不支持卖空)。股票的股数总是会被调整成对应的一手的股票数的倍数(1手是100股)。百分比是一个小数,并且小于1(<100%),0.5表示的是50%.需要注意,百分比不能为1,因为下单时手续费将会计入下单金额中。当买入股票所需金额加上手续费大于资金时,该API将不会创建发送订单。

参数

参数 类型 注释
id_or_ins str或instrument对象 order_book_id或symbol或instrument object,用户必须指定
percent float 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。用户必须指定
style OrderType 订单类型,默认是市价单。目前支持的订单类型有:
  • style=MarketOrder()
  • style=LimitOrder(limit_price)

范例

  • 买入等于现有投资组合50%价值的平安银行股票。如果现在平安银行的股价是¥10/股并且现在的投资组合总价值是¥4000,用来买入的资金为¥2000,那么将会买入200股的平安银行股票。(不包含交易成本和滑点的损失):
order_percent('000001.XSHE', 0.5)

4.order_target_value - 目标价值下单(股票专用)

order_target_value(id_or_ins, cash_amount, style=OrderType)

       买入/卖出并且自动调整该证券的仓位到一个目标价值(暂不支持卖空)。如果还没有任何该证券的仓位,那么会买入全部目标价值的证券。如果已经有了该证券的仓位,则会买入/卖出调整该证券的现在仓位和目标仓位的价值差值的数目的证券。需要注意,如果资金不足,该API将不会创建发送订单。

参数

参数 类型 注释
id_or_ins str或instrument对象 order_book_id或symbol或instrument object,用户必须指定
cash_amount float-required 最终的该证券的仓位目标价值
style OrderType 订单类型,默认是市价单。目前支持的订单类型有:
  • style=MarketOrder()
  • style=LimitOrder(limit_price)

范例

  • 如果现在的投资组合中持有价值¥3000的平安银行股票的仓位并且设置其目标价值为¥10000,以下代码范例会发送价值¥7000的平安银行的买单到市场。(向下调整到最接近每手股数即100的倍数的股数):
order_target_value('000001.XSHE', 10000)

5.滑点

       为了更好模拟实际交易中订单对市场的冲击,我们引入滑点的设置。您可以在策略编辑页面"更多"选项下进行滑点设置,允许设置的范围是[0, 1)。该设置将在一定程度上使最后的成交价"恶化",也就是买得更贵,卖得更便宜。我们的滑点方式是按照最后成交价的一定比例进行恶化。例如,设置滑点为0.1,那么如果原本买入交易的成交价为10元,则设置之后成交价将变成11元,即买得更贵。

注意,滑点默认为0,原有的默认0.246%的滑点值以及通过context.slippage设置的方式被废弃。

你可能感兴趣的:(RiceQuant量化)