# `ZenQuant.Options.Snapshot`
[🔗](https://github.com/ZenHive/zen_quant/blob/v0.8.1/lib/zen_quant/options/snapshot.ex#L1)

Structured options briefing over a pre-fetched chain.

`to_report/2` is pure: it never fetches from an exchange. Callers supply a
chain snapshot (optionally with spot and skew observations) and a source
timestamp. Each section is independent — a failed or unavailable section is
explicit and does not erase successful sections.

## Sections

* `:oi_concentration` — OI by strike/expiry, put/call totals, HHI-style concentration
* `:skew` — `Options.Skew.term_structure/1` over caller-supplied observations
* `:gamma_walls` — `Options.GammaWalls.aggregate/3` (requires spot and greeks)
* `:pin_risk` — `Options.pin_risk/3` proximity heuristic (requires spot)

Every section records the inputs/assumptions it used.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `to_report` | 2 | Compose a structured options briefing from a pre-fetched chain snapshot. | `snapshot: exchange_data` |

# `as_of`

```elixir
@type as_of() :: DateTime.t() | integer()
```

Source timestamp for the briefing (caller-owned; not wall-clock)

# `error_reason`

```elixir
@type error_reason() ::
  :invalid_input
  | :missing_chain
  | :invalid_chain
  | :missing_as_of
  | :invalid_as_of
  | :invalid_opts
```

Input validation failure

# `option_chain`

```elixir
@type option_chain() :: %{optional(String.t()) =&gt; map()}
```

Pre-fetched option chain map

# `report`

```elixir
@type report() :: %{
  as_of: as_of(),
  oi_concentration: section(),
  skew: section(),
  gamma_walls: section(),
  pin_risk: section()
}
```

Structured options briefing

# `section`

```elixir
@type section() :: section_ok() | section_error()
```

Independently named report section

# `section_error`

```elixir
@type section_error() :: %{status: :error, reason: term(), inputs: section_inputs()}
```

Failed or unavailable section payload

# `section_inputs`

```elixir
@type section_inputs() :: map()
```

Per-section inputs/assumptions echo

# `section_ok`

```elixir
@type section_ok() :: %{status: :ok, value: term(), inputs: section_inputs()}
```

Successful section payload

# `snapshot_input`

```elixir
@type snapshot_input() :: %{
  :chain =&gt; option_chain(),
  :as_of =&gt; as_of(),
  optional(:spot) =&gt; number(),
  optional(:skew_observations) =&gt; [map()]
}
```

Snapshot input for `to_report/2`

# `to_report`

```elixir
@spec to_report(
  snapshot_input() | term(),
  keyword()
) :: {:ok, report()} | {:error, error_reason()}
```

Build a structured briefing from a pre-fetched chain.

Does not call any exchange. Section failures are isolated.

---

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