PolymarketStrategies

Blueprint / example trading strategies for the paper_ex paper-trading engine.

This package is a reference set of textbook strategies — a starting point for building your own. Each one is a plain PaperEx.Strategy implementation: pure decision logic over PaperEx types (MarketSnapshot, Order, Portfolio), with hard-validated config in init/1. There is no proprietary alpha here; these are the classic patterns, clearly written and documented, so you can read them, run them on paper, and use them as a template.

The strategies

TagModuleCategoryIdea
momentumPolymarketStrategies.Momentum:flowBuy after a sustained upward move, betting it continues.
mean_reversionPolymarketStrategies.MeanReversion:flowBuy a dip below the trailing mean, betting it snaps back.
favorite_takerPolymarketStrategies.FavoriteTaker:takerTake the ask on moderate favorites when the spread is tight.
market_makerPolymarketStrategies.MarketMaker:restingQuote two-sided around the mid and re-quote as it moves.
stink_bidPolymarketStrategies.StinkBid:restingRest one discounted limit buy below the market and wait.
resolution_snipePolymarketStrategies.ResolutionSnipe:takerBuy a near-certain outcome and collect the last few cents at resolution.
basket_arbPolymarketStrategies.BasketArb:arbBuy every leg of a mutually-exclusive basket when the asks sum to under $1.

Each module's @moduledoc explains the mechanics, the per-tick behavior, and every option (with defaults and validation rules).

Installation

Add both this package and paper_ex to your deps:

def deps do
[
{:polymarket_strategies, "~> 0.1"},
{:paper_ex, "~> 0.8"}
]
end

Using the catalog

PolymarketStrategies.Catalog is a small registry so you can enumerate strategies by tag (to drive a UI, build runners, or wire up per-strategy settings) instead of hardcoding the list:

PolymarketStrategies.Catalog.all()
#=> [%{tag: "stink_bid", module: PolymarketStrategies.StinkBid,
# name: "Stink Bid", category: :resting}, ...]
PolymarketStrategies.Catalog.tags()
#=> ["stink_bid", "market_maker", "favorite_taker", ...]
PolymarketStrategies.Catalog.fetch("momentum")
#=> {:ok, %{tag: "momentum", module: PolymarketStrategies.Momentum, ...}}

Running a strategy

Every strategy implements the PaperEx.Strategy behaviour, so you drive it with paper_ex exactly like any other. For example, initialising and asking one for a decision:

{:ok, state} =
PolymarketStrategies.Momentum.init(lookback: 10, threshold: 0.05, size: 100)
{orders, state} =
PolymarketStrategies.Momentum.decide(
%{instrument_id: token_id, snapshot: snapshot, portfolio: portfolio},
state
)

See the paper_ex docs for the full runner / engine wiring and the PaperEx.Strategy contract.

Writing your own

These modules are meant to be copied and modified. A strategy is any module that implements PaperEx.Strategy — validate its options in init/1, keep decide/2 pure over the snapshot and portfolio, and make it idempotent against its own resting orders (so it doesn't double up). To surface a custom strategy in the catalog, register it without touching this package:

# via config
config :polymarket_strategies,
extra: [%{tag: "my_strat", module: MyApp.MyStrat, name: "My Strat", category: :custom}]
# or at runtime
PolymarketStrategies.Catalog.register(%{
tag: "my_strat",
module: MyApp.MyStrat,
name: "My Strat",
category: :custom
})

License

MIT. See the LICENSE file distributed with this package.