websocket level2行情接口构建交易系统

累计阅读:77287


为什么要使用level2行情?

Level-2产品是由上海证券交易所推出的实时行情信息服务,提供在证券交易所上市交易的证券产品的实时交易数据。

相比level1基础行情3秒一次切片推送,level2为实时推送。经FPGA高速分发,每一笔成交延迟可控制在毫秒内。

为什么使用websocket协议推送行情信息?

为保证推送的实时性,任何交推送都不可能通过简单的http方式达成,必须依赖长链接的行全双工通信的协议。

WebSocket是一种在单个TCP连接上进行全双工通信的协议。相比普通tcp/udp协议,在保证消息实时性的前提下,websocket提供了更通用的封装。

在交易所交易成交流的场景下,相比http轮询的请求方式,websocket具有更高的吞吐量和更低的延迟。

在接入方式上,常用的编程语言如Python/Golang/PHP/NodeJs都集成有相应的websocket模块,C/C++/JAVA也有相应的代码包可用,可以极大的降低level2行情解析成本。

WEBSOCKET行情接入

行情在线测试 websocket行情接口

交易在线测试 在线交易接口

官方文档地址 行情交易接口用户文档

分配服务器

注意:每次分配的服务器地址会发生变化,连接服务前,请务必调用该接口获取最新的服务器地址。

获取服务器:

http://jvQuant.com/server?market=ab&type=websocket&token=<token>

Copy

接口参数:

#参数名类型描述
1marketstring市场标志,沪深为ab
2typestring接口类别,行情类别为websocket
3tokenstringjvQuant token

接口返回:

#参数名类型描述
1codestring请求状态码
2serverstring分配服务器地址及端口号

返回示例:

  1. {
  2. "code": "0",
  3. "server": "xx.xx.x.xx:xxxx/xxx"
  4. }

Copy

CODE规范

jvQuant支持沪深主板、科创板、创业板,股票以及可转债行情,提供level1和level2数据推送。

订阅代码由行情标志证券代码组成,用分隔符"_"连接。

如:

lv1_600519,代表贵州茅台level1行情

lv2_127063,代表贵轮转债level2行情

#行情标志类型描述
1lv1stringlevel1行情
2lv2stringlevel2行情

连接登录

使用分配的服务器地址,通过websokcet协议连接服务器。

websocket接口地址:

ws://xx.xx.x.xx:xxxx/xxx?token=<token>

Copy

订阅行情

创建websocket连接后,您可以输入以下指令进行行情订阅:

#指令参数描述
1addstring增加订阅code
2delstring删除订阅code
3allstring覆盖全部code
4liststring查看全部订阅code

指令后接code参数,用分隔符"="连接,多个code用分隔符","分隔。

例:

add=lv1_600519,lv2_127063 ,表示增加订阅lv1_600519,lv2_127063行情。

del=lv1_600519,lv2_127063 ,表示删除订阅lv1_600519,lv2_127063行情。

all=lv1_600519 ,表示覆盖全部订阅code。

all= ,后接参数为空,表示删除全部订阅code。

list ,无需参数,表示查看全部订阅code。

解析行情

为提高数据传输速率,行情推送采用二进制方式传输,请在接收端解压缩为字符串。

level1

level1行情推送数据以换行符"\n"为分隔,每一行以lv1_xxxxxx=为开头,代表该类别code对应的行情。

lv1每笔交易数据字段以","为分隔符,定义如下:

推送时间,证券名称,最新价格,涨幅,成交量,成交额,买五档[挂单数量,挂单价格],卖五档[挂单数量,挂单价格]

leve1推送数据包格式如下:

lv1_证券代码1=推送时间,证券名称,最新价格,涨幅,成交量,成交额,买五档[挂单数量,挂单价格],卖五档[挂单数量,挂单价格]... lv1_证券代码2=推送时间,证券名称,最新价格,涨幅,成交量,成交额,买五档[挂单数量,挂单价格],卖五档[挂单数量,挂单价格]...

level2

level2行情推送数据以换行符"\n"为分隔,每一行以lv2_xxxxxx=为开头,代表该类别code对应的行情。

同一时刻会存在多笔交易,以"|"为分隔符。

lv2每笔交易数据字段以","为分隔符,定义如下:

成交时间(毫秒),成交编号,成交价格,成交数量/(股)

推送数据包格式如下:

