用 Codex 下載美股歷史數據並以 Python 匯出 CSV
美股历史数据下载:用 Codex 取数,Python 导出 CSV
文章示範用已接入行情數據工具的 Codex 查詢美股歷史日線,保存原始 JSON,再用 Python 校驗並匯出 CSV。示例查詢 AAPL.US 在 2026-10-12 至 2026-10-16 的 5 條不復權日線,並將查詢設定及實際返回範圍寫入元數據。腳本檢查回應狀態、標的與週期、時間戳及開高低收和成交量欄位;它不檢查交易日曆是否完整,也不處理多年數據分頁。
简介: 面向已在 Codex 中接入行情数据工具的研究者,记录美股历史数据下载的完整流程:确定股票、周期、日期与复权方式,用 Codex 按日期取数并保存原始 JSON,再用 Python 脚本校验并导出 CSV。覆盖美股历史行情、历史 K 线、MCP 取数、CSV 导出、空数据排查等关键词。核心主线是定条件、取数、校验、导出、回查,价值在于让每次取数都可追溯、可复用,减少重复查询和设置混淆。
面向已在 Codex 中接入行情数据工具的研究者,记录美股历史数据下载的完整流程:确定股票、周期、日期与复权方式,用 Codex 按日期取数并保存原始 JSON,再用 Python 脚本校验并导出 CSV。覆盖美股历史行情、历史 K 线、MCP 取数、CSV 导出、空数据排查等关键词。核心主线是定条件、取数、校验、导出、回查,价值在于让每次取数都可追溯、可复用,减少重复查询和设置混淆。
这篇记录美股历史数据下载的一次完整流程:用 Codex 取数,再用 Python 导出 CSV。把一只美股某段历史价格放进 Excel 或 Python 做分析时,股票代码、日期范围、K 线周期和复权方式需要一起保存。后面重新取数或复查结果,才能知道两份文件是否使用了相同设置。
这篇教程使用历史 K 线能力,经 MCP 把按需查询的日线交给 Codex,再整理成可复用的研究文件。核心只有一条线:定条件、取数、校验、导出、回查。
本例在 2026 年 10 月 27 日于 Codex 中调用数据工具,取得 AAPL.US 在 10 月 12 日至 16 日 UTC 日期范围内的 5 条不复权日线,并用文中的 Python 脚本导出 CSV。你可以沿同一流程更换研究对象与日期。
定条件(股票 / 周期 / 日期 / 复权方式)
↓
Codex 调用 get_kline,保存原始 JSON
↓
脚本校验(code、标的、时间戳、字段)
↓
导出 CSV + meta.json
↓
回查(条数、首尾时间、交易日历)
美股历史数据下载的流程分工
这条流程的分工很清楚:使用者定条件,Codex 调工具,脚本负责转换和记录。TickDB 为开发者和 AI 应用提供统一的全球行情数据接口,让团队通过一套接入获取多市场实时与历史数据,更快构建行情、分析和监控产品。
先确定研究对象和取数设置,再让 Codex 调用历史 K 线工具。返回的价格保留在原始响应中,后续解释、表格计算和文件转换都可以回到这份输入核对。官方 AI 接入说明提供了让客户端调用行情工具的入口。
这条流程里的分工是:
| 环节 | 负责的动作 | 交给下一步的内容 |
|---|---|---|
| 使用者 | 确定研究对象、日期、周期与复权方式 | 一组明确的查询条件 |
| Codex | 根据条件调用已连接的数据工具,并保存返回结果 | 原始业务 JSON |
| 数据接口 | 按请求返回历史日线与对应的数据字段 | 股票、周期、复权方式、时间和价格成交量记录 |
| 本文 Python 脚本 | 检查响应与所选条件,转换文件并记录范围 | CSV 与实际返回范围记录 |
CSV 转换和范围记录由本文脚本完成。数据接口在这里的作用,是向 AI 研究流程提供带明确对象、周期和复权方式的历史行情输入;使用者可以在 Excel、Python 或后续 AI 分析中复用同一份原始数据。
历史 K 线接口怎样减少重复查询
减少重查的关键,不是多存一份价格,而是把请求条件和返回字段一起保留。这次使用的 get_kline 不只返回几行价格。请求条件与返回字段一起保留,才能说明这份文件来自哪一次取数。下面几项直接影响后续使用:
| 参数或返回字段 | 本例怎样使用 | 研究时保留了什么依据 |
|---|---|---|
symbol、interval |
锁定 AAPL.US 与 1d,导出前检查返回值 |
知道文件对应哪只股票、什么周期 |
adjust |
请求并核对 none |
知道文件采用不复权价格,便于与相同设置的数据比较 |
time |
保留原始毫秒时间戳,另写一列 UTC 时间 | 可以回查记录时点,避免展示时丢掉时间依据 |
open/high/low/close/volume |
原值写入 CSV,不做四舍五入或缺失填零 | 下游计算可以追溯到同一份接口返回 |
例如,研究者准备观察 AAPL.US 这段日线时,先请求 1d、none 和指定日期;返回后检查对象与设置,再决定把这份数据用于接下来的计算。下次换日期或改为其他复权方式时,可以对照原始响应和范围记录,定位变化来自请求条件还是返回数据。
这里完成的是数据准备。历史数据进入回测时,还需根据研究方法处理交易日历、交易成本和样本等条件;本次没有运行完整回测。
用 Codex 下载美股历史数据的前置条件
需要三样东西:已接入数据工具的 Codex、Python 环境,以及能查询指定日期范围的账号权限。准备已接入 MCP 的 Codex 环境,以及 Python 3.9 或以上版本。MCP 是让 AI 助手实际调用外部数据工具的连接方式;本例在 Python 3.14.2 上运行,CSV 转换使用标准库,无需另装数据处理包。
尚未连接的读者,可以先查看官方 AI 工具页的 MCP 配置说明。密钥填在客户端的连接配置中,下面的转换脚本不需要密钥。
还要确认账号具备查询美股和指定历史日期范围的权限。当前 K 线文档注明,指定 start_time、end_time 时间范围需要相应账号权限;具体可访问的数据以账号权限和实际返回为准。
第一步:确定股票、日期和复权方式
先固定四项设置,后面取数和转换都围绕它们。先把这四项固定下来:
| 项目 | 本例设置 |
|---|---|
| 股票代码 | AAPL.US |
| 数据周期 | 日线,1d |
| 日期范围 | 2026-10-12 至 2026-10-16,按 UTC 日期筛选,两端日期均包含 |
| 复权方式 | none,不复权 |
UTC 是统一时间基准。复权方式决定历史价格是否按分红拆股调整。本例保留原始时间戳及 UTC 时间,不把时间戳自动改写为交易所的交易日标签。将来研究盘前盘后或具体交易时刻时,需要另外处理美东时区和交易时段。
复权方式也要跟文件一起保存。不同复权方式的历史价格不能直接混在一列里比较;如果改为前复权或后复权,需要同时修改取数参数和转换命令。
第二步:用 Codex 按日期取数并保存原始 JSON
让 Codex 实际调用工具,并把原始业务 JSON 原样保存。在已连接数据工具的 Codex 对话中输入:
请实际调用 get_kline 工具,查询下面这段美股历史日线:
symbol: AAPL.US
type: stock
interval: 1d
adjust: none
start_time: 1791763200000
end_time: 1792195199999
limit: 1000
这对应 2026-10-12 00:00:00.000 UTC 至
2026-10-16 23:59:59.999 UTC。
把完整的原始业务 JSON 响应保存为 aapl_daily.json,
保留 code、message、data 和价格字符串,不补齐或改写行情。
若工具调用失败,直接报告错误,不生成替代数据。
如果不能保存文件,请完整展示原始业务 JSON,供我保存。
这里的原始业务响应,指包含 code、message、data 的那份 JSON。AI 助手如果不能操作本地文件,可以把这份 JSON 复制到文本编辑器,按 UTF-8 保存为 aapl_daily.json,不要把 Markdown 的三个反引号一起复制进去。
本次工具返回 code=0,data 中保留了 symbol=AAPL.US、interval=1d、adjust=none 和 5 条日线。下面的收盘价来自这份原始响应,便于导出后逐项核对:
| 原始记录的 UTC 时间 | close 原值 |
|---|---|
| 2026-10-12 04:00:00+00:00 | 340.97000000 |
| 2026-10-13 04:00:00+00:00 | 341.27000000 |
| 2026-10-14 04:00:00+00:00 | 342.96000000 |
| 2026-10-15 04:00:00+00:00 | 342.00000000 |
| 2026-10-16 04:00:00+00:00 | 343.46000000 |
5 个交易日收盘价从 340.97 缓步到 343.46,中间 10 月 15 日小幅回落。表中的时间来自返回记录,不能据此把 04:00 UTC 理解成美股开盘时间。下载时先保留这些原值,后面的展示和计算另做处理。
第三步:用 Python 脚本导出 CSV
脚本先校验,再导出;校验不通过就停止。把下面的代码保存为 export_csv.py,与 aapl_daily.json 放在同一个文件夹。
脚本先检查查询状态、股票代码、周期和复权方式,再检查时间戳是否重复或超出所选日期范围。检查通过后,原始价格和成交量字符串直接写入 CSV,不做四舍五入,也不把缺失数据填成零。
# 测试环境:Python 3.14.2 / 2026-10-27
import argparse
import csv
import json
from datetime import date, datetime, time, timedelta, timezone
from pathlib import Path
def main():
p = argparse.ArgumentParser(description="Export a TickDB daily response to CSV")
p.add_argument("source", help="Original business JSON response")
p.add_argument("--symbol", default="AAPL.US")
p.add_argument("--start", default="2026-10-12", help="UTC calendar date")
p.add_argument("--end", default="2026-10-16", help="Inclusive UTC date")
p.add_argument("--adjust", choices=["none", "forward", "backward"], default="none")
a = p.parse_args()
start_date, end_date = date.fromisoformat(a.start), date.fromisoformat(a.end)
if start_date > end_date:
raise ValueError("Start date must not be after end date")
start = int(datetime.combine(start_date, time.min, timezone.utc).timestamp() * 1000)
end = int(datetime.combine(end_date + timedelta(days=1), time.min, timezone.utc).timestamp() * 1000) - 1
source = Path(a.source)
response = json.loads(source.read_text(encoding="utf-8-sig"))
if response.get("code") != 0:
raise ValueError("Query failed; inspect code/message before exporting")
data = response["data"]
if (data.get("symbol"), data.get("interval"), data.get("adjust")) != (a.symbol, "1d", a.adjust):
raise ValueError("Returned symbol/interval/adjust differs from your settings")
rows = sorted(data["klines"], key=lambda row: int(row["time"]))
if not rows or len(rows) >= 1000:
raise ValueError("Empty result or response limit reached; inspect the query")
stamps = [int(row["time"]) for row in rows]
if len(stamps) != len(set(stamps)) or any(not start <= ts <= end for ts in stamps):
raise ValueError("Duplicate or out-of-range timestamps; export stopped")
fields = ["open", "high", "low", "close", "volume"]
if any(row.get(field) is None for row in rows for field in fields):
raise ValueError("Missing OHLCV field; export stopped")
def utc(ts):
return datetime.fromtimestamp(ts / 1000, timezone.utc).isoformat()
output = source.with_suffix(".csv")
with output.open("w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(["symbol", "interval", "adjust", "time_ms", "time_utc"] + fields)
for row in rows:
writer.writerow([a.symbol, "1d", a.adjust, row["time"], utc(int(row["time"]))] + [row[k] for k in fields])
meta = dict(converted_at_utc=datetime.now(timezone.utc).isoformat(),
source=source.name, symbol=a.symbol, interval="1d", adjust=a.adjust,
requested_start_utc=utc(start), requested_end_utc=utc(end),
returned_rows=len(rows), actual_first_utc=utc(stamps[0]),
actual_last_utc=utc(stamps[-1]), calendar_completeness="not_checked")
output.with_suffix(".meta.json").write_text(json.dumps(meta, indent=2), encoding="utf-8")
print(f"SOURCE API code={response['code']} symbol={a.symbol} interval=1d adjust={a.adjust}")
print(f"PASS rows={len(rows)} first_utc={utc(stamps[0])} last_utc={utc(stamps[-1])}")
print(f"CSV {output.name}")
print("SUMMARY response=PASS timestamp_checks=PASS csv_export=PASS")
print("BOUNDARY one saved response; exchange calendar completeness not checked")
if __name__ == "__main__":
try:
main()
except (ValueError, KeyError, TypeError, OSError) as exc:
raise SystemExit(f"ERROR: {exc}")
脚本内部的校验顺序可以单独看:
读 JSON
→ code == 0 ?
→ symbol / interval / adjust 与请求一致 ?
→ 按 time 排序,去重,检查是否越界 ?
→ OHLCV 字段是否齐全 ?
→ 全部通过才写 CSV,否则停止并报错
在这个文件夹打开终端,运行:
python3 export_csv.py aapl_daily.json --symbol AAPL.US --start 2026-10-12 --end 2026-10-16 --adjust none
如果电脑使用 python 命令启动 Python,把命令开头的 python3 换成 python。
本次执行输出为:
SOURCE API code=0 symbol=AAPL.US interval=1d adjust=none
PASS rows=5 first_utc=2026-10-12T04:00:00+00:00 last_utc=2026-10-16T04:00:00+00:00
CSV aapl_daily.csv
SUMMARY response=PASS timestamp_checks=PASS csv_export=PASS
BOUNDARY one saved response; exchange calendar completeness not checked
文件夹里会多出两个文件:
aapl_daily.csv:可供 Excel、WPS 或后续程序读取的日线表格。aapl_daily.meta.json:记录转换时间、所选日期、复权方式、返回条数和实际首尾时间。
CSV 包含股票代码、周期、复权方式、原始毫秒时间戳、UTC 时间,以及开盘价、最高价、最低价、收盘价和成交量。CSV 使用带 BOM 的 UTF-8 编码,方便常见表格软件识别。
CSV 导出后怎样核对数据范围
先看元数据文件里的条数和首尾时间,再看原始 JSON。先看 aapl_daily.meta.json 中的 returned_rows、actual_first_utc 和 actual_last_utc。它们能帮助你确认这次实际拿到了哪段数据。本例返回 5 条,首尾记录分别为 10 月 12 日与 16 日。
脚本检查的是返回数据本身的重复、范围和必要字段,没有对照交易日历验证是否漏了应有交易日。如果换成其他股票或日期后条数不符合预期,应先查看原始 JSON 和权限,再结合交易日历确认休市、上市时间或数据缺口,不要直接把空档补成零。
用 Excel 打开时,长时间戳可能显示为科学计数法,可以优先查看 time_utc。建议保留原始 JSON 和 CSV,展示或计算用另一份工作表,方便回查。
当前示例在单次响应内完成,不承担多年历史的分页下载。若工具返回达到单次上限,脚本会停止,避免把截断结果当成整个区间。需要批量获取时,可参考官方文档中的历史数据批量拉取方案;其中的具体接口与权限应对照当前文档使用。
把一次导出接入自己的研究流程
把原始 JSON、CSV 和范围记录放在一起,下一次换条件时同步改命令。建议把三份文件放在同一目录。下一次更换股票或日期时,先修改查询条件,再同步修改转换命令;这样,表格里的结果仍能对应到一份明确的原始输入。
如果你的任务发展为多标的、分段历史数据准备,可以在这条路径上增加分页、续传和交易日历检查。若要建设持续接收盘中变化的监控产品,则需要按 WebSocket 文档设计订阅、心跳与断线恢复;本文使用的 MCP 是按需查询入口。
尚未接入的读者,可以先从官方入口确认账号与查询权限,再按照 AI 工具页的 MCP 说明连接 Codex。已经连接的读者,直接用自己的股票和短日期区间完成一次取数、导出和回查。
常见问题
美股历史数据下载第一次从哪里开始
先连接 MCP,确认账号能查美股及指定日期范围,再使用上面的短区间样例。原始 JSON 成功返回后,运行转换脚本。先取得一份能复查的小文件,再扩大日期范围。
返回空数据或导出报错怎么排查
先检查 JSON 中的 code 和 message,再核对股票代码、日期与权限。脚本若提示返回的股票、周期或复权方式不一致、重复时间戳或范围越界,会停止导出;保留原文件,定位问题后重新取数和转换。
CSV 导出后能用来做什么
可以把它作为 Excel 观察、Python 分析或回测前的数据输入。需要长期批量更新时,再增加分段查询、续传和交易日历检查;需要做行情界面时,可参考历史走势与 CSV 导出的面板示例。
把示例换成你要研究的股票和日期时,要同时修改取数请求与转换命令,保存对应的原始 JSON 和范围记录。
文中股票与价格用于数据操作演示,不构成投资建议。
來源:阿里雲開發者社區 AI · developer.aliyun.com