协议接口

  • FutuOpenD是futu-api项目的网关客户端,在本机或云端成功运行后,第三方应用即可通过约定的TCP协议与之通讯,从而达到调用指定行情和交易接口的目的。
  • py-futu-api 可以简化在python编程上协议通讯的复杂度,其他语言接口正在陆续开发中……

特点

  • 基于TCP传输协议实现,稳定高效。
  • 支持protobuf/json两种协议格式, 灵活接入。
  • 协议设计支持加密、数据校验及回放功击保护,安全可靠。

协议清单

协议ID Protobuf文件 说明
1001 InitConnect.proto 初始化连接
1002 GetGlobalState.proto 获取全局状态
1003 Notify.proto 系统通知推送
1004 KeepAlive.proto 保活心跳
2001 Trd_GetAccList.proto 获取业务账户列表
2005 Trd_UnlockTrade.proto 解锁或锁定交易
2008 Trd_SubAccPush.proto 订阅业务账户的交易推送数据
2101 Trd_GetFunds.proto 获取账户资金
2102 Trd_GetPositionList.proto 获取账户持仓
2111 Trd_GetMaxTrdQtys.proto 获取最大交易数量
2201 Trd_GetOrderList.proto 获取订单列表
2202 Trd_PlaceOrder.proto 下单
2205 Trd_ModifyOrder.proto 修改订单
2208 Trd_UpdateOrder.proto 推送订单状态变动通知
2211 Trd_GetOrderFillList.proto 获取成交列表
2218 Trd_UpdateOrderFill.proto 推送成交通知
2221 Trd_GetHistoryOrderList.proto 获取历史订单列表
2222 Trd_GetHistoryOrderFillList.proto 获取历史成交列表
3001 Qot_Sub.proto 订阅或者反订阅
3002 Qot_RegQotPush.proto 注册推送
3003 Qot_GetSubInfo.proto 获取订阅信息
3004 Qot_GetBasicQot.proto 获取股票基本报价
3005 Qot_UpdateBasicQot.proto 推送股票基本报价
3006 Qot_GetKL.proto 获取K线
3007 Qot_UpdateKL.proto 推送K线
3008 Qot_GetRT.proto 获取分时
3009 Qot_UpdateRT.proto 推送分时
3010 Qot_GetTicker.proto 获取逐笔
3011 Qot_UpdateTicker.proto 推送逐笔
3012 Qot_GetOrderBook.proto 获取买卖盘
3013 Qot_UpdateOrderBook.proto 推送买卖盘
3014 Qot_GetBroker.proto 获取经纪队列
3015 Qot_UpdateBroker.proto 推送经纪队列
3100 Qot_GetHistoryKL.proto 从本地下载历史数据获取单只股票一段历史K线
3101 Qot_GetHistoryKLPoints.proto 从本地下载历史数据获取多只股票多点历史K线
3102 Qot_GetRehab.proto 从本地下载历史数据获取复权信息
3103 Qot_RequestHistoryKL.proto 在线获取单只股票一段历史K线
3105 Qot_RequestRehab.proto 在线获取单只股票复权信息
3200 Qot_GetTradeDate.proto 获取市场交易日
3202 Qot_GetStaticInfo.proto 获取股票静态信息
3203 Qot_GetSecuritySnapshot.proto 获取股票快照
3204 Qot_GetPlateSet.proto 获取板块集合下的板块
3205 Qot_GetPlateSecurity.proto 获取板块下的股票
3206 Qot_GetReference.proto 获取正股相关股票
3207 Qot_GetOwnerPlate.proto 获取股票所属板块
3208 Qot_GetHoldingChangeList.proto 获取持股变化列表
3209 Qot_GetOptionChain.proto 获取期权链
3210 Qot_GetWarrant.proto 获取涡轮
3211 Qot_GetCapitalFlow.proto 获取资金流向
3212 Qot_GetCapitalDistribution.proto 获取资金分布
3213 Qot_GetUserSecurity.proto 获取自选股分组下的股票
3214 Qot_ModifyUserSecurity.proto 修改自选股分组下的股票
3215 Qot_StockFilter.proto 获取条件选股

Note

  • 所有 Protobuf 文件可从 futu-api Python开源项目下获取

协议请求限制

API用户等级

部分协议的请求限制与API用户等级相关,划分如下:
  • 用户净资产大于10000港币为二级用户
  • 小于10000港币为三级用户
  • 一级用户提供给有一定交易额的实盘交易用户,可与富途联系获取

解锁或锁定交易

  • 协议ID: 2005
  • 30 秒内请求次数最多 10

获取最大交易数量

  • 协议ID: 2111
  • 30 秒内请求次数最多 10

下单

  • 请求协议ID: 2202
  • 30 秒内请求最多 15 次,同时 1 秒内最多 5

修改订单

  • 请求协议ID: 2205
  • 30 秒内请求最多 20 次,同时 1 秒内最多 5

获取历史订单列表

  • 请求协议ID: 2221
  • 30 秒内请求最多 10

获取历史成交列表

  • 请求协议ID: 2222
  • 30 秒内请求最多 10

订阅反订阅

  • 请求协议ID: 3001
  • 支持多种实时数据类型的定阅,参见 SubType , 每支股票订阅一个类型占用一个额度。
  • 订阅额度上限与用户等级相关,一级: 1000, 二级: 300 , 三级: 100
  • 至少订阅一分钟才可以反订阅。

获取K线

  • 请求协议ID: 3006
  • 最多能获取最近 1000
  • 市盈率,换手率字段只有日K及日K以上周期的正股才有数据。

获取逐笔

  • 请求协议ID: 3010
  • 最多能获取最近 1000

在线获取单只股票一段历史K线

  • 请求协议ID: 3103
  • 30天内在线获取历史K线最多可请求股票数与用户等级相关,一级: 1000 , 二级: 300 , 三级: 100
  • 30 秒内请求最多 10 次,可分页的请求,第1页限频,后续页请求不限频
  • 分K提供最近2年数据,日K及以上提供近10年数据。

在线获取单只股票复权信息

  • 请求协议ID: 3105
  • 30 秒内请求最多 10

获取股票快照

  • 请求协议ID: 3203
  • 每次最多可请求股票数与用户等级相关, 一级: 400 , 二级: 300 , 三级: 200
  • 30秒内快照最多请求次数与用户等级相关,一级: 30 , 二级: 20 , 三级: 10

获取板块集合下的板块

  • 请求协议ID: 3204
  • 30 秒内请求最多 10

获取板块下的股票

  • 请求协议ID: 3205
  • 30 秒内请求最多 10

获取板块下的股票

  • 请求协议ID: 3205
  • 30 秒内请求最多 10

获取股票所属板块

  • 请求协议ID: 3207
  • 30 秒内请求最多 10
  • 传入股票最多 200
  • 仅支持正股和指数

获取持股变化列表

  • 请求协议ID: 3208
  • 30 秒内请求最多 10
  • 最多返回前 100 大股东的变化
  • 仅支持美股

获取期权链

  • 请求协议ID: 3209
  • 30 秒内请求最多 10
  • 传入时间跨度最多 30

获取涡轮

  • 请求协议ID: 3210
  • 30 秒内请求最多 10
  • 每次请求的数据个数最多 200
  • 仅支持港股

获取资金流向

  • 请求协议ID: 3211
  • 30 秒内请求最多 10
  • 仅支持正股、涡轮和基金

获取资金分布

  • 请求协议ID: 3212
  • 30 秒内请求最多 10
  • 仅支持正股、涡轮和基金

获取自选股分组下的股票

  • 请求协议ID: 3213
  • 30 秒内请求最多 10
  • 仅支持自定义分组

修改自选股分组下的股票

  • 请求协议ID: 3214
  • 30 秒内请求最多 10
  • 仅支持自定义分组
  • 自选股的上限,一般最多是 500 支股票。
  • 如果有同名的分组,会返回排序第一个分组的信息。
  • 用户分组的删除操作,只做本组的移除操作,系统分组的“全部”分组下股票的数量并不会减少。

获取条件选股

  • 请求协议ID: 3215
  • 30 秒内请求最多 10
  • 每次请求的数据个数最多 200

获取账户资金

  • 请求协议ID: 2101_
  • 30 秒内请求最多 10
  • 仅当refreshCache为True时限制频率

获取账户持仓

  • 请求协议ID: 2102_
  • 30 秒内请求最多 10
  • 仅当refreshCache为True时限制频率

获取成交列表

  • 请求协议ID: 2211_
  • 30 秒内请求最多 10
  • 仅当refreshCache为True时限制频率

获取账户持仓

  • 请求协议ID: 2102_
  • 30 秒内请求最多 10
  • 仅当refreshCache为True时限制频率

协议请求流程

  • 建立连接
  • 初始化连接
  • 请求数据或接收推送数据
  • 定时发送 KeepAlive 保持连接
../_images/proto.png

协议设计

协议数据包括协议头以及协议体,协议头固定字段,协议体根据具体协议决定。

协议头结构

struct APIProtoHeader
{
    u8_t szHeaderFlag[2];
    u32_t nProtoID;
    u8_t nProtoFmtType;
    u8_t nProtoVer;
    u32_t nSerialNo;
    u32_t nBodyLen;
    u8_t arrBodySHA1[20];
    u8_t arrReserved[8];
};
字段 说明
szHeaderFlag 包头起始标志,固定为“FT”
nProtoID 协议ID
nProtoFmtType 协议格式类型,0为Protobuf格式,1为Json格式
nProtoVer 协议版本,用于迭代兼容, 目前填0
nSerialNo 包序列号,用于对应请求包和回包, 要求递增
nBodyLen 包体长度
arrBodySHA1 包体原始数据(解密后)的SHA1哈希值
arrReserved 保留8字节扩展

