PolymarketNotify.Controls (PolymarketNotify v0.1.0)

Copy Markdown View Source

The notification control model — what the user wants to see and where, as per-category defaults plus per-strategy overrides. Pure data

  • pure resolution; no I/O, so it's trivially testable and a UI/editor can read & write it later.

Shape:

%{
  categories: %{
    fills:        %{enabled: true, min_value: 25.0, channels: [:telegram]},
    resolutions:  %{enabled: true, channels: [:telegram]},
    errors:       %{enabled: true, channels: [:telegram, :log]},
    daily_summary: %{enabled: true, channels: [:telegram]}
  },
  # per-strategy overrides: tag => %{category => partial pref}
  strategies: %{
    "surge"  => %{fills: %{enabled: false}},
    "ai"     => %{fills: %{enabled: true, min_value: 0.0}}
  },
  default_channels: [:log]
}

Resolution merges the category default with any per-strategy override for that (strategy, category). Strategy tags are arbitrary strings, so user-written strategies configure exactly like built-ins.

Summary

Functions

Should category (for optional strategy, at optional value) be delivered?

Channel names for category (for optional strategy).

The default control set: every category on, routed to default_channels, no overrides.

Seed controls from a strategy catalog (list of tags or maps with a :tag), so every strategy — built-in or user-written — is present and individually configurable (UI/editor can flip each). Overrides start empty (inherit the category default).

Types

t()

@type t() :: %{
  optional(:categories) => map(),
  optional(:strategies) => map(),
  optional(:default_channels) => [atom()]
}

Functions

allow?(controls, category, strategy, value)

@spec allow?(t(), atom(), String.t() | nil, number() | nil) :: boolean()

Should category (for optional strategy, at optional value) be delivered?

channels_for(controls, category, strategy)

@spec channels_for(t(), atom(), String.t() | nil) :: [atom()]

Channel names for category (for optional strategy).

default()

@spec default() :: t()

The default control set: every category on, routed to default_channels, no overrides.

from_catalog(catalog, opts \\ [])

@spec from_catalog(
  [String.t() | %{tag: String.t()}],
  keyword()
) :: t()

Seed controls from a strategy catalog (list of tags or maps with a :tag), so every strategy — built-in or user-written — is present and individually configurable (UI/editor can flip each). Overrides start empty (inherit the category default).