交易引擎

支持回测和实盘。

主入口

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 函数中修改,修改后的数据可以在 initializehandle_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

## 示例代码
def initialize(context):
    # 初始化策略基本参数,比如双均线策略中短期均线周期和长期均线周期
    context.short_length = 7
    context.long_length = 21
handle_data(context, data)

[回调函数] 必须实现的函数,该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次,由于我们现在数据只有日K,所以是按天回调。在回测中,可以通过对象data获取单只股票或多只股票的时间窗口价格数据。如果算法中没有schedule_function函数,那么该函数为必选函数。一般策略的交易逻辑和订单生成体现在该函数中。

参数:
  • context

    交易context

  • data – 股票信息 BarData
## 示例代码
def handle_data(context, data):
    # 可参考 调用函数
 pass
before_trading_start(context, data)

[回调函数] 每个单位时间开始前调用一次,即每日开盘前调用一次,该函数是可选函数。你的算法可以在该函数中进行一些数据处理计算,比如确定当天有交易信号的股票池。

参数:
  • context

    交易context

  • data – 股票信息 BarData
## 示例代码
def before_trading_start(context, data):
    # 可参考 调用函数
    pass
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)

获取订单

参数:sidEquity 对象,为可选参数,如果缺省,则返回全部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)

重要对象

class Equity

标的

sid

integer: 股票ID

symbol

string: 股票代码

asset_name

string: 股票全称

# 获取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