# `DpExchange.Core.Types.Watchlist`
[🔗](https://github.com/DistortionPoint/dp-exchange-core/blob/v0.3.120/lib/dp_exchange/core/types/watchlist.ex#L1)

A named list of instruments held **at the venue**.

## The venue's list is not the host's list

A host already knows which symbols it cares about. This is a different list, stored by the
venue, and the two can disagree — which is the reason to expose it rather than to assume
the host's own list is authoritative. A watchlist edited in the venue's own app is a fact
about the account, and a host reconciling against it needs to read it.

So this type carries the venue's identifier and the venue's membership, and does not merge
them with anything the host holds. **Merging is the host's decision**, and it needs both
sides to make it.

## `:symbols` is `nil` when unfetched, `[]` when empty

Venues list watchlists and their contents through separate endpoints, so a watchlist
fetched from the index has a name and no membership. `nil` says "not fetched"; `[]` says
"fetched, and empty". A caller syncing against `nil` read as empty would delete every
symbol in the list.

# `t`

```elixir
@type t() :: %DpExchange.Core.Types.Watchlist{
  id: String.t(),
  name: String.t() | nil,
  provider: atom(),
  symbols: [String.t()] | nil,
  venue_time: DateTime.t() | nil
}
```

# `new`

```elixir
@spec new(keyword() | map()) :: t()
```

Builds a `t:t/0`, failing closed if a required field is absent or `nil`.

`@enforce_keys` guards presence, not `nil` — see `DpExchange.Core.Types.Validate`.

Also raises on a `:symbols` that is not a proper list of non-blank strings. `nil` ("not
fetched") and `[]` ("fetched, and empty") are both accepted and stay apart.

---

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