Note

  • u8_t表示8位无符号整数,u32_t表示32位无符号整数
  • FutuOpenD内部处理使用Protobuf,因此协议格式建议使用Protobuf,减少Json转换开销
  • nProtoFmtType字段指定了包体的数据类型,回包会回对应类型的数据;推送协议数据类型由FutuOpenD配置文件指定
  • arrBodySHA1用于校验请求数据在网络传输前后的一致性,必须正确填入
  • 协议头的二进制流使用的是小端字节序,即一般不需要使用ntohl等相关函数转换数据

协议体结构

Protobuf协议请求包体结构

message C2S
{
    required int64 req = 1;
}

message Request
{
    required C2S c2s = 1;
}

Protobuf协议回应包体结构

message S2C
{
    required int64 data = 1;
}

message Response
{
    required int32 retType = 1 [default = -400]; //RetType,返回结果
    optional string retMsg = 2;
    optional int32 errCode = 3;
    optional S2C s2c = 4;
}

Json协议请求包体结构

{
    "c2s":
    {
         "req": 0
    }
}

Json协议回应包体结构

{
    "retType" : 0
    "retMsg" : ""
    "errCode" : 0
    "s2c":
    {
        "data": 0
    }
}

字段 说明
c2s 请求参数结构
req 请求参数,实际根据协议定义
retType 请求结果
retMsg 若请求失败,说明失败原因
errCode 若请求失败对应错误码
s2c 回应数据结构,部分协议不返回数据则无该字段
data 回应数据,实际根据协议定义

Note

  • 包体格式类型请求包由协议头 nProtoFmtType 指定, FutuOPenD主动推送格式参见 FutuOpenD配置 约定的 “push_proto_type“ 配置项
  • 原始协议文件格式是以Protobuf格式定义,若需要json格式传输,建议使用protobuf3的接口直接转换成json
  • 枚举值字段定义使用有符号整形,注释指明对应枚举,枚举一般定义于Common.proto,Qot_Common.proto,Trd_Common.proto文件中
  • 协议中价格、百分比等数据用浮点类型来传输,直接使用会有精度问题,需要根据精度(如协议中未指明,默认小数点后三位)做四舍五入之后再使用

加密通信流程

  • 若FutuOpenD配置了加密, InitConnect 初始化连接协议必须使用RSA公钥加密,后续其他协议使用 InitConnect 返回的随机密钥进行AES加密通信。
  • FutuOpenD的加密流程借鉴了SSL协议,但考虑到一般是本地部署服务和应用,简化了相关流程,FutuOpenD与接入Client共用了同一个RSA 私钥文件,请妥善保存和分发私钥文件。
  • 可到”http://web.chacuo.net/netrsakeypair“这个网址在线生成随机RSA密钥对,密钥格式必须为PCKS#1,密钥长度512,1024都可以,不要设置密码,将生成的私钥复制保存到文件中,然后将私钥文件路径配置到 FutuOpenD配置 约定的 “rsa_private_key”配置项中
  • 强烈建议有实盘交易的用户配置加密,避免账户和交易信息泄露
../_images/encrypt.png

RSA加解密

  • FutuOpenD配置 约定”rsa_private_key”为私钥文件路径
  • FutuOpenD 与接入客户端共用相同的私钥文件
  • RSA加解密仅用于 InitConnect 请求,用于安全获取其它请求协议的对称加密Key
  • FutuOpenD的RSA密钥为1024位, 填充方式PKCS1, 公钥加密,私钥解密,公钥可通过私钥生成
  • Python API 参考实现: RsaCrypt 类的encrypt / decrypt 接口

发送数据加密

  • RSA加密规则:若密钥位数是key_size, 单次加密串的最大长度为 (key_size)/8 - 11, 目前位数1024, 一次加密长度可定为100
  • 将明文数据分成一个或数个最长100字节的小段进行加密,拼接分段加密数据即为最终的Body加密数据

接收数据解密

  • RSA解密同样遵循分段规则,对于1024位密钥, 每小段待解密数据长度为128字节
  • 将密文数据分成一个或数个128字节长的小段进行解密,拼接分段解密数据即为最终的Body解密数据

AES加解密

  • 加密key由 InitConnect 协议返回
  • 使用的是AES的ecb加密模式。
  • Python API 参考实现: FutuConnMng 类的encrypt_conn_data / decrypt_conn_data 接口

发送数据加密

  • AES加密要求源数据长度必须是16的整数倍, 故需补‘0’对齐后再加密,记录mod_len为源数据长度与16取模值
  • 因加密前有可能对源数据作修改, 故需在加密后的数据尾再增加一个16字节的填充数据块,其最后一个字节赋值mod_len, 其余字节赋值‘0’, 将加密数据和额外的填充数据块拼接作为最终要发送协议的body数据

接收数据解密

  • 协议body数据, 先将最后一个字节取出,记为mod_len, 然后将body截掉尾部16字节填充数据块后再解密(与加密填充额外数据块逻辑对应)
  • mod_len 为0时,上述解密后的数据即为协议返回的body数据, 否则需截掉尾部(16 - mod_len)长度的用于填充对齐的数据
../_images/AES.png