ZenQuant.Options.Deribit (zen_quant v0.11.2)

Copy Markdown View Source

Deribit option symbol parsing and chain fetching utilities.

Parses both Deribit option symbol families into structured data for analysis, and provides convenience functions for fetching enriched option chains. Inverse coin-settled options read "BTC-31JAN26-84000-C"; the USDC-quoted linear options Deribit lists under currency=USDC (SOL, XRP, HYPE, TRX, AVAX — and BTC/ETH a second time) read "SOL_USDC-25DEC26-115-P", with d as the decimal separator in fractional strikes ("AVAX_USDC-29AUG26-6d4-C" is a 6.4 strike).

Example

ZenQuant.Options.Deribit.parse_option("BTC-31JAN26-84000-C")
# => {:ok, %{underlying: "BTC", expiry: ~D[2026-01-31], strike: 84000.0, type: :call, settlement: :inverse}}

ZenQuant.Options.Deribit.parse_option("SOL_USDC-25DEC26-115-P")
# => {:ok, %{underlying: "SOL", expiry: ~D[2026-12-25], strike: 115.0, type: :put, settlement: :linear}}

API Functions

FunctionArityDescriptionParam Kinds
gamma_walls3Fetch option chain and compute gamma exposure walls. Requires a single underlying and settlement regime; returns {:error, :heterogeneous_chain} otherwise.ccxt: value, exchange: value
chain3Fetch a complete enriched option chain from Deribit.ccxt: value, exchange: value
dvol3Fetch and parse Deribit DVOL volatility index history.ccxt: value, exchange: value
parse_dvol1Parse raw DVOL volatility index history into structured data.history_data: value
valid_option?1Check if a symbol is a valid Deribit option format.symbol: value
underlying1Extract underlying asset from a Deribit option symbol.symbol: value
option_type1Extract option type (:call or :put) from a Deribit option symbol.symbol: value
expiry1Extract expiry date from a Deribit option symbol.symbol: value
strike1Extract strike price from a Deribit option symbol.symbol: value
parse_option!1Parse a Deribit option symbol, raising on failure.symbol: value
parse_option1Parse a Deribit option symbol into structured data.symbol: value

Summary

Types

Chain result with option maps keyed by symbol

Parsed DVOL history entry: timestamp and volatility index value

Parsed DVOL result with current value and full history

Gamma walls result with wall entries and metadata

Parsed option symbol data. :underlying is always the base coin ("SOL" for "SOL_USDC-…"); :settlement says which family the symbol belongs to — :inverse for coin-settled ("BTC-…"), :linear for USDC-quoted ("SOL_USDC-…").

Functions

Fetch a complete enriched option chain from Deribit.

Fetch and parse Deribit DVOL volatility index history.

Extract expiry date from a Deribit option symbol.

Fetch option chain and compute gamma exposure walls. Requires a single underlying and settlement regime; returns {:error, :heterogeneous_chain} otherwise.

Extract option type (:call or :put) from a Deribit option symbol.

Parse raw DVOL volatility index history into structured data.

Parse a Deribit option symbol into structured data.

Parse a Deribit option symbol, raising on failure.

Extract strike price from a Deribit option symbol.

Extract underlying asset from a Deribit option symbol.

Check if a symbol is a valid Deribit option format.

Types

chain_result()

@type chain_result() :: %{
  chain: %{required(String.t()) => map()},
  spot: float(),
  enriched_count: non_neg_integer()
}

Chain result with option maps keyed by symbol

dvol_entry()

@type dvol_entry() :: {DateTime.t(), float()}

Parsed DVOL history entry: timestamp and volatility index value

dvol_result()

@type dvol_result() :: %{current: float(), history: [dvol_entry()]}

Parsed DVOL result with current value and full history

gamma_walls_result()

@type gamma_walls_result() :: %{
  walls: [ZenQuant.Options.GammaWalls.wall_entry()],
  spot: float(),
  chain_size: non_neg_integer(),
  enriched_count: non_neg_integer()
}

Gamma walls result with wall entries and metadata

parsed_option()

@type parsed_option() :: %{
  underlying: String.t(),
  expiry: Date.t(),
  strike: float(),
  type: :call | :put,
  settlement: :inverse | :linear
}

Parsed option symbol data. :underlying is always the base coin ("SOL" for "SOL_USDC-…"); :settlement says which family the symbol belongs to — :inverse for coin-settled ("BTC-…"), :linear for USDC-quoted ("SOL_USDC-…").

Functions

chain(ccxt, exchange, opts \\ [])

@spec chain(module(), map(), keyword()) :: {:ok, chain_result()} | {:error, term()}

Fetch a complete enriched option chain from Deribit.

Parameters

  • ccxt - Bourse dispatcher module (the top-level Bourse module) (value)
  • exchange - Built %Bourse.Exchange{} handle from Bourse.exchange(:deribit) (value)

Options

  • currency - Currency to fetch (default: "BTC")
  • enrich - :none or :greeks (default: :none)
  • enrich_limit - Max instruments to enrich by OI (default: 50)
  • max_concurrency - Parallelism for enrichment (default: 10)

Returns

{:ok, %{chain, spot, enriched_count}} or {:error, reason} (tuple)

Example

{:ok,
 %{
   spot: 83500.0,
   chain: %{"BTC-31JAN26-84000-C" => %{open_interest: 1200.0}},
   enriched_count: 25
 }}

Errors

  • :exchange_error - Pass-through error from ccxt.fetch_option_chain/3

Composes With

  • gamma_walls
# descripex:contract
%{
  opts: %{
    currency: %{default: "BTC", type: :string, description: "Currency to fetch"},
    max_concurrency: %{
      default: 10,
      type: :integer,
      description: "Parallelism for enrichment"
    },
    enrich: %{default: :none, type: :atom, description: ":none or :greeks"},
    enrich_limit: %{
      default: 50,
      type: :integer,
      description: "Max instruments to enrich by OI"
    }
  },
  params: %{
    exchange: %{
      description: "Built `%Bourse.Exchange{}` handle from `Bourse.exchange(:deribit)`",
      kind: :value
    },
    ccxt: %{
      description: "Bourse dispatcher module (the top-level `Bourse` module)",
      kind: :value
    }
  },
  errors: [exchange_error: "Pass-through error from ccxt.fetch_option_chain/3"],
  returns: %{
    type: :tuple,
    description: "{:ok, %{chain, spot, enriched_count}} or {:error, reason}"
  },
  returns_example: {:ok,
   %{
     spot: 83500.0,
     chain: %{"BTC-31JAN26-84000-C" => %{open_interest: 1200.0}},
     enriched_count: 25
   }},
  composes_with: [:gamma_walls]
}

dvol(ccxt, exchange, opts \\ [])

@spec dvol(module(), map(), keyword()) :: {:ok, dvol_result()} | {:error, term()}

Fetch and parse Deribit DVOL volatility index history.

Parameters

  • ccxt - Bourse dispatcher module (the top-level Bourse module) (value)
  • exchange - Built %Bourse.Exchange{} handle from Bourse.exchange(:deribit) (value)

Options

  • currency - Currency to fetch (default: "BTC")

Returns

{:ok, %{current, history}} or {:error, reason} (tuple)

Example

{:ok, %{history: [{~U[2026-02-25 12:00:00.000Z], 45.2}], current: 45.2}}

Errors

  • :exchange_error - Pass-through error from ccxt.fetch_volatility_history/3
  • :empty_history - No valid DVOL rows in response
  • :invalid_input - DVOL payload shape is invalid
# descripex:contract
%{
  opts: %{
    currency: %{default: "BTC", type: :string, description: "Currency to fetch"}
  },
  params: %{
    exchange: %{
      description: "Built `%Bourse.Exchange{}` handle from `Bourse.exchange(:deribit)`",
      kind: :value
    },
    ccxt: %{
      description: "Bourse dispatcher module (the top-level `Bourse` module)",
      kind: :value
    }
  },
  errors: [
    exchange_error: "Pass-through error from ccxt.fetch_volatility_history/3",
    empty_history: "No valid DVOL rows in response",
    invalid_input: "DVOL payload shape is invalid"
  ],
  returns: %{
    type: :tuple,
    description: "{:ok, %{current, history}} or {:error, reason}"
  },
  returns_example: {:ok,
   %{history: [{~U[2026-02-25 12:00:00.000Z], 45.2}], current: 45.2}}
}

expiry(symbol)

@spec expiry(String.t()) :: {:ok, Date.t()} | {:error, :invalid_format}

Extract expiry date from a Deribit option symbol.

Parameters

  • symbol - Deribit option symbol (value)

Returns

{:ok, Date.t()} or {:error, :invalid_format} (tuple)

Example

{:ok, ~D[2026-01-31]}

Errors

  • :invalid_format
# descripex:contract
%{
  params: %{symbol: %{description: "Deribit option symbol", kind: :value}},
  errors: [:invalid_format],
  returns: %{
    type: :tuple,
    description: "{:ok, Date.t()} or {:error, :invalid_format}"
  },
  returns_example: {:ok, ~D[2026-01-31]}
}

gamma_walls(ccxt, exchange, opts \\ [])

@spec gamma_walls(module(), map(), keyword()) ::
  {:ok, gamma_walls_result()} | {:error, term()}

Fetch option chain and compute gamma exposure walls. Requires a single underlying and settlement regime; returns {:error, :heterogeneous_chain} otherwise.

