如何获取Level2实时行情和交易报单接口及历史数据回测?

摘要:相同的二级市场,相同的市场数据,为什么自己的账户总是亏的。真正拉开差距的,往往是信息的获取速度和执行效率。 你还在手动盯盘、手动下单的时候,别人已经用程序化交易在毫秒间完成了买卖。 可能他们有更好的策略、更多的资金,或者更丰富的经验。但说实
相同的二级市场,相同的市场数据,为什么自己的账户总是亏的。真正拉开差距的,往往是信息的获取速度和执行效率。 你还在手动盯盘、手动下单的时候,别人已经用程序化交易在毫秒间完成了买卖。 可能他们有更好的策略、更多的资金,或者更丰富的经验。但说实话,这些都不是最核心的原因。 普通投资者接入了实时行情和交易接口,也能搭建自己的量化交易系统。 实时行情接入:为什么Level2行情是量化交易的“刚需”? 很多量化新手一开始都会去抓取基础行情数据,比如Akshare或者一些券商的普通行情接口。但很快就会发现,这些数据远远不够,并发抓取更是灾难。 而且Level2行情根本抓不到,对于高频交易和策略优化来说,Level2行情是必需的数据源。 之前也抓过不少行情源,刷新间隔太大,基本都在3~6s,再刷新拉板都封死了。 Wind 恒生等服务商只对机构合作。只有搞到Level2高速行情,才算是拉平了数据源的差距。用WebSocket接口非常稳定,延迟低,数据全,接入也很简单,没有那么复杂的协议编码。下面是找的一个C++示例,通过WebSocket来接入Level2行情: #include <websocketpp/config/asio_no_tls_client.hpp> #include <websocketpp/client.hpp> #include <string> #include <iostream> #include <memory> #include <assert.h> #include <cstring> #include "zlib.h" #define CHUNK 16384 using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; using websocketpp::lib::bind; typedef websocketpp::client <websocketpp::config::asio_client> client; typedef websocketpp::config::asio_client::message_type::ptr message_ptr; int DecompressString(const char *in_str, size_t in_len, std::string &out_str); /** * 接收处理 */ void on_message(client *c, websocketpp::connection_hdl hdl, message_ptr msg) { //文本消息 if (msg->get_opcode()==websocketpp::frame::opcode::text){ std::cout <<"Text响应:"<<msg->get_payload().c_str()<< std::endl; } //二进制消息 if (msg->get_opcode()==websocketpp::frame::opcode::binary){ std::string tmp = ""; std::string &out_decompress = tmp; DecompressString( msg->get_payload().c_str(), msg->get_payload().size(), out_decompress); std::cout <<"Binary响应:"<<out_decompress<< std::endl; } } /** * 连接处理 */ void on_open(client *c, websocketpp::connection_hdl hdl) { //发送订阅指令 c->send(hdl, "add=lv1_600519,lv2_600519", websocketpp::frame::opcode::text); std::cout << "连接成功" << std::endl; } int main(int argc, char *argv[]) { //服务地址。 注意:C++版本的地址 问号前需加斜杠 std::string wsUrl = "ws://<服务器地址>/?token=<jvQuant token>"; client c; //连接相关 try { //debug日志开关 // c.set_access_channels(websocketpp::log::alevel::all); c.clear_access_channels(websocketpp::log::alevel::all); c.init_asio(); // 注册处理函数 c.set_message_handler(bind(&on_message, &c, ::_1, ::_2)); c.set_open_handler(bind(&on_open, &c, _1)); websocketpp::lib::error_code ec; client::connection_ptr con = c.get_connection(wsUrl, ec); if (ec) { std::cout << "连接失败: " << ec.message() << std::endl; return 0; } c.connect(con); c.run(); } catch (websocketpp::exception const &e) { std::cout << e.what() << std::endl; } } /** *解压缩方法 */ int DecompressString(const char *in_str, size_t in_len, std::string &out_str) { if (!in_str) return Z_DATA_ERROR; int ret; unsigned have; z_stream strm; unsigned char out[CHUNK]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) return ret; std::shared_ptr <z_stream> sp_strm(&strm, [](z_stream *strm) { (void) inflateEnd(strm); }); const char *end = in_str + in_len; size_t pos_index = 0; size_t distance = 0; int flush = 0; do { distance = end - in_str; strm.avail_in = (distance >= CHUNK) ? CHUNK : distance; strm.next_in = (Bytef *) in_str; in_str += strm.avail_in; flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH; do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate(&strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR) break; switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; case Z_DATA_ERROR: case Z_MEM_ERROR: return ret; } have = CHUNK - strm.avail_out; out_str.append((const char *) out, have); } while (strm.avail_out == 0); } while (flush != Z_FINISH); return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; } copy下来运行就可以实时获取到Level2行情数据,包括买卖盘口、逐笔成交等细节信息。 Python版的Demo请参考:Python 示例 · 开发文档 交易接口:如何实现自动下单? 有了行情数据,接下来就是如何自动下单了。很多量化新手在这一步卡住,因为市面上的交易接口要么不稳定,要么接入复杂。我用的这家服务商提供的交易接口非常简单易用,支持港股、美股和A股的自动下单。 下面是一个简单的交易委托示例: # 交易委托示例 # 报单模版 http://<柜台地址>/<type>?&token=<token>&ticket=<交易凭证>&code=<证券代码>&name=<证券名称>&price=<委托价格>&volume=<委托数量> 简单的请求,就可以实现自动买入、卖出操作。接口返回的order_id用来跟踪订单状态。 如何快速查询历史数据和生成选股策略? 除了实时行情和交易接口,研究交易策略还需要大量的历史数据进行回测和分析。 K线级别的历史数据很好弄到,各大财经网站都有数据,更细粒度的历史行情就不好弄了。 有些券商提供分时回放功能,这家服务商也有类似功能,历史指数行情也有回放,可以用市场大盘来协同回测股票。 数据库服务还有了智能语义查询功能,类似于智能选股,比写筛选逻辑更简单,校验过,数据都很靠谱。 比如,你想查询沪深主板上非ST股票,且市盈率大于60的股票,用语义化语句这样写: 查询沪深主板上非ST股票,市盈率大于60 query=沪深主板,非ST,市盈率大于60 数据库还支持多条件组合查询、模糊查询等功能,非常适合需要复杂数据筛选的场景。官方的查询语句示例: 字段精确条件 查询沪深主板上非ST股票,要求市盈率、行业,并且昨日最高涨幅大于4%,前2日最低涨幅小于8%: 示例:query=沪深主板,非ST,市盈率,行业,昨日最高涨幅大于4,前2日最低涨幅小于8 字段模糊条件 查询包含“集合竞价抢筹”或“30日均线向上”等模糊条件的股票: 示例:query=集合竞价抢筹,30日均线向上,macd底背离 多个指定日期条件查询(历史数据支持最近3年) 查询在2015年9月13日跌停,且在2015年9月14日涨停的股票(示例中的日期应替换为实际查询的日期): 示例:query=2015-09-13跌停,2015-09-14涨停 多个条件组合查询 查询主板上市盈率大于60的股票,或者属于华为概念且市盈率小于50的股票: 示例:主板,市盈率大于60,或者(华为概念并且市盈率小于50)) 实时行情和交易接口以及数据库的更多细节可以参考 官方文档 其实,量化交易的核心在于信息的速度和执行的效率。手动盯盘、手动下单,已经比别人慢了很多。用程序接入实时行情、交易接口和金融数据库,大幅提升交易效率和策略稳定性,剩下的,你只需要研究和检验策略执行效果即可,其他的交给时间。