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
@type symbol_format() :: %{separator: String.t(), case: :upper | :lower | :mixed}
@type ws_symbol_format() ::
:dash_separated
| :lowercase_no_slash
| :uppercase_no_slash
| :slash
| :unknown
Functions
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"
Builds a unified symbol from components.
CCXT.Symbol.build("BTC", "USDT")
#=> "BTC/USDT"
CCXT.Symbol.build("BTC", "USD", "BTC")
#=> "BTC/USD:BTC"
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"
@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:separatorand:casekeys
@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.
@spec detect_market_type(parsed_extended()) :: :spot | :swap | :future | :option
Detects market type from parsed extended symbol components.
Priority: option > future > swap > spot.
@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 withsymbol_patternspopulatedmarket_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"
@spec from_exchange_id!(String.t(), CCXT.Exchange.t(), atom()) :: String.t()
Converts an exchange-specific ID to unified symbol, raising on failure.
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"]
@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:separatorand:casekeysopts- 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.
@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"}}
@spec parse!(String.t()) :: parsed_symbol()
Parses a unified symbol into its components, raising on error.
@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"}}
Inverts an alias map for reverse lookups (unified → exchange code).
CCXT.Symbol.reverse_aliases(%{"XBT" => "BTC", "ZEUR" => "EUR"})
#=> %{"BTC" => "XBT", "EUR" => "ZEUR"}
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"}
@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: BTC → XBT). 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 withsymbol_patternspopulated
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"
@spec to_exchange_id!(String.t(), CCXT.Exchange.t()) :: String.t()
Converts a unified symbol to exchange-specific ID, raising on failure.