Parameters

  • ccxt - Bourse dispatcher module (the top-level Bourse module) (value)
  • exchange - Built %Bourse.Exchange{} handle from Bourse.exchange(:deribit) (value)

Options

  • currency - Currency to fetch (default: "BTC")
  • enrich_limit - Max instruments to enrich (default: 50)
  • max_concurrency - Parallelism (default: 10)
  • side - :dealer or :customer sign convention (default: :dealer)
  • min_oi - Minimum OI to include (default: 0)
  • top_n - Return only top N walls

Returns

{:ok, %{walls, spot, chain_size, enriched_count}} or {:error, reason} (tuple)

Example

{:ok,
 %{
   spot: 83500.0,
   enriched_count: 50,
   walls: [%{type: :support, strike: 84000.0, gex: 1250.0}],
   chain_size: 120
 }}

Errors

  • :heterogeneous_chain - Fetched legs span underlyings or settlement regimes
  • :no_spot_price - Spot extracted from chain is <= 0
  • :exchange_error - Pass-through error from chain/3 or exchange module
# descripex:contract
%{
  opts: %{
    currency: %{default: "BTC", type: :string, description: "Currency to fetch"},
    max_concurrency: %{default: 10, type: :integer, description: "Parallelism"},
    side: %{
      default: :dealer,
      type: :atom,
      description: ":dealer or :customer sign convention"
    },
    min_oi: %{default: 0, type: :number, description: "Minimum OI to include"},
    enrich_limit: %{
      default: 50,
      type: :integer,
      description: "Max instruments to enrich"
    },
    top_n: %{
      default: nil,
      type: :integer,
      description: "Return only top N walls"
    }
  },
  params: %{
    exchange: %{
      description: "Built `%Bourse.Exchange{}` handle from `Bourse.exchange(:deribit)`",
      kind: :value
    },
    ccxt: %{
      description: "Bourse dispatcher module (the top-level `Bourse` module)",
      kind: :value
    }
  },
  errors: [
    heterogeneous_chain: "Fetched legs span underlyings or settlement regimes",
    no_spot_price: "Spot extracted from chain is <= 0",
    exchange_error: "Pass-through error from chain/3 or exchange module"
  ],
  returns: %{
    type: :tuple,
    description: "{:ok, %{walls, spot, chain_size, enriched_count}} or {:error, reason}"
  },
  returns_example: {:ok,
   %{
     spot: 83500.0,
     enriched_count: 50,
     walls: [%{type: :support, strike: 84000.0, gex: 1250.0}],
     chain_size: 120
   }}
}

option_type(symbol)

@spec option_type(String.t()) :: {:ok, :call | :put} | {:error, :invalid_format}

Extract option type (:call or :put) from a Deribit option symbol.

Parameters

  • symbol - Deribit option symbol (value)

Returns

{:ok, :call | :put} or {:error, :invalid_format} (tuple)

Example

{:ok, :call}

Errors

  • :invalid_format
# descripex:contract
%{
  params: %{symbol: %{description: "Deribit option symbol", kind: :value}},
  errors: [:invalid_format],
  returns: %{
    type: :tuple,
    description: "{:ok, :call | :put} or {:error, :invalid_format}"
  },
  returns_example: {:ok, :call}
}

parse_dvol(history_data)

@spec parse_dvol(term()) ::
  {:ok, dvol_result()} | {:error, :empty_history | :invalid_input}

Parse raw DVOL volatility index history into structured data.

Parameters

  • history_data - List of DVOL rows, all of one of these shapes: five-element OHLC candles [unix_ms, open, high, low, close] as returned by Deribit's public/get_volatility_index_data (the close is taken as the value), two-element [unix_ms, value] pairs, or parsed volatility-history maps/structs with :timestamp and :volatility. Any other row shape rejects the whole payload as :invalid_input rather than being silently dropped. (value)

Returns

{:ok, %{current, history}} or {:error, :empty_history | :invalid_input} (tuple)

Example

{:ok, %{history: [{~U[2026-02-25 12:00:00.000Z], 45.2}], current: 45.2}}

Errors

  • :empty_history - The list was empty — the venue returned no rows
  • :invalid_input - Not a list, or a row whose shape is none of the accepted ones (unrecognised arity, non-numeric field, or a timestamp that is not a representable epoch millisecond)
