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

Basis and funding carry math for spot/perp hedge profitability decisions.

Yield semantics:
- `basis/2` is an instantaneous premium or discount (stock): `(perp - spot) / spot * 100`.
- `basis_yield/1` (private) is the one-time basis capture over the hold — equal to `basis/2`
  at entry, not time-prorated.
- `funding_yield/1` sums per-period funding rates over `holding_days` (flow).

`net_yield` adds the one-time basis stock to accumulated funding flow so both terms are
percentages over the same holding window.

All inputs are caller-supplied values. This module performs no exchange access,
persistence, or portfolio state lookup.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `net_carry` | 1 | Combine funding income or cost with basis yield over a holding period. | `params: value` |
| `breakeven_funding` | 1 | Calculate the per-period funding rate where basis-adjusted carry is zero. | `params: value` |
| `basis` | 2 | Calculate spot/perp basis as an instantaneous percentage premium or discount. | `spot_price: value`, `perp_price: value` |

# `carry_params`

```elixir
@type carry_params() :: %{
  :spot_price =&gt; decimal_input(),
  :perp_price =&gt; decimal_input(),
  optional(:funding_rate) =&gt; decimal_input(),
  optional(:holding_days) =&gt; pos_integer() | Decimal.t(),
  optional(:periods_per_day) =&gt; pos_integer() | Decimal.t()
}
```

Inputs shared by carry calculations.

# `carry_result`

```elixir
@type carry_result() :: %{
  basis: Decimal.t(),
  basis_yield: Decimal.t(),
  funding_yield: Decimal.t(),
  net_yield: Decimal.t(),
  breakeven_funding: Decimal.t(),
  profitable?: boolean()
}
```

Net carry decision output as percentage yields.

# `decimal_input`

```elixir
@type decimal_input() :: DeltaCalc.Decimal.input()
```

# `basis`

```elixir
@spec basis(decimal_input(), decimal_input()) :: Decimal.t()
```

Return `(perp_price - spot_price) / spot_price * 100`, or zero when spot is not positive.

# `breakeven_funding`

```elixir
@spec breakeven_funding(carry_params()) :: Decimal.t()
```

Return the per-period funding rate that exactly offsets basis yield over the hold.

# `net_carry`

```elixir
@spec net_carry(carry_params()) :: carry_result()
```

Return basis, funding, net yield, break-even rate, and profitability for a hedge.

---

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