lv2_证券代码1=成交时间1,成交编号1,成交价格1,成交数量1|成交编号2,成交时间2,成交价格2,成交数量2... lv2_证券代码2=成交时间1,成交编号1,成交价格1,成交数量1|成交编号2,成交时间2,成交价格2,成交数量2...

在线测试

交易接入

jvQuant OpenAPI直达券商,提供多种登录及交易方式。

您只需输入对应券商的资金账号密码,即可调用jvQuant OpenAPI进行交易。

*个人账户仅支持东方财富登录,机构账户无限制。

分配服务器

为实现更好的用户体验,jvQuant会根据您所在的地区分配合适的服务器。

注意:每次分配的服务器地址会发生变化,连接服务前,请务必调用该接口获取最新的服务器地址。

分配服务器地址:

http://jvQuant.com/server?market=ab&type=trade&token=<token>

Copy

接口参数:

#参数名类型描述
1marketstring市场标志,沪深为ab
2typestring接口类别,交易类别为trade
3tokenstringjvQuant token

接口返回:

#参数名类型描述
1codestring请求状态码
2serverstring分配服务器地址及端口号

返回示例:

  1. {
  2. "code": "0",
  3. "server": "xx.xx.x.xx:xxxx"
  4. }

Copy

登录柜台

输入交易账户及密码,通过柜台验证后返回授权交易凭证ticket。

请妥善保管好交易凭证,在ticket有效期内,您可以免登录进行后续的交易操作。

接口地址:

http://xx.xx.x.xx:xxxx/login?&token=<token>&acc=<资金账号>&pass=<密码>

Copy

接口参数:

#参数名类型描述
1tokenstringjvQuant token
2accstring12位资金账号
3passstring资金交易密码

接口返回:

#参数名类型描述
1codestring请求状态码
2ticketstring登录凭证
2expireintticket有效时间(秒)

返回示例:

  1. {
  2. "code": "0",
  3. "ticket": "xxxx",
  4. "expire": xxx
  5. }

Copy

查询持仓信息

接口地址:

http://xx.xx.x.xx:xxxx/check_hold?&token=<token>&ticket=<交易凭证>

Copy

接口参数:

#参数名类型描述
1tokenstringjvQuant token
2ticketstring交易凭证ticket

接口返回:

#参数名类型描述
1messagestring错误信息
2totalstring账户总资产
2usablestring账户可用资金
3day_earnstring账户当日盈亏
4hold_earnstring账户持仓盈亏
5hold_listarray账户持仓明细
5.1hold_list[x].codestring账户持仓证券列表
5.2hold_list[x].namestring持仓证券名
5.3hold_list[x].hold_volstring持仓数量
5.4hold_list[x].hold_volstring持仓数量
5.5hold_list[x].usable_volstring可用数量
5.6hold_list[x].usable_volstring可用数量
5.7hold_list[x].day_earnstring当日盈亏
5.8hold_list[x].hold_earnstring持仓盈亏

返回示例:

  1. {
  2. "code": "0",
  3. "message": "",
  4. "total": "501527.77",
  5. "usable": "422977.27",
  6. "day_earn": "16325.27",
  7. "hold_earn": "18273.22",
  8. "hold_list": [
  9. {
  10. "code": "128079",
  11. "name": "英联转债",
  12. "hold_vol": "0",
  13. "usable_vol": "0",
  14. "hold_earn": "12242.69",
  15. "day_earn": "12242.32"
  16. },
  17. {
  18. "code": "111013",
  19. "name": "新港转债",
  20. "hold_vol": "0",
  21. "usable_vol": "0",
  22. "hold_earn": "-560.93",
  23. "day_earn": "-560.96"
  24. }
  25. ]
  26. }

Copy

查询交易信息

接口地址:

http://xx.xx.x.xx:xxxx/check_order?&token=<token>&ticket=<交易凭证>

Copy

接口参数:

#参数名类型描述
1tokenstringjvQuant token
2ticketstring交易凭证ticket

接口返回:

#参数名类型描述
1messagestring错误信息
2listarray交易明细列表
2.1list[x].order_idstring委托编号
2.2list[x].order_idday委托日期
2.3list[x].timestring委托时间
2.4list[x].codestring委托证券代码
2.5list[x].namestring委托证券名
2.6list[x].typestring委托类型
2.7list[x].statusstring委托状态
2.8list[x].order_pricestring委托价格
2.9list[x].order_volumestring委托数量
2.10list[x].deal_pricestring成交价格
2.11list[x].deal_volumestring成交数量

