量化必備:Level2實(shí)時(shí)行情接口和交易報(bào)單接口,以及歷史數(shù)據(jù)回測
相同的二級(jí)市場,相同的市場數(shù)據(jù),為什么自己的賬戶總是虧的。真正拉開差距的,往往是信息的獲取速度和執(zhí)行效率。 你還在手動(dòng)盯盤、手動(dòng)下單的時(shí)候,別人已經(jīng)用程序化交易在毫秒間完成了買賣。
可能他們有更好的策略、更多的資金,或者更豐富的經(jīng)驗(yàn)。但說實(shí)話,這些都不是最核心的原因。
普通投資者接入了實(shí)時(shí)行情和交易接口,也能搭建自己的量化交易系統(tǒng)。
實(shí)時(shí)行情接入:為什么Level2行情是量化交易的“剛需”?
很多量化新手一開始都會(huì)去抓取基礎(chǔ)行情數(shù)據(jù),比如Akshare或者一些券商的普通行情接口。但很快就會(huì)發(fā)現(xiàn),這些數(shù)據(jù)遠(yuǎn)遠(yuǎn)不夠,并發(fā)抓取更是災(zāi)難。
而且Level2行情根本抓不到,對于高頻交易和策略優(yōu)化來說,Level2行情是必需的數(shù)據(jù)源。
之前也抓過不少行情源,刷新間隔太大,基本都在3~6s,再刷新拉板都封死了。
Wind 恒生等服務(wù)商只對機(jī)構(gòu)合作。只有搞到Level2高速行情,才算是拉平了數(shù)據(jù)源的差距。用WebSocket接口非常穩(wěn)定,延遲低,數(shù)據(jù)全,接入也很簡單,沒有那么復(fù)雜的協(xié)議編碼。下面是找的一個(gè)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響應(yīng):"<<msg->get_payload().c_str()<< std::endl;
}
//二進(jìn)制消息
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響應(yīng):"<<out_decompress<< std::endl;
}
}
/**
* 連接處理
*/
void on_open(client *c, websocketpp::connection_hdl hdl) {
//發(fā)送訂閱指令
c->send(hdl, "add=lv1_600519,lv2_600519", websocketpp::frame::opcode::text);
std::cout << "連接成功" << std::endl;
}
int main(int argc, char *argv[]) {
//服務(wù)地址。 注意:C++版本的地址 問號(hào)前需加斜杠
std::string wsUrl = "ws://<服務(wù)器地址>/?token=<jvQuant token>";
client c;
//連接相關(guān)
try {
//debug日志開關(guān)
// c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::all);
c.init_asio();
// 注冊處理函數(shù)
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下來運(yùn)行就可以實(shí)時(shí)獲取到Level2行情數(shù)據(jù),包括買賣盤口、逐筆成交等細(xì)節(jié)信息。
Python版的Demo請參考:Python 示例 · 開發(fā)文檔
交易接口:如何實(shí)現(xiàn)自動(dòng)下單?
有了行情數(shù)據(jù),接下來就是如何自動(dòng)下單了。很多量化新手在這一步卡住,因?yàn)槭忻嫔系慕灰捉涌谝床环€(wěn)定,要么接入復(fù)雜。我用的這家服務(wù)商提供的交易接口非常簡單易用,支持港股、美股和A股的自動(dòng)下單。
下面是一個(gè)簡單的交易委托示例:
# 交易委托示例
# 報(bào)單模版
http://<柜臺(tái)地址>/<type>?&token=<token>&ticket=<交易憑證>&code=<證券代碼>&name=<證券名稱>&price=<委托價(jià)格>&volume=<委托數(shù)量>
簡單的請求,就可以實(shí)現(xiàn)自動(dòng)買入、賣出操作。接口返回的order_id用來跟蹤訂單狀態(tài)。
如何快速查詢歷史數(shù)據(jù)和生成選股策略?
除了實(shí)時(shí)行情和交易接口,研究交易策略還需要大量的歷史數(shù)據(jù)進(jìn)行回測和分析。
K線級(jí)別的歷史數(shù)據(jù)很好弄到,各大財(cái)經(jīng)網(wǎng)站都有數(shù)據(jù),更細(xì)粒度的歷史行情就不好弄了。
有些券商提供分時(shí)回放功能,這家服務(wù)商也有類似功能,歷史指數(shù)行情也有回放,可以用市場大盤來協(xié)同回測股票。
數(shù)據(jù)庫服務(wù)還有了智能語義查詢功能,類似于智能選股,比寫篩選邏輯更簡單,校驗(yàn)過,數(shù)據(jù)都很靠譜。
比如,你想查詢滬深主板上非ST股票,且市盈率大于60的股票,用語義化語句這樣寫:
查詢滬深主板上非ST股票,市盈率大于60 query=滬深主板,非ST,市盈率大于60
數(shù)據(jù)庫還支持多條件組合查詢、模糊查詢等功能,非常適合需要復(fù)雜數(shù)據(jù)篩選的場景。官方的查詢語句示例:
字段精確條件
查詢滬深主板上非ST股票,要求市盈率、行業(yè),并且昨日最高漲幅大于4%,前2日最低漲幅小于8%:
示例:query=滬深主板,非ST,市盈率,行業(yè),昨日最高漲幅大于4,前2日最低漲幅小于8
字段模糊條件
查詢包含“集合競價(jià)搶籌”或“30日均線向上”等模糊條件的股票:
示例:query=集合競價(jià)搶籌,30日均線向上,macd底背離
多個(gè)指定日期條件查詢(歷史數(shù)據(jù)支持最近3年)
查詢在2015年9月13日跌停,且在2015年9月14日漲停的股票(示例中的日期應(yīng)替換為實(shí)際查詢的日期):
示例:query=2015-09-13跌停,2015-09-14漲停
多個(gè)條件組合查詢
查詢主板上市盈率大于60的股票,或者屬于華為概念且市盈率小于50的股票:
示例:主板,市盈率大于60,或者(華為概念并且市盈率小于50))
實(shí)時(shí)行情和交易接口以及數(shù)據(jù)庫的更多細(xì)節(jié)可以參考 官方文檔
其實(shí),量化交易的核心在于信息的速度和執(zhí)行的效率。手動(dòng)盯盤、手動(dòng)下單,已經(jīng)比別人慢了很多。用程序接入實(shí)時(shí)行情、交易接口和金融數(shù)據(jù)庫,大幅提升交易效率和策略穩(wěn)定性,剩下的,你只需要研究和檢驗(yàn)策略執(zhí)行效果即可,其他的交給時(shí)間。
原文鏈接:https://zhuanlan.zhihu.com/p/29605505797
————————————————
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
原文鏈接:https://blog.csdn.net/FuckTheWindows/article/details/146196431
浙公網(wǎng)安備 33010602011771號(hào)