| 参数 |
类型 |
说明 |
| notify_type |
[SysNotifyType](./common.md#5896) |
通知类型 |
| sub_type |
[ProgramStatusType](./common.md#6427) |
子类型。当 notify_type == SysNotifyType.PROGRAM_STATUS 时,sub_type 返回程序状态类型 |
| [GtwEventType](./common.md#7799) |
子类型。当 notify_type == SysNotifyType.GTW_EVENT 时,sub_type 返回 OpenD 事件通知类型 |
| 0 |
当 notify_type != SysNotifyType.PROGRAM_STATUS 且 notify_type != SysNotifyType.GTW_EVENT 时,sub_type 返回 0 |
| msg |
dict |
事件信息。当 notify_type == SysNotifyType.CONN_STATUS 时,msg 返回 连接状态事件信息 字典 |
| 事件信息。当 notify_type == SysNotifyType.QOT_RIGHT 时,msg 返回 行情权限事件信息 字典 |
* **连接状态事件信息** 字典结构如下(连接状态类型为 bool,True 表示连接正常,False 表示连接断开):
```protobuf
{
'qot_logined': bool1,
'trd_logined': bool2,
}
```
* **行情权限事件信息** 字典结构如下(点击了解 [行情权限](../quote/quote.md#2867)):
```protobuf
{
'hk_qot_right': value1,
'hk_option_qot_right': value2,
'hk_future_qot_right': value3,
'us_qot_right': value4,
'us_option_qot_right': value5,
'us_future_qot_right': value6, // 已废弃
'cn_qot_right': value7,
'us_index_qot_right': value8,
'us_otc_qot_right': value9,
'sg_future_qot_right': value10,
'jp_future_qot_right': value11,
'us_future_qot_right_cme': value12,
'us_future_qot_right_cbot': value13,
'us_future_qot_right_nymex': value14,
'us_future_qot_right_comex': value15,
'us_future_qot_right_cboe': value16,
}
```
* **Example**
```python
import time
from futu import *
class SysNotifyTest(SysNotifyHandlerBase):
def on_recv_rsp(self, rsp_str):
ret_code, data = super(SysNotifyTest, self).on_recv_rsp(rsp_str)
notify_type, sub_type, msg = data
if ret_code != RET_OK:
logger.debug("SysNotifyTest: error, msg: {}".format(msg))
return RET_ERROR, data
if notify_type == SysNotifyType.GTW_EVENT: # OpenD 事件通知
print("GTW_EVENT, type: {} msg: {}".format(sub_type, msg))
elif notify_type == SysNotifyType.PROGRAM_STATUS: # 程序状态变化通知
print("PROGRAM_STATUS, type: {} msg: {}".format(sub_type, msg))
elif notify_type == SysNotifyType.CONN_STATUS: ## 连接状态变化通知
print("CONN_STATUS, qot: {}".format(msg['qot_logined']))
print("CONN_STATUS, trd: {}".format(msg['trd_logined']))
elif notify_type == SysNotifyType.QOT_RIGHT: # 行情权限变化通知
print("QOT_RIGHT, hk: {}".format(msg['hk_qot_right']))
print("QOT_RIGHT, hk_option: {}".format(msg['hk_option_qot_right']))
print("QOT_RIGHT, hk_future: {}".format(msg['hk_future_qot_right']))
print("QOT_RIGHT, us: {}".format(msg['us_qot_right']))
print("QOT_RIGHT, us_option: {}".format(msg['us_option_qot_right']))
print("QOT_RIGHT, cn: {}".format(msg['cn_qot_right']))
print("QOT_RIGHT, us_index: {}".format(msg['us_index_qot_right']))
print("QOT_RIGHT, us_otc: {}".format(msg['us_otc_qot_right']))
print("QOT_RIGHT, sg_future: {}".format(msg['sg_future_qot_right']))
print("QOT_RIGHT, jp_future: {}".format(msg['jp_future_qot_right']))
print("QOT_RIGHT, us_future_cme: {}".format(msg['us_future_qot_right_cme']))
print("QOT_RIGHT, us_future_cbot: {}".format(msg['us_future_qot_right_cbot']))
print("QOT_RIGHT, us_future_nymex: {}".format(msg['us_future_qot_right_nymex']))
print("QOT_RIGHT, us_future_comex: {}".format(msg['us_future_qot_right_comex']))
print("QOT_RIGHT, us_future_cboe: {}".format(msg['us_future_qot_right_cboe']))
return RET_OK, data
quote_ctx = OpenQuoteContext(host='127.0.0.1', port=11111)
handler = SysNotifyTest()
quote_ctx.set_handler(handler) # 设置回调
time.sleep(15) # 设置脚本接收 OpenD 的推送持续时间为15秒
quote_ctx.close() # 结束后记得关闭当条连接,防止连接条数用尽`
```
---
---
# 通用定义
## 接口调用结果
> **RET_CODE**
* `RET_OK`
成功
* `RET_ERROR`
失败
## 协议格式
> **ProtoFMT**
* `Protobuf`
Google Protobuf 格式
* `Json`
Json 格式
## 包加密算法
## 程序状态类型
> **ProgramStatusType**
* `NONE`
未知
* `LOADED`
已完成必要模块加载
* `LOGING`
登录中
* `NEED_PIC_VERIFY_CODE`
需要图形验证码
* `NEED_PHONE_VERIFY_CODE`
需要手机验证码
* `LOGIN_FAILED`
登录失败
* `FORCE_UPDATE`
客户端版本过低
* `NESSARY_DATA_PREPARING`
正在拉取必要信息
* `NESSARY_DATA_MISSING`
缺少必要信息
* `UN_AGREE_DISCLAIMER`
未同意免责声明
* `READY`
正常可用状态
* `FORCE_LOGOUT`
OpenD 登录后被强制退出登录
## 网关事件通知类型
> **GtwEventType**
* `LocalCfgLoadFailed`
本地配置文件加载失败
* `APISvrRunFailed`
网关监听服务运行失败
* `ForceUpdate`
强制升级网关
* `LoginFailed`
登录富途服务器失败
* `UnAgreeDisclaimer`
未同意免责声明,无法运行
* `LOGIN_FAILED`
登录失败
* `NetCfgMissing`
缺少网络连接配置
* `KickedOut`
登录被踢下线
* `LoginPwdChanged`
登录密码变更
* `BanLogin`
牛牛后台不允许该账号登录
* `NeedPicVerifyCode`
登录需要输入图形验证码
* `NeedPhoneVerifyCode`
登录需要输入手机验证码
* `AppDataNotExist`
程序打包数据丢失
* `NessaryDataMissing`
必要的数据没同步成功
* `TradePwdChanged`
交易密码变更通知
* `EnableDeviceLock`
需启用设备锁
## 系统通知类型
> **SysNotifyType**
* `GTW_EVENT`
网关事件
* `PROGRAM_STATUS`
程序状态变化
* `CONN_STATUS`
与后台服务的连接状态变化
* `QOT_RIGHT`
行情权限变化
## 包唯一标识
**PacketID**
```protobuf
message PacketID
{
required uint64 connID = 1; //当前 TCP 连接的连接 ID,一条连接的唯一标识,InitConnect 协议会返回
required uint32 serialNo = 2; //自增序列号
}
```
## 程序状态
**ProgramStatus**
```protobuf
message ProgramStatus
{
required ProgramStatusType type = 1; //当前状态
optional string strExtDesc = 2; // 额外描述
}
```
---
---
# 底层协议介绍
Futu API 是富途为主流的编程语言(Python、Java、C#、C++、JavaScript)封装的 API SDK,以方便您调用,降低策略开发难度。
这部分主要介绍策略脚本与 OpenD 服务之间通信的底层协议,适用于非上述 5 种编程语言用户,自行对接实现底层裸协议。
:::tip 提示
* 如果您使用的编程语言在上述的 5 种主流编程语言之内,可以直接跳过这部分内容。
:::
## 协议请求流程
* 建立连接
* 初始化连接
* 请求数据或接收推送数据
* 定时发送 KeepAlive 保持连接

## 协议设计
协议数据包括协议头以及协议体,协议头固定字段,协议体根据具体协议决定。
### 协议头
```
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 字节扩展
::: tip 提示
* u8_t 表示 8 位无符号整数,u32_t 表示 32 位无符号整数
* OpenD 内部处理使用 Protobuf,因此协议格式建议使用 Protobuf,减少 Json 转换开销
* nProtoFmtType 字段指定了包体的数据类型,回包会回对应类型的数据;推送协议数据类型由 OpenD 配置文件指定
* **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;
}
```
字段|说明
:-|:-
c2s|请求参数结构
req|请求参数,实际根据协议定义
retType|请求结果
retMsg|若请求失败,说明失败原因
errCode|若请求失败对应错误码
s2c|回应数据结构,部分协议不返回数据则无该字段
data|回应数据,实际根据协议定义
::: tip 提示
* 包体格式类型请求包由协议头 nProtoFmtType 指定,OpenD 主动推送格式在 [InitConnect](../ftapi/init.md#1515) 设置。
* 原始协议文件格式是以 Protobuf 格式定义,若需要 json 格式传输,建议使用 protobuf3 的接口直接转换成 json。
* 枚举值字段定义使用有符号整形,注释指明对应枚举,枚举一般定义于 Common.proto,Qot_Common.proto,Trd_Common.proto 文件中。
* 协议中价格、百分比等数据用浮点类型来传输,直接使用会有精度问题,需要根据精度(如协议中未指明,默认小数点后三位)做四舍五入之后再使用。
:::
## 心跳保活
```protobuf
syntax = "proto2";
package KeepAlive;
option java_package = "com.futu.openapi.pb";
option go_package = "github.com/futuopen/ftapi4go/pb/keepalive";
import "Common.proto";
message C2S
{
required int64 time = 1; //客户端发包时的格林威治时间戳,单位秒
}
message S2C
{
required int64 time = 1; //服务器回包时的格林威治时间戳,单位秒
}
message Request
{
required C2S c2s = 1;
}
message Response
{
required int32 retType = 1 [default = -400]; //RetType,返回结果
optional string retMsg = 2;
optional int32 errCode = 3;
optional S2C s2c = 4;
}
```
* **介绍**
心跳保活
* **协议 ID**
1004
* **使用**
根据[初始化链接](./init.md#1990)返回的心跳保活间隔时间,向 OpenD 发送保活协议
## 加密通信流程
* 若 OpenD 配置了加密,[InitConnect](../ftapi/init.md#1515) 初始化连接协议必须使用 [RSA](../qa/other.md#4601) 公钥加密,后续其他协议使用 InitConnect 返回的随机密钥进行 AES 加密通信。
* OpenD 的加密流程借鉴了 SSL 协议,但考虑到一般是本地部署服务和应用,简化了相关流程,OpenD 与接入 Client 共用了同一个 [RSA](../qa/other.md#4601) 私钥文件,请妥善保存和分发私钥文件。
* 可到这个 [网址](http://web.chacuo.net/netrsakeypair) 在线生成随机 [RSA](../qa/other.md#4601) 密钥对,密钥格式必须为 PCKS#1,密钥长度 512,1024 都可以,不要设置密码,将生成的私钥复制保存到文件中,然后将私钥文件路径配置到 [OpenD 配置](../opend/opend-cmd.md#8799) 约定的 **rsa_private_key** 配置项中。
* **建议有实盘交易的用户配置加密,避免账户和交易信息泄露。**

## RSA 加解密
* [OpenD 配置](../opend/opend-cmd.md#8799) 约定 **rsa_private_key** 为私钥文件路径
* OpenD 与接入客户端共用相同的私钥文件
* RSA 加解密仅用于 InitConnect 请求,用于安全获取其它请求协议的对称加密 Key
* OpenD 的 [RSA](../qa/other.md#4601) 密钥为 1024 位,填充方式 PKCS1,公钥加密,私钥解密,公钥可通过私钥生成
* Python API 参考实现:[RsaCrypt](https://github.com/FutunnOpen/py-futu-api/tree/master/futu/common/sys_config.py) 类的 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 参考实现: [ConnMng](https://github.com/FutunnOpen/py-futu-api/tree/master/futu/common/conn_mng.py) 类的 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)长度的用于填充对齐的数据。

---
---
# OpenD 相关
## Q1:OpenD 因未完成“问卷评估及协议确认”自动退出
A: 您需要进行相关问卷评估及协议确认,才可以使用 OpenD,请先 [前往完成](https://www.futunn.com/about/api-disclaimer?lang=zh-CN)。
## Q2:OpenD 因”程序自带数据不存在“退出
A: 一般因权限问题导致自带数据拷贝失败,可以尝试将程序目录下
| 市场 |
品类 |
市场状态 |
时间段(当地时间) |
| 香港市场 |
证券类产品(含股票、ETFs、窝轮、牛熊、界内证) |
* NONE:无交易 |
CST 08:55 - 09:00 |
| * AUCTION:盘前竞价 |
CST 09:00 - 09:20 |
| * WAITING_OPEN:等待开盘 |
CST 09:20 - 09:30 |
| * MORNING:早盘 |
CST 09:30 - 12:00 |
| * REST: 午间休市 |
CST 12:00 - 13:00 |
| * AFTERNOON:午盘 |
CST 13:00 - 16:00 |
| * HK_CAS:港股盘后竞价(港股市场增加 CAS 机制对应的市场状态) |
CST 16:00 - 16:08 |
| * CLOSED:收盘 |
CST 16:08 - 08:55(T+1) |
| 期权、期货(仅日市) |
* NONE:期权待开盘 |
CST 08:55 - 09:30 |
| * MORNING:早盘 |
CST 09:30 - 12:00 |
| * REST: 午间休市 |
CST 12:00 - 13:00 |
| * AFTERNOON:午盘 |
CST 13:00 - 16:00 |
| * CLOSED:收盘 |
CST 16:00 - 08:55(T+1) |
| 期货(日夜市) |
* FUTURE_DAY_WAIT_FOR_OPEN:期货待开盘 |
不同品种交易时间不同 |
| * NIGHT_OPEN: 夜市交易时段 |
| * NIGHT_END:夜市收盘 |
| * FUTURE_DAY_WAIT_FOR_OPEN:期货待开盘 |
| * FUTURE_DAY_OPEN:日市交易时段 |
| * FUTURE_DAY_CLOSE:日市收盘 |
| 美国市场 |
证券类产品(含股票、ETFs) |
* PRE_MARKET_BEGIN:美股盘前交易时段 |
EST 04:00 - 09:30 |
| * AFTERNOON:美股持续交易时段 |
EST 09:30 - 16:00 |
| * AFTER_HOURS_BEGIN:美股盘后交易时段 |
EST 16:00 - 20:00 |
| * AFTER_HOURS_END:美股盘后收盘 |
EST 20:00 - 04:00(T+1) |
| * OVERNIGHT:美股夜盘交易时段 |
EST 20:00 - 04:00(T+1) |
| 期权 |
* NONE:期权待开盘 |
不同品种交易时间不同 |
| * REST:美指期权午间休市 |
| * AFTERNOON:美股持续交易时段 |
| * TRADE_AT_LAST:美指期权盘尾交易时段 |
| * NIGHT:美指期权夜市交易时段 |
| * CLOSED:收盘 |
| 期货 |
* FUTURE_SWITCH_DATE:美期待开盘 |
不同品种交易时间不同 |
| * FUTURE_OPEN:美期交易时段 |
| * FUTURE_BREAK:美期中盘休息 |
| * FUTRUE_BREAK_OVER:美期休息后交易时段 |
| * FUTURE_CLOSE:美期收盘 |
| A股市场 |
证券类产品(含股票、ETFs) |
* NONE:无交易 |
CST 08:55 - 09:15 |
| * Auction:盘前竞价 |
CST 09:15 - 09:25 |
| * WAITING_OPEN:等待开盘 |
CST 09:25 - 09:30 |
| * MORNING:早盘 |
CST 09:30 - 11:30 |
| * REST:午间休市 |
CST 11:30 - 13:00 |
| * AFTERNOON:午盘 |
CST 13:00 - 15:00 |
| * CLOSED:收盘 |
CST 15:00 - 08:55(T+1) |
| 新加坡市场 |
期货 |
* FUTURE_DAY_WAIT_FOR_OPEN:期货待开盘 |
不同品种交易时间不同 |
| * NIGHT_OPEN:夜市交易时段 |
| * NIGHT_END:夜市收盘 |
| * FUTURE_DAY_OPEN:日市交易时段 |
| * FUTURE_DAY_CLOSE:日市收盘 |
| 日本市场 |
期货 |
* FUTURE_DAY_WAIT_FOR_OPEN:期货待开盘 |
JST 16:25(T-1)- 16:30(T-1) |
| * NIGHT_OPEN:夜市交易时段 |
JST 16:30(T-1) - 05:30 |
| * NIGHT_END:夜市收盘 |
JST 05:30 - 08:45 |
| * FUTURE_DAY_OPEN:日市交易时段 |
JST 08:45 - 15:15 |
| * FUTURE_DAY_CLOSE:日市收盘 |
JST 15:15 - 16:25 |
\* CST, EST, JST 分别表示中国时间,美东时间,日本时间
## Q15:接口参数股票代码的格式
A:
* 使用不同编程语言的用户,需要的股票代码的格式不同:
* **Python 用户**
股票代码 code 格式:`行情市场.代码`。
例如:腾讯控股,参数 code 传入'HK.00700'。
* **非 Python 用户**
股票结构参见 [Security](../quote/quote.html#1377)。
例如:腾讯控股,参数 market 传入 QotMarket_HK_Security,参数 code 传入'00700'。
* 查询方式:
通过 APP 查看代码和行情市场:行情 > 自选 > 全部。
行情市场定义,请参考 [这里](../quote/quote.html#427)。

## Q16:复权因子相关
A:
### 概述
所谓 [复权](../quote/get-rehab.html#770) 就是对股价和成交量进行权息修复,按照股票的实际涨跌绘制股价走势图,并把成交量调整为相同的股本口径。
公司行动(如:拆股、合股、送股、转增股、配股、增发股、分红)均可能对股价产生影响,而复权计算可对量价进行调整,剔除公司行动的影响,保持股价走势的连续性。
### 名词解释
- 公司行动:上市公司进行一些股权、股票等影响公司股价和股东持仓变化的行为。
- 前复权:保持现有的股价不变,以当前的股价为基准,对以前的股价进行复权计算。
- 后复权:保持先前的股价不变,以过去的股价为基准,对以后的股价进行复权计算。
- 复权因子:即权息修复比例,用于计算复权后的价格及持仓数量。
- 除权除息日:即股权登记日下一个交易日。在股票的除权除息日,证券交易所都要计算出股票的除权除息价,以作为股民在除权除息日开盘的参考。其意义是股票股利分配给股东的日期。
### 复权方法
主流的复权计算方法分为两种:事件法和连乘法;而 OpenAPI 针对不同市场使用不同的计算方法。
- 事件复权法:通过还原除权除息的各类事件进行复权;存在两个复权因子(复权因子 A 和 复权因子 B),复权因子 B 主要调整现金分红对股价的影响,而复权因子 A 调整其他公司行动对股价的影响。
- 连乘复权法:通过复权因子连乘的方式进行复权,只保留 复权因子 A(或将 复权因子 B 置为0),复权因子 A 为 除权除息日前收盘价/该日经权息调整后的前收盘价。
::: tip 提示
* OpenAPI 对美股前复权使用连乘法,即将 复权因子 B 置为0。
* OpenAPI 对除美股以外的标的(A股、港股、新加坡股票等)及美股后复权使用事件法。
:::
### 计算公式
#### 单次复权
- 前复权:
前复权价格 = 不复权价格 × 前复权因子 A + 前复权因子 B
- 后复权:
后复权价格 = 不复权价格 × 后复权因子 A + 后复权因子 B
#### 多次复权
- 前复权:按照时间顺序,筛选出大于计算日期的复权因子,优先使用时间较早的复权因子进行复权计算。以两次复权为例:

- 后复权:按照时间倒序,筛选出小于等于计算日期的复权因子,优先使用时间较晚的复权因子进行复权计算。以两次复权为例:

### 示例
#### 单次前复权示例
以牧原股份为例:
- 筛选复权因子如下:
除权除息日|股票代码|方案说明|前复权因子 A |前复权因子 B
:-|:-|:-|:-|:-
2021/06/03|SZ.002714|10转4.0股派14.61元(含税)|0.71429|-1.04357
- 不复权数据如下:
日期|股票代码|不复权收盘价
:-|:-|:-
2021/06/02|SZ.002714|93.11
2021/06/03|SZ.002714|66.25
- 前复权数据如下:
日期|股票代码|前复权收盘价
:-|:-|:-
2021/06/02|SZ.002714|65.4639719
2021/06/03|SZ.002714|66.25
- 前复权数据计算方法:
牧原股份在 2021/06/03 进行拆股及现金分红行动(10转4.0股派14.61元),根据前复权计算公式对 2021/06/02 的收盘价进行调整计算,则:前复权价格(65.4639719) = 不复权价格(93.11) × 前复权因子 A(0.71429) + 前复权因子 B(-1.04357)

#### 多次后复权示例
接上一个例子,计算牧原股份在 2021/06/02 的后复权价格:
- 筛选复权因子如下:
除权除息日|股票代码|方案说明|后复权因子 A |后复权因子 B
:-|:-|:-|:-|:-|
2014/07/04|SZ.002714|10派2.34元(含税)|1|0.234
2015-06-10|SZ.002714|10转10.0股派0.61元(含税)|2|0.061
2016-07-08|SZ.002714|10转10.0股派3.53元(含税)|2|0.353
2017-07-11|SZ.002714|10转8.0股派6.9元(含税)|1.8|0.69
2018-07-03|SZ.002714|10派6.91元(含税)|1|0.691
2019-07-04|SZ.002714|10派0.5元(含税)|1|0.05
2020-06-04|SZ.002714|10转7.0股派5.5元(含税)|1.7|0.55
- 不复权数据如下:
日期|股票代码|不复权收盘价
:-|:-|:-
2021/06/02|SZ.002714|93.11
- 后复权数据如下:
日期|股票代码|后复权收盘价
:-|:-|:-
2021/06/02|SZ.002714|1152.7226
- 后复权数据计算方法:
为了计算牧原股份在 2021/06/02 的后复权价格,需要将早于 2021/06/02 的复权事件进行一一复权,得到最后的后复权价格,具体计算如下:

---
---
# 交易相关
## Q1:模拟交易相关
A:
### 概述
模拟交易是在真实的市场环境中,用虚拟资金做交易,不会对您的真实账户的资产造成影响。
#### 交易时间
模拟交易仅支持在常规交易时段交易,不支持在非交易时段、美股盘前盘后时段、A股港股盘前盘后竞价时段交易。详情可点击 [模拟交易规则](https://support.futunn.com/topic692)。
#### 支持品类
OpenAPI 支持模拟交易的品类请参考 [这里](../intro/intro.md#1396)。
#### 解锁
与真实交易不同,模拟交易无需对账户进行解锁,即可下单或改单撤单。
#### 订单
1. 订单类型:限价单和市价单。
2. 改单操作类型:模拟交易不支持使生效、使失效、删除,仅支持修改订单、 撤单。
3. 成交:模拟交易不支持成交相关操作,包括 [查询今日成交](../trade/get-order-fill-list.md#2621)、[查询历史成交](../trade/get-history-order-fill-list.md#9015)、[响应成交推送回调](../trade/update-order-fill.md#210)。
4. 有效期限:模拟交易有效期限仅支持当日有效。
5. 卖空:期权和期货支持卖空。股票仅美股支持卖空。
#### 操作平台
1. 移动端:我的 — 模拟交易

2. 桌面端:左侧模拟 tab

3. 网页端:[模拟交易界面](https://m-match.futunn.com/simulate/)
4. OpenAPI:在调用接口时,设置参数交易环境为模拟环境即可。详见 [如何使用 OpenAPI 进行模拟交易](../qa/trade.md#8728)。
::: tip 提示
* 以上四种方式只是操作平台不同,四种方式操作的模拟账户是共通的。
:::
### 如何使用 OpenAPI 进行模拟交易?
#### 创建连接
先根据交易品种 [创建相应的连接](../trade/base.md#7902) 。当交易品种是股票或期权时,请使用 `OpenSecTradeContext`。当交易品种是期货时,请使用 `OpenFutureTradeContext`。
#### 获取交易业务账户列表
使用 [获取交易业务账户列表](../trade/get-acc-list.md#5754) 查看交易账户(包括模拟账户、真实账户)。以 Python 为例:返回字段交易环境 `trd_env` 为 `SIMULATE`,表示模拟账户。
* **Example:Stocks and Options**
```python
from futu import *
trd_ctx = OpenSecTradeContext(filter_trdmarket=TrdMarket.HK, host='127.0.0.1', port=11111, security_firm=SecurityFirm.FUTUSECURITIES)
#trd_ctx = OpenFutureTradeContext(host='127.0.0.1', port=11111, is_encrypt=None, security_firm=SecurityFirm.FUTUSECURITIES)
ret, data = trd_ctx.get_acc_list()
if ret == RET_OK:
print(data)
print(data['acc_id'][0]) # get the first account id
print(data['acc_id'].values.tolist()) # convert to list format
else:
print('get_acc_list error: ', data)
trd_ctx.close()
```
* **Output**
```python
acc_id trd_env acc_type card_num security_firm \
0 281756480572583411 REAL MARGIN 1001318721909873 FUTUSECURITIES
1 9053218 SIMULATE CASH N/A N/A
2 9048221 SIMULATE MARGIN N/A N/A
sim_acc_type trdmarket_auth
0 N/A [HK, US, HKCC]
1 STOCK [HK]
2 OPTION [HK]
```
::: tip 提示
* 模拟交易中,区分股票账户和期权账户,股票账户只能交易股票,期权账户只能交易期权;以 Python 为例:返回字段中模拟账户类型 `sim_acc_type` 为 `STOCK`,表示股票账户;为`OPTION`,表示期权账户。
:::
* **Example: Futures**
```python
from futu import *
#trd_ctx = OpenSecTradeContext(filter_trdmarket=TrdMarket.HK, host='127.0.0.1', port=11111, security_firm=SecurityFirm.FUTUSECURITIES)
trd_ctx = OpenFutureTradeContext(host='127.0.0.1', port=11111, is_encrypt=None, security_firm=SecurityFirm.FUTUSECURITIES)
ret, data = trd_ctx.get_acc_list()
if ret == RET_OK:
print(data)
print(data['acc_id'][0]) # get the first account id
print(data['acc_id'].values.tolist()) # convert to list format
else:
print('get_acc_list error: ', data)
trd_ctx.close()
```
* **Output**
```python
acc_id trd_env acc_type card_num security_firm sim_acc_type \
0 9497808 SIMULATE MARGIN N/A N/A FUTURES
1 9497809 SIMULATE MARGIN N/A N/A FUTURES
2 9497810 SIMULATE MARGIN N/A N/A FUTURES
3 9497811 SIMULATE MARGIN N/A N/A FUTURES
trdmarket_auth
0 [FUTURES_SIMULATE_HK]
1 [FUTURES_SIMULATE_US]
2 [FUTURES_SIMULATE_SG]
3 [FUTURES_SIMULATE_JP]
```
#### 下单
使用 [下单接口](../trade/place-order.md) 时,设置交易环境为模拟环境即可。以 Python 为例:`trd_env = TrdEnv.SIMULATE`。
* **Example**
```python
from futu import *
trd_ctx = OpenSecTradeContext(filter_trdmarket=TrdMarket.HK, host='127.0.0.1', port=11111, security_firm=SecurityFirm.FUTUSECURITIES)
ret, data = trd_ctx.place_order(price=510.0, qty=100, code="HK.00700", trd_side=TrdSide.BUY, trd_env=TrdEnv.SIMULATE)
if ret == RET_OK:
print(data)
else:
print('place_order error: ', data)
trd_ctx.close()
```
* **Output**
```python
code stock_name trd_side order_type order_status order_id qty price create_time updated_time dealt_qty dealt_avg_price last_err_msg remark time_in_force fill_outside_rth
0 HK.00700 腾讯控股 BUY NORMAL SUBMITTING 4642000476506964749 100.0 510.0 2021-10-09 11:34:54 2021-10-09 11:34:54 0.0 0.0 DAY N/A
```
#### 撤单改单
使用 [撤单接口](../trade/modify-order.md) 时,设置交易环境为模拟环境即可。以 Python 为例: `trd_env = TrdEnv.SIMULATE`。
* **Example**
```python
from futu import *
trd_ctx = OpenSecTradeContext(filter_trdmarket=TrdMarket.HK, host='127.0.0.1', port=11111, security_firm=SecurityFirm.FUTUSECURITIES)
order_id = "4642000476506964749"
ret, data = trd_ctx.modify_order(ModifyOrderOp.CANCEL, order_id, 0, 0, trd_env=TrdEnv.SIMULATE)
if ret == RET_OK:
print(data)
else:
print('modify_order error: ', data)
trd_ctx.close()
```
* **Output**
```python
trd_env order_id
0 SIMULATE 4642000476506964749
```
#### 查询历史订单
使用 [查询历史订单接口](../trade/get-history-order-list.md) 时,设置交易环境为模拟环境即可。以 Python 为例:`trd_env = TrdEnv.SIMULATE`。
* **Example**
```python
from futu import *
trd_ctx = OpenSecTradeContext(filter_trdmarket=TrdMarket.HK, host='127.0.0.1', port=11111, security_firm=SecurityFirm.FUTUSECURITIES)
ret, data = trd_ctx.history_order_list_query(trd_env=TrdEnv.SIMULATE)
if ret == RET_OK:
print(data)
else:
print('history_order_list_query error: ', data)
trd_ctx.close()
```
* **Output**
```python
code stock_name trd_side order_type order_status order_id qty price create_time updated_time dealt_qty dealt_avg_price last_err_msg remark time_in_force fill_outside_rth
0 HK.00700 腾讯控股 BUY ABSOLUTE_LIMIT CANCELLED_ALL 4642000476506964749 100.0 510.0 2021-10-09 11:34:54 2021-10-09 11:37:08 0.0 0.0 DAY N/A
```
### 如何重置模拟账户?
目前 OpenAPI 不支持重置模拟账户,您可在移动端使用复活卡重置指定模拟账户,重置后账户资金将恢复至初始值,历史订单将会被清空。
#### 具体操作
移动端:我的 — 模拟交易 — 我的头像 — 我的道具 — 复活卡。

## Q2:是否支持 A 股交易?
A: 模拟交易支持 A 股交易。但真实交易仅可通过 A 股通交易部分 A 股,具体详见 [A 股通名单](https://www.hkex.com.hk/Mutual-Market/Stock-Connect/Eligible-Stocks/View-All-Eligible-Securities?sc_lang=zh-HK)。
## Q3:各市场支持的交易方向
A: 除了期货,其他股票都只支持传入 BUY 和 SELL 两个交易方向。在空仓情况下传入 SELL,产生的订单交易方向是卖空。
## Q4:真实交易中,各市场支持的订单类型
A: