Advertisement

金融平台(掘金量化)量化PYTHON(二)-量化回测框架介绍

阅读量:

策略创建运行流程

1.创建运行策略

1.1创建策略

打开“掘金量化3.0”客户端,进入“我的策略”-“新建策略”,如下所示:

平台集成了众多经典策略方案,在实际应用中采用"空策略"这一概念,并将其命名为"量化策略示例"。代码部分已附上。

复制代码
 # coding=utf-8

    
 from __future__ import print_function, absolute_import
    
 from gm.api import *
    
  
    
  
    
 # 策略中必须有init方法
    
 def init(context):
    
     pass
    
  
    
  
    
 if __name__ == '__main__':
    
     '''
    
     strategy_id策略ID, 由系统生成
    
     filename文件名, 请与本文件名保持一致
    
     mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    
     token绑定计算机的ID, 可在系统设置-密钥管理中生成
    
     backtest_start_time回测开始时间
    
     backtest_end_time回测结束时间
    
     backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    
     backtest_initial_cash回测初始资金
    
     backtest_commission_ratio回测佣金比例
    
     backtest_slippage_ratio回测滑点比例
    
     '''
    
     run(strategy_id='2e012d59-16b0-11ec-85b2-82771950a4e5',
    
     filename='main.py',
    
     mode=MODE_BACKTEST,
    
     token='7d132cd2b781bcb8b42430748dd94edc145750cb',
    
     backtest_start_time='2020-11-01 08:00:00',
    
     backtest_end_time='2020-11-10 16:00:00',
    
     backtest_adjust=ADJUST_PREV,
    
     backtest_initial_cash=10000000,
    
     backtest_commission_ratio=0.0001,
    
     backtest_slippage_ratio=0.0001)

常用的策略结构分为3类:

1.定时任务示例:

每个交易日的14:50分市价买入200股浦发银行股票:

复制代码
 # coding=utf-8

    
 from __future__ import print_function, absolute_import 
    
 from gm.api import *
    
  
    
 def init(context):
    
     # 每天14:50 定时执行algo任务, 
    
     # algo执行定时任务函数,只能传context参数
    
     # date_rule执行频率,目前暂时支持1d、1w、1m,其中1w、1m仅用于回测,实时模式1d以上的频率,需要在 algo判断日期
    
     # time_rule执行时间, 注意多个定时任务设置同一个时间点,前面的定时任务会被后面的覆盖
    
     schedule(schedule_func=algo, date_rule='1d', time_rule='14:50:00')
    
  
    
 def algo(context):
    
     # 以市价购买200股浦发银行股票, price在市价类型不生效
    
      order_volume(symbol='SHSE.600000', volume=200, side=OrderSide_Buy, 
    
                order_type=OrderType_Market, position_effect=PositionEffect_Open, 
    
               price=0)
    
  
    
 def on_backtest_finished(context, indicator): 
    
     print(indicator) 
    
  
    
  if __name__ == '__main__': 
    
  ''' 
    
  strategy_id策略ID, 由系统生成 
    
  filename文件名, 请与本文件名保持一致 
    
  mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST 
    
  token绑定计算机的ID, 可在系统设置-密钥管理中生成 
    
  backtest_start_time回测开始时间 
    
  backtest_end_time回测结束时间 
    
  backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST 
    
  backtest_initial_cash回测初始资金 
    
  backtest_commission_ratio回测佣金比例 
    
  backtest_slippage_ratio回测滑点比例 
    
  ''' 
    
  run(strategy_id='strategy_id', 
    
  filename='main.py', 
    
  mode=MODE_BACKTEST, 
    
  token='token_id', 
    
  backtest_start_time='2020-11-01 08:00:00', 
    
  backtest_end_time='2020-11-10 16:00:00', 
    
  backtest_adjust=ADJUST_PREV, 
    
  backtest_initial_cash=10000000, 
    
  backtest_commission_ratio=0.0001, 
    
  backtest_slippage_ratio=0.0001)

在algo()函数中,使用了order_volume()按指定量委比函数,函数原型如下:

order_volume 是一个包含多个关键参数的函数调用:symbol(符号名称)、volume(交易量)、side(买卖方向)、order_type(订单类型)、position_effect(头寸影响)、价格字段设置为零值、下单持续时间字段以及订单资格字段均为空字符串

订单委托方向、订单委托类型和开平仓类型的枚举常量分别为:...

委托方向:

side = OrderSide_Buy 为买入方向;

订单委托类型:

市价委托,是指以当前股价价格购买;限价委托,需要自己指定价格;

开平仓类型:

position_effect=PositionEffect_Open,开仓操作;

委托时间属性:

仅在实盘模式生效。

委托成交属性:

仅在实盘模式生效。

2.数据事件驱动示例

实现功能:

通过使用 subscribe() 接口进行标的订阅后,在后台系统会返回 tick 数据或 bar 数据两种类型的信息。每当生成一个或多个数据时(即每次数据更新),就会自动触发 on_tick() 或 on_bar() 中定义的功能模块来执行相应的操作。例如下面示例代码段中:订阅浦发银行每隔一天和每隔60秒生成 bar 数据,在每次bar数据生成时就会触发on_bar()函数,并打印获取到的bar信息:

复制代码
 # coding=utf-8

    
 from __future__ import print_function, absolute_import 
    
 from gm.api import *
    
  
    
 def init(context): 
    
 # 订阅浦发银行, bar频率为一天和一分钟 
    
 # 订阅订阅多个频率的数据,可多次调用subscribe 
    
   subscribe(symbols='SHSE.600000', frequency='1d') 
    
   subscribe(symbols='SHSE.600000', frequency='60s') 
    
  
    
  
    
 def on_bar(context, bars): 
    
 # 打印bar数据 
    
    print(bars) 
    
  
    
  if __name__ == '__main__': 
    
 ''' 
    
 strategy_id策略ID, 由系统生成 
    
 filename文件名, 请与本文件名保持一致 
    
 mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST 
    
 token绑定计算机的ID, 可在系统设置-密钥管理中生成 
    
 backtest_start_time回测开始时间 
    
 backtest_end_time回测结束时间 
    
 backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST 
    
 backtest_initial_cash回测初始资金 
    
 backtest_commission_ratio回测佣金比例 
    
 backtest_slippage_ratio回测滑点比例 
    
 ''' 
    
 run(strategy_id='strategy_id', 
    
 filename='main.py', 
    
 mode=MODE_BACKTEST, 
    
 token='token_id', 
    
 backtest_start_time='2020-11-01 08:00:00', 
    
 backtest_end_time='2020-11-10 16:00:00', 
    
 backtest_adjust=ADJUST_PREV, 
    
 backtest_initial_cash=10000000, 
    
 backtest_commission_ratio=0.0001, 
    
 backtest_slippage_ratio=0.0001)

tick对象数据简介:

行情详细记录中包含了成交记录这一核心要素。其中包含了各交易品种的分笔成交信息:即对单、限价、市价等各类订单类型均有详细的记录;此外还包含了市场中的集合竞价时段(9点15分至9点25分之间)每一tick时间点都有相应的价格变动信息;对于股票类交易品种而言其报价更新周期定为每隔3秒钟进行一次;而对于期货类交易品种则采用更频繁的报价机制即每隔半秒钟就进行一次报价更新;最后对于指数类金融工具则采用的是每隔5秒钟进行一次指数计算的方式以反映市场整体走势

tick数据也是exchange entity对order book中的order insertion、order cancellation、order modification以及market order records进行操作所生成的数据;当order book中的bid price, bid quantity, ask price和ask quantity发生变动时会产生tick.

国内交易所发送的信息属于切片数据类型,并非真正的tick数据。在500毫秒的时间间隔内进行说明,在这一时间段内发生的所有变化都无法被完整捕捉到。通过下图中的立方体模型可以看出tick数据结构:每个切片单元可以视为一个快照记录(红色立方体),而深青色立方体则代表被忽略的数据部分。

解释一下:

2百毫秒后(即上午1百:3十一:百8秒) ,某人以每股16O元的价格买入了2百股 ,当日成交价维持在16O元/股水平 ,当日总成交量达到 **2448.9万 股 。然而,在当前时刻(距离事件开始还剩 **5百毫秒) ,尚未达到数据推送的时间节点

