CCXT.Symbol (ccxt_client v0.6.1)

Copy Markdown View Source

Bidirectional symbol normalization between unified and exchange-specific formats.

CCXT uses a unified symbol format: BASE/QUOTE (e.g., "BTC/USDT"). Different exchanges use different formats:

  • Binance: "BTCUSDT" (no separator, uppercase)
  • Coinbase: "BTC-USD" (dash separator)
  • Gate.io: "BTC_USDT" (underscore separator)
  • Bitstamp: "btcusd" (lowercase, no separator)
  • Derivatives: "BTC/USDT:USDT" (with settle currency)
  • Kraken: "XXBTZUSD" (X/Z prefixes for currencies)
  • KrakenFutures: "PI_XBTUSD" (contract type prefixes)

Format-Based Conversion

Use with a format map for simple normalization:

format = %{separator: "-", case: :upper}
CCXT.Symbol.normalize("BTC-USD", format)
#=> "BTC/USD"

CCXT.Symbol.denormalize("BTC/USD", format)
#=> "BTC-USD"

Parsing and Building

Parse unified symbols into components:

CCXT.Symbol.parse("BTC/USDT:USDT")
#=> {:ok, %{base: "BTC", quote: "USDT", settle: "USDT"}}

CCXT.Symbol.build("BTC", "USDT", "USDT")
#=> "BTC/USDT:USDT"

Currency Aliases

Apply exchange-specific currency code mappings:

aliases = %{"XBT" => "BTC", "XXRP" => "XRP"}
CCXT.Symbol.apply_alias("XBT", aliases)
#=> "BTC"

Summary

Functions

Applies a currency alias mapping to a single currency code.

Builds a unified symbol from components.

Converts dates between derivative symbol formats.

Converts a unified symbol to exchange-specific format.

Converts a unified symbol to WebSocket channel format.

Detects market type from parsed extended symbol components.

Converts an exchange-specific ID to unified symbol format.

Converts an exchange-specific ID to unified symbol, raising on failure.

Returns the list of known quote currencies, optionally extended with exchange-specific currencies.

Converts an exchange-specific symbol to unified format.

Parses a unified symbol into its components.

Parses a unified symbol into its components, raising on error.

Parses a unified symbol into extended components including derivative fields.

Inverts an alias map for reverse lookups (unified → exchange code).

Strips known exchange prefixes from a symbol.

Converts a unified symbol to exchange-specific ID.

Converts a unified symbol to exchange-specific ID, raising on failure.

Types

parsed_extended()

@type parsed_extended() :: %{
  base: String.t(),
  quote: String.t(),
  settle: String.t() | nil,
  expiry: String.t() | nil,
  strike: String.t() | nil,
  option_type: String.t() | nil
}

parsed_symbol()

@type parsed_symbol() :: %{
  base: String.t(),
  quote: String.t(),
  settle: String.t() | nil
}

pattern_config()

@type pattern_config() :: %{
  pattern: atom(),
  separator: String.t(),
  case: :upper | :lower | :mixed,
  date_format: :yymmdd | :ddmmmyy | :yyyymmdd | nil,
  suffix: String.t() | nil,
  prefix: String.t() | nil
}

symbol_format()

@type symbol_format() :: %{separator: String.t(), case: :upper | :lower | :mixed}

ws_symbol_format()

@type ws_symbol_format() ::
  :dash_separated
  | :lowercase_no_slash
  | :uppercase_no_slash
  | :slash
  | :unknown

Functions

apply_alias(currency, aliases)

@spec apply_alias(String.t(), map()) :: String.t()

Applies a currency alias mapping to a single currency code.

Used with commonCurrencies data from exchange specs.

CCXT.Symbol.apply_alias("XBT", %{"XBT" => "BTC"})
#=> "BTC"

CCXT.Symbol.apply_alias("ETH", %{"XBT" => "BTC"})
#=> "ETH"

build(base, quote_currency, settle \\ nil)

@spec build(String.t(), String.t(), String.t() | nil) :: String.t()

Builds a unified symbol from components.

CCXT.Symbol.build("BTC", "USDT")
#=> "BTC/USDT"

CCXT.Symbol.build("BTC", "USD", "BTC")
#=> "BTC/USD:BTC"

convert_date(date_str, format, format)

@spec convert_date(String.t(), atom(), atom()) :: String.t()

Converts dates between derivative symbol formats.

Supported formats: :yymmdd, :ddmmmyy, :yyyymmdd.

CCXT.Symbol.convert_date("260327", :yymmdd, :ddmmmyy)
#=> "27MAR26"

CCXT.Symbol.convert_date("27MAR26", :ddmmmyy, :yymmdd)
#=> "260327"

CCXT.Symbol.convert_date("260327", :yymmdd, :yyyymmdd)
#=> "20260327"

denormalize(symbol, map)

@spec denormalize(String.t(), symbol_format()) :: String.t()

Converts a unified symbol to exchange-specific format.

Strips settle currency (colon suffix) before conversion, then applies separator replacement and case transformation.

Parameters

  • symbol - The unified symbol (e.g., "BTC/USDT" or "BTC/USDT:USDT")
  • format - Map with :separator and :case keys

denormalize_ws(symbol, arg2)

@spec denormalize_ws(String.t(), ws_symbol_format()) :: String.t()

Converts a unified symbol to WebSocket channel format.

WebSocket channels often use different symbol formats than REST APIs.

detect_market_type(parsed)

@spec detect_market_type(parsed_extended()) :: :spot | :swap | :future | :option

Detects market type from parsed extended symbol components.

Priority: option > future > swap > spot.

from_exchange_id(exchange_id, exchange, market_type)

@spec from_exchange_id(String.t(), CCXT.Exchange.t(), atom()) :: String.t()

Converts an exchange-specific ID to unified symbol format.

Requires market_type since exchange IDs are ambiguous without context.

Parameters

  • exchange_id - The exchange-specific ID (e.g., "BTCUSDT_260327")
  • exchange - A %CCXT.Exchange{} struct with symbol_patterns populated
  • market_type - The market type (:spot, :swap, :future, :option)

Examples

CCXT.Symbol.from_exchange_id("BTCUSDT", binance_exchange, :spot)
#=> "BTC/USDT"

CCXT.Symbol.from_exchange_id("BTC-PERPETUAL", deribit_exchange, :swap)
#=> "BTC/USD:BTC"

CCXT.Symbol.from_exchange_id("BTC-12JAN26-84000-C", deribit_exchange, :option)
#=> "BTC/USD:BTC-260112-84000-C"

from_exchange_id!(exchange_id, exchange, market_type)

@spec from_exchange_id!(String.t(), CCXT.Exchange.t(), atom()) :: String.t()

Converts an exchange-specific ID to unified symbol, raising on failure.

get_quote_currencies(extra \\ nil)

@spec get_quote_currencies([String.t()] | nil) :: [String.t()]

Returns the list of known quote currencies, optionally extended with exchange-specific currencies.

Currencies are sorted by length descending for longest-match-first splitting.

CCXT.Symbol.get_quote_currencies()
#=> ["FDUSD", "USDD", "USDT", "USDC", "BUSD", "TUSD", ...]

CCXT.Symbol.get_quote_currencies(["TRY", "BRL"])
#=> ["FDUSD", "USDD", "USDT", ..., "TRY", "BRL"]

normalize(symbol, format, opts \\ [])

@spec normalize(String.t(), symbol_format(), keyword()) :: String.t()

Converts an exchange-specific symbol to unified format.

Takes a format map with :separator and :case keys. Optionally applies currency aliases (from commonCurrencies spec data) to map exchange-specific codes to unified codes.

Parameters

  • symbol - The exchange-specific symbol (e.g., "BTCUSDT")
  • format - Map with :separator and :case keys
  • opts - Keyword options:
    • :aliases - Currency alias map (e.g., %{"XBT" => "BTC"})
    • :quote_currencies - Custom list of known quote currencies for no-separator splitting

Returns

The unified symbol (e.g., "BTC/USDT"), or original if cannot parse.

parse(symbol)

@spec parse(String.t()) :: {:ok, parsed_symbol()} | {:error, :invalid_format}

Parses a unified symbol into its components.

Returns

{:ok, %{base, quote, settle}} or {:error, :invalid_format}.

CCXT.Symbol.parse("BTC/USDT")
#=> {:ok, %{base: "BTC", quote: "USDT", settle: nil}}

CCXT.Symbol.parse("BTC/USDT:USDT")
#=> {:ok, %{base: "BTC", quote: "USDT", settle: "USDT"}}

parse!(symbol)

@spec parse!(String.t()) :: parsed_symbol()

Parses a unified symbol into its components, raising on error.

parse_extended(symbol)

@spec parse_extended(String.t()) ::
  {:ok, parsed_extended()} | {:error, :invalid_format}

Parses a unified symbol into extended components including derivative fields.

CCXT.Symbol.parse_extended("BTC/USDT:USDT-260327")
#=> {:ok, %{base: "BTC", quote: "USDT", settle: "USDT", expiry: "260327", strike: nil, option_type: nil}}

CCXT.Symbol.parse_extended("BTC/USD:BTC-260112-84000-C")
#=> {:ok, %{base: "BTC", quote: "USD", settle: "BTC", expiry: "260112", strike: "84000", option_type: "C"}}

reverse_aliases(aliases)

@spec reverse_aliases(map()) :: map()

Inverts an alias map for reverse lookups (unified → exchange code).

CCXT.Symbol.reverse_aliases(%{"XBT" => "BTC", "ZEUR" => "EUR"})
#=> %{"BTC" => "XBT", "EUR" => "ZEUR"}

strip_prefix(symbol)

@spec strip_prefix(String.t()) :: {String.t() | nil, String.t()}

Strips known exchange prefixes from a symbol.

Handles KrakenFutures contract prefixes (PI, PF, FI, FF, PV_) and Kraken currency prefixes (X for crypto, Z for fiat).

CCXT.Symbol.strip_prefix("PI_XBTUSD")
#=> {"PI_", "XBTUSD"}

CCXT.Symbol.strip_prefix("XXBT")
#=> {"X", "XBT"}

CCXT.Symbol.strip_prefix("ZUSD")
#=> {"Z", "USD"}

CCXT.Symbol.strip_prefix("BTCUSDT")
#=> {nil, "BTCUSDT"}

to_exchange_id(unified_symbol, exchange)

@spec to_exchange_id(String.t(), CCXT.Exchange.t()) :: String.t()

Converts a unified symbol to exchange-specific ID.

Uses pattern configs from the exchange's symbol_patterns to handle spot, swap, future, and option symbols. Falls back to denormalize/2 when no pattern config exists for the detected market type.

Outbound currency aliases come from exchange.outbound_aliases (default %{}), populated only for exchanges that accept the alias on input (e.g. Kraken: BTCXBT). Inbound aliasing (from_exchange_id) uses common_currencies directly — that direction is universal.

Parameters

  • unified_symbol - The unified symbol (e.g., "BTC/USDT:USDT-260327")
  • exchange - A %CCXT.Exchange{} struct with symbol_patterns populated

Examples

CCXT.Symbol.to_exchange_id("BTC/USDT", binance_exchange)
#=> "BTCUSDT"

CCXT.Symbol.to_exchange_id("BTC/USD:BTC-260112-84000-C", deribit_exchange)
#=> "BTC-12JAN26-84000-C"

to_exchange_id!(unified_symbol, exchange)

@spec to_exchange_id!(String.t(), CCXT.Exchange.t()) :: String.t()

Converts a unified symbol to exchange-specific ID, raising on failure.