# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
context.s1 = '000001.XSHE'
#000001.XSHE是合约代码也就是order_book_id,symbol是合约简称也就是平安银行
# 你所选择的证券的每一个交易数据更新,都将会触发此段逻辑
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)
一、关键方法和交易函数概述
1.init (必须实现)
init(context)
初始化方法 - 在回测和实时模拟交易只会在启动的时候触发一次。你的算法会使用这个方法来设置你需要的各种初始化配置。 context
对象将会在你的算法的所有其他的方法之间进行传递以方便你可以拿取到。
参数
参数 类型 注释 context python简单对象 将会在整个算法中当做一个全局变量来使用。属性通过点标记(".")来取到。
范例
def init(context):
# cash_limit的属性是根据用户需求自己定义的,你可以定义无限多种自己随后需要的属性,ricequant的系统默认只是会占用context.portfolio的关键字来调用策略的投资组合信息
context.cash_limit = 5000
2.handle_bar (必须实现)
handle_bar(context, bar_dict)
bar数据的更新会自动触发该方法的调用。策略具体逻辑可在该方法内实现,包括交易信号的产生、订单的创建等。在实时模拟交易中,该函数在交易时间内会每分钟被触发一次。 注意:由于该方法会每分钟被触发,请尽量不要在该函数中放入查询类(如带有query()参数的API)代码以免运行时间过长,该类逻辑可放在 init() 中执行。
参数
参数 类型 注释 context python简单对象 储存策略自定义参数、设置、仓位、投资组合信息的全局变量,属性通过点标记(".")来取到 bar_dict dict key为order_book_id,value为bar数据。当前合约池内所有合约的bar数据信息都会更新在bar_dict里面
范例
def handle_bar(context, bar_dict):
# put all your algorithm main logic here.
# ...
order_shares('000001.XSHE', 500)
# ...
3.order_shares - 指定股数交易(股票专用)
order_shares(id_or_ins, amount, style=MarketOrder())
落指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。
参数
参数 类型 注释 id_or_ins str或instrument对象 order_book_id或symbol或instrument对象,用户必须指定 amount float-required 需要落单的股数。正数代表买入,负数代表卖出。将会根据一手xx股来向下调整到一手的倍数,比如中国A股就是调整成100股的倍数。 style OrderType 订单类型,默认是市价单。目前支持的订单类型有:
- style=MarketOrder()
- style=LimitOrder(limit_price)
范例
- 购买Buy 2000 股的平安银行股票,并以市价单发送:
order_shares('000001.XSHE', 2000)
- 卖出2000股的平安银行股票,并以市价单发送:
order_shares('000001.XSHE', -2000)
- 购买1000股的平安银行股票,并以限价单发送,价格为¥10:
order_shares('000001.XSHE', 1000, style=LimitOrder(10))
4.update_universe - 更新股票池
update_universe(order_book_id)
该方法用于更新现在关注的证券的集合(e.g.:股票池)。PS:会在下一个bar事件触发时候产生(新的关注的股票池更新)效果。并且update_universe会是覆盖(overwrite)的操作而不是在已有的股票池的基础上进行增量添加。比如已有的股票池为['000001.XSHE', '000024.XSHE']
然后调用了update_universe(['000030.XSHE'])
之后,股票池就会变成000030.XSHE
一个股票了,随后的数据更新也只会跟踪000030.XSHE
这一个股票了。
参数
参数 类型 注释 order_book_id str OR str list 合约代码,可传入order_book_id, order_book_id list
范例
下面的代码是将股票池变更为只有2个股票000001.XSHE
和000024.XSHE
:
update_universe(['000001.XSHE', '000024.XSHE'])
当然,您也可以使用合约简称:
update_universe(['平安银行', '招商地产'])
二、具体入门
每一个交易策略都需要定义init
和handle_bar
两个方法。在每次创建一个新的策略的时候,都会自动生成,你只需要在每个方法中填入你自己策略逻辑就可以了。
在策略运行的时候init
方法会先于其它所有方法运行,且只运行一次。handle_bar
在每次数据更新的时候会运行一次。比如说每日回测,在你限定的交易时间范围内,从最早的交易日到最新的交易日,按时间序列先后,每次数据更新都会运行一次handle_bar
方法。
在init
方法中,你可以看到我们传入了一个context参数,它是一个Python Dictionary。简单来讲,context就是一个字典,其中包含了很多变量,并可以不断往context里面加入变量。
比如下面的例子就是用户在context中加入了一个stockcode变量,并把它赋值为"000001.XSHE",之所以使用引号,表示的是stockcode变量的值为字符串类型,用于区别其它类型。
def init(context):
...
context.stockcode = "000001.XSHE"
context.stockcode2 = "000024.XSHE"
update_universe([context.stockcode, context.stockcode2])
#update_universe用来订阅所有你感兴趣的股票。
update_universe
用来订阅所有你感兴趣的股票。
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')
方法可以用来计算简单移动平均值 (simple moving average),frequency是策略的频率,
下面我们会详细讲解如何利用简单移动平均线来写一个简单的金叉策略。
移动平均线是一个广为使用的指标,其中最为基础的是简单移动均线 (simple 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中股票的仓位,quantity是当前持仓股数
current_position = context.portfolio.positions[context.s1].quantity
# 计算现在portfolio中的现金可以购买多少股票
shares = context.portfolio.cash / bar_dict[context.s1].close
portfolio - 投资组合信息
context.portfolio
该投资组合在单一股票或期货策略中分别为股票投资组合和期货投资组合。在股票+期货的混合策略中代表汇总之后的总投资组合。请参考下面 portfolio对象
Portfolio对象
- portfolio对象
属性 | 类型 | 注释 |
---|---|---|
cash | float | 可用资金,为子账户可用资金的加总 |
frozen_cash | float | 冻结资金,为子账户冻结资金加总 |
total_returns | float | 投资组合至今的累积收益率 |
daily_returns | float | 投资组合每日收益率 |
daily_pnl | float | 当日盈亏,子账户当日盈亏的加总 |
market_value | float | 投资组合当前的市场价值,为子账户市场价值的加总 |
total_value | float | 总权益,为子账户总权益加总 |
units | float | 份额。在没有出入金的情况下,策略的初始资金 |
unit_net_value | float | 单位净值 |
static_unit_net_value | float | 静态单位权益 |
transaction_cost | float | 当日费用 |
pnl | float | 当前投资组合的累计盈亏 |
start_date | datetime.datetime | 策略投资组合的回测/实时模拟交易的开始日期 |
annualized_returns | float | 投资组合的年化收益率 |
positions | dict | 一个包含所有仓位的字典,以order_book_id作为键,position 对象作为值,关于position的更多的信息可以在下面的部分找到。 |
Position对象
- 股票position对象
属性 | 类型 | 注释 |
---|---|---|
order_book_id | str | 合约代码 |
quantity | int | 当前持仓股数 |
pnl | float | 持仓累计盈亏 |
sellable | int | 该仓位可卖出股数。T+1的市场中sellable = 所有持仓-今日买入的仓位 |
market_value | float | 获得该持仓的实时市场价值 |
value_percent | float | 获得该持仓的实时市场价值在总投资组合价值中所占比例,取值范围[0, 1] |
avg_price | float | 平均建仓成本 |
- 期货position对象
属性 | 类型 | 注释 |
---|---|---|
order_book_id | str | 合约代码 |
pnl | float | 累计盈亏 |
daily_pnl | float | 当日盈亏,当日浮动盈亏+当日平仓盈亏 |
holding_pnl | float | 当日持仓盈亏 |
realized_pnl | float | 当日平仓盈亏 |
transaction_cost | float | 仓位交易费用 |
margin | float | 仓位总保证金 |
market_value | float | 当前仓位的名义价值。如果当前净持仓为空方向持仓,则名义价值为负 |
buy_daily_pnl | float | 多头仓位当日盈亏 |
buy_pnl | float | 多头仓位累计盈亏 |
buy_transaction_cost | float | 多头费用 |
closable_buy_quantity | float | 可平多头持仓 |
buy_margin | float | 多头持仓占用保证金 |
buy_today_quantity | int | 多头今仓 |
buy_quantity | int | 多头持仓 |
buy_avg_open_price | float | 多头开仓均价 |
buy_avg_holding_price | float | 多头持仓均价 |
sell_daily_pnl | float | 空头仓位当日盈亏 |
sell_pnl | float | 空头仓位累计盈亏 |
sell_transaction_cost | float | 空头费用 |
closable_sell_quantity | int | 可平空头持仓 |
sell_margin | float | 空头持仓占用保证金 |
sell_today_quantity | int | 空头今仓 |
sell_quantity | int | 空头持仓 |
sell_avg_open_price | float | 空头开仓均价 |
sell_avg_holding_price | float | 空头持仓均价 |