当时间为上午10点31分零8秒时,在4oo毫秒的时候

当时间为上午10:31:08时500毫秒的时间段内发生了某一方以买入价164.7元/股(注:原文应为"买入价"可能是笔误?根据上下文推测应为买入价)的价格完成了999999股(注:原文应为"卖出")的卖出交易。此时交易所系统生成了一份详细记录,并将其通过网络平台进行了公开发布。”

按照如图所示的流程进行操作时,请注意以下事项:假设当日最低价位为160元,则可能导致因信息缺失无法及时获取相关信息。因此国内交易所通常会补充发布当日的最高和最低价数据来弥补这一信息缺口。

bar对象数据简介:

**

**

在程序中,在线订阅 subscribe(symbols='SHSE.600000', frequency='1d') 函数,并指定其股票代码以及每日时间频率参数后执行

subscribe(symbols='SHSE.600000', frequency='1d')(日K线):

{
'symbol': 'SHSE.600000',
'eob': datetime.datetime(2020, 11, 2, 15, 15, 1).strftime('%Y-%m-%d %H:%M:%S'),
'bob': datetime.datetime(2020, 11, 2).strftime('%Y-%m-%d'),
'open': "约9.28",
'close': "约9.25",
'high': "约9.33",
'low': "约9.22",
'volume': "约4654万",
'amount': "约43亿",
'pre_close': "约9.26",
'position': "无",
'frequency': "每日",
'receive_local_time': 1632462639
}

SHSE Component A股票代码为SHSE.600000
该记录显示记录时间为2020年11月3日午盘收盘
开市价为9.31
收盘价为9.3
最高价为9.4
最低价为9.28
当天总交易量达6,787,611
总金额为$6,32,97,38,元
当天无持仓变化
股票交易频率设定为每日一次
本地接收时间为2022年8月4日(此处可能有笔误应根据实际情况修改)

subscribe(symbols='SHSE.600000', frequency='60s')(1分钟K线):

收到本地时间为1632462960.06秒的股票行情数据:SHSE.600000股票代码对应的行情信息如下:开盘时间为2020年11月2日9:31: tzfile('PRC')时区;收盘时间为同一日的9:30: tzfile('PRC')时区;开盘价为约9.28元人民币;收盘价为约9.3元人民币;最高价格达到约9.33元人民币;最低价格维持在约9.28元人民币;成交量为约142.9万手;成交金额约为1.328×1e7元人民币;当前持仓数量为零;行情更新频率为每6秒一次;本数据接收时间为本地时间为1632462965秒

该合约代码为SHSE.600000,在9月3日9时32分至9时31分之间的交易时段内达到有效状态;开盘价位为9.30元人民币(美分单位),收盘价同样为9.30元人民币;当日交易中最高价位触及9.31元人民币(美分单位),最低价位则为9.29元人民币(美分单位);该合约共计成交量为1,144,313股(手),总交易金额达1亿零六百四十八万七千八百二美元(元人民币);合约净持仓量维持在零位水平

{
'symbol': 'SHSE.600000',
'eob': 交易结束时间为2020年11月2日9时33分(GMT+8),
'bob': 某个时间段(例如:9时32分至9时33分),
'open': 开盘价为9.31元,
'close': 收盘价同样为9.31元,
'high': 当天最高价位至9.33元,
'low': 最低价维持在9.3元,
'volume': 当天交易量达到约114万股,
'amount': 累计金额约为1亿零五百九十一万三千四百元,
'pre_close': 前一天的收盘价位为9.3元,
'holding amount': 持有数量仍为零,
'frequency': 时间间隔设置为每60秒一次更新,
'receive_local_time': 当前接收时间戳为1632462968秒
}

3. 时间序列数据事件驱动示例

策略订阅代码时需设置时间窗口长度与周期参数。 平台生成移动时间窗口,并导入初始时间段的数据。 每当新的bar出现时, 该系统会自动更新时间序列数据。 当on_bar事件触发时, 策略能够获取相应的历史价格信息。

以下是一个简化的示例代码片段:订阅浦发银行的日线及分钟级别的bar数据;每当bar数据更新时,on_bar函数就会被自动调用;每次通过context.data获取最新更新的50条分钟级别的bar数据

复制代码
 from __future__ import print_function, absolute_import

    
 from gm.api import *
    
  
    
  
    
 def init(context):
    
     # 订阅浦发银行, bar频率为一天和一分钟
    
     # 指定数据窗口大小为50
    
     # 订阅订阅多个频率的数据,可多次调用subscribe
    
     subscribe(symbols='SHSE.600000', frequency='1d', count=50)
    
     subscribe(symbols='SHSE.600000', frequency='60s', count=50)
    
  
    
  
    
 def on_bar(context, bars):
    
     # context.data提取缓存的数据滑窗, 可用于计算指标
    
     # 注意:context.data里的count要小于或者等于subscribe里的count
    
     data = context.data(symbol=bars[0]['symbol'], frequency='60s', count=50, fields='close,bob')
    
  
    
     # # 打印最后5条bar数据(最后一条是最新的bar)
    
     print(data)
    
  
    
  
    
 if __name__ == '__main__':
    
     '''
    
     strategy_id策略ID, 由系统生成
    
     filename文件名, 请与本文件名保持一致
    
     mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    
     token绑定计算机的ID, 可在系统设置-密钥管理中生成
    
     backtest_start_time回测开始时间
    
     backtest_end_time回测结束时间
    
     backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    
     backtest_initial_cash回测初始资金
    
     backtest_commission_ratio回测佣金比例
    
     backtest_slippage_ratio回测滑点比例
    
     '''
    
     run(strategy_id='a8fba419-201d-11ec-8cbc-82771950a4e5',
    
     filename='main.py',
    
     mode=MODE_BACKTEST,
    
     token='7d132cd2b781bcb8b42430748dd94edc145750cb',
    
     backtest_start_time='2020-11-01 08:00:00',
    
     backtest_end_time='2020-11-10 16:00:00',
    
     backtest_adjust=ADJUST_PREV,
    
     backtest_initial_cash=10000000,
    
     backtest_commission_ratio=0.0001,
    
     backtest_slippage_ratio=0.0001)

打印的数据如下:

close bob
0 9.46 2020-11-10 14:08:00+08:00
1 9.47 2020-11-10 14:09:00+08:00
2 9.46 2020-11-10 14:10:00+08:00
3 9.46 2020-11-10 14:11:00+08:00
4 9.46 2020-11-10 14:12:00+08:00
5 9.46 2020-11-10 14:13:00+08:00
6 9.47 2020-11-10 14:14:00+08:00
7 9.46 2020-11-10 14:15:00+08:00
8 9.45 2020-11-10 14:16:00+08:00
9 9.45 2020-11-10 14:17:00+08:00
10 9.45 2020-11-10 14:18:00+08:00
11 9.46 2020-11-10 14:19:00+08:00
12 9.45 2020-11-10 14:20:00+08:00
13 9.45 2020-11-10 14:21:00+08:00
14 9.45 2020-11-10 14:22:00+08:00
15 9.45 2020-11-10 14:23:00+08:00
16 9.45 2020-11-10 14:24:00+08:00
17 9.45 2020-11-10 14:25:00+08:00
18 9.45 2020-11-10 14:26:00+08:00
19 9.45 2020-11-10 14:27:00+08:00
20 9.45 2020-11-10 14:28:00+08:00
21 9.45 2020-11-10 14:29:00+08:00
22 9.46 2020-11-10 14:30:00+08:00
23 9.46 2020-11-10 14:31:00+08:00
24 9.45 2020-11-10 14:32:00+08:00
25 9.45 2020-11-10 14:33:00+08:00
26 9.45 2020-11-10 14:34:00+08:00
27 9.46 2020-11-10 14:35:00+08:00
28 9.46 2020-11-10 14:36:00+08:00
29 9.45 2020-11-10 14:37:00+08:00
30 9.45 2020-11-10 14:38:00+08:00
31 9.46 2020-11-10 14:39:00+08:00
32 9.46 2020-11-10 14:40:00+08:00
33 9.46 2020-11-10 14:41:00+08:00
34 9.45 2020-11-10 14:42:00+08:00
35 9.46 2020-11-10 14:43:00+08:00
36 9.47 2020-11-10 14:44:00+08:00
37 9.47 2020-11-10 14:45:00+08:00
38 9.46 2020-11-10 14:46:00+08:00
39 9.46 2020-11-10 14:47:00+08:00
40 9.46 2020-11-10 14:48:00+08:00
41 9.46 2020-11-10 14:49:00+08:00
42 9.46 2020-11-10 14:50:00+08:00
43 9.47 2020-11-10 14:51:00+08:00
44 9.47 2020-11-10 14:52:00+08:00
45 9.46 2020-11-10 14:53:00+08:00
46 9.47 2020-11-10 14:54:00+08:00
47 9.47 2020-11-10 14:55:00+08:00
48 9.46 2020-11-10 14:56:00+08:00
49 9.46 2020-11-10 14:57:00+08:00
close bob
0 9.47 2020-11-10 14:09:00+08:00
1 9.46 2020-11-10 14:10:00+08:00
2 9.46 2020-11-10 14:11:00+08:00
3 9.46 2020-11-10 14:12:00+08:00
4 9.46 2020-11-10 14:13:00+08:00
5 9.47 2020-11-10 14:14:00+08:00
6 9.46 2020-11-10 14:15:00+08:00
7 9.45 2020-11-10 14:16:00+08:00
8 9.45 2020-11-10 14:17:00+08:00
9 9.45 2020-11-10 14:18:00+08:00
10 9.46 2020-11-10 14:19:00+08:00
11 9.45 2020-11-10 14:20:00+08:00
12 9.45 2020-11-10 14:21:00+08:00
13 9.45 2020-11-10 14:22:00+08:00
14 9.45 2020-11-10 14:23:00+08:00
15 9.45 2020-11-10 14:24:00+08:00
16 9.45 2020-11-10 14:25:00+08:00
17 9.45 2020-11-10 14:26:00+08:00
18 9.45 2020-11-10 14:27:00+08:00
19 9.45 2020-11-10 14:28:00+08:00
20 9.45 2020-11-10 14:29:00+08:00
21 9.46 2020-11-10 14:30:00+08:00
22 9.46 2020-11-10 14:31:00+08:00
23 9.45 2020-11-10 14:32:00+08:00
24 9.45 2020-11-10 14:33:00+08:00
25 9.45 2020-11-10 14:34:00+08:00
26 9.46 2020-11-10 14:35:00+08:00
27 9.46 2020-11-10 14:36:00+08:00
28 9.45 2020-11-10 14:37:00+08:00
29 9.45 2020-11-10 14:38:00+08:00
30 9.46 2020-11-10 14:39:00+08:00
31 9.46 2020-11-10 14:40:00+08:00
32 9.46 2020-11-10 14:41:00+08:00
33 9.45 2020-11-10 14:42:00+08:00
34 9.46 2020-11-10 14:43:00+08:00
35 9.47 2020-11-10 14:44:00+08:00
36 9.47 2020-11-10 14:45:00+08:00
37 9.46 2020-11-10 14:46:00+08:00
38 9.46 2020-11-10 14:47:00+08:00
39 9.46 2020-11-10 14:48:00+08:00
40 9.46 2020-11-10 14:49:00+08:00
41 9.46 2020-11-10 14:50:00+08:00
42 9.47 2020-11-10 14:51:00+08:00
43 9.47 2020-11-10 14:52:00+08:00
44 9.46 2020-11-10 14:53:00+08:00
45 9.47 2020-11-10 14:54:00+08:00
46 9.47 2020-11-10 14:55:00+08:00
47 9.46 2020-11-10 14:56:00+08:00
48 9.46 2020-11-10 14:57:00+08:00
49 9.46 2020-11-10 14:59:00+08:00

在subscribe()函数中设置参数count=50,则用于指定数据窗口大小的值定为50;每次接收的数据量固定为50个单位;其中最后一组则由[N-49,N]范围内的数据组成。

4. 多个标的数据事件驱动示例

全部评论 (0)

还没有任何评论哟~