# descripex:contract
%{
  params: %{
    history_data: %{
      description: "List of DVOL rows, all of one of these shapes: five-element OHLC candles [unix_ms, open, high, low, close] as returned by Deribit's public/get_volatility_index_data (the close is taken as the value), two-element [unix_ms, value] pairs, or parsed volatility-history maps/structs with :timestamp and :volatility. Any other row shape rejects the whole payload as :invalid_input rather than being silently dropped.",
      kind: :value
    }
  },
  errors: [
    empty_history: "The list was empty — the venue returned no rows",
    invalid_input: "Not a list, or a row whose shape is none of the accepted ones (unrecognised arity, non-numeric field, or a timestamp that is not a representable epoch millisecond)"
  ],
  returns: %{
    type: :tuple,
    description: "{:ok, %{current, history}} or {:error, :empty_history | :invalid_input}"
  },
  returns_example: {:ok,
   %{history: [{~U[2026-02-25 12:00:00.000Z], 45.2}], current: 45.2}}
}

parse_option(symbol)

@spec parse_option(String.t()) :: {:ok, parsed_option()} | {:error, :invalid_format}

Parse a Deribit option symbol into structured data.

Parameters

  • symbol - Deribit option symbol — inverse ("BTC-31JAN26-84000-C") or USDC-quoted linear ("SOL_USDC-25DEC26-115-P", fractional strikes spelled with d: "AVAX_USDC-29AUG26-6d4-C") (value)

Returns

{:ok, %{underlying, expiry, strike, type, settlement}} or {:error, :invalid_format} (tuple)

Example

{:ok,
 %{
   type: :call,
   expiry: ~D[2026-01-31],
   strike: 84000.0,
   settlement: :inverse,
   underlying: "BTC"
 }}

Errors

  • :invalid_format

Composes With

  • strike
  • expiry
  • option_type
  • underlying
  • valid_option?
# descripex:contract
%{
  params: %{
    symbol: %{
      description: "Deribit option symbol — inverse (\"BTC-31JAN26-84000-C\") or USDC-quoted linear (\"SOL_USDC-25DEC26-115-P\", fractional strikes spelled with `d`: \"AVAX_USDC-29AUG26-6d4-C\")",
      kind: :value
    }
  },
  errors: [:invalid_format],
  returns: %{
    type: :tuple,
    description: "{:ok, %{underlying, expiry, strike, type, settlement}} or {:error, :invalid_format}"
  },
  returns_example: {:ok,
   %{
     type: :call,
     expiry: ~D[2026-01-31],
     strike: 84000.0,
     settlement: :inverse,
     underlying: "BTC"
   }},
  composes_with: [:strike, :expiry, :option_type, :underlying, :valid_option?]
}

parse_option!(symbol)

@spec parse_option!(String.t()) :: parsed_option()

Parse a Deribit option symbol, raising on failure.

Parameters

  • symbol - Deribit option symbol (value)

Returns

%{underlying, expiry, strike, type, settlement} or raises ArgumentError (map)

Example

%{
  type: :call,
  expiry: ~D[2026-01-31],
  strike: 84000.0,
  settlement: :inverse,
  underlying: "BTC"
}
# descripex:contract
%{
  params: %{symbol: %{description: "Deribit option symbol", kind: :value}},
  returns: %{
    type: :map,
    description: "%{underlying, expiry, strike, type, settlement} or raises ArgumentError"
  },
  returns_example: %{
    type: :call,
    expiry: ~D[2026-01-31],
    strike: 84000.0,
    settlement: :inverse,
    underlying: "BTC"
  }
}

strike(symbol)

@spec strike(String.t()) :: {:ok, float()} | {:error, :invalid_format}

Extract strike price from a Deribit option symbol.

Parameters

  • symbol - Deribit option symbol (value)

Returns

{:ok, float()} or {:error, :invalid_format} (tuple)

Example

{:ok, 84000.0}

Errors

  • :invalid_format
# descripex:contract
%{
  params: %{symbol: %{description: "Deribit option symbol", kind: :value}},
  errors: [:invalid_format],
  returns: %{
    type: :tuple,
    description: "{:ok, float()} or {:error, :invalid_format}"
  },
  returns_example: {:ok, 84000.0}
}

underlying(symbol)

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

Extract underlying asset from a Deribit option symbol.

Parameters

  • symbol - Deribit option symbol (value)

Returns

{:ok, String.t()} or {:error, :invalid_format} (tuple)

Example

{:ok, "BTC"}

Errors

  • :invalid_format
# descripex:contract
%{
  params: %{symbol: %{description: "Deribit option symbol", kind: :value}},
  errors: [:invalid_format],
  returns: %{
    type: :tuple,
    description: "{:ok, String.t()} or {:error, :invalid_format}"
  },
  returns_example: {:ok, "BTC"}
}

valid_option?(symbol)

@spec valid_option?(String.t()) :: boolean()

Check if a symbol is a valid Deribit option format.

Parameters

  • symbol - String to validate (value)

Returns

true if valid Deribit option symbol (boolean)

Example

true
# descripex:contract
%{
  params: %{symbol: %{description: "String to validate", kind: :value}},
  returns: %{type: :boolean, description: "true if valid Deribit option symbol"},
  returns_example: true
}