寻找量化造梦者,以下是我们的联系方式,我们期待你的加入!
官网:https://www.ricequant.com
博客:https://www.ricequant.com/community
企业官方微博:Ricequant
微信公众号:Ricequant
Ricequant全国高校量化比赛即将启动~~~敬请期待~~
我们在上一份教学中初步介绍了为什么用计算机来辅助金融分析和Ricequant,在这份教学中我们直入主题,教您如何在Ricequant上面开始编写第一个量化策略。
点击网页上方的“我的策略”,进入策略列表,再点击“创建新的策略”,你将看到一个自动生成的简单算法示例,更简化的版本如下:
# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.s1 = '000001.XSHE'# 你所选择的证券的每一个交易数据更新,都将会触发此段逻辑def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! order_shares(context.s1, 1000)每一个交易策略都需要定义init和handle_bar两个方法。在每次创建一个新的策略的时候,都会自动生成,你只需要在每个方法中填入你自己策略逻辑就可以了。
在策略运行的时候init方法会先于其它所有方法运行,且只运行一次。handle_bar在每次数据更新的时候会运行一次。比如说每日回测,在你限定的交易时间范围内,从最早的交易日到最新的交易日,按时间序列先后,每次数据更新都会运行一次handle_bar方法。
在init方法中,你可以看到我们传入了一个context参数,它是一个Python Dictionary。简单来讲,context就是一个字典,其中包含了很多变量,并可以不断往context里面加入变量。比如下面的例子就是用户在context中加入了一个stockcode变量,并把它赋值为"000001.XSHE",之所以使用引号,表示的是stockcode变量的值为字符串类型,用于区别其它类型。update_universe用来订阅所有你感兴趣的股票。
def init(context): ... context.stockcode = "000001.XSHE" context.stockcode2 = "000024.XSHE" update_universe([context.stockcode, context.stockcode2])聪明的你应该已经发现,handle_bar的其中一个参数也是context,它其实是和init方法中的参数是同一个。因为init方法优先于其它任何方法,所以如果你需要定义一些变量,使得它们能穿梭于其它的方法,并被调用,那么你就可以采取往context中加入新的变量来达到需求。
下面来介绍handle_bar中的另一个参数bar_dict,它也是一个字典,包含了每次数据更新的时候所有属性的值,比如说开盘价 (open), 收盘价 (close)等值,你可以参考Bar对象查看它所有的属性。
def handle_bar(context, bar_dict): order_book = bar_dict[context.stockcode].order_book_id open_price = bar_dict[context.stockcode].open close_price = bar_dict[context.stockcode].close MA20 = bar_dict[context.s1].mavg(20, frequency='day') ...mavg(intervals, frequency='day')方法可以用来计算简单移动平均值 (sample moving average),下面我们会详细讲解如何利用简单移动平均线来写一个简单的金叉策略。
移动平均线是一个广为使用的指标,其中最为基础的是简单移动均线 (sample moving average)。每天都会计算平均值,比如说10日均线,就是每天计算过去10日的平均值。随着时间推移,最开始的值会被更新的值取代,结果体现为平均值是随着时间移动。
图中的绿线为收盘价的走势图,红色线为它的20日简单均线图,紫色线为收盘价的50日简单均线图。你会发现当20日的均线向上穿过50日均线,收盘价会有上升趋势,那我们可以在交叉点出现时买入该股票。当20日均线向下穿过50日均线时,收盘价会有下降趋势,那我们可以在交叉点出现时卖出该股票。
首先,我们要先完成init的初始化。在这个策略里我们选取一只股票,使用两条均线。
def init(context): context.s1 = "000001.XSHE" update_universe([context.s1])接下来,在每一个handle_bar里,我们需要完成当天的长均线和短均线的计算。
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')我们在获得均值之后,可以进一步按照金叉的逻辑预测来买卖股票。但在需要注意的地方是:在买入时,需要计算现在我们所持有的仓位;在卖出时,需要计算现有的资金能购买多少share的股票。对于portfolio和positions的属性介绍可以分别参考Portfolio对象和Position对象。
# 计算现在portfolio中股票的仓位 current_position = context.portfolio.positions[context.s1].quantity # 计算现在portfolio中的现金可以购买多少股票 shares = context.portfolio.cash / bar_dict[context.s1].close到目前为止,我们已经介绍了整个自动交易策略的基本构成,我们需要清楚了解这其中的两个方法init和handle_bar的作用,在此基础上我们才能更容易的实现我们想要实现的策略,在后续的教学文档中,我们会详细讲解如何使用ricequant的落单功能,用历史数据对我们的第一个金叉策略进行回测。