一份自选股日报,至少要能回答三个问题:这条价格属于哪个交易日?变化是相对哪一天算的?如果数字有疑问,能否找到当时的请求和原始响应?
同时跟踪 A 股、港股和美股时,这三个问题会变得具体起来。北京时间到了周末,三个市场的最近交易日未必相同;接口成功返回,也不代表自选股所需的目标日期已经齐全。
本文用 TickDB 的交易日历、股票信息和历史日 K,跑通一次六只股票的复盘流程。生成的是数据复盘日报:逐项保留交易日期、币种、计算口径与证据,不生成买卖建议,也不根据价格变化编写新闻归因。
先看最终日报:每行都有自己的日期
本次在北京时间 2026 年 9 月 27 日 08:46—08:47 采集数据,使用已经结束的交易窗口。自选清单包含 600519.SH、000001.SZ、700.HK、9988.HK、AAPL.US、MSFT.US,只是流程样本,不代表推荐名单。
最终日报如下。价格保留各自交易币种;百分比由本次返回的两根日 K 收盘价计算,展示到两位小数。
| 标的 | 目标交易日 | 前一交易日 | 目标日收盘价 | 前一日收盘价 | 未复权收盘价变化 |
|---|---|---|---|---|---|
| 贵州茅台 600519.SH | 09-24 | 09-23 | 1237.00 CNY | 1251.24 CNY | -1.14% |
| 平安银行 000001.SZ | 09-24 | 09-23 | 11.30 CNY | 11.60 CNY | -2.59% |
| 腾讯控股 700.HK | 09-25 | 09-24 | 436.60 HKD | 438.40 HKD | -0.41% |
| 阿里巴巴-W 9988.HK | 09-25 | 09-24 | 108.40 HKD | 110.00 HKD | -1.45% |
| 苹果 AAPL.US | 09-25 | 09-24 | 341.07 USD | 335.92 USD | +1.53% |
| 微软 MSFT.US | 09-25 | 09-24 | 516.17 USD | 497.93 USD | +3.66% |
日期均为 2026 年、对应市场当地交易日期。以上为 TickDB 本次返回值及离线计算结果,未与第二家行情源交叉验证。这里的百分比是未复权收盘价变化,不等同于交易所官方涨跌幅、持仓收益或含分红的总回报;除权除息等事件可能影响解释。三地目标日不同,也不把这六行合成“同一天的全球强弱榜”。
这张表最终齐全,但首轮取数时只有四只股票满足目标日与前一交易日都在场的条件。两只港股需要补查。这正是日报值得保留状态字段的原因。
第一步:从自选清单生成每个市场的目标日
不要把“昨天”直接写进所有请求。先按市场查询交易日历,再确定复盘目标日。
TickDB 的交易日历接口接受 market、beg_day、end_day,日期使用 YYYYMMDD,分别返回全日和半日交易日。本次查询三个市场的 20260921—20260927:
| 市场 | 本次日历返回的全日交易日 | 本次选择的目标日 |
|---|---|---|
| CN | 09-21、22、23、24 | 09-24 |
| HK | 09-21、22、23、24、25 | 09-25 |
| US | 09-21、22、23、24、25 | 09-25 |
三个市场的半日交易日列表本次均为空。A 股的日期差异有日历依据:上交所休市公告列明 9 月 25—27 日休市。香港证券市场的年度假期表没有把 9 月 25 日列为休市日,不能将 A 股假期直接套到港股。
本次在周日回看,因此上述目标日均已结束。若把流程改成工作日自动运行,还要判断目标交易日是否结束,处理半日市、当地时区和数据到达缓冲时间;不能只取交易日历最大值就开始计算。
图 1:本次日报在 9 月 27 日生成,A 股使用 9 月 24 日,港股和美股使用 9 月 25 日。为本次样本的日期组织示意,不是通用收盘时间表。
自选清单只需先明确四项:symbol、market、timezone、type。例如美股使用 America/New_York,港股使用 Asia/Hong_Kong,A 股使用 Asia/Shanghai。按 IANA 时区做日期转换,避免将纽约全年写成固定 UTC 偏移。
第二步:取两天收盘价,并确认目标日期真的在响应中
TickDB 的历史 K 线接口用于已结束周期;本次明确使用 type="stock"、interval="1d",而不是当前仍可能更新的实时 K 线。股票名称和币种通过股票信息接口按 symbol 关联,不依赖返回顺序。
本次六只股票首轮使用相同的 UTC 取数边界:
{
"symbol": "700.HK",
"type": "stock",
"interval": "1d",
"start_time": 1789862400000,
"end_time": 1790467200000,
"limit": 20
}
这是本次 MCP 工具 get_kline 的实际参数;文档对应的 REST 路径是 GET /v1/market/kline。窗口为 UTC 9 月 20 日 00:00 至 9 月 27 日 00:00。此处展示参数,不声称是一份已经配置鉴权的 REST 客户端。
接口数据规范将时间戳定义为 UTC 毫秒。本次观察到,日 K 时间转成市场当地时间后落在当天 00:00:腾讯目标日 1790265600000 对应香港 9 月 25 日 00:00,苹果目标日 1790308800000 对应纽约 9 月 25 日 00:00。它们是这批日 K 的日期标签,不能当成实际收盘时刻。这也是为什么不应直接截取 UTC 日期来关联交易日历。
验证规则很简单:目标日和日历上的前一交易日都必须存在。不能用“数组最后两条”替代这项检查,否则缺一天时,计算会悄悄变成跨多个交易日的变化。
第三步:把缺口变成待办,再决定日报能写什么
这次首轮返回了 26 根日 K。其中两只 A 股各四根、两只港股各四根、两只美股各五根。所有请求均返回 code=0,但两只港股缺少目标日 9 月 25 日。
| 阶段 | 600519.SH / 000001.SZ | 700.HK / 9988.HK | AAPL.US / MSFT.US |
|---|---|---|---|
| 首轮日期检查 | 目标日与前一日齐全 | 缺目标日,待补查 | 目标日与前一日齐全 |
| 港股定向补查后 | 齐全 | 两只均取得 09-25 日 K | 齐全 |
随后对两只港股分别发起一次目标日查询,时间窗改为 UTC 9 月 24 日 16:00 至 9 月 25 日 16:00,即香港当地 9 月 25 日的日期窗口。每次都返回一根目标日 K 线。两轮结果按 symbol + interval + adjust + time 合并,得到 28 根独立日 K,再重算最终日报。
**宽窗口为什么少一天,本轮没有确定原因。**可能的原因需要额外证据,不将它直接归结为缓存、权限或日历错误,也不把这两个样本概括成所有港股都存在相同行为。日报工作流已经可以做出可靠选择:目标日没取到就显示缺口,取到后再更新结果,并保留版本。
图 2:首轮 4/6 只满足本篇的两日数据条件;港股各补查一次后达到 6/6。此处是本次流程记录,不是接口成功率或服务可用性统计。
实际实现时可以给每行保留 complete、missing_target、missing_previous、request_error 等状态。这些是应用自己的分类,不是 TickDB 返回的业务状态码。遇到缺口,日报仍然可以生成,但要显示“待补”,不把上一日价格挪到目标日下面,也不默认填成 0% 涨跌。
第四步:计算交给代码,解释只写证据支持的内容
本篇只计算一个指标:
未复权收盘价变化(%)=(目标日 close ÷ 前一交易日 close − 1)× 100
所有日 K 响应都带有 adjust="none"。计算使用十进制数,前收盘价必须大于零;展示时才四舍五入到两位小数。下面是核心逻辑,bars_by_day 应当来自前面完成日期校验后的数据:
from decimal import Decimal, ROUND_HALF_UP
def close_change(bars_by_day, target_day, previous_day):
if target_day not in bars_by_day:
return {"status": "missing_target", "change_pct": None}
if previous_day not in bars_by_day:
return {"status": "missing_previous", "change_pct": None}
close = Decimal(bars_by_day[target_day]["close"])
previous = Decimal(bars_by_day[previous_day]["close"])
if not close.is_finite() or not previous.is_finite() or previous <= 0:
return {"status": "invalid_price", "change_pct": None}
change = ((close / previous - 1) * 100).quantize(
Decimal("0.01"), rounding=ROUND_HALF_UP
)
return {"status": "complete", "change_pct": str(change)}
以苹果为例:341.07 ÷ 335.92 − 1,换算后得到 +1.53%。这句话可以写进日报,因为原始两根 K 线和公式都在。至于“为何上涨”“是否突破”“明天应该怎么买”,单凭这组日 K 无法回答。
如果接入 AI 生成摘要,建议将输入限定为已经计算好的结构化行,要求保留市场日期、币种和数据状态。例如:
按市场总结以下日报。保留每行的目标交易日;只描述提供的收盘价变化;缺失项写待补。不推测新闻原因,不生成买卖建议,不将不同交易日合成同日排名。
本次示例摘要可以写成:A 股两只样本使用 9 月 24 日数据,未复权收盘价均低于前一交易日;港股两只样本经目标日补查后使用 9 月 25 日数据,变化分别为 -0.41% 和 -1.45%;美股两只样本使用 9 月 25 日数据,变化分别为 +1.53% 和 +3.66%。这些结论仅描述六只样本,不代表三个市场整体表现。
第五步:让日报的每个数字都能追溯回去
建议一次运行生成一个独立目录,至少保存以下内容:
| 文件 | 回答的问题 |
|---|---|
| 自选清单与运行元信息 | 这次看哪些股票、何时生成、各市场目标日是什么? |
| 请求参数与原始响应 | 用了什么窗口,接口实际返回了什么,是否发生错误? |
| 计算脚本与结果表 | 指标怎么计算,展示数字能否重新算出? |
| 日报正文与版本说明 | 首轮缺哪些数据,补查后哪些行改变? |
最有用的证据链是“日报行 → 请求 ID → 原始 K 线 → 计算公式”。本次腾讯行可以追到首轮 daily-700.HK 和补查 verify-700.HK,两个请求共同提供前一日与目标日收盘价。记录请求开始、结束的 UTC 和北京时间,另外保存 K 线自己的时间戳,不混用采集时间和行情日期。
本次共 15 次串行行情工具请求:交易日历 3 次、历史日 K 首轮 6 次、交易时段 3 次、股票信息 1 次、港股补查 2 次。没有返回错误码的行情请求,也没有进行压力测试。交易时段响应作为辅助证据留存,但不将其中某段的结束时间直接等同于完整收盘流程,更没有据此宣布已经验证了工作日自动调度。
本次覆盖六只股票和一个已结束窗口;未验证长期定时运行、停牌退市样本、半日市运行、历史币种变更或复权总回报。原始响应中的成交量和成交额保留在证据中,本篇没有用它们扩展成交活跃度结论。
从自己的六只股票开始
TickDB 在这条流程里承担的是数据输入:按市场提供交易日历,提供股票名称与币种,再取得已结束周期的历史 K 线。日期校验、缺口状态、指标计算和日报排版由应用完成。
如果准备做自己的版本,可以从历史 K 线文档开始,先选少量自选股,完成一次“取数—校验—补查—复算—归档”。验收时不要只看有没有一张漂亮表格,还要随机挑一行,沿着证据链找到它的两个收盘价和计算结果。
能复算、能解释日期差异、能把缺口明确留下来的日报,才适合成为第二天继续研究的起点。
