Skip to content

feat(us): US market APIs + DC-region guards#106

Open
hogan-yuan wants to merge 13 commits into
feat/dc-region-routingfrom
feat/us-market-apis
Open

feat(us): US market APIs + DC-region guards#106
hogan-yuan wants to merge 13 commits into
feat/dc-region-routingfrom
feat/us-market-apis

Conversation

@hogan-yuan

Copy link
Copy Markdown
Member

What

Adds 14 US-market-only API methods across the SDK, and back-ports the AP-only region guard from the Rust SDK (openapi#554).

Also merges the fix/realtime-quote-nil-pointer fix (#104) from fix/realtime-quote-nil-pointer.

New US-only APIs

All methods call CheckRegion(path, "US") at entry and return *http.RegionRestrictedError for non-US tokens.

P0 — Quote / Trade / Asset

Method Path
QuoteContext.CryptoOverview GET /v1/gemini/crypto-overview
TradeContext.QueryUSOrders POST /v1/orders/query
TradeContext.USOrderDetail GET /v3/orders/{order_id}
TradeContext.USAssetOverview GET /v1/us/assets/overview
TradeContext.USRealizedPL GET /v1/us/assets/pl/realized

P1 — Fundamental

Method Path
FundamentalContext.CompanyOverview GET /v1/stock-info/company-overview
FundamentalContext.ValuationOverview GET /v1/stock-info/valuation-overview
FundamentalContext.FinancialOverview GET /v1/stock-info/finn-overview
FundamentalContext.FinancialStatementV3 GET /v1/us/quote/financials/statements
FundamentalContext.KeyFinancialMetrics GET /v1/stock-info/fin-keyfactor
FundamentalContext.AnalystConsensus GET /v1/stock-info/fin-consensus
FundamentalContext.ETFDividendInfo GET /v1/stock-info/etf-dividend-info
FundamentalContext.CompanyDividends GET /v1/stock-info/company-dividends

P2 — Fundamental

Method Path
FundamentalContext.ETFFiles GET /v1/stock-info/etf-files

AP-only guards (synced from Rust PR #554)

Methods that are AP-only now return *http.RegionRestrictedError when called with a US token:

  • DCAContext: all 9 methods (List, Create, Update, Pause, Resume, Stop, History, Stats, CheckSupport, CalcDate, SetReminder)
  • FundamentalContext.Operating
  • MarketContext.BrokerHolding, BrokerHoldingDetail, BrokerHoldingDaily
  • QuoteContext.Brokers (WebSocket)

Structured error

http.RegionRestrictedError mirrors Rust's HttpClientError::DcRegionRestricted:

type RegionRestrictedError struct {
    Path     string // API path
    Required string // "US" or "AP"
    Current  string // "US" or "AP"
}
// "this API (/v1/orders/query) is only available in the US data center
//  and is not supported for your AP-region account"

http.Client.CheckRegion(path, "US"|"AP") is the single call site — returns nil on match, *RegionRestrictedError on mismatch.

🤖 Generated with Claude Code

hogan-yuan and others added 5 commits June 26, 2026 19:03
GetQuote returns nil when no WS push has been received for a symbol
(e.g. non-trading hours). Appending nil into the slice and then ranging
over it causes a nil-pointer dereference panic on the caller side.

Fix: skip nil entries so callers receive only symbols that have data.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ontexts

- http/Client.IsUS(): detect US credentials from "us_" prefix
- trade: USAssetOverview, USRealizedPL, QueryUSOrders, USOrderDetail (P0 E1/E2/#14/#16)
- quote: CryptoOverview (P0 #3)
- fundamental: CompanyOverview, ValuationOverview, FinancialOverview, FinancialStatementV3,
  KeyFinancialMetrics, AnalystConsensus, ETFDividendInfo, CompanyDividends, ETFFiles (P1/P2)
- All US methods return ErrUSOnly when called with non-US credentials

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…R #554

Mirrors rust/crates/httpclient dc_restrict mechanism in Go:

- http: RegionRestrictedError{Path, Required, Current} — structured error
  matching Rust HttpClientError::DcRegionRestricted message format
- http: Client.CheckRegion(path, "AP"|"US") — short-circuits with the
  structured error when the session region doesn't match
- http: Client.region() helper; Client.IsUS() now uses it

AP-only guards (US token → error):
- dca: all 9 public methods (List/Create/Update/Pause/Resume/Stop/
  History/Stats/CheckSupport/CalcDate/SetReminder)
- fundamental: Operating (/v1/quote/operatings)
- market: BrokerHolding, BrokerHoldingDetail, BrokerHoldingDaily
- quote: Brokers (WebSocket broker queue)

US-only guards updated to use CheckRegion (previously ErrUSOnly sentinel):
- trade: QueryUSOrders, USOrderDetail, USAssetOverview, USRealizedPL
- quote: CryptoOverview
- fundamental: all 9 US methods

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ntinel

- Merge PR #104: skip nil entries in RealtimeQuote when WS cache is empty
- Remove unused ErrUSOnly sentinel from fundamental/us_context.go;
  all US-only guards now use CheckRegion(path, "US") uniformly

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
hogan-yuan and others added 8 commits July 2, 2026 18:15
Matches convention of all existing HK/CN methods: accept user-facing
symbol (e.g. "AAPL.US", "SPY.US", "BTC.US") and convert internally
to counter_id via symbolToCounterID / quoteSymbolToCounterID.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…x RankTag.rank_type type

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Embed US-ETF.csv, US-IX.csv, US-WT.csv (from Rust SDK) into the counter
package. counter.SymbolToID() now resolves the correct prefix:
  SPY.US  → ETF/US/SPY  (was ST/US/SPY)
  AAPL.US → ST/US/AAPL  (unchanged)

Both fundamental.symbolToCounterID and quote.quoteSymbolToCounterID now
delegate to counter.SymbolToID, fixing ETFDividendInfo and ETFFiles.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Conversion rules:
  BTCUSD.HAS → VA/HAS/BTCUSD  ({PAIR}.{EXCHANGE})
  BTCUSD     → VA/HAS/BTCUSD  (default exchange HAS)
  BTC/USD    → VA/HAS/BTCUSD  (slash removed)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…SD.HAS)

Remove BTC/USD and BTCUSD fallbacks — CLI handles those conversions upstream.
BTCUSD.HAS → VA/HAS/BTCUSD; no .EXCHANGE suffix passes through as-is.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…D/IDToSymbol

- SymbolToID: BTCUSD.HAS → VA/HAS/BTCUSD (non-standard market suffix = crypto exchange)
- IDToSymbol: VA/HAS/BTCUSD → BTCUSD.HAS (VA prefix = crypto, returns PAIR.EXCHANGE)
- CryptoOverview now uses counter.SymbolToID, same as all other symbol-based methods
- Remove cryptoSymbolToCounterID private function

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…clusion

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant