DeltaCalc.Hedging (DeltaCalc v0.3.0)

Copy Markdown View Source

Pure spot-hedging formulas for portfolio balance and coverage calculations.

All functions take plain Decimal values — no Ecto, Repo, Scope, or Snapshot struct coupling. Callers fetch values from their own storage and pass them in.

API Functions

FunctionArityDescriptionParam Kinds
suggest_hedge_distribution1Split a hedge target across exchanges by capital efficiency.params: value
cex_sufficient?2Check whether CEX spot balance meets the required hedge allocation.cex_spot: value, required_cex_balance: value
calculate_110_percent_hedge1Compute hedge notional for 110% coverage of spot holdings.spot_value: value
enforce_max_hedge2Cap requested hedge at 1:1 of spot for portfolio margin safety.spot_value: value, requested_hedge: value
get_basis_spread2Calculate spot vs perpetual basis spread.spot_price: value, perp_price: value
needs_cex_transfer?2Check whether CEX spot balance is insufficient for the required hedge.cex_spot: value, required_cex_balance: value
calculate_funding_cost3Estimate daily funding cost for a perpetual position.position_size: value, funding_rate: value, periods_per_day: value
calculate_hedge_requirements2Compute required hedge and CEX balance for a target coverage percentage.total_spot: value, inputs: value
calculate_percentage_change2Compute percentage changes in spot, CEX, cold wallet, and hedge coverage between two snapshots.prior: value, current: value
calculate_change2Compute absolute changes in spot, CEX, cold wallet, and hedge coverage between two snapshots.prior: value, current: value
needs_rebalancing?2Check whether current hedge coverage falls below the target threshold.hedge_coverage_pct: value, target_hedge_percent: value
check_hedge_coverage3Determine whether current CEX holdings meet the target hedge percentage.cex_value: value, total_spot: value, target_hedge_percent: value
calculate_required_cex_balance2Compute the CEX balance required to hedge a given percentage of spot holdings.total_spot: value, hedge_percent: value

Summary

Types

Spot vs perpetual basis spread.

Absolute change between two snapshots.

Per-exchange hedge allocation suggestion.

Inputs for hedge requirement calculation.

Hedge requirement result with CEX sufficiency flags.

Percentage change between two snapshots.

Snapshot values map required by change functions.

Functions

Return hedge notional sized to 110% of spot_value.

Return absolute Decimal deltas and elapsed hours between prior and current snapshots.

Return estimated daily funding cost from per-period rate and settlement frequency.

Return hedge and CEX requirements for total_spot at the given target percentage.

Return percentage Decimal deltas and elapsed hours between prior and current snapshots.

Return the CEX balance needed to cover hedge_percent of total_spot.

Return true when cex_spot is at least required_cex_balance.

Return :ok with coverage percentage, or :needs_rebalancing when below target.

Return min(requested_hedge, spot_value) so portfolio margin never exceeds 1:1.

Return absolute and percentage basis spread between spot and perpetual prices.

Return true when cex_spot is below required_cex_balance.

Return true when hedge_coverage_pct is below target_hedge_percent.

Suggest per-exchange hedge allocation favoring capital-efficient venues.

Types

basis_spread()

@type basis_spread() :: %{
  spread: Decimal.t(),
  spread_pct: Decimal.t(),
  direction: :contango | :backwardation | :flat
}

Spot vs perpetual basis spread.

change_result()

@type change_result() :: %{
  total_change: Decimal.t(),
  cex_change: Decimal.t(),
  cold_change: Decimal.t(),
  hedge_change: Decimal.t(),
  duration_hours: float()
}

Absolute change between two snapshots.

hedge_distribution()

@type hedge_distribution() :: %{
  allocations: %{required(atom()) => Decimal.t()},
  notes: [String.t()]
}

Per-exchange hedge allocation suggestion.

hedge_inputs()

@type hedge_inputs() :: %{cex_spot: Decimal.t(), target_hedge_percent: Decimal.t()}

Inputs for hedge requirement calculation.

hedge_requirements()

@type hedge_requirements() :: %{
  required_hedge: Decimal.t(),
  required_cex_balance: Decimal.t(),
  effective_target_percent: Decimal.t(),
  capped_at_max: boolean(),
  cex_sufficient: boolean(),
  needs_transfer: boolean()
}

Hedge requirement result with CEX sufficiency flags.

pct_change_result()

@type pct_change_result() :: %{
  total_pct: Decimal.t(),
  cex_pct: Decimal.t(),
  cold_pct: Decimal.t(),
  hedge_pct: Decimal.t(),
  duration_hours: float()
}

Percentage change between two snapshots.

snapshot_values()

@type snapshot_values() :: %{
  total_spot: Decimal.t(),
  cex_spot: Decimal.t(),
  cold_wallet: Decimal.t(),
  hedge_coverage_pct: Decimal.t(),
  captured_at: DateTime.t()
}

Snapshot values map required by change functions.

Functions

calculate_110_percent_hedge(spot_value)

@spec calculate_110_percent_hedge(Decimal.t()) :: Decimal.t()

Return hedge notional sized to 110% of spot_value.

calculate_change(prior, current)

@spec calculate_change(snapshot_values(), snapshot_values()) :: change_result()

Return absolute Decimal deltas and elapsed hours between prior and current snapshots.

calculate_funding_cost(position_size, funding_rate, periods_per_day)

@spec calculate_funding_cost(Decimal.t(), Decimal.t(), pos_integer()) :: Decimal.t()

Return estimated daily funding cost from per-period rate and settlement frequency.

calculate_hedge_requirements(total_spot, map)

@spec calculate_hedge_requirements(Decimal.t(), hedge_inputs()) ::
  hedge_requirements()

Return hedge and CEX requirements for total_spot at the given target percentage.

calculate_percentage_change(prior, current)

@spec calculate_percentage_change(snapshot_values(), snapshot_values()) ::
  pct_change_result()

Return percentage Decimal deltas and elapsed hours between prior and current snapshots.

calculate_required_cex_balance(total_spot, hedge_percent)

@spec calculate_required_cex_balance(Decimal.t(), Decimal.t()) :: Decimal.t()

Return the CEX balance needed to cover hedge_percent of total_spot.

cex_sufficient?(cex_spot, required_cex_balance)

@spec cex_sufficient?(Decimal.t(), Decimal.t()) :: boolean()

Return true when cex_spot is at least required_cex_balance.

check_hedge_coverage(cex_value, total_spot, target_hedge_percent)

@spec check_hedge_coverage(Decimal.t(), Decimal.t(), Decimal.t()) ::
  {:ok, Decimal.t()} | {:needs_rebalancing, Decimal.t(), Decimal.t()}

Return :ok with coverage percentage, or :needs_rebalancing when below target.

enforce_max_hedge(spot_value, requested_hedge)

@spec enforce_max_hedge(Decimal.t(), Decimal.t()) :: Decimal.t()

Return min(requested_hedge, spot_value) so portfolio margin never exceeds 1:1.

get_basis_spread(spot_price, perp_price)

@spec get_basis_spread(Decimal.t(), Decimal.t()) :: basis_spread()

Return absolute and percentage basis spread between spot and perpetual prices.

needs_cex_transfer?(cex_spot, required_cex_balance)

@spec needs_cex_transfer?(Decimal.t(), Decimal.t()) :: boolean()

Return true when cex_spot is below required_cex_balance.

needs_rebalancing?(hedge_coverage_pct, target_hedge_percent \\ Decimal.new(60))

@spec needs_rebalancing?(Decimal.t(), Decimal.t()) :: boolean()

Return true when hedge_coverage_pct is below target_hedge_percent.

suggest_hedge_distribution(params)

@spec suggest_hedge_distribution(map()) :: hedge_distribution()

Suggest per-exchange hedge allocation favoring capital-efficient venues.