Longbridge.Symbol (longbridge v0.1.0)

Copy Markdown View Source

Symbol ↔ counter_id conversion utilities.

Longbridge's HTTP endpoints address instruments by an internal counter_id (e.g. ST/US/AAPL, ST/HK/700, ETF/US/SPY, IX/HK/HSI), not by the user-facing symbol (AAPL.US, 700.HK, ...). The WebSocket layer accepts user symbols and normalises them on the server, but the HTTP MarketContext endpoints (broker-holding, ahpremium, ...) require the converted form.

Local conversion (offline)

to_counter_id/1 and friends mirror symbol_to_counter_id/1 from longbridge/openapi/rust/src/utils/counter.rs exactly:

  • Leading-dot symbols (e.g. .DJI.US) are US-style indexes and always map to the IX/ prefix.
  • HK numeric codes have leading zeros stripped (00700.HKST/HK/700).
  • SZ/CN codes keep leading zeros (000001.SZST/SZ/000001).
  • ETFs / warrants / non-stock indexes are matched against the embedded directory first.
  • Everything else falls back to ST/{MARKET}/{CODE}.

Embedded directory entries live in priv/counter_ids/. New listings resolved at runtime can be added to Longbridge.Symbol.Cache (loaded from $LONGBRIDGE_CACHE_DIR/counter-ids.csv when present).

Remote batch lookup (online)

For symbols missing from the embedded directory (e.g. newly listed ETFs), resolve_counter_ids/2 calls POST /v1/quote/symbol-to-counter-ids with the unresolved symbols and merges the server's resolution back into the result. Resolved entries are added to the local cache so subsequent lookups don't need a network round-trip.

Mirrors QuoteContext::symbol_to_counter_ids and QuoteContext::resolve_counter_ids in longbridge/openapi Rust SDK (added in 4.3.0).

Summary

Functions

Convert a counter_id (e.g. "ST/US/AAPL", "IX/HK/HSI") back to its user-facing display symbol.

Convert a user-supplied index symbol ("HSI.HK", "/DJI.US", "SPX.US") to its counter_id, always using the IX/ prefix.

Resolves a list of symbols to their counter_ids.

Convert a user-supplied symbol ("AAPL.US", "00700.HK") to its internal counter_id ("ST/US/AAPL", "ST/HK/700").

Functions

from_counter_id(counter_id)

@spec from_counter_id(String.t()) :: String.t()

Convert a counter_id (e.g. "ST/US/AAPL", "IX/HK/HSI") back to its user-facing display symbol.

This is best-effort and intended for log messages / debugging. Some internal counter_ids (e.g. ST/HK/<4-digit-code> for HK warrants) have no public equivalent — the input is returned unchanged in that case.

iex> Longbridge.Symbol.from_counter_id("ST/US/AAPL")
"AAPL.US"

iex> Longbridge.Symbol.from_counter_id("IX/HK/HSI")
"HSI.HK"

index_to_counter_id(symbol)

@spec index_to_counter_id(String.t()) :: String.t()

Convert a user-supplied index symbol ("HSI.HK", "/DJI.US", "SPX.US") to its counter_id, always using the IX/ prefix.

Leading zeros are stripped from the index code where they appear (mirroring Symbol::to_counter_id for IX/...). Examples:

iex> Longbridge.Symbol.index_to_counter_id("HSI.HK")
"IX/HK/HSI"

iex> Longbridge.Symbol.index_to_counter_id(".DJI.US")
"IX/US/DJI"

resolve_counter_ids(config, symbols)

@spec resolve_counter_ids(Longbridge.Config.t(), [String.t()]) ::
  {:ok, [%{required(String.t()) => String.t()}]}

Resolves a list of symbols to their counter_ids.

Uses the embedded directory first, then the remote API at POST /v1/quote/symbol-to-counter-ids for any unknown symbols. Resolved entries are added to the local cache so subsequent lookups don't repeat the network call.

Returns {:ok, [%{symbol: String.t(), counter_id: String.t()}]} with one entry per input symbol, in the same order. Symbols the backend does not recognize fall back to the local default ST/{MARKET}/{CODE} conversion.

to_counter_id(symbol)

@spec to_counter_id(String.t()) :: String.t()

Convert a user-supplied symbol ("AAPL.US", "00700.HK") to its internal counter_id ("ST/US/AAPL", "ST/HK/700").

Mirrors the upstream Symbol::to_counter_id helper from longbridge/openapi/rust (the SDK vendored US-ETF / US-IX / US-WT directory lives in priv/counter_ids/ and is loaded by Longbridge.Symbol.Directory).

Rules:

  • AAPL.US, TSLA.US — looked up in the embedded directory for a specific counter_id (mostly relevant for ETFs and warrants that have non-ST/US/<CODE> ids). If unknown, returns ST/US/<CODE>.
  • 00700.HK — leading zeros stripped → ST/HK/700.
  • 600000.SH / 000001.SZ — leading zeros kept → ST/SH/600000 / ST/SZ/000001.
  • /DJI.US — leading-dot index symbol → IX/US/DJI.
  • Anything without a . — returned unchanged (caller bug).

The result is purely local (no network). For an authoritative resolution when the symbol is unknown locally, use resolve_counter_ids/2, which falls back to the server.