# `DeltaCalc.Hedging`
[🔗](https://github.com/ZenHive/delta_calc/blob/v0.3.0/lib/delta_calc/hedging.ex#L1)

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
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `suggest_hedge_distribution` | 1 | Split a hedge target across exchanges by capital efficiency. | `params: value` |
| `cex_sufficient?` | 2 | Check whether CEX spot balance meets the required hedge allocation. | `cex_spot: value`, `required_cex_balance: value` |
| `calculate_110_percent_hedge` | 1 | Compute hedge notional for 110% coverage of spot holdings. | `spot_value: value` |
| `enforce_max_hedge` | 2 | Cap requested hedge at 1:1 of spot for portfolio margin safety. | `spot_value: value`, `requested_hedge: value` |
| `get_basis_spread` | 2 | Calculate spot vs perpetual basis spread. | `spot_price: value`, `perp_price: value` |
| `needs_cex_transfer?` | 2 | Check whether CEX spot balance is insufficient for the required hedge. | `cex_spot: value`, `required_cex_balance: value` |
| `calculate_funding_cost` | 3 | Estimate daily funding cost for a perpetual position. | `position_size: value`, `funding_rate: value`, `periods_per_day: value` |
| `calculate_hedge_requirements` | 2 | Compute required hedge and CEX balance for a target coverage percentage. | `total_spot: value`, `inputs: value` |
| `calculate_percentage_change` | 2 | Compute percentage changes in spot, CEX, cold wallet, and hedge coverage between two snapshots. | `prior: value`, `current: value` |
| `calculate_change` | 2 | Compute absolute changes in spot, CEX, cold wallet, and hedge coverage between two snapshots. | `prior: value`, `current: value` |
| `needs_rebalancing?` | 2 | Check whether current hedge coverage falls below the target threshold. | `hedge_coverage_pct: value`, `target_hedge_percent: value` |
| `check_hedge_coverage` | 3 | Determine whether current CEX holdings meet the target hedge percentage. | `cex_value: value`, `total_spot: value`, `target_hedge_percent: value` |
| `calculate_required_cex_balance` | 2 | Compute the CEX balance required to hedge a given percentage of spot holdings. | `total_spot: value`, `hedge_percent: value` |

# `basis_spread`

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

Spot vs perpetual basis spread.

# `change_result`

```elixir
@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`

```elixir
@type hedge_distribution() :: %{
  allocations: %{required(atom()) =&gt; Decimal.t()},
  notes: [String.t()]
}
```

Per-exchange hedge allocation suggestion.

# `hedge_inputs`

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

Inputs for hedge requirement calculation.

# `hedge_requirements`

```elixir
@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`

```elixir
@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`

```elixir
@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.

# `calculate_110_percent_hedge`

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

Return hedge notional sized to 110% of `spot_value`.

# `calculate_change`

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

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

# `calculate_funding_cost`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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?`

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

Return `true` when `cex_spot` is at least `required_cex_balance`.

# `check_hedge_coverage`

```elixir
@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`

```elixir
@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`

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

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

# `needs_cex_transfer?`

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

Return `true` when `cex_spot` is below `required_cex_balance`.

# `needs_rebalancing?`

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

Return `true` when `hedge_coverage_pct` is below `target_hedge_percent`.

# `suggest_hedge_distribution`

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

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
