Insights·2026-07-25

要让 AI 通过 Toss 证券 Open API 交易股票,需要准备什么?

Toss 证券 Open API 是一套 REST API,涵盖行情与个股信息、账户与持仓、下单与改单撤单,以及监视价格并在触发时自动下单的条件单。登录 Toss 证券 WTS,在设置中的 Open API 菜单里签发 client_id 与 client_secret,并把调用来源 IP 登记到允许列表,准备工作就完成了。再接上 Claude Code 或 Codex 这类终端 AI 代理,就可以用自然语言描述交易规则来自动化查询与下单,而不必自己写代码。但查询一旦打通,下单也随之打通,所以在真实下单之前必须由人先设好闸门:默认演练模式、显式执行标志、金额上限与幂等键。

토스증권 Open API 가이드의 시작하기 화면. 클라이언트 등록, 허용 IP 등록, 액세스 토큰 발급, API 호출의 네 단계와 토큰 발급·시세 조회·보유 주식 조회 curl 예시가 보인다.
토스증권 Open API 가이드의 시작하기 4단계. 2번 허용 IP 등록이 첫 연동에서 가장 많이 막히는 지점이다.

Toss 证券 Open API 开放了什么

API 是让程序代替人去敲的窗口。可以把它理解成券商开的一扇门,平时在 App 里用手点的查询和下单,现在可以按固定格式发送请求来完成。与自动点击 App 界面的取巧做法不同,这是官方通道,不必担心账号被限制。

功能分为五类:认证(Auth)、行情与个股信息(Market Data、Stock Info、Market Info、Market Indicators、Ranking)、账户与资产(Account、Asset)、订单(Order、Order History、Order Info)、条件单(Conditional Order、Conditional Order History)。覆盖韩国(KRX)与美国股票。

行情与个股信息对所有用户一致,只要有令牌就能调用:现价、盘口、成交、K 线(1 分钟与日线)、涨跌停价、个股主数据、买入注意事项、汇率、韩美市场日历、成交额与涨跌幅排行,以及指数与分投资者成交额。

账户与资产、订单、条件单会直接影响自己的账户,因此除令牌外还需要账户识别请求头。本文真正要讲的正是这一半。

目前只提供 REST。用于实时推送的 WebSocket 标注为后续支持,所以现阶段需要按需轮询。

在哪里、怎么申请

申请入口不是开发者表单,而是 Toss 证券的网页交易端 WTS(tossinvest.com)。用已有的 Toss 证券账户登录后进入设置,就能看到 Open API 项,在那里自行签发 client_id 与 client_secret。没有审核排队,当场完成。

client_id 相当于账号,client_secret 相当于密码。离开签发页面后通常无法再次查看 secret,请当场复制保存到安全的地方。

第二步才是真正的关口。在同一页面下方的允许 IP 管理里,登记将要调用 API 的 IP。不在列表中的 IP 即使密钥正确也会被 403 拦截。公网 IP 可以在终端用一行 curl ifconfig.me 查到。

家庭或办公室线路的公网 IP 可能变动,这点最好提前知道。某天忽然出现 403,多半不是密钥问题而是地址变了。如果打算在服务器或云上运行自动化,请登记那台机器的出口 IP。

开放是按账户逐步进行的,如果设置里看不到 Open API 菜单,说明还没轮到。此时可以通过页面横幅的预约申请登记,开放时会收到通知。

取得令牌并完成第一次调用

所有调用都需要 OAuth 2.0 访问令牌,签发方式是 Client Credentials Grant,即由程序用自己的 id 与 secret 换取令牌,而不是让人走登录界面。这正是它适合无人值守自动化的原因。

记住三点即可。有效期为 86400 秒,也就是 24 小时。没有刷新令牌,过期后向同一端点重新申请即可。每个客户端同时只有一个有效令牌,重新签发会立即让此前的令牌失效。若多个脚本各自申请令牌就会互相顶掉,因此应把令牌缓存到文件中共享使用直到过期。

官方指南的示例是把 client_id 与 client_secret 放在请求体里。不过在我的环境中请求体方式返回 invalid_client,改用 HTTP Basic 认证请求头才签发成功。哪种可用就用哪种。

拿到令牌后,先从不触及账户的查询开始。个股信息与现价只要令牌即可。随后查询账户列表可以拿到 accountSeq,这个值就是之后持仓、订单、条件单调用中 X-Tossinvest-Account 请求头的内容。

令牌签发与三个查询
# 1) 令牌签发(官方示例:请求体方式)
curl -s -X POST 'https://openapi.tossinvest.com/oauth2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'client_secret=YOUR_CLIENT_SECRET'

# 若返回 invalid_client,改用 Basic 请求头
curl -s -X POST 'https://openapi.tossinvest.com/oauth2/token' \
  -u "$TOSS_API_KEY:$TOSS_SECRET_KEY" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials'

# 2) 个股信息(仅需令牌)
curl -s 'https://openapi.tossinvest.com/api/v1/stocks?symbols=005930' \
  -H "Authorization: Bearer $TOKEN"

# 3) 持仓(令牌 + 账户请求头)
curl -s 'https://openapi.tossinvest.com/api/v1/holdings' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tossinvest-Account: 1'

Claude Code 与 Codex 是什么,如何安装

Claude Code 出自 Anthropic,Codex 出自 OpenAI,都是运行在终端里的 AI 编码代理。不是在聊天窗口给你代码让你粘贴,而是由代理直接在你的电脑上读写文件、执行命令。因此特别适合 API 对接这种读文档、写代码、运行、核对结果的循环。

只要装有 Node.js,安装就是一行:npm install -g @anthropic-ai/claude-code 或 npm install -g @openai/codex,之后用 claude 或 codex 启动。首次运行需要登录或登记密钥,Claude Code 用付费 Claude 订阅账户,Codex 用 ChatGPT 账户或 OpenAI API 密钥。

两者装一个就够。若都装,意义在于交叉复核:让一方审阅另一方写的代码。涉及下单的代码,这种复核很值。

有一条原则不可妥协。签发的密钥要放进 .env 文件,并把该文件写入 .gitignore,避免进入代码仓库。不要把密钥直接写进聊天窗口或代码。券商密钥一旦泄露,别人就能在你的账户里下单。

还有一点,不要在代理可以访问下单 API 的情况下,开启无需确认就执行一切命令的模式。很多人为了省事这么用,但在可能产生真实成交的环境里,逐条确认才是正确的默认值。

安装与密钥保管
# 终端 AI 代理(需要 Node.js)
npm install -g @anthropic-ai/claude-code   # 运行:claude
npm install -g @openai/codex               # 运行:codex

# 密钥放在 .env 并排除出仓库
cat >> .env <<'EOF'
TOSS_API_KEY=你的_client_id
TOSS_SECRET_KEY=你的_client_secret
EOF
echo '.env' >> .gitignore

该让代理做什么

第一件事是让它读官方文档。Toss 证券另外提供了适合机器阅读的版本,公开了规范原始 JSON 与 Markdown 概览,把地址告诉代理,它就不会去猜端点与请求格式。

接着从查询开始。让它写一个从 .env 读取密钥、把持仓与浮动盈亏输出成表格的脚本,得到的就是令牌签发与缓存、账户查询、持仓查询的组合。运行后用肉眼与 App 界面核对数字。跳过这一步,之后所有自动化都建立在未经验证的地基上。

查询对上之后,用自然语言描述交易规则,例如自最高价回落 20% 就全部卖出。关键不在于规则如何编码,而在于你能否说清楚它在什么时点、以哪个价格为准判定:按收盘价还是盘中价,一天检查几次。

最后,把反复使用的工作固化成代理的技能或命令文件。既不用每次重复解释,也能把安全规则一并写进去。

把下单交出去之前必须设好的闸门

查询一旦打通,下单也随之打通。用同样的令牌与请求头发一次 POST,就是真实成交。所以在写下单代码之前先定好安全装置更稳妥。

把安全装置分成两层来想会更清楚:API 本身提供的一层,以及自己在脚本里加的一层。

API 一侧最具代表性的是幂等键。在下单请求里放入 clientOrderId,即使因网络重试发送两次,订单也只受理一次;用同一个键发送内容不同的订单会被拒绝,因此也能拦住失误。另外还有一条:订单金额达到 1 亿韩元以上时,必须把 confirmHighValueOrder 设为 true 才会受理。

我加的一层是这样。默认始终是演练模式,仅凭参数不会真正下单。真实下单同时要求执行标志与标的一致性确认。订单金额上限写在文件里,超过就必须另加标志才放行。默认限价,市价只有明确指定时才开启。下单前买入先查可用金额、卖出先查可卖数量。

这一层按自己的代码来设计即可。形式不重要,原则才重要:真实下单必须由人再明确确认一次,自动化不能自行越过上限。