返回示例:

  1. {
  2. "code": "0",
  3. "message": "",
  4. "list": [
  5. {
  6. "order_id": "1334564",
  7. "day": "20180402",
  8. "time": "142423",
  9. "code": "110074",
  10. "name": "精达转债",
  11. "type": "证券卖出",
  12. "status": "已成",
  13. "order_price": "151.885",
  14. "order_volume": "8000",
  15. "deal_price": "151.927",
  16. "deal_volume": "8000"
  17. }
  18. ]
  19. }

Copy

委托报单

接口地址:

http://xx.xx.x.xx:xxxx/<trade>?&token=<token>&ticket=<交易凭证>&code=<证券代码>&name=<证券名称>&price=<委托价格>&volume=<委托数量>

Copy

接口参数:

#参数名类型描述
1tradestring买入(buy)或卖出(sale)
2tokenstringjvQuant token
3ticketstring交易凭证ticket
4codestring证券代码
5namestring证券名称
6pricefloat委托价格
7volumeint委托数量

接口返回:

#参数名类型描述
1messagestring错误信息
2order_idstring委托编号

返回示例:

  1. {
  2. "code": "0",
  3. "message": "",
  4. "order_id":"4362316"
  5. }

Copy

撤销报单

接口地址:

http://xx.xx.x.xx:xxxx/cancel?&token=<token>&ticket=<交易凭证>&order_id=<委托编号>

Copy

接口参数:

#参数名类型描述
1tokenstringjvQuant token
2ticketstring交易凭证ticket
3order_idstring委托编号

接口返回:

#参数名类型描述
1codestring返回状态码
2messagestring错误信息

返回示例:

  1. {
  2. "code": "0",
  3. "message": "",
  4. "order_id":"4362316"
  5. }

Copy

在线测试

历史行情

jvQuant提供2008创立至今的历史股票行情数据,包含沪深主板、科创板、创业板,股票日内行情。

下载地址

http://jvquant.com/query/history?&token=<token>&year=<数据年份>

Copy

股票数据查询

jvQuant提供包含沪深主板、科创板、创业板在内的申万二级行业分类信息查询,以及沪深可转债对应正股查询。

数据随交易所最新发布实时更新。可用作选股和大盘行情趋势跟踪依据。

行业分类查询

数据按申万发布的二级行业分类信息进行聚合,返回全部行业所属证券代码及名称。

可用于行业细分筛选。

接口地址:

http://jvquant.com/query/industry?&token=<token>

Copy

可转债正股查询

数据按交易所发布的可转债最新信息,返回全部可转债代码以及对应正股代码。

可用于可转债趋势预判。

接口地址:

http://jvquant.com/query/bond?&token=<token>

Copy

计费标准

行情

行情订阅采用按天计费方式,一个自然天内只计费一次。

行情报价如下:

#行情类别单价描述
1leve12分订阅level1行情 单价
2leve22毛订阅level2行情 单价

交易

交易API采用按量计费方式,个人账户单次报单最高限额100万,机构账户按合同规则计费。

交易接口报价如下:

#类别单价描述
1查询持仓信息2分查询持仓 单价
2查询交易信息2分查询交易 单价
3委托买入2毛买入报单 单价
4委托卖出2毛卖出报单 单价
5撤销委托2毛撤销委托 单价
6登录柜台5毛登录柜台 单价

历史数据

历史数据采用按次计费方式,按年份划分压缩包,下载一次数据包单价为20元

历史数据报价如下:

#年份单价描述
12008~至今20元/年每一年数据价格

股票信息

股票信息数据采用按次计费方式,一般日内调用一次,保存配置在本地查询即可。

股票信息数据报价如下:

#类别单价描述
1申万二级行业分类信息免费单次调用价格
2沪深可转债信息免费单次调用价格

积分明细

为保护您的隐私安全,jvQuant不会记录您的调用明细,只提供当日调用聚合统计。

请留意您的调用记录,避免产生对账偏差。

行情

行情账单出账期为5s,按行情类别进行聚合统计。

日内新增订阅code产生一次计费操作,请前往账户主页关注订阅统计。

交易

交易账单出账期为1min,按交易接口类别进行聚合统计。

新增API调用产生一次计费操作,请前往账户主页关注调用统计。

行情接入示例

PYTHON

  1. #!python3
  2. # -*- coding:utf-8 -*-
  3. import time
  4. import websocket
  5. import zlib
  6. # 发送订阅
  7. def on_open(ws):
  8. ws.send("all=lv2_600519,lv1_000001")
  9. # 接收推送
  10. def on_message(ws, message, type, flag):
  11. # 命令返回文本消息
  12. if type == websocket.ABNF.OPCODE_TEXT:
  13. print(time.strftime('%H:%M:%S', time.localtime(time.time())), "Text响应:", message)
  14. print(time.strftime('%H:%M:%S', time.localtime(time.time())), "Text响应:", message)
  15. # 行情推送压缩二进制消息,在此解压缩
  16. if type == websocket.ABNF.OPCODE_BINARY:
  17. rb = zlib.decompress(message, -zlib.MAX_WBITS)
  18. print(time.strftime('%H:%M:%S', time.localtime(time.time())), "Binary响应:", rb.decode("utf-8"))
  19. def on_error(ws, error):
  20. print(error)
  21. def on_close(ws, code, msg):
  22. print(time.strftime('%H:%M:%S', time.localtime(time.time())), "连接已断开")
  23. wsUrl = "ws://<服务器地址>?token=<jvQuant token>"
  24. ws = websocket.WebSocketApp(wsUrl,
  25. on_open=on_open,
  26. on_data=on_message,
  27. on_error=on_error,
  28. on_close=on_close)
  29. ws.run_forever()

Copy

GOLANG

  1. package main
  2. import (
  3. "bytes"
  4. "compress/flate"
  5. "github.com/gorilla/websocket"
  6. "log"
  7. "time"
  8. )
  9. func main() {
  10. //连接地址
  11. wsUrl := "ws://<服务器地址>?token=<jvQuant token>"
  12. conn, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)
  13. if err != nil {
  14. log.Fatalln("连接错误:", err)
  15. }
  16. //接收协程
  17. go func() {
  18. receive(conn)
  19. }()
  20. //发送订阅
  21. cmd := "all=lv2_600519,lv1_000001"
  22. err = conn.WriteMessage(websocket.TextMessage, []byte(cmd))
  23. if err != nil {
  24. log.Fatalln("发送指令错误:", err)
  25. }
  26. log.Println("发送指令成功,等待接收")
  27. for {
  28. time.Sleep(time.Second)
  29. }
  30. }
  31. func receive(conn *websocket.Conn) {
  32. for {
  33. //阻塞接收
  34. messageType, rb, err := conn.ReadMessage()
  35. if err != nil {
  36. log.Fatalln("接收错误:", err)
  37. return
  38. }
  39. //文本消息
  40. if messageType == websocket.TextMessage {
  41. log.Println("Text响应:", string(rb))
  42. }
  43. //二进制消息
  44. if messageType == websocket.BinaryMessage {
  45. unZipByte := DeCompress(rb)
  46. log.Println("Binary推送:", string(unZipByte))
  47. }
  48. }
  49. }
  50. //解压方法
  51. func DeCompress(b []byte) []byte {
  52. var buffer bytes.Buffer
  53. buffer.Write([]byte(b))
  54. reader := flate.NewReader(&buffer)
  55. var result bytes.Buffer
  56. result.ReadFrom(reader)
  57. reader.Close()
  58. return result.Bytes()
  59. }

Copy

PHP

  1. <?php
  2. //需安装swoole扩展
  3. use Swoole\Coroutine\Http\Client;
  4. use function Swoole\Coroutine\run;
  5. run(function () {
  6. //服务器地址
  7. $host = '<服务器地址>';
  8. //服务器端口
  9. $port = <服务器端口>;
  10. //连接
  11. $conn = new Client($host, $port);
  12. $conn->upgrade("/?token=<jvQuant token>");
  13. //发送订阅
  14. $conn->push("add=lv2_600519,lv1_000001");
  15. //开启接收协程
  16. go("receive", $conn);
  17. });
  18. function receive($client)
  19. {
  20. while (true) {
  21. $data = $client->recv();
  22. $time = date("H:i:s");
  23. //解压
  24. @$zipStr = gzinflate($data->data);
  25. if ($zipStr) {
  26. echo "{$time} Binary推送:{$zipStr}\n";
  27. } else {
  28. echo "{$time} Text响应:{$data->data}\n";
  29. }
  30. }
  31. }
近期文章: