phenomenoner/neoapi-skill · Archived

neoapi-python

Fubon Neo (富邦新一代/富邦 API) Python SDK guidance focused on trading and market data workflows, including login, market data access, order placement, and locating the right docs/llms outputs. Use when prompts mention FubonNeo API or the Python SDK.

First seen May 5, 2026

Installation

$ npx skills add phenomenoner/neoapi-skill --skill neoapi-python

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 16
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0-beta.32

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 17,644 B
  • docs SUMMARY.md 278 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

NeoAPI Python

Overview

本 skill 教導 AI 編程代理使用 Fubon Neo Python SDK 進行台股證券交易與行情資料存取。適用 Python 3.8–3.13、SDK >= 2.x(避免 3.14)。預設 SDK ~2.2.8,除非使用者另外指定。

TL;DR — 三大工作流程:
1. 登入 → sdk.login(ID, PWD, cert, cert_pwd) 取得帳號清單
2. 下單 → 建構 Order(...) → sdk.stock.place_order(acc, order)
3. 行情 → sdk.initrealtime() → sdk.marketdata.restclient.stock.intraday.*

Shioaji migration routing

When the user asks to migrate or port existing Shioaji code, keep the tone practical and neutral: help them translate working code safely; do not frame the answer as a broker comparison. Load references/migration-shioaji.md first, then add the narrow reference below when needed.

Migration task Load / check
Login / CA / account selection references/migration-shioaji.md + official login docs
Stock order placement references/migration-shioaji.md + references/implementation-practices.md
Modify / cancel / status tracking references/migration-shioaji.md + references/response-shapes.md
Quantity or lot-size confusion references/migration-shioaji.md (Neo quantity is shares)
Test vs production behavior references/test-environment.md
WebSocket / callback migration references/migration-shioaji.md + references/examples-guidance.md

常見錯誤(Common Mistakes)

錯誤 正確做法
pip install fubon-neo SDK 不在 PyPI,需從官方頁面下載 .whl 安裝
在測試環境用 intraday.quote 判斷可下單價格 測試環境應用 sdk.stock.querysymbolquote(acc, symbol)
SDK >= 2.2.1 仍用 FubonSDK() 初始化 需用 FubonSDK(30, 2) (或含 url= 參數)
預設憑證密碼卻傳 cert_pass="" SDK >= 1.3.2 應省略第 4 個參數:sdk.login(id, pwd, cert_path);不要用空字串代替
下單後找不到已刪的單 已刪單仍在 getorderresults 中,status=30
登入後直接用 sdk.marketdata.rest_client 需先呼叫 sdk.init_realtime()
user_def 字串過長 建議 10 字元以內,過長會被截斷
在 Python 3.14 使用 SDK v2 官方目前支援 Python 3.8–3.13,不支援 3.14
數量填「張數」而非「股數」 FubonNeo 數量一律為股數(1 張 = 1000 股)
WebSocket on_message 直接取 message["price"] 訊息是 envelope 結構,交易資料在 message["data"] 內,需先檢查 message["event"] == "data"
用 data["price"] == "市價" 判斷 WebSocket 價格狀態 價格欄位是數值;值為 0 時應搭配同欄位的 isLimitUp / isLimitDown 旗標解碼,不能比對字串或臆測原始委託型別

Public Docs Access

