0%

旧接口地址:http://hq.sinajs.cn/list=TICKER
字段含义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这个字符串由许多数据拼接在一起,不同含义的数据用逗号隔开了,按照程序员的思路,顺序号从0开始。 
0:豆粕连续,名字
1:145958,不明数字(难道是数据提供商代码?)
2:3170,开盘价
3:3190,最高价
4:3145,最低价
5:3178,昨日收盘价 (2013年6月27日)
6:3153,买价,即“买一”报价
7:3154,卖价,即“卖一”报价
8:3154,最新价,即收盘价
9:3162,结算价
10:3169,昨结算
11:1325,买 量
12:223,卖 量
13:1371608,持仓量
14:1611074,成交量
15:连,大连商品交易所简称
16:豆粕,品种名简称
17:2013-06-28,日期

参考帖子:新浪期货接口:https://blog.csdn.net/qq_37193537/article/details/89359425

但旧接口已经不再维护了,部分品种旧接口无法查询到数据(结果空,比如NR,20号胶)
新接口地址:https://hq.sinajs.cn/list=nf_NR2003(相比旧接口,品种代码前多了nf_前缀)
响应数据含义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var hq_str_nf_NR2003=
0,20号胶2003
1,112959
2,10780.000,开盘价
3,10930.000,最高
4,10710.000,最低价
5,0.000,结算价
6,10700.000,买价
7,10715.000,卖价
8,10710.000,最新价
9,0.000,不明确
10,10815.000,昨结价
11,3,买量
12,3,卖量
13,17793.000,持仓量
14,2718,成交量
15,沪,所属市场
16,20号胶,品种名称
17,2020-01-02,日期
18,0,不明确
2x,_,,,,,,间隔很多个的结尾数字,不明确

概况图:
| 公司 | 版本 | 股票 | 债券 | 期货 | 期权 | 数字 | 回测 | 模拟 | 实盘 |
| —– | ——— | ———- | —- | —- | ——- | —- | —- | —- | —- |
| 米框 | 在线 | A股1m | 1m | 1m | 1m(权限) | 无 | 是 | 是 | 否 |
| 米框 | RQData | A股1m | 1m | 1m | 1m(权限) | 无 | 否 | 否 | 否 |
| 优矿 | 在线 | A股1m港股1d | 无 | 1m | 1d | 无 | 是 | 是 | 否 |
| 聚宽 | 在线 | A股1m | 无 | 1m | 1m(实1d) | 无 | 是 | 是 | 是 |
| 聚宽 | jqdatasdk | A股1m | 无 | 1m | 1m(实1d) | 无 | 否 | 否 | 否 |
| 天勤 | tqsdk | A股1m | 无 | 1m | 1m | 无 | 是 | 是 | 是 |
| 掘金 | 本地sdk | A股1m | 无 | 1m | 无 | 无 | 是 | 未 | 是 |
| 发明者 | 在线 | A股1m | 1m | 1m | 未 | 1m | 是 | 是 | 是 |
| 发明者 | 本地sdk | A股1m | 1m | 1m | 未 | 1m | 是 | 否 | 是 |
说明:
RQ回测里面很多研究平台可用查询在回测时无法使用.比如获取期权某日可用列表.感觉研究和回测平台是分离开的
权限:需要额外权限
实1d:实际是1天的

米框

在线分析,回测。提供sdk,可分析,无法回测

1
2
A股,期货的1min
支持机构实盘,不支持个人

优矿

在线版

1
2
3
4
5
股票:沪深交易所股票的基本信息以及日/分钟级别的股票行情
港股:香港交易所股票基本信息以及日级别的股票行情。
期货:国内四大期货交易所期货合约的基本信息,日/分钟/tick级别的期货行情,以及国债期货的转换因子等信息。
期权:上交所期权合约的基本信息,日/分钟/tick级别的期权行情,以及每日盘前静态数据等信息。是日k线
期权实际只有日行情.

聚宽

在线研究,在线回测。提供本地sdk(需要授权).查询行情(也就是说支持分析,但无法回测)

1
2
3
4
5
6
7
股票,期货1分钟起

实盘:期货目前支持长江期货账户、中信期货账户、银河期货账户和光大期货账户进行期货实盘;
其中50ETF期权从2017-01-01开始,商品期权从2019-12-02开始。(期权分钟价格数据有错误,按日查询则是对的)

(2)jqdata是在官网调用数据时需要引用的包,import jqdata 或 from jqdata import *,具体使用方法见官网API:https://www.joinquant.com/help/api/help?name=api
(3)jqdata和jqdatasdk中的数据略有不同,主要区别在于jqdatasdk目前不支持聚源数据,而官网可以输入from jqdata import jy调用聚源数据 。

天勤(开源TqSdk),据说期货期权行情都有

官方说明:https://doc.shinnytech.com/tqsdk/latest/intro.html
提供当前所有可交易合约从上市开始的 全部Tick数据和K线数据
支持数十家期货公司的 实盘交易
支持 模拟交易
支持 Tick级和K线级回测, 支持 复杂策略回测
无强制框架结构, 支持任意复杂度的策略, 在一个交易策略程序中使用多个品种的K线/实时行情并交易多个品种

掘金

本地SDK模式,支持本地分析(需token),本地回测,期货,股票
支持对接实盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
股票行情
A股日线数据: 2005年1月1日起至今
1分钟线数据: 2015年1月1日起至今
Tick数据: 最近2个月
大于1分钟任何频度Bar: 2015年1月1日起至今
小于1分钟任何频度Bar: 最近2个月

期货行情
日线数据: 全部原始合约的完整数据;全部主力合约和连续合约完整数据
1分钟线数据: 2015年6月1日起至今
Tick数据: 最近2个月
大于1分钟任何频度Bar: 2015年6月1日起至今
小于1分钟任何频度Bar: 最近2个月

实盘:支持,联系商务沟通

发明者

支持在线分析,在线回测,本地回测
支持实盘

1
2
3
4
支持tick数据
商品期货 Futures_CTP, 支持国内所有期货公司
外盘易盛 Futures_Esunny
数字货币现货

bigquant

1
2
A股,期权,期货的1min
期权是日数据

果仁

1
A股,日

京东量化

1
京东量化平台免费提供了可靠的沪深股市数据,数据包含沪深股市行情,以及指数行情信息,三大财务报表及业务绩预告数据。京东量化平台提供的分钟级别的历史行情数据,目前从2011年1月1日开始至当前日期, 提供的历史财务数据从1989年12月31日开始。

同花顺的MindGo

1
2
3
4
5
6
7
8
9
10
股票数据	分钟行情	2010-01-04	2019-07-26 20:00:01	历史分钟数据每日17:30后更新一次,实时数据即时同步行情端
日线行情 2005-01-04 2019-07-27 17:32:38 每日00:30后更新
财务数据 2005-01-04 2019-07-27 03:00:00 每日20:00后更新
资金数据 2007-01-04 2019-07-27 05:50:17 日数据每日00:00后更新,分钟数据实时同步行情端
指数数据 分钟行情 2010-01-04 2019-07-26 20:00:01 历史分钟数据每日17:30后更新一次,实时数据即时同步行情端
日线行情 2005-01-04 2019-07-27 17:32:38 每日00:30后更新
期货数据 分钟行情 2016-01-04 2019-07-27 02:21:45 次日09:00后更新(包含夜盘)
日线行情 2005-01-04 2019-07-27 06:30:00 每日00:30后更新
期权,分钟,查询非常慢
只有金融期权,没有商品期权数据

windquant

1
2
我们有顶级金融信息服务商 Wind 提供数据支持,涉及国内外全市场股票、债券、基金、商品、指数、外汇、期权等7个品种的历史日线、Tick、分钟、实时行情数据,上市公司财务数据,以及中国市场所有品种的专题统计报表、中国及海外股票板块数据、宏观经济数据,此外还整理了针对多因子选股研究的 point-in-time 量化因子库。
有期权分钟,但是有权限限制,普通用户无法查看

雷矿

1
2
3
A股分钟
我们拥有2012至今A股数据。
当日的16:00更新完毕最新数据。

真格量化

1
2
3
4
5
真格量化提供哪些数据?
期货:国内五大商品期货交易所期货合约的基本信息、日/分钟/tick级别的期货行情、品种成交持仓排名、合约成交持仓排名、仓单日报表、以及国债期货的转换因子等信息。
期权:股票期权和期货期权合约的基本信息、日/分钟/tick级别的期权行情、最痛点位、以及每日盘前静态数据等信息。
期权下载下来,压缩包无法解压,无密码
支持实盘

国泰君安量化交易系统

1
2
3
4
期权数据好像是jqdata,存在鬼数据
get_price('M2005-C-2700.XDCE', start_date='2020-03-19', end_date='2020-03-21', frequency='1m', fields=None, skip_paused=False, count=None)

get_price('M2005-C-2700.XDCE', start_date='2020-03-19', end_date='2020-03-21', frequency='1m', fields=None, skip_paused=False, count=None)

第一个结果

第二个结果

同一个期权,同一天,价格还不同

ontrade

1
2
3
4
5
6
7
cataEngine:
processTradeEvent
self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)

backtesting
def crossLimitOrder(self):
def crossStopOrder(self):

onOrder

1
2
3
4
5
6
7
8
cataEngine:
processOrderEvent
self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)

backtesting
def cancelOrder(self, vtOrderID):
def crossLimitOrder(self):
def crossStopOrder(self):

onStopOrder

1
2
3
4
5
6
7
8
cataEngine:
def cancelStopOrder(self, stopOrderID):
def processStopOrder(self, tick):
def sendStopOrder(self, vtSymbol, orderType, price, volume, strategy):

backtesting
def cancelStopOrder(self, stopOrderID):
def crossStopOrder(self):

特殊注意

1
2
so.status = STOPORDER_TRIGGERED
so.strategy.onStopOrder(so)

停止单被触发和停止单被执行,并不完全相同,触发是发送个券商,执行才是真正完成

1,申请券商模拟盘帐号(提交模拟帐号和appid)
2,填写测试申请表,填写后券商邮件回复中包含有终端认证码:终端认证码xxx
3,结合模拟帐号,密码,appid和终端认证码以及券商接口信息,使用ctptest接口对接。

1
2
3
4
譬如东航
IP 地址:210.13.65.102 交易端口:43205 行情端口:43213
BrokerID:7070
API 版本号:API_6.3.13_T4

4, 截图,登录图,下单图,异常信息图,填写测试反馈表和承诺书,提交给券商。
5,券商通过后则终端认证码就是正式终端认证码了。可对接正式使用了。
6,参考

1
https://www.vnpy.com/forum/topic/603-kan-wan-zhe-pian-che-di-gao-ding-qi-huo-chuan-tou-shi-ctp-apijie-ru

7,可以官方提供so里面函数直接读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
libtest = cdll.LoadLibrary('/home/john/下载/v6.3.13_20181119_tradeapi/v6.3.13_20181119_api_clientdatacollectdll_linux64/LinuxDataCollect.so')
//_Z28CTP_GetSystemInfoUnAesEncodePcRi
//_Z17CTP_GetSystemInfoPcRi
//_Z21CTP_GetRealSystemInfoPcRi
func = getattr(libtest, '_Z21CTP_GetRealSystemInfoPcRi')
a=create_string_buffer(264)
b=c_int()
print (func(a, byref(b)))
print (a.value)
print (b)

b'2@2019-07-16 18:47:37@172.16.0.154@@aced5cf6d10a@@john-P95-@4.15.@AA00000000000000@E9060900FFFBEBBF@Not'
c_int(103)

大概是2@2019-07-16 18:47:37[当前时间]@172.16.0.154[本机IP]@@aced5cf6d10a[MAC地址]@@john-P95-[机器名]@4.15.@AA00000000000000@E9060900FFFBEBBF@Not

01,常规软件安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1,
先修改默认编辑器为vim(默认为nano):
sudo update-alternatives --config editor
2,pip
sudo apt install python-pip -y

3,vim,git,aria2
apt-get install vim
sudo apt install git -y
apt-get -y install aria2

4,安装Anaconda
参考:Linux系统安装Anaconda:https://blog.csdn.net/teeyohuang/article/details/79076239
wget https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh
bash bash Anaconda3-2019.03-Linux-x86_64.sh
一般都是yes
留意:Do you wish the installer to initialize Anaconda3
这个推荐no,最好也写yes,yes后不需要手动修改bashrc了

vim ~/.bashrc
最后一行添加 :export PATH="/home/Teeyo/anaconda3/bin:$PATH"
source .bashrc
执行:python,提示信息中有anaconda就说明使用anaconda的python,可以认为成功了。

02,vnpy安装整体流程

参考:ubuntu18下vnpy的安装_第五次安装,目标v1.9(ok)
主要参考:https://github.com/vnpy/vnpy/wiki/Ubuntu环境安装
1,创建conda环境
conda create -n vnpy27 python=2.7
source activate vnpy27

2,env下安装
pip install future

3,切换到系统下面安装(非env环境),系统默认其实也是ana的环境,是ana就ana吧
sudo apt-get install git
sudo apt-get install mongodb -y
sudo apt-get install libboost-all-dev
sudo apt-get install cmake
sudo apt-get install libsnappy-dev
sudo apt-get install python-snappy

4,系统环境下安装
sudo apt-get install build-essential
sudo apt-get install python-dev

5,env下安装
source activate vnpy27
mkdir PYTHON
cd PYTHON
git clone https://github.com/vnpy/vnpy.git
cd vnpy
git checkout v1.9.2-LTS
bash install.sh
中间有些报错:
Failed building wheel for ta-lib等
暂时不理会

执行脚本:
cd examples/VnTrader/
python run.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
报错:qtpy.PythonQtError: No Qt bindings could be found
执行:conda install pyqt
执行python
import qtpy
成功!
貌似这个也需要安装conda install qtpy

python run.py
报错:
File "/home/john/anaconda3/envs/vnpy27/lib/python2.7/site-packages/vnpy-1.9.2-py2.7.egg/vnpy/api/rest/RestClient.py", line 11, in
from enum import Enum
ImportError: No module named enum
pip install enum
成功!

cd ~/PYTHON/vnpy/examples/VnTrader
python run.py
报错:
File "/home/john/anaconda3/envs/vnpy27/lib/python2.7/site-packages/vnpy-1.9.2-py2.7.egg/vnpy/api/rest/RestClient.py", line 12, in
from typing import Any, Callable, Optional
ImportError: No module named typing
pip install typing
成功

