Packages
polymarket_strategies
0.1.0
Blueprint / example trading strategies for the paper_ex paper-trading engine — a reference set of textbook strategies (momentum, mean-reversion, favorite/longshot, market-making, stink-bid, resolution-snipe, basket arbitrage) implementing PaperEx.Strategy.
Current section
Files
Jump to
Current section
Files
lib/catalog.ex
defmodule PolymarketStrategies.Catalog do
@moduledoc """
The registry of available strategies — the built-in example set plus
any **user-registered** ones — so the rest of the system can enumerate
them by `tag` (drive a UI, build runners, wire up settings) without
hardcoding the list.
Each entry is `%{tag, module, name, category}`:
* `:tag` — the string a strategy stamps on its orders/positions
(also a natural key for per-strategy settings);
* `:module` — a `PaperEx.Strategy` implementation;
* `:name` — human label;
* `:category` — coarse grouping (`:taker`, `:resting`, `:arb`,
`:flow`, `:custom`).
## Extensibility (user-written strategies)
Any module implementing `PaperEx.Strategy` is a valid strategy. To
surface a custom one in the catalog (and thus in whatever UI or
settings you drive from it), register it via config — no change to
this package:
config :polymarket_strategies,
extra: [%{tag: "my_strat", module: MyApp.MyStrat, name: "My Strat", category: :custom}]
or at runtime via `register/1`. This catalog ships only the
**blueprint** strategies bundled here; treat it as a starting point
and add your own.
"""
alias PolymarketStrategies, as: S
@built_in [
%{tag: "stink_bid", module: S.StinkBid, name: "Stink Bid", category: :resting},
%{tag: "market_maker", module: S.MarketMaker, name: "Market Maker", category: :resting},
%{tag: "favorite_taker", module: S.FavoriteTaker, name: "Favorite Taker", category: :taker},
%{tag: "resolution_snipe", module: S.ResolutionSnipe, name: "Resolution Snipe", category: :taker},
%{tag: "momentum", module: S.Momentum, name: "Momentum", category: :flow},
%{tag: "mean_reversion", module: S.MeanReversion, name: "Mean Reversion", category: :flow},
%{tag: "basket_arb", module: S.BasketArb, name: "Basket Arb", category: :arb}
]
@type entry :: %{tag: String.t(), module: module(), name: String.t(), category: atom()}
@doc "All strategies: built-in ++ user-registered (config `:extra`)."
@spec all() :: [entry()]
def all do
extra = Application.get_env(:polymarket_strategies, :extra, [])
@built_in ++ Enum.map(extra, &normalize/1)
end
@doc "Just the built-in (blueprint) strategies."
@spec built_in() :: [entry()]
def built_in, do: @built_in
@doc "All strategy tags (built-in ++ registered)."
@spec tags() :: [String.t()]
def tags, do: Enum.map(all(), & &1.tag)
@doc "Look up an entry by its tag."
@spec fetch(String.t()) :: {:ok, entry()} | :error
def fetch(tag) do
case Enum.find(all(), &(&1.tag == tag)) do
nil -> :error
entry -> {:ok, entry}
end
end
@doc """
Register a custom strategy at runtime (appends to config `:extra`).
The module must implement `PaperEx.Strategy`.
"""
@spec register(entry()) :: :ok
def register(%{tag: tag, module: module} = entry) when is_binary(tag) and is_atom(module) do
extra = Application.get_env(:polymarket_strategies, :extra, [])
Application.put_env(:polymarket_strategies, :extra, extra ++ [normalize(entry)])
:ok
end
defp normalize(entry) do
%{
tag: entry.tag,
module: entry.module,
name: Map.get(entry, :name, entry.tag),
category: Map.get(entry, :category, :custom)
}
end
end