- <https://www.fbs.com.tw/TradeAPI/llms.txt>; - <https://www.fbs.com.tw/TradeAPI/llms-full.txt>; - <https://www.fbs.com.tw/TradeAPI/en/llms.txt>; - <https://www.fbs.com.tw/TradeAPI/en/llms-full.txt>;

  • Note: The .md URL trick is no longer supported; use .txt instead. Every page under /TradeAPI/docs/ or /TradeAPI/en/docs/ can be accessed as plain text by appending .txt (e.g., https://www.fbs.com.tw/TradeAPI/docs/trading/introduction.txt). Use llms.txt to find the page paths.

Usage Cheat Sheet

Quickstart (Trading)

from fubon_neo.sdk import FubonSDK, Order, Mode
from fubon_neo.constant import BSAction, MarketType, PriceType, TimeInForce, OrderType

# Init & Login
sdk = FubonSDK()  # Use FubonSDK(30, 2) if on SDK 2.2.1+
accounts = sdk.login("ID", "PWD", "C:/path/to/cert.pfx", "CertPWD")
acc = accounts.data[0]  # Pick stock account

# Place Order (Buy 1000 shares of 2330 at Limit 580)
# Keyword form recommended (matches official docs); positional form also works.
order = Order(
    buy_sell=BSAction.Buy,
    symbol="2330",
    quantity=1000,
    market_type=MarketType.Common,
    price_type=PriceType.Limit,
    time_in_force=TimeInForce.ROD,
    order_type=OrderType.Stock,
    price="580"
)
res = sdk.stock.place_order(acc, order)
print(f"Order: {res.data.order_no}")

Certificate Password Login

# Certificate with a user-defined password
accounts = sdk.login(user_id, login_password, cert_path, cert_password)

# Certificate using the official default-password mode (SDK >= 1.3.2)
# Omit the fourth argument entirely; do not pass "" or None.
accounts = sdk.login(user_id, login_password, cert_path)

若程式從環境變數讀取自訂憑證密碼,請在缺值時直接報錯,不要用 os.getenv("CERT_PASSWORD", "") 靜默退回空字串。測試環境的憑證密碼則依官方測試包為 12345678。

官方依據:https://www.fbs.com.tw/TradeAPI/docs/trading/quickstart.txt。

Critical Constants

Category Class Common Values
Action BSAction .Buy, .Sell
Price PriceType .Limit (限價), .Market (市價), .Reference (參考價)
Time TimeInForce .ROD (當日有效), .IOC (立即成交否則取消), .FOK (全部成交否則取消)
Market MarketType .Common (整股), .IntradayOdd (盤中零股), .Odd (盤後零股)
Order OrderType .Stock (現股), .MarginTrading (融資), .ShortSelling (融券)

Validating Prices

Real-time quotes (intraday.quote) may differ from valid order prices (especially in Test Env).

  • For Orders: Always check sdk.stock.querysymbolquote(acc, symbol).

- Use limitupprice / limitdownprice from this result for placing limit orders. - This source reflects the order system's view of validity.

  • For Display: Use sdk.marketdata.rest_client.stock.intraday.quote(symbol).

Rate Limits (Summary)

  • REST: 300 req/min (IP-based).
  • WebSocket: 200 subscriptions per connection.

SDK 版本相容性(Version Compatibility)

SDK Version Python Constructor 備註
>= 2.2.6 3.8–3.13 FubonSDK(30, 2) 下單錯誤拋出 FugleAPIError
2.2.1–2.2.5 3.8–3.13 FubonSDK(30, 2) 錯誤在 response 物件中
2.0–2.2.0 3.8–3.13 FubonSDK() 無位置參數
1.3.1–1.x 3.8–3.12 FubonSDK() 測試環境最低要求

測試環境一律加 url="wss://neoapitest.fbs.com.tw/TASP/XCPXWS" 參數。

工作流程決策樹(Workflow Decision Tree)

需求是什麼?
├── 交易(Trading)
│   ├── 下單 / 改單 / 刪單
│   │   ├── 測試環境?→ FubonSDK(30, 2, url=test_url) + query_symbol_quote 取價格
│   │   └── 正式環境?→ FubonSDK(30, 2) + intraday.ticker 取漲跌停
│   ├── 查詢帳務 → sdk.stock.get_order_results / get_inventories
│   └── 當沖(Day Trade)→ 見下方「當沖」章節
├── 行情(Market Data)
│   ├── 即時快照 → HTTP: intraday.quote(成交)/ intraday.ticker(參考價/漲跌停)
│   ├── 歷史資料 → HTTP: historical
│   └── 即時串流 → WebSocket: sdk.init_realtime() + subscribe
└── 環境確認
    ├── SDK 版本 → 見上方「版本相容性」
    ├── 安裝方式 → 官方 .whl(非 PyPI)
    └── 文件查詢 → references/doc-index.md

Trading Workflow

  • Start from docs/trading/prepare and docs/trading/quickstart for setup.
  • Use Python library references under docs/trading/library/python/ for exact function names, parameters, and return types.
  • Typical flow: login (password or API key) → place/modify/cancel order → query order/account info → logout.
  • Always mention rate limits when relevant (docs/trading/trade-rate-limit).

Market Data Workflow

  • Decide on HTTP vs WebSocket:

- HTTP API for snapshots, intraday, historical. - WebSocket API for real-time streams.

  • Use docs/market-data/http-api/getting-started and docs/market-data/websocket-api/getting-started.
  • Mention connection setup and rate limits when relevant.
  • To use sdk.marketdata.restclient, call sdk.initrealtime() after login.
  • For limit-up/limit-down prices in market data, use intraday.ticker (not intraday.quote).
  • Raw WebSocket JSON uses camelCase flags such as isLimitUpPrice and isLimitDownAsk; these booleans may be omitted when the condition is false, so read them with data.get(flag, False).
  • WebSocket price / bid / ask are numeric. If a price is 0, decode it together with the matching field-specific limit flags; never compare it to the string "市價", and do not claim the public quote reveals the original order type.
  • Trading hours reference (Taiwan cash equities): references/twse-trading-hours.md (Asia/Taipei)

Official field definitions: docs/market-data/websocket-api/market-data-channels/trades.txt and aggregates.txt.

def decode_ws_price_state(data: dict, field: str = "price") -> dict:
    flag_names = {
        "price": ("isLimitUpPrice", "isLimitDownPrice"),
        "bid": ("isLimitUpBid", "isLimitDownBid"),
        "ask": ("isLimitUpAsk", "isLimitDownAsk"),
    }
    if field not in flag_names:
        raise ValueError(f"Unsupported WebSocket price field: {field}")
    up_flag, down_flag = flag_names[field]
    value = data.get(field)
    if value is not None and (
        not isinstance(value, (int, float)) or isinstance(value, bool)
    ):
        raise TypeError(f"WebSocket {field} must be numeric")
    is_limit_up = bool(data.get(up_flag, False))
    is_limit_down = bool(data.get(down_flag, False))
    return {
        "value": value,
        "is_zero_encoded": value == 0,
        "is_limit_up": is_limit_up,
        "is_limit_down": is_limit_down,
        "has_limit_marker": is_limit_up or is_limit_down,
    }

可直接重用並測試的完整版本在 references/guardrail_patterns.py。

當沖(Day Trading)

台股當沖分為:

  • 先買後賣(現股當沖-買):先以 BSAction.Buy 下單,同日再以 BSAction.Sell 賣出。使用 OrderType.Stock。
  • 先賣後買(現股當沖-賣/融券當沖):先以融券賣出,同日再買回。使用 OrderType.ShortSelling。

關鍵判斷

  • 使用 intraday.ticker 回傳的 canDayTrade / canBuyDayTrade 欄位確認標的可否當沖(行情端的快速旗標)。
  • 若你要更精確地判斷「先買後賣」vs「先賣後買」能不能做,建議查交易端的 status bitmask:

- 來源常見於: - sdk.stock.querysymbolquote(acc, symbol) 回傳的 data.status - sdk.stock.daytradeandstockinfo(acc, symbol) 回傳的 data.status(有些 wrapper 會叫 dispositionstatus) - bitmask 定義(加總): - 1:平盤下可融券賣出 - 2:平盤下可借券賣出 - 4:可先買後賣當沖(buy-first daytrade) - 8:可先賣後買當沖(sell-first daytrade / daytrade short) - 判斷請用 位元運算,不要用 >=:

def decode_daytrade_status(status: int) -> dict[str, bool]:
    return {
        "can_short_sell_below_flat": bool(status & 1),
        "can_borrow_sell_below_flat": bool(status & 2),
        "can_daytrade_buy_first": bool(status & 4),
        "can_daytrade_sell_first": bool(status & 8),
    }

# examples
# status=15 -> all True (1+2+4+8)
# status=3  -> only the first two True (1+2)
# status=8  -> sell-first daytrade only
  • 部位平倉(沖銷):在收盤前以反向委託等量股數沖銷。

條件單當沖

SDK >= 2.2.4 支援條件單當沖(搜尋 llms-full.txt 中 ConditionDayTrade 或「當沖條件單」),可設定停損停利自動回補。

參考實作

期貨 / 選擇權(Futures & Options)

本 skill 目前以證券(Stock)交易與行情為主要範圍。SDK 支援期貨/選擇權帳號(account_type == "futopt"),但本 skill 尚未涵蓋對應的下單/行情 API。期貨條件單說明可搜尋 llms-full.txt 中「期貨條件單」。歡迎社群補充期貨/選擇權工作流程。

Examples

  • Use references/examples-guidance.md to map SDK calls to docs and avoid common modification pitfalls.

Testing / Sandbox

  • Official test bundle: https://www.fbs.com.tw/TradeAPISDK/samplecode/test_environment.zip
  • Use SDK v1.3.1+ and the test URL wss://neoapitest.fbs.com.tw/TASP/XCPXWS.
  • SDK v2.2.0 and earlier: FubonSDK(url=...)
  • SDK v2.2.1 and later: FubonSDK(30, 2, url=...) (30/2 are reference values).
  • Test credentials: ID from certificate; login password and cert password are 12345678.
  • See references/test-environment.md for operational notes (trading hours, shared account caveats).
  • Python SDK is downloaded from the official site (not PyPI); install the wheel locally.
  • Skill validation checklist: references/skill-tests.md.
  • Local integrated runner (maintainer-only; may be absent in some distributed skill copies): .test/test_runner.py

- If present, it can run: - --suite smoke: basic login + market/trade sanity checks - --suite complex: multi-symbol marketdata + dual-order lifecycle + callback coverage - --suite all: full coverage (includes complex checks) - If it is missing, use the minimal smoke snippet below (login → logout; no orders).

Minimal smoke (test env, no orders):

from fubon_neo.sdk import FubonSDK
import os

URL = os.getenv("NEOAPI_TEST_URL", "wss://neoapitest.fbs.com.tw/TASP/XCPXWS")
# SDK v2.2.1+: use FubonSDK(30, 2, url=...)
sdk = FubonSDK(30, 2, url=URL)

accounts = sdk.login(
    os.getenv("NEOAPI_TEST_ID"),
    os.getenv("NEOAPI_TEST_PASSWORD"),
    os.getenv("NEOAPI_TEST_CERT_PATH"),
    os.getenv("NEOAPI_TEST_CERT_PASSWORD"),
)
print("login_ok=", bool(getattr(accounts, "is_success", True)))

sdk.logout()
  • For limit-down/limit-up in test env, prefer sdk.stock.querysymbolquote (test environment data). intraday.quote uses market data (prod) and may differ.

SDK Install (Quick Note)

  • Python SDK is not on PyPI. Download the wheel from the official page and install locally.
  • SDK >= v2 works on Python 3.8–3.13 (avoid 3.14 for now).

即時成交回報 + Safe-net Readback

For live or latency-sensitive trading systems, treat filled callbacks as the primary fill source and getorderresults as a periodic reconciliation safe-net.

  • Register callbacks before login/re-login when possible:

- sdk.setonorder(onorder) for order acknowledgements (OrderResult) - sdk.setonorderchanged(onorderchanged) for modify/cancel reports (OrderResult) - sdk.setonfilled(onfilled) for execution fills (FilledData) - sdk.setonevent(onevent) for connection/re-login events

  • Compute entry/exit average from execution data, not from submitted order price:

- preferred: FilledData.filledavgprice - otherwise aggregate filledprice * filledqty across fills - reconciliation fallback: OrderResult.filledmoney / filledqty from sdk.stock.getorderresults(acc)

  • Never use submitted limit price (price, after_price, limit-up/down) as P/L entry price fallback. If fill price is missing, mark the position as unresolved and reconcile.
  • Run getorderresults periodically (for example every ~30 seconds) to detect missed callbacks and reconcile filledqty, filledmoney, and status.
  • Reconcile records by orderno + seqno when available; include filled_no for idempotent fill dedupe.
  • Record a fillsource in receipts/state, such as activefilledcallback or orderresults_readback, so operators can tell whether the low-latency path or the safe-net supplied the fill.

Implementation Patterns

For production-tested patterns, see references/implementation-practices.md. Key topics:

  • SDK Manager: Connection lifecycle, auto-reconnect, graceful termination
  • WebSocket: Multi-connection load balancing (200 symbols/connection limit)
  • Async Patterns: ThreadPoolExecutor for blocking calls, per-symbol locking
  • Error Handling: FugleAPIError compatibility for old/new SDK versions
  • Order Placement: Order creation, placement, and fill handling
  • Strategy Patterns: Tick-to-decision pipeline, stop loss, position sizing
  • Error & Status Codes: Order status codes, HTTP errors, common rejection reasons

References

  • Doc index: references/doc-index.md
  • Implementation practices: references/implementation-practices.md
  • Response shapes: references/response-shapes.md
  • Source docs (maintainers): docs/ and i18n/en/docusaurus-plugin-content-docs/current

When code or docs need updating, mirror changes in the English localization if the content is user-facing.