python run.py
报错:
File "/home/john/anaconda3/envs/vnpy27/lib/python2.7/site-packages/vnpy-1.9.2-py2.7.egg/vnpy/rpc/vnrpc.py", line 7, in
import zmq
ImportError: No module named zmq
执行:pip install zmq

python run.py
报错:
QXcbConnection: Could not connect to display
Aborted
2中可能
第一种:之前自己本机跑时也需要注释掉一段代码,现在还没注释
注释掉xtpGateway
第二种,图形终端必须在vnc中python run.py才能启动,否则无法调用渲染
按照第二种处理,在vnc中打开终端,然后终端执行python run.py
vnc打开终端,没反应。
网上资料,有人说组件没安装完整
补充安装:
sudo apt-get install x-window-system-core
sudo apt-get install ubuntu-desktop gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal
目测上面都是已有的,完整的
本地终端启动(环境vnpy27中启动):
依然不行
QXcbConnection: Could not connect to display
Aborted
解决方案01:export DISPLAY=':0.0'
不行。
如何得知虚拟机机器的display呢?
由于我们已经连接到远程桌面上了,虽然没有terminal终端但有个xtearm一样东西可以执行命令
执行:
echo ${DISPLAY}
:1
修该远程主机的display参数
export DISPLAY=':1.0'
执行python run.py
ok了,不过字符乱码了

6,env下安装jqdatasdk
pip install jqdatasdk

03,字符乱码问题

参考:
01:https://www.simongong.net/vpskaiqivncfuwubingjiejuezhongwenluanmadefangfaubuntuxitong/
02:https://www.centos.bz/2017/12/%E8%A7%A3%E5%86%B3ubuntu%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
参考文章01,
(没有的文件未添加)
追加:sudo vim /etc/environment
LANG="zh_CN.UTF-8"
LANGUAGE="zh_CN:zh:en_US:en"
LC_CTYPE="zh_CN.UTF-8"

追加:sudo vi /etc/default/locale
LANG="zh_CN.UTF-8"
LANGUAGE="zh_CN:zh"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"

执行:sudo locale-gen
执行:sudo reboot

依然乱码。

参考文章02(文中提到没有文件需要添加)
执行(base和vnpy27):sudo apt-get install language-pack-zh-hans
追加:/etc/environment
LANG="zh_CN.UTF-8"
LANGUAGE="zh_CN:zh:en_US:en"
新建,追加:/var/lib/locales/supported.d/local(没有这个文件就新建,同样在末尾追加):
en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
zh_CN.GBK GBK
zh_CN GB2312
执行(双环境base,vnpy27):sudo locale-gen
执行(base):sudo apt-get install fonts-droid-fallback ttf-wqy-zenhei ttf-wqy-microhei fonts-arphic-ukai fonts-arphic-uming
ok

04,分辨率问题

01,启动vnc添加参数:
vncserver -geometry 1600x900
02,修改配置文件/root/.vnc/xstartup
xterm -geometry 1600x900+0+0
这个数字x修改为设定窗口大小。后边两个加号的数字是 窗口左上角的坐标,即设定窗口位置的。
重启vncserver 即可。
参考:https://bbs.csdn.net/topics/390978948

05,安装jqdatasdk

1
pip install jqdatasdk

06,执行JQ的download下载数据

numpy版本问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
your numpy version is 1.11.3.
Please upgrade numpy to >= 1.12.0 to use this pandas version

conda install numpy=1.12

由于安装时卸载了talib,所以需要重新安装talib

sudo chmod -R 777 anaconda3
conda install -chttps://conda.anaconda.org/quantopian ta-lib
这种方式会将numpy又变回到4.11版本

参考官网提供方式:
conda install -c jaikumarm ta-lib
地址:https://anaconda.org/jaikumarm/ta-lib
报错:ImportError: libta_lib.so.0: cannot open shared object file: No such file or directory
强制升级TA-Lib
pip install --upgrade --force-reinstall TA-Lib
安装numpy
conda install numpy
执行:
python downloadData.py

报错
01,ImportError: libta_lib.so.0: cannot open shared object file: No such file or directory
处理问题01,同类问题
进入python
>>> import talib
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/anaconda3/envs/vnpy27/lib/python2.7/site-packages/talib/__init__.py", line 4, in <module>
from . import common
ImportError: libta_lib.so.0: cannot open shared object file: No such file or directory
所以根源在talib的问题,改到06继续讨论
02,UnicodeEncodeError: 'ascii' codec can't encode character u'\uff08' in position 13: ordinal not in range(128)
处理问题02添加:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
推送到github
不行,

新建文件:sitecustomize.py
参考:https://www.cnblogs.com/kevingrace/p/5893121.html
不行

参考:https://oomake.com/question/281941
终端执行:
export PYTHONIOENCODING=utf-8
ok,
可打印出中文
将其配置到~/.bashrc文件中

07,tablib问题

import talib报错

1
2
3
4
5
6
7
>>> import talib
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/anaconda3/envs/vnpy27/lib/python2.7/site-packages/talib/__init__.py", line 4, in <module>
from . import common
ImportError: libta_lib.so.0: cannot open shared object file: No such file or directory
所以根源在talib的问题,改到06继续讨论

先卸载

1
2
conda uninstall ta-lib  
卸载掉的是4.9

conda安装

1
2
3
4
5
sudo chmod -R 777 anaconda3
conda install -c quantopian ta-lib
安装的版本4.6.11
同时numpy被降级,从1.13.1降低到1.11.3
问题是降级后pandas不就好使了。

numpy安装特定版本1.12

1
2
3
4
5
6
7
8
9
pip install numpy==1.12.0
提示:
Installing collected packages: numpy
Found existing installation: numpy 1.16.2
Uninstalling numpy-1.16.2:
Successfully uninstalled numpy-1.16.2
Successfully installed numpy-1.12.0

conda刚刚降为11,但是pip视角看为1.16.2版本

08,mongo问题

安装mongo3.6版本否则空间不够用
参考:https://blog.csdn.net/gaoyan2011/article/details/79420034
mongo旧版用mongodump导出数据出来,然后mondorestore恢复
新版安装试用apt-get的阿里云源,可以安装3.6版本,之后如果直接使用mongod启动(不带其他参数)则数据文件必须放在/data/db种,mkdir这个路径就行了,否则无法启动,然后恢复数据mongorestore
添加自动启动

1
2
3
vim /etc/profile
追加
/usr/bin/mongod --dbpath /var/lib/mongodb/ --logpath /var/log/mongodb/mongodb.log --logappend &

本机界面环境启动回测

01,有界面的启动:

1
cd vnpy/examples/VnTrader$ python run.py

02,系统-连接CTP
03,人工操作:功能->CTA策略->加载策略,启动策略
策略配置位置:vnpy/examples/VnTrader/cta_setting.json

本机无界面环境启动回测

参考

Ubuntu 16.04 + VNPY 1.9.2,半自动环境搭建脚本分享:http://www.vnpie.com/forum.php?mod=viewthread&tid=3175
为远程主机安装图形界面,还是用teamview进行远程的
Ubuntu环境安装:https://github.com/vnpy/vnpy/wiki/Ubuntu%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85
为远程主机安装图形界面,以及用xrdp进行远程桌面
阿里云 ECS 建立 vnpy 环境:http://www.vnpie.com/forum.php?mod=viewthread&tid=2537
阿里云服务器安装vn.py(Ubuntu 16.04 LTS):https://github.com/vnpy/vnpy/wiki/%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%89%E8%A3%85vn.py%EF%BC%88Ubuntu-16.04-LTS%EF%BC%89
使用阿里云的vnc安装方式实现远程桌面
Ubuntu 16.04下vnpy的安装:https://xingjian.space/Quant/vnpy/installing-vnpy-on-ubuntu16.04/

 阅读<海龟交易法则>时,对其评估指标部分,非常认同.其实自己之前在做股票量化时也注意到这个问题,就是起始日期对回撤影响大,尤其是在上证50上做测试时,相差一天结果可能天壤之别.书中提到的一些指标,个人还是比较认同的,所以想在vnpy中实现下,自己回测过程中也可以留意下是否真的更客观的反映策略优劣.

海龟交易法则12.4:回归年度回报率:

 定义:线形回归线和它所代表的回报率为我们提供了一个新指标,我 称之为RAR (regressed annual return,回归年度回报率)。这个指标 对测试期起止日的变化远不像CAGR那样敏感。从图12 - 2中可以 看到,当RAR的测试起止日改变时,回归线斜率的变化要小得多。

 实际:书中X轴采用的年度,y轴是累积年回报.
笔者使用vnpy主要是计划做日内或CTA所以x轴采用日相对合理.
 那么rar可以看做是日角度的回归斜率.但如果是全局斜率的化(比如最近1年)可能受到远期数据干扰较大,所以计划使用20日滚动斜率代替,得到的序列的均值作为整个时间区间的衡量(同时,方差信息也是有用的,不过直接采用 20日斜率的均值/方差,担心高方差使得拉低整体取值,所以暂只考虑均值,不考虑方差)

海龟交易法则12.5:R立方:一个新的风险回报比指标

定义:平均最大衰落就是5次最大衰落幅度的平均值。长度调整就是 将这5个衰落期的平均天数除以365天,然后用这个结果乘以平均 最大衰落。平均衰落天数的计算原理与平均衰落幅度相同,也就是将5次衰落期的天数相加再除以5。因此,如果RAR是50%,平均 最大衰落是25%,而平均衰落长度是1年,也就是365天,那么R 立方就等于2.0——也就是50%/ (25% X365/365)。作为一个风险-回报比指标,R立方从程度和时间这两个角度考虑了风险问题
实际:这个指标核心在于和RAR正比,和最大回撤反比和最大回撤持续时间反比,其中最大回撤持续时间这个因素个人并不认同.个人认为这个因子作用不大

1
2
第一,如果最大回撤10%,持续1周,之后恢复而实际操作过程中,如果有一天回撤2%基本策略就停止了,不可能让他真正的运行一周.  
第二,回撤如果是行情风格转换造成的,那么更希望回撤是平缓回撤,持续时间长短我们并不关心,更希望避免的突然的回撤,慢慢的回撤当积累到一定程度自然会被其他策略给替代掉.

所以个人理解较好处理是RAR/最大回撤.

海龟交易法则12.6:稳健夏普比率

 定义:稳健夏普比率就是RAR除以年度化的月度回报标准差。这个指标对数据变化的敏感度较低,
 实际:使用日回报标准差代替月度回报标准差

其他信息

20日相关信息

1
2
3
4
5
'近20日的最大回撤'  
'近20日总收益%'
'近20日收益标准差%'
'近20日最大单日跌率%'
'近20日下跌天数'

 之前自己对CTA一直很好奇,原因之一是其回测曲线形态非常诱人,基本都是是单调上涨的,今天阅读了vnpy的源代码才弄明白,原来其回测曲线是基于交易次数,而非交易时间的,也就是说x轴表示次数。这样的的话就很好解释为何其形态表现好了。但这么评价也存在较大风险或漏洞。

问题1:忽视基础资产在这个区间表现

 大部分cta都是基于趋势的(或者通道突破)都差不多,这种行情下,策略表现优劣极大程度由行情本身决定的,比如,赶上一个小牛市,那么大部分标的的行情都是存在明显趋势的,cta表现就很好。策略表现很大程度取决于行情而非策略本身。换句话来说,即使一个差策略,总能找到一些标的在一些时间上回测结果较好(或者通过严苛的开仓条件进行优化,分钟线基础上即使开仓严苛也会有较多信号产生)。
 比较合理的做法是将策略的净值曲线和基础资产曲线都表示出来,如果基础资产上涨10%,考虑高杠杆因素,如果策略涨幅超过10%*10杠杆,那么认为极好的。如果低于10%*10杠杆,但是波动率非常低,也可以认为不错,如果低于10%*10,但波动率又很高,即使回测曲线笔笔挣钱,也很难说明策略优秀。
 举个例子,双均线在小时级别k线角度的回测上变现一般不大好,原因是开仓频率过低,比如长期60-120均线,一般大牛市都能捕捉到(结合止损策略,回撤也可以做小),但是由于开仓阈值太高,导致大部分行情都是空仓,最终效果可能比不过基准标的。但是如果用cta的交易次数衡量的化,其效益一样会比较诱人。这里意思并非cta的次数衡量不好,而是说其丢失了一部分信息,而这部分信息其实是比较重要的。就是收益从那种很那个行情形态中获取的。 采用时序-收益图,行情虽然不太完美,但可以较明显的看出特定行情对特定策略的收益关联性,实际对于我们跑实盘是有很大参考意义的。

问题2:按照交易终止的配对来判断交易盈亏

 (暂时不考虑其隐含了先进先出的交易配对规则,以及当日平仓操作的低手续费)(同样隐含了忽略时间价值的问题)。
每一笔交易都以exittrade作为结算点,

1
2
3
4
比如:(样例,价格是元)  
0101:买入3单位,价格3元
0103:卖出1单位,价格4元,
0107:卖出2单位,价格5元

那么对应tradelist-pair:

1
2
0101,0103,1单位,1元,总收益1*1=1:第一个1是2-1,个单位,第二个1是价格4-3,  
0101,0107,2单位,2元,总收益2*2=4:

那么反映到收益图上其实是

1
2
3
0103:1(盈利)  
0107:4(盈利)
总收益5

 虽然理论上也是对的,按照这个操作方式的确可以取得这个收益,但是这个可以作为评价策略的指标么?
不妨再补充下行情

1
2
3
4
5
6
7
0101:价格3,这里买3  
0102:价格8
0103:价格4,这里卖1
0104:价格7
0105:价格11
0106:价格7
0107:价格5,这里卖2

如图:

从交易次数角度,胜率100%,无亏损,非常不错的策略了
 但从图上可见,实际策略卖在局部最低价,卖点是极差的
 其优化潜力非常大,用交易次数-收益视图,却无法看出(还有一种理解,换用不同的配对策略,先进先出和后进先出等,总盈利不影响,盈亏比和收益曲线会受到影响)。
 这表明用传统的次数型评价是有缺陷的。
 如果用时间-资产角度的评估,则问题1和2都可以解决。对于1,可以观察到何种行情就会给策略带来较好表现,对于2也可以看出策略潜力。

`

对vnpy原始的策略评估方法做了调整,去掉部分不重要虽重要但从图中可以看出的冗余信息(比如最大回撤),没必要专用一图绘制表达.
策略:vnpy的样例策略strategyAtrRsi
回测信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
2019-04-07 20:17:45.237743	开始载入数据
2019-04-07 20:17:45.298343 载入完成,数据量:132026
2019-04-07 20:17:45.298398 开始回测
2019-04-07 20:17:45.380278 策略初始化完成
2019-04-07 20:17:45.380334 策略启动完成
2019-04-07 20:17:45.380345 开始回放数据
2019-04-07 20:18:01.712193 数据回放结束
2019-04-07 20:18:01.712272 计算回测结果
2019-04-07 20:18:01.810235 ------------------------------
2019-04-07 20:18:01.810293 第一笔交易: 2014-01-13 10:30:00
2019-04-07 20:18:01.810320 最后一笔交易: 2015-12-31 15:15:00
2019-04-07 20:18:01.810373 总交易次数: 2,103.0
2019-04-07 20:18:01.810397 总盈亏: 845,985.78
2019-04-07 20:18:01.810418 最大回撤: -164,071.12
2019-04-07 20:18:01.810438 平均每笔盈利: 402.28
2019-04-07 20:18:01.810456 平均每笔滑点: 120.0
2019-04-07 20:18:01.810475 平均每笔佣金: 65.11
2019-04-07 20:18:01.810493 胜率 37.9%
2019-04-07 20:18:01.810512 盈利交易平均值 9,815.46
2019-04-07 20:18:01.810531 亏损交易平均值 -5,342.22
2019-04-07 20:18:01.810549 盈亏比: 1.84
2019-04-07 20:18:07.159576 计算按日统计结果
2019-04-07 20:18:07.932968 ------------------------------
2019-04-07 20:18:07.933012 首个交易日: 2014-01-13
2019-04-07 20:18:07.933033 最后交易日: 2015-12-31
2019-04-07 20:18:07.933048 总交易日: 482
2019-04-07 20:18:07.933063 盈利交易日 247
2019-04-07 20:18:07.933076 亏损交易日: 235
2019-04-07 20:18:07.933090 起始资金: 1000000
2019-04-07 20:18:07.933114 结束资金: 1,846,078.7
2019-04-07 20:18:07.933133 总收益率: 84.61%
2019-04-07 20:18:07.933151 年化收益: 32.7%
2019-04-07 20:18:07.933169 总盈亏: 846,078.7
2019-04-07 20:18:07.933187 最大回撤: -142,187.16
2019-04-07 20:18:07.933205 百分比最大回撤: -8.62%
2019-04-07 20:18:07.933223 总手续费: 136,901.3
2019-04-07 20:18:07.933240 总滑点: 252,300.0
2019-04-07 20:18:07.933258 总成交金额: 4,563,376,620.0
2019-04-07 20:18:07.933276 总成交笔数: 4,205.0
2019-04-07 20:18:07.933294 日均盈亏: 1,755.35
2019-04-07 20:18:07.933311 日均手续费: 284.03
2019-04-07 20:18:07.933328 日均滑点: 523.44
2019-04-07 20:18:07.933346 日均成交金额: 9,467,586.35
2019-04-07 20:18:07.933363 日均成交笔数: 8.72
2019-04-07 20:18:07.933381 日均收益率: 0.14%
2019-04-07 20:18:07.933398 收益标准差: 1.34%
2019-04-07 20:18:07.933415 Sharpe Ratio: 1.57
2019-04-07 20:18:09.036527 ------------------------------
2019-04-07 20:18:09.036648 首个交易bar: 2014-01-13 09:16:00
2019-04-07 20:18:09.036726 最后交易bar: 2015-12-31 15:15:00
2019-04-07 20:18:09.036746 总交易bar: 130136
2019-04-07 20:18:09.036781 盈利交易bar 55358
2019-04-07 20:18:09.036817 亏损交易bar: 56905
2019-04-07 20:18:09.036851 bar均盈亏: 6.5
2019-04-07 20:18:09.036872 bar均手续费: 1.05
2019-04-07 20:18:09.036891 bar均滑点: 1.94
2019-04-07 20:18:09.036910 bar均成交金额: 35,066.21
2019-04-07 20:18:09.036928 bar均成交笔数: 0.03
2019-04-07 20:18:09.036948 bar均收益率: 0.0%
2019-04-07 20:18:09.036966 收益标准差: 0.08%

回测的结果可视化

说明:
 图1:vnpy原始收益图,基于交易次数的,x轴是时间轴。无法和标的直接比对,因为交易次数在时间上是非均匀的,所以头部水平线看起来很短,实际却对应了很长的时间,不过由于区间震荡时,产生交易信号少,所以看起来被压缩了(x轴代表次数,所以被压缩了)
 图2:原始标的的价格信息,用于和策略收益比对,可观察策略对行情的偏好(哪种行情下表现较好)(x轴代表时间)
 图3:时间角度的资产收益,相对交易次数更合理一些,和标的行情直接比对,看出策略真实表现(x轴代表时间)
 图4:交易频率图,图1和图2-3的x轴不同,虽都是时间但图1基于交易次数的,比如图1的左侧靠下部的行情很短,但是图2-3就比较长,如何解释?就是通过图4,图示可以看到到12月10日前,交易频率比较低,所以如果从交易次数视角,这一段时间会被压缩07月20日附件,频率非常高,说明这段时间放到交易次数图上会被拉长。
 通过这4张图,这样既可以得到交易次数的策略评估,也可以得到策略对特定行情之间的偏好关系

模板TargetPosTemplate的cancelAll()隐患

 在阅读vnpy的样例代码可以发现,其主要逻辑都是在onbar(or ontick)中实现,这个和大部分基于股票回测的类似zipline等基本类似。但稍有差异的是onbar中首先会清空之前订单,也即是调用self.cancelAll()方法。
但是,在使用模板TargetPosTemplate时,系统提供样例MultiSignalStrategy却没做相同处理,看了下其实是在

1
2
3
4
calculateTargetPos()
self.setTargetPos(targetPos)
self.trade()
self.cancelAll()

 但这么做其实有风险的,大部分时候如果仓位没变化不会调用这个方法的。但对于止损单来说,若采用随止损时却需要实时以最高价百分比下止损单,所以需要每个bar都调用cancelAll()进行旧止损订单清理。

数据初始化的几个小坑

self.am = ArrayManager(size=100)
 在系统样例中,可能会忽略,采用的都是默认值100,但如果回测时间需要很长的化就需要修改这个取值。
这个值会影响那些地方呢?
在样例策略中,有这么个共同点

1
2
3
onbar():
if not am.inited:
return

这里的am.inited就是指am中填充的数据是否足够,而足够就是由size=100来定义的。在初始化的数据填充足够后inited会变为True。

 另外一个需要注意的地方是:
initData = self.loadBar(self.initDays)
这里的self.initDays是天数,在bar为分钟等时,需要留意下,除240后填充到这里,避免初始化过多数据。

 还有就是在BacktestingEngine

1
2
3
self.strategy.inited = True
self.output(u'策略初始化完成')
self.strategy.trading = True

当am.inited被设置为True之后,如果self.strategy.trading=True会正常下单,否则虽然onbar执行逻辑正常,但是订单却不会被撮合。
 理想的情况是我们需要240个分钟bar,则size=240,然后数据出事成功后,恰好am.inited=True,and ,trading = True但是实际可能不会那么凑巧。
 建议回测时将initday设置偏小,比如需要360分钟bar,initday取(360/240)=1.5->1,然后初始结束后am.inited=False,回测引擎会继续执行后续的onbar填充am,直到am达到360才会执行onbar的后续业务相关逻辑。
 这么做虽然会跳过一段时间,但是整体业务是顺的,不会出现应该下单的却找不到下单到哪里的诡异问题。
纠正错误
 上面思路没错,但会引起另一个问题,实盘时如果按照上面的思路回导致时间段跳过的问题,比如设定需要300个bar,那么由于initday设置的是1天,1天只有240个分钟bar,导致新的一天,60个bar用来积累数据了。
 所以可能还是按照超额设定initday合理一些,避免实盘错过时间段。

撮合规则

撮合普通限价单推送2条信息

1
2
self.strategy.onTrade(trade)
self.strategy.onOrder(order)

撮合止损单推送3条信息

1
2
3
self.strategy.onStopOrder(so)
self.strategy.onOrder(order)
self.strategy.onTrade(trade)

 如果需要在止损单触发时执行一段逻辑,最好在onStopOrder里面做修改,并且留意以订单的状态(所有止损单都会通知这里,包括新增订单,撤销订单和订单成交等)

停止单的orderid

并且对于停止单而言,下单成功后返回的

1
order_ids = self.cover(xxx,True)

这里的order_ids是list,里面每个元素大概长这样“CtaStopOrder.26”,以CtaStopOrder开头的。而非常规数字id
在回调函数中onStopOrder的so入参对应onStopOrder.stopOrderID变量

行情的时间为bar开始时间(vnpy19)

比如9.00-9.01的行情时间戳为9.00的,
这个不同平台规则不同,有些会算到9.01上,在数据导入时需要留意,保持一致
如果不一致会有什么问题?
vnpy19在组合bar为am时(barCircle),会采用(分钟+1)%barCircle的整除判断,所以收到14.59(此时时间时间为9.00的第一个tick(或夜盘的第一个tick))的bar时就会凑整,推送新am,进而产生信号.
所以如果导入的数据以15.00结尾,由于尚且处于回放阶段(ontrade=false)所以,虽然触发了发单操作(有信号的化)但被trading状态阻止,所以无法发出,只有在9.30时才追触发新发单操作.

上海能源所(INE)平今问题

上海期货所一般都知道,平今和平昨需要指令区分,其实能源所INE一样的,vnpy20并未考虑到.需要手工修改,修改点并不多,
搜索Exchange.SHFE,if xx==Exchange.SHFE.
改为Exchange.SHFE,if xx in [Exchange.SHFE.Exchange.INE]

其他异常or报错

1,UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 0: ordinal not in range(128)

1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf-8')