装置防止什么
APIclientOrderId 幂等键网络重试导致同一笔订单被受理两次
APIconfirmHighValueOrder1 亿韩元以上的订单未经确认发出
API可用金额与可卖数量查询直接发出超过余额的订单
我的脚本默认演练模式参数输错就产生真实下单
我的脚本执行标志加标的确认订单落到错误的标的上
我的脚本订单金额上限自动化执行超出预期的金额
我的脚本默认限价,市价需显式指定盘口很薄时以市价被推着成交
创建订单 — 限价买入
curl -s -X POST 'https://openapi.tossinvest.com/api/v1/orders' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tossinvest-Account: 1' \
  -H 'Content-Type: application/json' \
  -d '{
    "symbol": "005930",
    "side": "BUY",
    "orderType": "LIMIT",
    "quantity": 10,
    "price": "70000",
    "clientOrderId": "my-order-20260725-001"
  }'

条件单 — 把监视交给券商服务器

要自动止损或止盈,通常需要一个持续盯价的程序,而那台机器休眠或关机时监视就中断了。条件单把这份监视交给券商服务器。

类型有三种。SINGLE 只监视一个条件。OCO 同时监视两个条件,其中之一触发后自动撤销另一个,也就是止损与止盈成对的经典用法;两条腿都是卖出,第一个触发价要高于现价,第二个要低于现价。OTO 则在第一个条件成交之后才开始监视第二个,第一腿买入、第二腿卖出,可以把入场与离场一次登记。

限制也要知道。OCO 与 OTO 只支持限价,同一标的只能有一个组合条件单,若设定的价格已经满足条件则会被拒绝。SINGLE 没有每标的数量限制。

与自建监视程序相比,取舍很清楚。条件单由服务器监视,与自己电脑的状态无关,反应也更快,但条件仅限于单纯的价格水平。需要计算的条件,例如均线或突破新高,仍要在自己这边判定后再下单。实务上比较顺手的分工是:止损止盈这类防线交给条件单,需要计算的入场判断留给自己的脚本。

登记条件单 — SINGLE
curl -s -X POST 'https://openapi.tossinvest.com/api/v1/conditional-orders' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tossinvest-Account: 1' \
  -H 'Content-Type: application/json' \
  -d '{
    "symbol": "005930",
    "type": "SINGLE",
    "quantity": 100,
    "orderType": "LIMIT",
    "clientOrderId": "my-cond-20260725-001",
    "expireDate": "2026-09-10",
    "first": {
      "orderSide": "SELL",
      "triggerPrice": "295",
      "orderPrice": "295"
    }
  }'

如何应对调用限额与错误

所有 API 都按客户端与 API 分组限制每秒请求数。行情为每秒 10 次,订单为每秒 6 次,而开盘后的 09:00 至 09:10 降为每秒 3 次。账户列表查询最紧,为每秒 1 次,因此账户编号这类几乎不变的值应取一次并缓存。

超限会返回 429。按响应头 Retry-After 等待后重试,若反复出现则以 1 秒、2 秒、4 秒的方式退避并加入少量随机延迟。正常响应也会带回剩余额度,额度下降时提前放慢速度更安全。

错误格式统一,按 code 分支即可:令牌过期为 expired-token,余额不足为 insufficient-buying-power,非受理时间为 order-hours-closed,价格超出涨跌停为 price-out-of-range,同一幂等键内容不同为 idempotency-key-conflict。需要咨询时附上响应中的 requestId。

把脚本交给代理时,最好一开始就要求写好这些错误处理。若只说做出来,往往只写成功路径,那样接到定时任务上就会静默失败。

总结:按这个顺序开始

第一,在 Toss 证券 WTS 设置里签发 Open API 密钥并登记允许 IP。第二,在终端用 curl 取得令牌并查询一条个股信息,这一步确认连通。

第三,安装 Claude Code 或 Codex,把密钥放进 .env,让它写出持仓查询脚本,并与 App 界面核对数字。第四,编写下单脚本,默认演练模式,并从一开始就装好真实下单的闸门。第五,用极小数量真实下单一次,并确认改单与撤单。第六,把止损止盈这类防线迁移到条件单。

最后一点虽然显而易见仍要说明。自动交易会把错误的规则又快又忠实地重复执行。开始时务必用小额,充分演练之后再实盘,结果责任完全由本人承担。

至于如何验证规则过去是否真的赚钱,也就是用历史数据检验交易规则的回测,将在下一篇讨论。