常见问题 FAQ
认证、配置与网络
如何获取 Tiger ID、私钥和账户号
登录开发者中心,页面上可直接看到 Tiger ID。点击「生成密钥」即可生成密钥对,下载配置文件(tiger_openapi_config.properties),其中包含 tiger_id、private_key、account 等字段。账户号也可在老虎 APP「我的-账户管理」中查看。
Python 用什么格式的私钥?Java 呢?
各 SDK 都推荐用 PKCS#8 格式的私钥。
在开发者中心生成密钥时,可分别下载两种格式。如需手动转换:
# PKCS#1 转 PKCS#8
openssl pkcs8 -topk8 -inform PEM -in private_pkcs1.pem -outform PEM -nocrypt -out private_pkcs8.pem
# PKCS#8 转 PKCS#1
openssl rsa -in private_pkcs8.pem -out private_pkcs1.pem
# 从私钥导出公钥
openssl rsa -in private_pkcs1.pem -pubout -out public_key.pemAPI 的服务器地址是什么?
SDK 已内置服务端地址(openapi.tigerfintech.com),无需手动配置。
报错 failed to verify signature / sign check error(code=1000)
failed to verify signature / sign check error(code=1000)可能原因:
- 私钥不正确
- 私钥与开发者中心已上传的公钥不匹配(如重新生成了密钥但请求时未替换为最新密钥)
- Windows 路径中反斜杠被当作转义字符
排查步骤:
- 确认私钥文件是否正确
- 在开发者中心重新生成密钥对,更新本地私钥
- Windows 用户:路径字符串前加
r前缀,如r'C:\Users\Foo\Desktop\rsa_private_key.pem'
报错 ValueError: Unable to read this file, version 136 != 0
ValueError: Unable to read this file, version 136 != 0原因:私钥格式不正确。
解决方法:在开发者中心按 SDK 需要的格式重新复制私钥。可通过文件头判断格式:
| 格式 | 文件头 |
|---|---|
| PKCS#1 | -----BEGIN RSA PRIVATE KEY----- |
| PKCS#8(各 SDK 推荐) | -----BEGIN PRIVATE KEY----- |
报错 Could not deserialize key data
Could not deserialize key data原因:本地安装的 cryptography 版本与当前 SDK 不兼容(例如 45.x)。
解决方法:降级到兼容版本:
pip install cryptography==42.0.8报错 request sign failed. int() argument must be a string
request sign failed. int() argument must be a string原因:私钥格式不正确,或密钥内容没有完整复制。
解决方法:在开发者中心重新生成密钥对,并完整复制私钥内容。
报错 OSError: [Errno 22] Invalid argument(Windows 路径转义)
OSError: [Errno 22] Invalid argument(Windows 路径转义)同类报错还有 request sign failed. Short octet stream on tag decoding。
原因:Windows 路径中的反斜杠 \ 被当作转义字符。
解决方法:路径字符串前加 r 前缀使用原始字符串,或改用正斜杠:
client_config.private_key = read_private_key(r'C:\Users\Foo\Desktop\rsa_private_key.pem')
# 或
client_config.private_key = read_private_key('C:/Users/Foo/Desktop/rsa_private_key.pem')报错 public key error(code=1000)
public key error(code=1000)原因:tiger_id 未正确传到服务端。
解决方法:确认 client_config.tiger_id 与开发者中心显示的 Tiger ID 一致,且没有多余空格或换行符。
报错 failed to get developer information(code=1000)
failed to get developer information(code=1000)原因:Tiger ID 不存在。
解决方法:确认 tiger_id 正确。
报错 unauthorized: Please login in(code=1200)
unauthorized: Please login in(code=1200)可能原因:
tiger_id与account不属于同一个开发者账号- 机构用户:该子账户未在机构后台 API 权限中授权
解决方法:机构用户联系管理员在机构中心的 API 权限管理中添加该账户。
报错 account is not authorized to the api user
account is not authorized to the api user原因:account 字段填写有误,或与当前 tiger_id 不匹配。
账号格式:
| 账户类型 | 账号格式 |
|---|---|
| 综合账户(实盘) | 5~10 位数字 |
| 环球账户(实盘) | 以 U 开头 |
| 模拟账户 | 17 位数字 |
报错 SSL: CERTIFICATE_VERIFY_FAILED 或 response sign verify failed
SSL: CERTIFICATE_VERIFY_FAILED 或 response sign verify failed可能原因:
- 将自己生成的公钥错误地填入了
tiger_public_key字段(该字段由 SDK 内部管理,用户不应修改) - Python 安装时未包含根证书(Mac 通过安装包方式安装的 Python 常见)
- 系统 SSL 证书过期或缺失
解决方法:
- 方法一(最推荐,Mac 通过安装包安装 Python 时):打开
应用程序/Python x.x/,双击运行Install Certificates.command - 方法二:安装证书库:
pip install certifi,仍未解决则:pip install pip-system-certs - 方法三(临时调试,不推荐用于生产):
import ssl
ssl._create_default_https_context = ssl._create_unverified_context方法三会跳过 SSL 证书验证,存在中间人攻击风险,仅建议在本地调试阶段临时使用。
报错 unable to get local issuer certificate
unable to get local issuer certificate原因:本地缺少根证书库。
解决方法:
pip install certifi
# 仍未解决则
pip install pip-system-certsMac 用户也可运行 应用程序/Python x.x/Install Certificates.command。
报错 module 'http.client' has no attribute 'HTTPConnection'
module 'http.client' has no attribute 'HTTPConnection'原因:系统未安装 OpenSSL,或 Python 编译时未链接 OpenSSL。
解决方法:先确认 OpenSSL 可用:
python -c "import ssl; print(ssl.OPENSSL_VERSION)"若报错,则重新安装 Python 并确保链接了 OpenSSL。
报错 stomp.exception.ConnectFailedException(长连接建立失败)
stomp.exception.ConnectFailedException(长连接建立失败)可能原因:
- 服务端临时故障
- 网络不可达或被防火墙拦截
- SSL 配置问题
排查步骤:
- 检查网络连通性
- 确认
PushClient的use_ssl参数没有被设为False(默认为True) - 稍后重试;持续失败请联系客服
报错 Unknown response frame type: '' (frame length was 3)
Unknown response frame type: '' (frame length was 3)原因:PushClient 初始化时设置了 use_ssl=False,导致通信协议不匹配。
解决方法:移除 use_ssl=False 参数,使用默认 SSL 连接。
报错 OSError: [WinError 10038](Windows,非套接字操作)
OSError: [WinError 10038](Windows,非套接字操作)原因:在长连接断线重连尚未完成时就调用了推送方法(如 query_subscribed_quote)。
解决方法:在 on_connected 回调中执行操作,或调用前先检查连接状态:
if push_client.is_connected():
push_client.query_subscribed_quote()连接 code=4001 kick out by a new connection
code=4001 kick out by a new connection原因:同一 Tiger ID 同时建立了多个长连接,新连接会踢出旧连接。
说明:同一 Tiger ID 下的模拟账户和实盘账户共用同一个 WebSocket 长连接。如需在一个连接中同时操作两个账户,在同一个 PushClient 实例中分别订阅不同 account 的数据即可。
行情
各市场行情权限说明
| 市场 | 权限名称 | 内容 |
|---|---|---|
| 美股 | L1(Nasdaq Basic) | 纳斯达克实时报价、买卖各 1 档盘口、逐笔成交 |
| 美股 | L2(Nasdaq Totalview) | 纳斯达克 40 档深度盘口 |
| 港股 | BMP | 手动刷新行情,仅实时报价,无盘口数据 |
| 港股 | L2 | 自动推送实时报价、买卖 10 档盘口、逐笔成交及经纪队列 |
| 美股期权 | L1 | 16 个交易所最优买卖报价及逐笔成交 |
| 港股期权 | L2 | 随港股期货交易所 L2 一同提供(不单独售卖) |
| 期货 | L2 | 实时报价、买卖 10 档深度、逐笔成交(L1 包含在 L2 内,不单独售卖) |
历史行情和推送订阅的额度(K 线数量、可订阅标的数量)根据账户资产或历史成交额自动升级,满足对应条件即可:
| 条件(满足其一即可) | 股票/ETF | 期货 | 期权 | 标准行情订阅 | 摆盘行情订阅 |
|---|---|---|---|---|---|
| 开通 API | 20 | 10 | 10 | 20 | 10 |
| 总资产 > 1 万 USD 或成交额 > 10 万 USD | 200 | 20 | 200 | 100 | 20 |
| 总资产 > 5 万 USD 或成交额 > 50 万 USD | 500 | 50 | 500 | 500 | 100 |
| 总资产 > 50 万 USD 或成交额 > 200 万 USD | 1000 | 100 | 1000 | 1000 | 200 |
| 总资产 > 100 万 USD 或成交额 > 500 万 USD | 2000 | 200 | 2000 | 2000 | 500 |
综合账户付费了美股 L2,模拟账户也能用吗?
是的。行情权限关联到 tiger_id,与账户无关。
美股期权 L1 权限在哪里开通?
在老虎证券 APP 内「行情商城」购买。购买后 API 自动生效,可调用 get_option_briefs、get_option_chain、get_option_trade_ticks、get_option_bars 等期权行情接口。
多台设备可以同时使用行情吗?
行情权限同时只有一台设备可持有。多设备使用时需调用 grab_quote_permission() 抢占。如需部署多台机器,建议只在一台机器上创建 QuoteClient(行情);交易接口(TradeClient)不受此限制,多台机器可同时下单。
行情推送退订报错 According to your user level, you can only unsubscribe after 1 minute
According to your user level, you can only unsubscribe after 1 minute原因:订阅后需等待至少 1 分钟才能退订,这是行情服务的限制。
解决方法:在上次订阅操作后等待 1 分钟再调用退订。
financial_report / stock_fundamental 接口报权限错误
financial_report / stock_fundamental 接口报权限错误get_financial_report、get_stock_fundamental、get_financial_daily 等基本面数据接口需要额外开通权限,默认不开通。
开通方式:联系客服申请。Java SDK 对应接口为 QuoteFinancialReportRequest 和 QuoteStockFundamentalRequest,权限要求相同。
如何获取盘前盘后行情和夜盘行情?
- 盘前/盘后:
get_stock_briefs(symbols, include_hour_trading=True)或get_bars时指定trade_session=TradingSession.PreMarket / AfterHours - 夜盘(Overnight):需要额外购买
usOvernight权限,使用get_bars(..., trade_session=TradingSession.OverNight) - 盘前/盘后 K 线:仅支持 2024 年 4 月后的 60 分钟及以下级别数据
get_bars 历史数据支持多久?限制是什么?
get_bars 历史数据支持多久?限制是什么?| 周期 | 历史数据范围 |
|---|---|
| 分钟(1/5/15/30/60 分钟) | 近 10 年(需使用 date 参数逐日查询) |
| 日 K 及以上(日/周/月/年) | 完整历史 |
单次请求最多返回 1200 条记录。使用 begin_time / end_time 区间查询时有额外限制:1 分钟及 5 分钟 K 线仅支持近 1 个月,15/30/60 分钟 K 线仅支持近 1 年。如需更早的分钟级 K 线,请改用 date 参数按日期逐步查询。
get_bars 支持复权吗?如何选择?
get_bars 支持复权吗?如何选择?支持,通过 right 参数控制:
| 参数值 | 含义 |
|---|---|
QuoteRight.BR(默认) | 前复权 |
QuoteRight.NR | 不复权 |
接口直接返回复权后的价格,不单独提供复权因子。
get_trading_calendar 支持查几年的数据?
get_trading_calendar 支持查几年的数据?提供2015 年至本年度末的市场交易日历(排除周末及法定节假日,未排除临时休市日期)。可指定市场(Market.US / Market.HK / Market.CN)和日期范围。
逐笔成交中 tickType 为 * 是什么意思?
tickType 为 * 是什么意思?* 表示中性成交,即当笔成交无法判断是主动买入还是主动卖出(通常发生在成交价正好等于买卖盘口中间价时)。+ 表示主动买入,- 表示主动卖出。
逐笔成交中的 sn 字段是唯一的吗?
sn 字段是唯一的吗?sn(序列号)在同一标的的同一交易日内单调递增,可用于判断消息顺序和本地去重。跨标的或跨交易日的 sn 不具备可比性。
逐笔成交的 partCode 是什么意思?
partCode 是什么意思?partCode 表示美股成交发生的交易所代码,常见对应关系:
| partCode | 交易所 |
|---|---|
n | NYSE(纽约证券交易所) |
t | NSDQ(纳斯达克) |
p | ARCA(纽交所 Arca) |
z | BZX(Cboe BZX) |
k | EDGX(Cboe EDGX) |
v | IEX |
d | ADF(FINRA) |
完整映射见 SDK 中的 tigeropen.common.consts.tick_constants.PART_CODE_MAP。
如何接收实时行情、订单状态、资产变动推送?
使用 PushClient 建立 WebSocket 长连接,通过回调函数(Callback)处理推送数据,无需轮询:
from tigeropen.push.push_client import PushClient
from tigeropen.tiger_open_config import TigerOpenClientConfig
client_config = TigerOpenClientConfig(props_path='your_config_directory_path')
protocol, host, port = client_config.socket_host_port
push_client = PushClient(host, port, use_ssl=(protocol == 'ssl'))
push_client.connect(client_config.tiger_id, client_config.private_key)
# 订阅股票行情
push_client.subscribe_quote(['AAPL'])
# 订阅资产变动(默认每5秒推送一次全量快照)
push_client.subscribe_asset(account='你的账户号')港股期权行情支持推送订阅吗?
支持。使用 push_client.subscribe_option 订阅港股期权行情,需要港股期货交易所 L2 权限(HKEXFuturesQuoteLv2,该权限包含港股期货和港股期权)。数据结构与美股期权类似,包含最新价、买卖盘口、成交量等字段。
期权订阅额度和股票订阅额度是共享的吗?
不共享。标准行情额度对该大类下各类数据分别生效,股票与期权订阅额度分别计算。标准行情与 Level 2 深度行情也作为独立大类分别计数。额度分类和等级上限见行情权限与限制。
期权代码(identifier)格式是什么?如何构造?
美股期权 identifier 为 21 位字符串,格式:SYMBOL YYMMDDP/CXXXXXXXX(symbol 与日期之间有两个空格,到期日 6 位,P/C 后面 8 位为行权价 ×1000,不足补零)。
示例:
AAPL 190118P00160000= AAPL,2019-01-18 到期,PUT,行权价 160.0
推荐使用 SDK 工具方法构造,避免手拼格式错误:
from tigeropen.common.util.contract_utils import get_option_identifier
identifier = get_option_identifier('AAPL', '20190104', 'PUT', 134)
# 返回: 'AAPL 190104P00134000'港股期权 identifier 则通过 get_option_symbols 接口获取,格式不同,不可手动构造。
推送连接断线后,订阅是否需要重新注册?
需要。PushClient 断线重连后,之前的订阅不会自动恢复。推荐在 on_connected 回调中重新执行所有订阅操作:
def on_connected(frame):
push_client.subscribe_quote(['AAPL', 'TSLA'])
push_client.subscribe_asset(account=client_config.account)
push_client.subscribe_order(account=client_config.account)
push_client.on_connected = on_connected断线期间的行情数据不会补发,重连后只能收到重连之后的推送。
账户与交易
get_prime_assets 和 get_assets 有什么区别?
get_prime_assets 和 get_assets 有什么区别?get_prime_assets | get_assets | |
|---|---|---|
| 适用账户 | 综合账户、模拟账户 | 环球账户(综合账户也可调用但字段多为空) |
| 返回对象 | PortfolioAccount,含 segments['S'](证券)和 segments['C'](期货) | list[PortfolioAccount],含 SecuritySegment 和 CommoditySegment |
| 推荐场景 | 获取净值、购买力、浮亏、持仓市值 | 环球账户子账户汇总 |
如果使用综合账户,始终用 get_prime_assets,不要用 get_assets(会有大量空字段)。
如何读取账户总资产和持仓盈亏?
from tigeropen.trade.trade_client import TradeClient
from tigeropen.tiger_open_config import TigerOpenClientConfig
client_config = TigerOpenClientConfig(props_path='your_config_directory_path')
trade_client = TradeClient(client_config)
# 获取综合账户资产
assets = trade_client.get_prime_assets()
# 通过 segments 访问各分段资产(S=证券, C=期货/商品)
net_liq = assets.segments['S'].net_liquidation # 净值
gross_pos = assets.segments['S'].gross_position_value # 总持仓市值
# gross_position_value > net_liquidation 说明使用了杠杆逐个持仓的已实现/未实现盈亏用 get_positions() 读取:
from tigeropen.common.consts import Currency, Market, SecurityType
positions = trade_client.get_positions(
sec_type=SecurityType.STK,
currency=Currency.ALL,
market=Market.ALL,
)
for position in positions:
print(position.contract.symbol, position.realized_pnl, position.unrealized_pnl)报错 'PortfolioAccount' object has no attribute 'net_liquidation'
'PortfolioAccount' object has no attribute 'net_liquidation'net_liquidation 不是 PortfolioAccount 的直接属性,需通过 segments 字典访问:
assets.segments['S'].net_liquidation # 证券段净值
assets.segments['C'].net_liquidation # 期货段净值(如有)realized_pnl 的币种是什么?
realized_pnl 的币种是什么?realized_pnl 的币种取决于持仓标的的交易市场:港股持仓为 HKD,美股为 USD。如需统一换算为某种货币,可在调用接口时传入 base_currency='USD' 参数。
如何实时监控持仓盈亏,需要轮询吗?
不需要轮询。使用 PushClient 订阅资产变动推送:
push_client.subscribe_asset(account='你的账户号')
# 服务端默认每 5 秒推送一次全量资产快照,包含当前持仓盈亏outside_rth=True 对所有订单类型都有效吗?
outside_rth=True 对所有订单类型都有效吗?不是。outside_rth(允许盘前盘后交易)仅对**限价单(LMT)**有效:
- 市价单(MKT):始终只在盘中执行,设置
outside_rth=True会被忽略 - 止损单(STP)、跟踪止损单(TRAIL):也只在盘中有效,
outside_rth参数被忽略 - 附加订单(止损/止盈 order_leg):建议明确设置
outside_rth=False
如需在盘前/盘后下单,必须使用限价单并设置 outside_rth=True:
from tigeropen.trade.domain.order import LimitOrder
order = LimitOrder(account=client_config.account,
contract=contract,
action='BUY',
quantity=1,
limit_price=150.0,
outside_rth=True)附加订单(止盈/止损)建议显式设置 outside_rth=False,避免在盘前盘后被触发:
from tigeropen.common.util.order_utils import order_leg
profit_taker = order_leg('PROFIT', 180.0, time_in_force='GTC', outside_rth=False)
stop_loss = order_leg('LOSS', 140.0, time_in_force='GTC', outside_rth=False)get_orders / get_open_orders / get_filled_orders 有什么区别?
get_orders / get_open_orders / get_filled_orders 有什么区别?| 方法 | 返回内容 | 注意 |
|---|---|---|
get_orders | 所有状态的订单(可按状态过滤) | 默认返回当日所有订单;states 参数仅环球账户支持 |
get_open_orders | 待成交的订单,包含部分成交但仍挂单的订单 | 部分成交的订单 filled > 0 但 remaining > 0 |
get_filled_orders | 有成交记录的订单,包含部分成交后被撤的订单 | 部分成交被撤时状态可能是 CANCELLED、HELD 等,并非一定是 FILLED |
get_cancelled_orders | 已撤销订单,包含部分成交后撤单的订单 |
典型场景:一个限价单成交了 50 股后被手动撤单——它会同时出现在 get_filled_orders(有成交)和 get_cancelled_orders(被撤)中。
下单必传的字段有哪些?
| 字段 | 说明 |
|---|---|
account | 账户号 |
symbol | 证券代码,如 'AAPL'、'00700' |
sec_type | 合约类型:STK(股票)/ OPT(期权)/ FUT(期货) |
action | 买卖方向:BUY / SELL |
order_type | 订单类型:MKT(市价)/ LMT(限价)/ STP(止损)/ STP_LMT(止损限价)/ TRAIL(跟踪止损) |
quantity | 委托数量 |
limit_price | 限价单必填 |
aux_price | 止损单必填(触发价) |
接口使用说明
使用 nextPageToken 时为什么每次返回的都是同一批数据?
nextPageToken 时为什么每次返回的都是同一批数据?使用 page_token 分页时,每次请求除 page_token 以外的其他参数必须保持不变。若每次修改了其他参数(如 start_time、limit),会导致服务端报错或从头开始返回。
正确用法:
page_token = ''
while page_token is not None:
response = trade_client.get_orders(page_token=page_token, limit=100)
orders = response.result
page_token = response.next_page_token # 为 None 时表示已获取全部nextPageToken 存在时表示什么?
nextPageToken 存在时表示什么?nextPageToken 不为空说明后续还有更多数据。即使当前页已返回了等于 limit 数量的数据,只要总数超过 limit,就会有 token。当返回的 next_page_token 为 None 或空时,表示已获取全部数据。
get_orders 的 start_time / end_time 是按什么时间过滤的?
get_orders 的 start_time / end_time 是按什么时间过滤的?默认按下单时间(LATEST_CREATED)过滤。如果想按最后状态更新时间过滤(例如查询某时间段内成交的订单),需要传 sort_by=OrderSortBy.LATEST_STATUS_UPDATED:
from tigeropen.common.consts import OrderSortBy
# 查询 2025-01-01 至今 状态有更新的订单(如成交、撤单等)
orders = trade_client.get_orders(
start_time='2025-01-01',
sort_by=OrderSortBy.LATEST_STATUS_UPDATED
)注意:sort_by 参数仅支持综合账户,环球账户不支持。
接口调用频率有限制吗?
有。按 TigerId + 接口 独立计数,窗口为 60 秒滚动窗口:
| 等级 | 频率上限 | 代表接口 |
|---|---|---|
| 高频 | 120 次/分钟 | place_order、get_orders、get_stock_briefs、get_trade_ticks、get_option_briefs 等 |
| 中频 | 60 次/分钟 | get_bars、get_depth_quote、get_prime_assets、get_positions、get_option_chain 等 |
| 低频 | 10 次/分钟 | grab_quote_permission、get_symbols、get_market_status、get_trade_rank 等 |
触发限流时会返回 HTTP 429 和业务码 5,错误消息会说明限流信息。频繁触发或持续超限有被加入黑名单的风险。
SDK 使用常见问题
输出显示 [5 rows x 9 columns],看不到完整数据
[5 rows x 9 columns],看不到完整数据pandas 默认截断输出。在代码开头添加:
import pandas as pd
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_rows', 5000)
pd.set_option('display.width', 5000)错误代码速查
| 错误码 | 含义 | 常见原因 |
|---|---|---|
0 | 成功 | — |
1 | 服务端异常 | 参数无法处理或服务端内部错误 |
2 | 网络超时 | 网络不稳定,考虑就近部署 |
4 | 访问拒绝 | IP 不在白名单 / 签名失败 / 订阅超限 / 机构用户未传 secret_key |
5 | 请求频率超限 | 返回 HTTP 429;错误消息包含限流说明 |
1000 | 公共参数错误 | 签名错误 / tiger_id 有误 / 请求参数格式错误 |
1010 | 业务参数错误 | symbol 为空 / 参数格式有误 / sec_type 不支持 |
1200 | 综合账号交易错误 | 下单时间段不对 / 盘前盘后不能下市价单 / 持仓不足 |
1300 | 模拟账号交易错误 | 与综合账号类似 |
4000 | 权限不足 | K 线时间段超限 / 行情设备多占 / 行情权限不足 |
4001 | 长连接被踢出 | 新连接建立,旧连接被断开 |
完整错误代码列表详见错误代码文档。
Updated 3 days ago
