【历史文档】策略回测-常用设置
由qxiao创建,最终由small_q 被浏览 568 用户
更新
本文内容对应旧版平台与旧版资源,其内容不再适合最新版平台,请查看新版平台的使用说明
新版量化开发IDE(AIStudio):
https://bigquant.com/wiki/doc/aistudio-aiide-NzAjgKapzW
新版模版策略:
https://bigquant.com/wiki/doc/demos-ecdRvuM1TU
新版数据平台:
https://bigquant.com/data/home
https://bigquant.com/wiki/doc/dai-PLSbc1SbZX
新版表达式算子:
https://bigquant.com/wiki/doc/dai-sql-Rceb2JQBdS
新版因子平台:
https://bigquant.com/wiki/doc/bigalpha-EOVmVtJMS5
\
set_commission
定义
set_commission(per_order)
手续费设置, 在initialize方法中调用。默认状态下,是股票交易设置手续费的API,买入时手续费为成交金额的万分之3,卖出时手续费为成交金额的千分之1.3,手续费不足5元按5元收取。 此外,还可以通过PerShare和PerTrade设置手续费。 手续费设置可以动态调整,比如股指期货我们可以在不同的交易日设置不同的手续费,以便回测更能接近真实情形。
参数
per_order – PerOrder对象 或者PerTrade对象 或者PerShare对象
示例代码
# 示例代码1
def initialize(context):
# buy_cost,买入时手续费
# sell_cost,卖出时手续费
# min_cost,最少的手续费
# 买入时手续费为成交金额的万分之3,卖出时手续费为成交金额的千分之1.3,手续费不足5元按5元收取。
context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
# 示例代码2
def initialize(context):
# 股票成交时,手续费按成交次数收取,每一次成交收取5元手续费
context.set_commission(PerTrade(5))
# 示例代码3
def initialize(context):
# 股票成交时,手续费按成交金额一定比例收取,手续费为成交金额的千分之一
context.set_commission(PerShare(0.001))
# 上面三个例子都是股票交易时如何设置手续费,如果是期货交易的话,可以参照如下示例代码设置
# 示例代码4
def initialize(context):
context.set_commission(futures_commission=PerContract(cost={'IF':(0.0023, 0.0015, 0.0023)}))
\
set_slippage
定义
set_slippage(slippage)
滑点设置, 只能在initialize方法中调用,定义在策略中的其他位置则无效。当您下单交易时,您的订单将影响市场。您的买单驱使价格上涨,您的卖单驱使价格下滑;这通常被称为您的交易的“价格影响”。价格影响的大小取决于您的订单与当前交易量相比有多大。如果您的订单太大,那么滑点方法也会进行评估:您的交易量不能超过市场的容量,通常您也不能期望交易量超过一小部分(比如百分之5,举牌)。所有这些概念都被封装在了set_slippage方法中。当订单因为不满足滑点条件没有完全成交,未成交的部分仍然可以在第二天继续成交。这会持续直到订单完全成交或被取消。
如果您没有指定set_slippage方式,则滑点默认为VolumeShareSlippage(volume_limit = 0.025,price_impact = 0.1)(您最多可以占用单支股票交易量的2.5%)。
滑点模型是通过set_slippage完成的,目前有:FixedBasisPointsSlippage、FixedSlippage、VolumeShareSlippage,同时,也可以自定义滑点模型。
FixedBasisPointsSlippage
\
固定基点滑点
context.slippage.FixedBasisPointsSlippage(basis_points=5, volume_limit=0.1)
参数
basis_point - 基点滑点 volume_limit - 成交量最大限制,默认为0.1,即10%
如果基点等于5,即0.05%,如果订单是买单,那么实际成交价是名义成交价的1*(1+0.05%)倍,如果订单是卖单,实际成交价是名义成交价的1*(1-0.05%)。比如名义成交价是100元,那么买单的成交价是100.05,卖单的成交价是99.95。 成交量最大限制参数确定了当根Bar最大能成交多少数量。举例,下单量是220手,volume_limit=0.1,接下来每根Bar成交量是1000手,在这种情形下,220手的订单会拆分为3笔成交(100手、100手、20手)分别在接下来三根Bar上完成撮合成交。 如果volume_limit=1.00,那么在接下来的一根Bar上最大可以成交1000手,因此220手的订单可以直接一下子成交,无须拆单。
VolumeShareSlippage
\
成交量比例滑点
context.slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1)
参数
volume_limit - 成交量最大限制,默认为0.025 price_impact - 价格影响幅度,默认为0.1 volume_limit参数含义同上,可以参考FixedBasisPointsSlippage。比如,当前下单的订单数量是60手,接下来的几根Bar的成交量都是1000手,那么在0.025的默认值下,订单会被拆分为25、25、10依次成交。 price_impact衡量的是滑点对价格的影响幅度,默认值为0.1,滑点的计算为:price_impact*(实际成交量/总成交量)^2 在前面的例子中,25手的单子的价格影响为:0.1*(25/1000)(25/1000)=0.00625%,对于10手的订单,价格影响为:0.1*(10/1000)*(10/1000)=0.001%。
固定滑点
context.slippage.FixedSlippage(spresd)
参数
spread - 价差
当采取固定滑点模型时,订单量的大小并不会影响撮合时的价格,但是蕴含假设为,下单时买一和卖一的价差-spread会影响价格。如果是买单,那么实际成交价为名义成交价+0.5spread,如果是卖单,那么实际成交价为名义成交价-0.5spread。
自定义滑点
您也可以构建一个自定义滑点模型,该模型使用您自己的逻辑将订单流转换为交易流。在initialize()函数中,您必须指定要使用的滑点模型和滑点模型将使用的任何特殊参数。您的自定义模型必须是一个继承自slippage.SlippageModel并实现process_order(self,data,order)函数的类。process_order方法必须返回一个元素(execution_price, execution_volume),它表示模型想要生成的交易价格和交易量。然后为您创建交易。具体使用请参考示例代码。
示例代码
# 示例代码1
# 自定义滑点模型
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%,若超过会进行分单处理,即订单不是一次性成交完毕,而是多日完成。
context.set_slippage(VolumeShareSlippage(volume_limit=0.01))
# 固定滑点模型,下一个买单时,价格会加0.5;而下一个卖单时,价格会减0.5。
context.set_slippage(FixedSlippage(spread=1.00))
context.spreads = {
context.symbol('000001.SZA'): 0.05
}
# 使用自定义的滑点模型
context.set_slippage(PerStockSpreadSlippage(context.spreads))
# 示例代码2
# 按指定价格成交
def initialize(context):
from zipline.finance.slippage import SlippageModel
class FixedPriceSlippage(SlippageModel):
def process_order(self, data, order, bar_volume=0, trigger_check_price=0):
if order.limit is None:
price_field = self._price_field_buy if order.amount > 0 else self._price_field_sell
price = data.current(order.asset, price_field)
else:
price = order.limit
# 返回希望成交的价格和数量
return (price, order.amount)
context.fix_slippage = FixedPriceSlippage()
# 设置price_field,在没有指定成交价格时,开盘价买入,收盘价卖出
context.fix_slippage = FixedPriceSlippage(price_field_buy='open', price_field_sell='close')
context.set_slippage(us_futures=fix_slippage) # us是universe的简写,如果是股票,需要传入us_equities
def handle_data(context, data):
# 生成限价单,订单的限价为指定的价格,如果是买单,价格高于low就能成交,并且成交价为my_price,如果是卖单,价格低于high就能成交,成交价格为my_price
sid = context.future_symbol('RB1901.SHF')
context.order(sid, 2, limit_price=my_price)
\
set_long_only
定义
set_long_only
回测设置只允许做多,不允许做空
示例代码
def initialize(context):
# 如果下一个订单,导致当前持股为负,则策略会抛出一个异常
context.set_long_only()
\
set_max_leverage
定义
set_max_leverage(max_leverage)
设置策略的最大杠杆限制
参数
max_leverage – float,策略允许的最大杠杆,若没有设置则没有最大限制
示例代码
from zipline.api import set_max_leverage
def initialize(context):
context.set_max_leverage(1)
\
set_need_settle
定义
set_need_settle(need_settle)
期货策略设置是否每日结算
参数
need_settle – bool,如果product_type为期货;默认为True,否则为False
示例代码
def initialize(context):
context.set_need_settle(False)
\
set_margin
定义
set_margin(security_code, margin)
设置期货品种的保证金比率,支持国内四大期货交易所,每个品种的默认设置请参考表《期货基本信息表》
参数
security_code – str,期货品种 margin - float,保证金比率,数值在0-1之间
示例代码
def initialize(context):
context.set_margin('RB', 0.1)
\
set_benchmark
定义
set_benchmark(benchmark)
设置策略基准。
参数
benchmark – Asset,这个资产将成为新的策略基准
示例代码
def initialize(context):
context.set_benchmark(context.symbol('000903.SHA'))
\
set_max_order_count
定义
set_max_order_count(max_count, on_error=’fail’)
设置在某一天可以提交的order数量上限
参数
max_count – int,在某一天可以提交的order数量上限
示例代码
from zipline.api import set_max_order_count
def initialize(context):
context.set_max_order_count(10)
\
set_max_order_size
定义
set_max_order_size(asset=None, max_shares=None,max_notional=None,on_error=’fail’)
设置在某一天可以提交的order上限。
参数
asset – Asset, optional,如果这个参数提供,则保证头寸限制规则只用在这个资产上 max_shares – int,optional,单次order最大股票数量上限 max_notional – float,单次order最大现金
示例代码
def initialize(context):
context.set_max_order_size(max_notional=4000)
\
set_max_position_size
定义
set_max_position_size(asset=None,max_shares=None,max_notional=None, on_error=’fail’)
针对某一头寸设置最大股票数量或最大头寸金额
参数
asset – Asset, optional,如果这个参数提供,则保证头寸限制规则只用在这个资产上
max_shares –int,optional,单次头寸最大股票数量上限
max_notional – float,单个头寸最大金额
示例代码
def initialize(context):
context.set_max_position_size(max_notional=4000)
\
周期执行调度函数
如果每根Bar不一定都要运行一下主函数(handle_data),因此你的策略可以回测的更快。比如按月调仓的多因子选股策略,只需要在特定的Bar上运行handle_data主函数,为此,平台提供了schedule_function这一周期执行调度函数。 不仅如此,周期执行调度函数还使用了日期和时间规则,以便更加灵活和高效。所有的周期执行调度函数都在初始化函数(initialize)中进行定义。
定义
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下的方法可获取,后面会给出具体详情
月度执行调度模型(month_start和month_end)正如字面含义,决定了在哪些日期点上运行,比如month_start表明在每个月月初第一天运行func,month_end表明在月末最后一天运行func。 可以传入参数——days_offset,默认该参数为0,该参数可以理解成一个时间偏移量,month_start(1)表明在该月第二个交易日运行func,依此类推,如果该参数超过当月交易日,那么该函数在该月就不会运行func。
示例代码
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))
\
多个周期执行调度函数
可以使用多个周期执行调度函数,比如在月初和月中都调用下换仓函数。 示例代码
def initialize(context):
# 在每个月的第二个交易日执行
schedule_function(
rabalance,
date_rules.month_start(days_offset=1)
)
# 在每个月的第十个交易日执行
schedule_function(
rebalance,
date_rules.month_start(days_offset=9)
)
def myfunc(context,data):
pass
\
期货基本信息表
序号 | 合约品种 | 交易所 | 交易所编码 | 名称 | 价格最小单位 | 乘数 | 保证金率 | 手续费计算方式 | 平昨手续费率 | 平今手续费率 | 开仓手续费率 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | A | DCE | DCE | 豆一 | 1 | 10 | 0.09 | 按数量 | 2 | 0 | 2 |
2 | AG | SHFE | SHF | 白银 | 1 | 15 | 0.12 | 按金额 | 0.00005 | 0.00005 | 0.00005 |
3 | AL | SHFE | SHF | 沪铝 | 5 | 5 | 0.08 | 按数量 | 3 | 0 | 3 |
4 | AU | SHFE | SHF | 黄金 | 0.05 | 1000 | 0.08 | 按数量 | 10 | 0 | 10 |
5 | AP | CZCE | CZC | 苹果 | 1 | 10 | 0.08 | 按数量 | 0.5 | 0 | 0.5 |
6 | B | DCE | DCE | 豆二 | 1 | 10 | 0.08 | 按数量 | 2 | 2 | 2 |
7 | BB | DCE | DCE | 胶板 | 0.05 | 500 | 0.4 | 按金额 | 0.0001 | 0.00005 | 0.0001 |
8 | BU | SHFE | SHF | 沥青 | 2 | 10 | 0.1 | 按金额 | 0.0001 | 0.0001 | 0.0001 |
9 | C | DCE | DCE | 玉米 | 1 | 10 | 0.08 | 按数量 | 1.2 | 0 | 1.2 |
10 | CF | CZCE | CZC | 棉花 | 5 | 5 | 0.07 | 按数量 | 4.3 | 0 | 4.3 |
11 | CS | DCE | DCE | 淀粉 | 1 | 10 | 0.07 | 按数量 | 1.5 | 0 | 1.5 |
12 | CU | SHFE | SHF | 沪铜 | 10 | 5 | 0.08 | 按金额 | 0.000025 | 0 | 0 |
13 | CY | CZCE | CZC | 棉纱 | 5 | 5 | 0.07 | 按数量 | 4 | 4 | 4 |
14 | FB | DCE | DCE | 纤板 | 0.05 | 500 | 0.1 | 按金额 | 0.00005 | 0 | 0.00005 |
15 | FG | CZCE | CZC | 玻璃 | 1 | 20 | 0.06 | 按数量 | 3 | 0 | 3 |
16 | FU | SHFE | SHF | 燃油 | 1 | 50 | 0.1 | 按金额 | 0.00002 | 0.00002 | 0.00002 |
17 | HC | SHFE | SHF | 热卷 | 1 | 10 | 0.08 | 按金额 | 0.00001 | 0.00001 | 0.00001 |
18 | I | DCE | DCE | 铁矿 | 0.5 | 100 | 0.11 | 按金额 | 0.00006 | 0.00003 | 0.00006 |
19 | IC | CFFEX | CFE | 中证500 | 0.2 | 200 | 0.3 | 按金额 | 0.000023 | 0.000115 | 0.000023 |
20 | IF | CFFEX | CFE | 沪深300 | 0.2 | 300 | 0.2 | 按金额 | 0.000023 | 0.000115 | 0.000023 |
21 | IH | CFFEX | CFE | 上证50 | 0.2 | 300 | 0.2 | 按金额 | 0.000023 | 0.000115 | 0.000023 |
22 | J | DCE | DCE | 焦炭 | 0.5 | 100 | 0.09 | 按金额 | 0.00006 | 0.00003 | 0.00006 |
23 | JD | DCE | DCE | 鸡蛋 | 1 | 10 | 0.07 | 按金额 | 0.00015 | 0.00015 | 0.00015 |
24 | JM | DCE | DCE | 焦煤 | 0.5 | 60 | 0.09 | 按金额 | 0.00006 | 0.00003 | 0.00006 |
25 | JR | CZCE | CZC | 粳稻 | 1 | 20 | 0.05 | 按数量 | 3 | 3 | 3 |
26 | L | DCE | DCE | 塑料 | 5 | 5 | 0.11 | 按数量 | 2 | 0 | 2 |
27 | LR | CZCE | CZC | 晚稻 | 1 | 20 | 0.05 | 按数量 | 3 | 0 | 3 |
28 | M | DCE | DCE | 豆粕 | 1 | 10 | 0.05 | 按数量 | 1.5 | 0 | 1.5 |
29 | MA | CZCE | CZC | 甲醇 | 1 | 10 | 0.07 | 按数量 | 1.4 | 0 | 1.4 |
30 | NI | SHFE | SHF | 沪镍 | 10 | 1 | 0.1 | 按数量 | 6 | 6 | 6 |
31 | OI | CZCE | CZC | 菜油 | 2 | 10 | 0.06 | 按数量 | 2.5 | 0 | 2.5 |
32 | P | DCE | DCE | 棕榈 | 2 | 10 | 0.05 | 按数量 | 2.5 | 0 | 2.5 |
33 | PB | SHFE | SHF | 沪铅 | 5 | 5 | 0.08 | 按金额 | 0.00004 | 0 | 0.00004 |
34 | PM | CZCE | CZC | 普麦 | 1 | 50 | 0.06 | 按数量 | 5 | 5 | 5 |
35 | PP | DCE | DCE | 聚丙烯 | 1 | 5 | 0.05 | 按金额 | 0.00005 | 0.000025 | 0.00005 |
36 | RB | SHFE | SHF | 螺纹 | 1 | 10 | 0.08 | 按金额 | 0.000045 | 0 | 0.000045 |
37 | RI | CZCE | CZC | 早稻 | 1 | 20 | 0.05 | 按数量 | 2.5 | 2.5 | 2.5 |
38 | RM | CZCE | CZC | 菜粕 | 1 | 10 | 0.06 | 按数量 | 1.5 | 0 | 1.5 |
39 | RS | CZCE | CZC | 菜籽 | 1 | 10 | 0.2 | 按数量 | 2 | 2 | 2 |
40 | RU | SHFE | SHF | 橡胶 | 5 | 10 | 0.08 | 按金额 | 0.000045 | 0.000045 | 0.000045 |
41 | SF | CZCE | CZC | 硅铁 | 2 | 5 | 0.07 | 按数量 | 3 | 0 | 3 |
42 | SM | CZCE | CZC | 锰硅 | 2 | 5 | 0.07 | 按数量 | 3 | 0 | 3 |
43 | SN | SHFE | SHF | 沪锡 | 10 | 1 | 0.08 | 按数量 | 3 | 0 | 3 |
44 | SR | CZCE | CZC | 白糖 | 1 | 10 | 0.07 | 按数量 | 3 | 0 | 3 |
45 | T | CFFEX | CFE | 债十 | 0.005 | 10000 | 0.02 | 按数量 | 3 | 0 | 3 |
46 | TA | CZCE | CZC | PTA | 2 | 5 | 0.06 | 按数量 | 3 | 3 | 3 |
47 | TF | CFFEX | CFE | 债五 | 0.005 | 10000 | 0.012 | 按数量 | 3 | 3 | 3 |
48 | V | DCE | DCE | PVC | 5 | 10000 | 0.09 | 按数量 | 2 | 0 | 2 |
49 | WH | CZCE | CZC | 强麦 | 1 | 20 | 0.05 | 按数量 | 2.5 | 0 | 2.5 |
50 | WR | SHFE | SHF | 线材 | 1 | 10 | 0.08 | 按金额 | 0.00004 | 0.00004 | 0.00004 |
51 | Y | DCE | DCE | 豆油 | 2 | 10 | 0.08 | 按数量 | 2.5 | 0 | 2.5 |
52 | ZC | CZCE | CZC | 郑煤 | 0.2 | 100 | 0.05 | 按数量 | 4 | 0 | 4 |
53 | ZN | SHFE | SHF | 沪锌 | 5 | 5 | 0.08 | 按数量 | 3 | 0 | 3 |
54 | SC | INE | INE | 原油 | 0.1 | 1000 | 0.05 | 按金额 | 0.0001 | 0.0001 | 0.0001 |
\