交易引擎¶
支持回测和实盘。
主入口¶
-
M.trade.
v3
(start_date='', end_date='', handle_data=None, instruments=None, prepare=None, initialize=None, before_trading_start=None, volume_limit=0.025, order_price_field_buy='open', order_price_field_sell='close', capital_base=1000000.0, benchmark='000300.SHA', auto_cancel_non_tradable_orders=True, data_frequency='daily', price_type='后复权', plot_charts=True, backtest_only=False, options_data=None, options=None, amount_integer=None, m_meta_kwargs={})¶ 量化交易引擎。支持回测和模拟实盘交易
参数: - start_date (str) – 开始日期,设定值只在回测模式有效,在模拟实盘模式下为当前日期,示例:2017-06-01。一般不需要指定,使用 证券代码列表 里的开始日期;默认值是。
- end_date (str) – 结束日期,设定值只在回测模式有效,在模拟实盘模式下为当前日期,示例:2017-06-01。一般不需要指定,使用 证券代码列表 里的结束日期;默认值是。
- handle_data (函数) – 主函数,[回调函数] 必须实现的函数,该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次,由于我们现在数据只有日K,所以是按天回调。在回测中,可以通过对象data获取单只股票或多只股票的时间窗口价格数据。如果算法中没有schedule_function函数,那么该函数为必选函数。一般策略的交易逻辑和订单生成体现在该函数中;默认值是None。
- instruments (列表|DataSource) – 证券代码列表,如果提供了 prepare 函数,可以在 prepare 中覆盖此参数提供的值;默认值是None。
- prepare (函数) – 数据准备函数,[回调函数] 准备数据函数,运行过程中只调用一次,在 initialize 前调用,准备交易中需要用到数据。目前支持设置交易中用到的股票列表,设置到 context.instruments。更多见 prepare ;默认值是None。
- initialize (函数) – 初始化函数,[回调函数] 初始化函数,整个回测中只在最开始时调用一次,用于初始化一些账户状态信息和策略基本参数,context也可以理解为一个全局变量,在回测中存放当前账户信息和策略基本参数便于会话;默认值是None。
- before_trading_start (函数) – 盘前处理函数,[回调函数] 每个单位时间开始前调用一次,即每日开盘前调用一次,该函数是可选函数。你的算法可以在该函数中进行一些数据处理计算,比如确定当天有交易信号的股票池;默认值是None。
- volume_limit (float) – 成交率限制:执行下单时控制成交量参数,默认值2.5%,若设置为0时,不进行成交量检查;默认值是0.025。
- order_price_field_buy (choice) – 买入点:open=开盘买入,close=收盘买入;可选值有: open, close;默认值是open。
- order_price_field_sell (choice) – 卖出点:open=开盘卖出,close=收盘卖出;可选值有: open, close;默认值是close。
- capital_base (float) – 初始资金;默认值是1000000.0。
- benchmark (str) – 基准指数,不影响回测结果;默认值是000300.SHA。
- auto_cancel_non_tradable_orders (bool) – 自动取消无法成交订单:是否自动取消因为停牌等原因不能成交的订单;默认值是True。
- data_frequency (choice) – 回测数据频率:目前只支持日线 (daily),未来将支持分钟线 (minute);可选值有: daily;默认值是daily。
- price_type (choice) – 回测价格类型:前复权(forward_adjusted),真实价格(original),后复权(backward_adjusted);可选值有: 前复权, 真实价格, 后复权;默认值是后复权。
- plot_charts (bool) – 显示回测结果图表;默认值是True。
- backtest_only (bool) – 只在回测模式下运行:默认情况下,Trade会在回测和实盘模拟模式下都运行。如果策略中有多个M.trade,在实盘模拟模式下,只能有一个设置为运行,其他的需要设置为 backtest_only=True,否则将会有未定义的行为错误;默认值是False。
- options_data (DataSource) – 其他输入数据:回测中用到的其他数据,比如预测数据、训练模型等。如果设定,在回测中通过 context.options[‘data’] 使用;默认值是None。
- options (字典) – 用户自定义数据,在回调函数中要用到的变量,需要从这里传入,并通过 context.options 使用;默认值是None。
- amount_integer (bool) – 已经废弃;默认值是None。
返回: - .raw_perf: 回测详细数据
返回类型: Outputs
回测模式¶
在 我的策略 开发策略并手动运行,对应的是回测模式。
回测模式读取给定的 start_date 和 end_date 时间段的 instruments 数据,被执行交易回测。用户也可以在 initialize 里修改 context.start_date、context.end_date 和 context.instruments,来改变这一行为。
实盘模式¶
使用 开始交易,策略被发送到实盘交易系统,在这里,策略进入实盘运行模式。在实盘模式下,start_date 和 end_date 会被重写。
实盘模式下,系统会使用策略实盘运行的日期覆盖start_date和end_date。用户在 initialize 函数里,可以通过 context.start_date 和 context.end_date 得到交易日期,并计算 context.instruments 和 其他需要的数据
示例代码¶
In [ ]:
# 1. 策略基本参数
# 证券池:这里使用所有股票
instruments = D.instruments()
# 起始日期
start_date = '2016-01-01'
# 结束日期
end_date = '2017-02-28'
# 初始资金
capital_base = 100000
# 策略比较参考标准,以沪深300为例
benchmark = '000300.INDX'
# 调仓周期(多少个交易日调仓)
rebalance_period = 22
# 每轮调仓买入的股票数量
stock_num = 30
# 2. 选择股票:为了得到更好的性能,在这里做批量计算
# 本样例策略逻辑:选取调仓当天,交易额最小的30只股票买入
# 加载数据:https://bigquant.com/docs/data_history_data.html
history_data = D.history_data(instruments, start_date, end_date, fields=['amount'])
# 过滤掉停牌股票:amount为0的数据
selected_data = history_data[history_data.amount > 0]
# 按天做聚合(groupby),对于每一天的数据,做(apply)按交易额升序排列(sort_values),并选取前30只([:stock_num])
selected_data = selected_data.groupby('date').apply(lambda df: df.sort_values('amount')[:stock_num])
# 3. 策略主体函数
# 初始化虚拟账户状态,只在第一个交易日运行
def initialize(context):
# 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
# 策略交易逻辑,每个交易日运行一次
def handle_data(context,data):
today = data.current_dt.strftime('%Y-%m-%d') # 交易日期
# context.trading_day_index:交易日序号,第一个交易日为0
if context.trading_day_index % context.options['rebalance_period'] != 0:
return
# 调仓:卖出所有持有股票
for equity in context.portfolio.positions:
# 停牌的股票,将不能卖出,将在下一个调仓期处理
if data.can_trade(equity):
order_target_percent(equity, 0)
# 调仓:买入新的股票
instruments_to_buy = context.options['selected_data'].ix[today].instrument
if len(instruments_to_buy) == 0:
return
# 等量分配资金买入股票
weight = 1.0 / len(instruments_to_buy)
for instrument in instruments_to_buy:
if data.can_trade(symbol(instrument)):
order_target_percent(symbol(instrument), weight)
# 4. 策略回测:https://bigquant.com/docs/strategy_backtest.html
m = M.trade.v1(
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=capital_base,
benchmark=benchmark,
# 传入数据给回测模块,所有回测函数里用到的数据都要从这里传入,并通过 context.options 使用,否则可能会遇到缓存问题
options={'selected_data': selected_data, 'rebalance_period': rebalance_period}
)
基本方法¶
-
prepare
(context)¶ - [回调函数] 准备数据函数,运行过程中只调用一次,在 initialize 前调用,准备交易中需要用到数据。目前支持设置交易中用到的股票列表,设置到 context.instruments。
参数: context – 交易context
- .start_date (字符串): 开始时间 - 在回测模式下,值为 M.trade 的参数值;在实盘模式,值为交易日期
- .end_date (字符串): 结束时间 - 在回测模式下,值为 M.trade 的参数值;在实盘模式,值为交易日期
- .instruments (字符串列表): 交易中用到的股票列表。初始值为 M.trade 的参数值。可以在 prepare 里修改此值,设置交易股票列表。
- .options (dict): 用户自定义数据,值为 M.trade 的参数值。可以在 prepare 函数中修改,修改后的数据可以在 initialize 和 handle_data 等函数中使用到。可以在 prepare 里修改此值,存放后续要用到的数据。
## 示例代码 1: 什么都不做,默认使用 M.trade 的 instruments def prepare(context): pass ## 示例代码 2: 载入交易期间所有的股票 def prepare(start_date, end_date, instruments, options): context.instruments = D.instruments(context.start_date, context.end_date) ## 示例代码 3: AI策略生成器默认prepare,使用stockranker预测 def prepare(context): # context.start_date / end_date,回测的时候,为trader传入参数;在实盘运行的时候,由系统替换为实盘日期 n1 = M.general_feature_extractor.v5( instruments=D.instruments(), start_date=context.start_date, end_date=context.end_date, model_id=context.options['model_id']) n2 = M.transform.v2( data=n1.data, transforms=T.get_stock_ranker_default_transforms(), drop_null=True, astype='int32', except_columns=['date', 'instrument'], clip_lower=0, clip_upper=200000000) n3 = M.stock_ranker_predict.v2(model_id=context.options['model_id'], data=n2.data) context.instruments = n3.instruments context.options['predictions'] = n3.predictions
-
initialize
(context)¶ - [回调函数] 初始化函数,整个回测中只在最开始时调用一次,用于初始化一些账户状态信息和策略基本参数,context可以理解为一个全局变量,会被传递给策略中所有其他的方法,在回测中存放当前账户信息和策略基本参数便于会话。
参数: context – 交易context
- .portfolio (Portfolio): 交易账户 Portfolio
- .trading_calendar (TradingCalendar): 交易日历 TradingCalendar
## 示例代码 def initialize(context): # 初始化策略基本参数,比如双均线策略中短期均线周期和长期均线周期 context.short_length = 7 context.long_length = 21
-
handle_data
(context, data)¶ [回调函数] 必须实现的函数,该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次,由于我们现在数据只有日K,所以是按天回调。在回测中,可以通过对象data获取单只股票或多只股票的时间窗口价格数据。如果算法中没有schedule_function函数,那么该函数为必选函数。一般策略的交易逻辑和订单生成体现在该函数中。
参数: - context –
交易context
- .portfolio (Portfolio): 交易账户 Portfolio
- .trading_calendar (TradingCalendar): 交易日历 TradingCalendar
- data – 股票信息 BarData
## 示例代码 def handle_data(context, data): # 可参考 调用函数 pass
- context –
-
before_trading_start
(context, data)¶ [回调函数] 每个单位时间开始前调用一次,即每日开盘前调用一次,该函数是可选函数。你的算法可以在该函数中进行一些数据处理计算,比如确定当天有交易信号的股票池。
参数: - context –
交易context
- .portfolio (Portfolio): 交易账户 Portfolio
- .trading_calendar (TradingCalendar): 交易日历 TradingCalendar
- data – 股票信息 BarData
## 示例代码 def before_trading_start(context, data): # 可参考 调用函数 pass
- context –
-
schedule_function
(func, date_rule, time_rule)¶ 周期执行调度函数,在符合date_rule, time_rule下周期性执行,需在 initialize 函数中调用。如果initialize中调用了schedule_function函数,那么算法会按照date_rule和time_rule周期性执行func函数,如果没有调用schedule_function函数,则算法会每个单位时间调用handle_data函数。
参数: - func – 被调用函数,包含两个参数 context 和 data, 同 handle_data
- date_rule – 日期规则,通过 date_rules 下的方法可获取,后面会给出具体详情
- time_rule – 时间规则,通过 time_rules 下的方法可获取,后面会给出具体详情
## 示例代码 def initialize(context): schedule_function(func=rebalance, date_rule=date_rules.week_start(), # 例如每周开始时执行一次 time_rule=time_rules.market_open(hours=1)) # 开盘后一个小时执行 def rebalance(context, data): # 策略交易逻辑和订单生成在此部分构建,代替了handle_data函数 pass
-
date_rule
在固定的日期规则下调用func函数
func为被调用函数,func函数需要传入context 和 data, 用法同 handle_data
## 示例代码 # 每天调用一次func函数 schedule_function(func=rebalance, date_rule=date_rules.every_day()) # 每周开始时调用一次func函数,默认为days_offset=0,该周交易日的第一天调用 schedule_function(func=rebalance, date_rule=date_rules.week_start()) # 每周开始时调用一次func函数,days_offset=1表示该周交易日的第二天调用,以此类推 schedule_function(func=rebalance, date_rule=date_rules.week_start(days_offset=1)) # 每月开始时调用一次func函数,days_offset默认为0,表示每个月交易日的第一天 schedule_function(func=rebalance, date_rule=date_rules.month_start()) # 每周结束时调用一次func函数,days_offset=0表示该周交易日的最后一天调用 schedule_function(func=rebalance, date_rule=date_rules.week_end()) # 每月结束时调用一次func函数,days_offset默认为0,表示每个月交易日的最后一天 schedule_function(func=rebalance, date_rule=date_rules.month_end())
-
time_rule
在固定的时间规则下调用func函数
market_open表明开盘时调用func,如果没有偏移,默认为开盘后一分钟调用func
market_close表明收盘时调用func,如果没有偏移,默认为收盘前两分钟调用func
## 示例代码 # 每日开盘后1小时30分钟调用func schedule_function(func=rebalance, date_rules.every_day(), time_rule=time_rules.market_open(hours=1, minutes=30)) # 每日收盘前5分钟调用func schedule_function(func=rebalance, date_rules.every_day(), time_rule=time_rules.market_close(minutes=5))
-
record
(*args, **kwargs)¶ 记录函数,在交易执行时记录用户自定义数据,该数据存放在回测输出结果的 m.raw_perf中
参数: kwargs – 记录的名称及数值 返回: 无返回 ## 示例代码,以平安银行为例 sid = symbol('000001.SZA') # 获取最新价格 price = data.current(sid, 'price') # 计算短周期均线 short_ma = data.history(sid, 'close', 5, '1d').mean() # 计算长周期均线 long_ma = data.history(sid, 'close', 20, '1d').mean() #将最新价、短周期均线、长周期均线记录在m.raw_perf中以便查询和调用 record(short_ma=short_ma, long_ma=long_ma, price=price)
交易相关方法¶
-
symbol
(symbol_str)¶ 通过股票代码获取股票对象
参数: symbol_str – 股票代码字符串 返回: Equity 对象 ## 示例代码 # 获取浦发银行Equity对象 symbol('600000.SHA')
-
symbols
(*args)¶ 通过多个股票代码获取股票对象列表
参数: args – iterable[str],股票代码字符串列表 返回: Equity 对象列表 ## 示例代码 symbols('000001.SZA','000002.SZA')
-
order
(asset, amount, style=OrderType)¶ 买卖股票,按股票数量生成订单,amount为负,表示做空。调用成功后, 您可以调用get_open_orders取得所有未完成的交易, 也可以调用cancel_order取消交易
参数: - asset – 股票
- amount – 交易数量, 正数表示买入, 负数表示卖出
- style –
(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
- style=MarketOrder(),下市价单
- style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
- style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
- style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
## 示例代码 from zipline.finance.execution import MarketOrder, LimitOrder, StopOrder, StopLimitOrder # 买入平安银行股票100股 order(symbol('000001.SZA'), 100) # 下一个市价单 order(symbol('000001.SZA'), 100, style=MarketOrder()) # 下一个市价单, 功能同上 # 下一个限价单(买入), 价位应低于市价,价格小于等于10元买入 order(symbol('000001.SZA'), 100, style=LimitOrder(10.0)) # 下一个止损单(卖出),价格小于等于10元卖出100股 order(symbol('000001.SZA'), -100, style=StopOrder(10.0)) # 关于限价单和止损单可以参加下面链接的这个解释 # http://www.investorguide.com/article/15778/limit-order-vs-stop-order-d1412/
-
order_target
(asset, amount, style=OrderType)¶ 买卖股票, 使成交之后最终持有的股票数量达到预期目标的amount(股数)
参数: - asset – 股票
- amount – 交易数量, 正数表示买入, 负数表示卖出
- style –
(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
- style=MarketOrder(),下市价单
- style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
- style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
- style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
## 示例代码 # 成交之后最终持有的股票数量为预期目标的0股,即卖出平安银行所有股票 order_target(symbol('000001.SZA'), 0) # 成交之后最终持有的股票数量为预期目标的200股。如果目前没有持有平安银行,则需要买入平安银行200股,如果已经持有平安银行100股,那么只需要买入100股,因此生成的订单为100股买单。 order_target(symbol('000001.SZA'), 200)
-
order_lots
(asset, amount)¶ 按照手数买卖股票, 按市价买入 amount(手数)* 100 股
参数: - asset – 股票
- amount – 手数
## 示例代码 # 买入1手(100股)平安银行 order_lots(symbol('000001.SZA'), 1)
-
order_value
(asset, value, style=OrderType)¶ 买卖股票,按股票交易金额生成订单,value为负,表示做空。
参数: - asset – 股票
- value – 交易金额, 正数表示买入, 负数表示卖出
- style –
(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
- style=MarketOrder(),下市价单
- style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
- style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
- style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
## 示例代码 # 卖出价值为10000元的平安银行股票 order_value(symbol('000001.SZA'), -10000) # 买入价值为10000元的平安银行股票 order_value(symbol('000001.SZA'), 10000)
-
order_target_value
(asset, value, style=OrderType)¶ 调整股票持有市值到预期目标的value
参数: - asset – 股票
- value – 交易金额, 正数表示买入, 负数表示卖出
- style –
(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
- style=MarketOrder(),下市价单
- style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
- style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
- style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
## 示例代码 # 预期平安银行持有市值为0,即卖出平安银行所有股票 order_target_value(symbol('000001.SZA'), 0) # 调整平安银行股票持有市值到10000元市值,如果没有持有平安银行股票,则需要生成买入10000元平安银行的买单,如果已经持有4000元市值,那么只需生成买入6000元平安银行的买单。 order_target_value(symbol('000001.SZA'), 10000)
-
order_target_percent
(asset, percent, style=OrderType)¶ 调整股票仓位至占投资组合(股票+现金)总金额的一定百分比(percent)
参数: - asset – 股票
- percent – 比例
- style –
(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
- style=MarketOrder(),下市价单
- style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
- style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
- style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
## 示例代码 # 调整平安银行股票到投资组合10%市值仓位,如果目前投资组合价值10000元,那么生成的订单为买入1000元(10000*0.1)平安银行的股票。由于资产配置中多采用等权重配置,因此order_target_percent下单函数比较常用。 order_target_percent(symbol('000001.SZA'), 0.1) # 卖出平安银行所有股票,当生成卖出全部股票的订单时,多使用如下这种方式。 order_target_percent(symbol('000001.SZA'), 0)
-
cancel_order
(order)¶ 取消订单 参数
参数: order – Order对象或者order_id ## 示例代码 # 在每个交易日开始之前, 将订单撤销 def before_trading_start(context): # 得到当前未完成订单 for orders in get_open_orders().values(): # 循环,撤销订单 for _order in orders: cancel_order(_order) pass
-
get_order
(order)¶ 获取订单
参数: order – Order对象或者order_id 返回: Order对象 ## 示例代码 order_object = order_target(sid, 100) print('订单:', get_order(order_object))
-
get_open_orders
(sid=None)¶ 获取订单
参数: sid – Equity 对象,为可选参数,如果缺省,则返回全部Order 返回: 返回一个dict, key是order_id, value是Order对象 ## 示例代码 # 每个交易日开始之前, 获取订单 def before_trading_start(context): open_orders = get_open_orders() pass
-
set_commission
(per_order)¶ 回测时, 为了模拟真实的交易场景, 系统会计算每笔交易的手续费, 在initialize方法中调用。默认状态下,买入时手续费为成交金额的万分之3,卖出时手续费为成交金额的千分之1.3,手续费不足5元按5元收取。
参数: per_order – PerOrder对象 ## 示例代码 def initialize(context): # buy_cost,买入时手续费 # sell_cost,卖出时手续费 # min_cost,最少的手续费 # 买入时手续费为成交金额的万分之3,卖出时手续费为成交金额的千分之1.3,手续费不足5元按5元收取。 set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
-
set_commission
(per_trade) 股票成交时,手续费按成交次数收取
参数: per_trade – PerTrade对象 ## 示例代码 def initialize(context): # 股票成交时,手续费按成交次数收取,每一次成交收取5元手续费 set_commission(PerTrade(5))
-
set_commission
(per_share) 股票成交时,手续费按成交金额一定比例收取
参数: per_share – PerShare对象 ## 示例代码 def initialize(context): # 股票成交时,手续费按成交金额一定比例收取,手续费为成交金额的千分之一 set_commission(PerShare(0.001))
-
set_slippage
(slippage)¶ 回测时, 为了模拟真实的交易场景, 系统会设置滑点, 只能在initialize方法中调用,定义在策略中的其他位置则无效。当您下单交易时,您的订单将影响市场。您的买单驱使价格上涨,您的卖单驱使价格下滑;这通常被称为您的交易的“价格影响”。价格影响的大小取决于您的订单与当前交易量相比有多大。如果您的订单太大,那么滑点方法也会进行评估:您的交易量不能超过市场的容量,通常您也不能期望交易量超过一小部分(比如百分之5,举牌)。所有这些概念都被封装在了set_slippage方法中。当订单因为不满足滑点条件没有完全成交,未成交的部分仍然可以在第二天继续成交。这会持续直到订单完全成交或被取消。
如果您没有指定set_slippage方式,则滑点默认为VolumeShareSlippage(volume_limit = 0.025,price_impact = 0.1)(您最多可以占用单支股票交易量的2.5%)。
参数: slippage – SlippageModel对象, 可选 VolumeShareSlippage、FixedSlippage或者您自定义的一个滑点模型
- VolumeShareSlippage: 您需要提供参数volume_limit(默认为0.025),它限制了您的订单交易量最多能占每条k线交易量的比例。例如:如果backtest在日线级别运行,您下订单60股;然后在未来几天内,每天交易量为1000股,而volume_limit为0.025,那么您的交易订单将分成三个订单(25股,25股,10股)。如若将volume_limit设置为1.00将允许backtest使用最多100%的交易量来成交您的订单。使用相同的例子,这将在未来一天成交60股。价格影响常数price_impact(默认0.1)定义了您的订单对回测的价格计算将产生多大的影响,通过将price_impact乘以订单交易股数与总交易量的比率的平方来计算滑点。在我们前面的例子中,对于25股订单,价格影响为:0.1*(25/1000)*(25/1000),或0.00625%。对于10股订单,价格影响为0.1 *(10/1000)*(10/1000),或者0.001%。
- FixedSlippage: 当使用FixedSlippage滑点模型时,您的订单大小不会影响交易执行时的价格,即这种滑点模型不会限制您订单的交易量。您可以指定一个参数spread,作为一个典型的买卖价差。当您下买单时,一半的价差将被加到价格上;当你下卖单时,一半的价差将从价格中减去。使用FixedSlippage滑点模型时要非常小心,它很容易产生不切实际的成交,特别是订单量巨大或在流动性不足的股票中。
- 自定义滑点模型: 您也可以构建一个自定义滑点模型,该模型使用您自己的逻辑将订单流转换为交易流。在initialize()函数中,您必须指定要使用的滑点模型和滑点模型将使用的任何特殊参数。您的自定义模型必须是一个继承自slippage.SlippageModel并实现process_order(self,data,order)函数的类。process_order方法必须返回一个元素(execution_price, execution_volume),它表示模型想要生成的交易价格和交易量。然后为您创建交易。具体使用请参考示例代码。
## 示例代码 # 自定义滑点模型 class PerStockSpreadSlippage(slippage.SlippageModel): # 指定初始化函数 def __init__(self, spreads): # 存储spread的字典,用股票代码作为key self.spreads = spreads def process_order(self, data, my_order): spread = self.spreads[my_order.sid] price = data.current(my_order.sid, 'price') # 在这个模型中滑点是spread的一半 slip_amount = spread / 2 # 计算交易的价格影响,价格影响跟订单交易方向有关,买单会增加价格,而卖单会减少价格。 new_price = price + (slip_amount * my_order.direction) return (new_price, my_order.amount) def initialize(context): # 限制每单交易不超过单只股票交易额的 1%,若超过会进行分单处理,即订单不是一次性成交完毕,而是多日完成。 set_slippage(VolumeShareSlippage(volume_limit=0.01)) # 固定滑点模型,下一个买单时,价格会加0.5;而下一个卖单时,价格会减0.5。 set_slippage(FixedSlippage(spread=1.00)) context.spreads = { symbol('000001.SZA'): 0.05 } # 使用自定义的滑点模型。 set_slippage(PerStockSpreadSlippage(context.spreads))
-
set_long_only
()¶ 不允许做空股票,即不能持有负数股
## 示例代码 def initialize(context): # 如果下一个订单,导致当前持股为负,则策略会抛出一个异常 set_long_only()
-
set_max_leverage
(max_leverage)¶ 设置策略的最大杠杆限制
参数: max_leverage – float,策略允许的最大杠杆,若没有设置则没有最大限制 ## 示例代码 from zipline.api import set_max_leverage def initialize(context): set_max_leverage(1)
重要对象¶
# 获取Equity对象 symbol
equity = symbol('000001.SHA') # 000001.SHA 必须在 context.instruments 指定,或者在 instruments 参数中指定
print(equity.symbol)
-
class
Order
¶ 当你在算法中生成一个(Order)订单后,Order会有以下属性
-
status
¶ integer 订单状态 0表示该订单还未实际成交,1表示订单已经成交,2表示订单已经取消
-
created
¶ datetime 订单生成时间
-
stop
¶ float 可选的止损价
-
limit
¶ float 可选的限定价
-
amount
¶ integer 订单数量
-
sid
¶ security对象 订单symbol
-
filled
¶ integer 截至到目前为止,订单已完成数量
-
stop_reached
¶ boolean 如果股票市价到达止损价为true
-
limit_reached
¶ boolean 如果股票市价到达限定价为true
-
commission
¶ integer 订单产生的佣金
-
# 打印下单的股票
open_orders = get_open_orders()
for equity in open_orders:
orders = open_orders[equity]
for order in orders:
print(order.sid)
-
class
Portfolio
¶ 交易账户,可以通过 context.portfolio 获取
-
cash
¶ float 账户现金
-
start_date
¶ datetime 交易账户对象统计开始时间
-
end_date
¶ datetime 交易账户对象统计结束时间
-
starting_cash
¶ float 交易账户初始金额
-
portfolio_value
¶ float 账户总价值(包括持仓市值+现金)
-
positions_value
¶ float 持仓市值
-
positions
¶ dictionary 持仓
-
capital_used
¶ float 账户买卖所消耗的净资产,为正时代表花费
-
pnl
¶ float 持仓收益
-
portfolio_value
float 账户价值,所有持仓股票价值加上当前的现金总量
-
positions_value
float 所有持仓的价值
-
starting_cash
float 回测或者实盘开始时的初始资金
-
returns
¶ float 账户累计收益,比如10%返回的是0.1
-
# 获取可用的现金
context.portfolio.cash
-
class
Position
¶ 持仓对象表示目前账户持有股票,为Dictionary格式,因此如果你需要查询某只股票的具体持仓(如中国平安 ‘000001.SZA’),查询语法为:context.portfolio.positions[symbol(‘000001.SZA’)]
-
amount
¶ integer: 持仓数量
-
cost_basis
¶ float: 持仓成本价
-
last_sale_price
¶ float: 该股票在交易时间的最后价格,等价于收盘价
-
sid
¶ integer: 持仓股票的ID
-
# 打印持仓的股票
positions = context.portfolio.positions
for equity in positions:
position = positions[equity]
print(position.sid)
-
class
TradingCalendar
¶ 交易日历
-
session_distance(start_session_label, end_session_label):
获取两个交易日之间的差值交易日
参数: - start_session_label – 开始交易日
- end_session_label – 结束交易日
## 示例代码 distance = context.trading_calendar.session_distance(pd.Timestamp('2017-06-13'), pd.Timestamp('2017-06-16')) # 预期输出: 3
-