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

Position PnL, return-on-equity, and fee/funding-adjusted breakeven math.

Callers supply entry, mark/exit prices, size, side, fee rates, margin, and
accrued funding from their own state — no exchange clients or I/O.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `breakeven` | 1 | Compute the price where the position turns green after fees and funding. | `params: value` |
| `roe` | 1 | Calculate return on equity as PnL divided by margin. | `params: value` |
| `realized_pnl` | 1 | Calculate net realized PnL at exit after roundtrip fees and accrued funding. | `params: value` |
| `unrealized_pnl` | 1 | Calculate mark-to-market unrealized PnL for an open position. | `params: value` |

# `breakeven_params`

```elixir
@type breakeven_params() :: %{
  :entry_price =&gt; decimal_input(),
  :size =&gt; decimal_input(),
  :open_fee_rate =&gt; decimal_input(),
  :close_fee_rate =&gt; decimal_input(),
  optional(:side) =&gt; side(),
  optional(:accrued_funding) =&gt; decimal_input()
}
```

Inputs for fee- and funding-adjusted breakeven price.

# `decimal_input`

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

# `realized_params`

```elixir
@type realized_params() :: %{
  :entry_price =&gt; decimal_input(),
  :exit_price =&gt; decimal_input(),
  :size =&gt; decimal_input(),
  :side =&gt; side(),
  :open_fee_rate =&gt; decimal_input(),
  :close_fee_rate =&gt; decimal_input(),
  optional(:accrued_funding) =&gt; decimal_input()
}
```

Inputs for exit-based realized PnL including fees and funding.

# `roe_params`

```elixir
@type roe_params() :: %{pnl: decimal_input(), margin: decimal_input()}
```

Inputs for return on equity.

# `side`

```elixir
@type side() :: :long | :short
```

Position side for PnL calculations.

# `unrealized_params`

```elixir
@type unrealized_params() :: %{
  entry_price: decimal_input(),
  mark_price: decimal_input(),
  size: decimal_input(),
  side: side()
}
```

Inputs for mark-to-market unrealized PnL.

# `breakeven`

```elixir
@spec breakeven(breakeven_params()) :: Decimal.t()
```

Return the breakeven exit price after roundtrip fees and accrued funding.

Delegates to `DeltaCalc.Fees.funding_adjusted_breakeven/3`.
Returns `entry_price` unchanged when `size` is zero.

# `realized_pnl`

```elixir
@spec realized_pnl(realized_params()) :: Decimal.t()
```

Return net realized PnL at `exit_price` after open/close fees and accrued funding.

Uses `DeltaCalc.Fees.roundtrip_cost/1` for the fee component.
Returns zero when `size` or `entry_price` is not positive.

# `roe`

```elixir
@spec roe(roe_params()) :: Decimal.t()
```

Return `pnl / margin * 100`, or zero when margin is not positive.

# `unrealized_pnl`

```elixir
@spec unrealized_pnl(unrealized_params()) :: Decimal.t()
```

Return side-aware unrealized PnL from entry to mark price.

Returns zero when `size` or `entry_price` is not positive.

---

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