Skip to content

使用 LongPort OpenAPI 拉取 QQQ.US 的 5m 历史 K 线 ,缺失夜盘数据 #890

@Skioleeya

Description

@Skioleeya

问题描述

我们在使用 LongPort OpenAPI 拉取 QQQ.US 的 5m 历史 K 线,用作 NQ 代理品种的全时段量化研究数据。

根据历史 K 线文档,接口支持 trade_session 参数,100 / TradeSessions.All 表示请求所有延长时段;TradeSession 命名词典中也包含盘前、盘中、盘后、夜盘。

但实际使用 Python SDK 请求 QQQ.US 时,即使传入 TradeSessions.All,返回结果只有:

  • TradeSession.Pre
  • TradeSession.Intraday
  • TradeSession.Post

没有任何夜盘 K 线数据。

我们账号已有美股 L1 实时行情权限。SDK 初始化时也能看到美股行情权限,例如:

US       | Nasdaq Basic
USOption | LV1 Real-time Quotes
HK       | LV1 Real-time Quotes
CN       | ChinaConnect LV1 Real-time Quotes

请问这是预期行为还是接口/权限问题?

我们想确认:

  1. 历史 K 线接口是否支持 QQQ.US 夜盘历史 K 线?
  2. TradeSessions.All 是否应包含 20:00-04:00 ET 的夜盘数据?
  3. Python SDK 的 TradeSessions.All 是否正确映射到了文档中的 trade_session=100
  4. 如果实时行情有夜盘,但历史 K 线不支持夜盘,文档是否可以明确说明这个差异?
  5. 是否需要额外开通某种权限,才能获取美股 ETF 夜盘历史 K 线?

业务影响:我们需要用 QQQ.US 作为 NQ 的代理品种做完整时段校准。由于 LongBridge OpenAPI 不支持 NQ 期货,我们必须依赖 QQQ.US 的盘前、盘中、盘后、夜盘历史 K 线。如果缺少夜盘,校准结果会失真,因此当前数据不能使用。

参考文档:

代码例子

from datetime import date, datetime, timezone
from zoneinfo import ZoneInfo
from collections import Counter

from longport.openapi import AdjustType, Config, Period, QuoteContext, TradeSessions


ET_TZ = ZoneInfo("America/New_York")
UTC_TZ = timezone.utc


def et_naive_to_utc_iso(ts_et_naive: datetime) -> tuple[str, str]:
    if ts_et_naive.tzinfo is None:
        ts_et_aware = ts_et_naive.replace(tzinfo=ET_TZ)
    else:
        ts_et_aware = ts_et_naive.astimezone(ET_TZ)
    ts_utc = ts_et_aware.astimezone(UTC_TZ)
    return (
        ts_utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
        ts_et_aware.replace(tzinfo=None).strftime("%Y-%m-%d %H:%M:%S"),
    )


ctx = QuoteContext(Config.from_env())

candles = ctx.history_candlesticks_by_date(
    symbol="QQQ.US",
    period=Period.Min_5,
    adjust_type=AdjustType.NoAdjust,
    start=date(2026, 4, 13),
    end=date(2026, 4, 13),
    trade_sessions=TradeSessions.All,
)

rows = []
for candle in candles:
    ts_utc, ts_et = et_naive_to_utc_iso(candle.timestamp)
    rows.append(
        {
            "timestamp_utc": ts_utc,
            "timestamp_et": ts_et,
            "open": float(candle.open),
            "high": float(candle.high),
            "low": float(candle.low),
            "close": float(candle.close),
            "volume": float(candle.volume),
            "trade_session": str(getattr(candle, "trade_session", "")),
        }
    )

print("row_count:", len(rows))
print("first:", rows[0] if rows else None)
print("last:", rows[-1] if rows else None)
print("trade_session_counts:", Counter(row["trade_session"] for row in rows))

night_count = 0
pre_count = 0
rth_count = 0
post_count = 0

for row in rows:
    ts = datetime.strptime(row["timestamp_et"], "%Y-%m-%d %H:%M:%S")
    hhmm = ts.hour * 100 + ts.minute

    if hhmm >= 2000 or hhmm < 400:
        night_count += 1
    elif 400 <= hhmm < 930:
        pre_count += 1
    elif 930 <= hhmm < 1600:
        rth_count += 1
    elif 1600 <= hhmm < 2000:
        post_count += 1

print("night_bar_count:", night_count)
print("pre_market_bar_count:", pre_count)
print("rth_bar_count:", rth_count)
print("post_market_bar_count:", post_count)

也用 offset query 做过对照:

from datetime import datetime
from longport.openapi import AdjustType, Config, Period, QuoteContext, TradeSessions

ctx = QuoteContext(Config.from_env())

candles = ctx.history_candlesticks_by_offset(
    "QQQ.US",
    Period.Min_5,
    AdjustType.NoAdjust,
    False,
    1000,
    datetime(2026, 4, 13, 23, 59, 0),
    trade_sessions=TradeSessions.All,
)

print("row_count:", len(candles))

错误信息或结果截图

没有报错,但返回结果缺少夜盘数据。

date query 结果:

row_count: 56
first_bar_time_et: 04:00:00
last_bar_time_et: 08:35:00
night_bar_count: 0
pre_market_bar_count: 56
rth_bar_count: 0
post_market_bar_count: 0
trade_session_values:
  TradeSession.Pre: 56

offset query 结果:

row_count: 1000
first_bar_time_et: 04:00:00
last_bar_time_et: 19:55:00
night_bar_count: 0
pre_market_bar_count: 370
rth_bar_count: 390
post_market_bar_count: 240
trade_session_values:
  TradeSession.Pre: 370
  TradeSession.Intraday: 390
  TradeSession.Post: 240

使用较长窗口拉取 QQQ.US 5m 数据后,统计结果为:

symbol: QQQ.US
trade_session_mode: all_extended
bar_interval_sec: 300
first_bar_time_et: 04:00:00
last_bar_time_et: 19:55:00

night_bar_count: 0
pre_market_bar_count: 5930
rth_bar_count: 6942
post_market_bar_count: 4236

trade_session_values:
  TradeSession.Pre: 5930
  TradeSession.Intraday: 6906
  TradeSession.Post: 4272

也就是说,实际返回时间范围是:

04:00:00 ET ~ 19:55:00 ET

没有 20:00-04:00 ET 夜盘历史 K 线。

  • 操作系统: Windows 10 10.0.19045
  • 开发语言: Python 3.12.9
  • SDK 版本号: longport 3.0.20

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions