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

One row from a venue's screener, mover list or ranking.

## The criteria are the venue's, and two venues' lists are not comparable

A "top mover" list is the output of a rule the venue chose: over what window, ranked by
what, filtered to which universe. Two venues publish lists under the same name that answer
different questions, and nothing in the rows says so.

So `:screener` carries the venue's own identifier for the list, and `:metrics` carries
whatever it ranked by, under the venue's own keys. **This interface does not re-rank, merge
or compare across venues** — doing so would produce a combined list whose ordering means
nothing, from rows that were each individually correct.

`:rank` is the venue's position in its own list, kept because a caller asking for the top
ten wants to know which was first, and lost the moment rows from two venues are mixed.

# `t`

```elixir
@type t() :: %DpExchange.Core.Types.ScreenerResult{
  metrics: %{optional(String.t()) =&gt; term()} | nil,
  provider: atom(),
  rank: pos_integer() | nil,
  screener: String.t(),
  symbol: String.t(),
  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 `:rank` that is not a positive integer (a position in the venue's own list
starts at 1; `nil` is "the venue gave none") and on `:metrics` that is not a plain map.

---

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