Packages

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
Raw

README.md

# PolymarketStrategies
Blueprint / example trading strategies for the
[`paper_ex`](https://hex.pm/packages/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
| Tag | Module | Category | Idea |
|--------------------|------------------------------------------|------------|------|
| `momentum` | `PolymarketStrategies.Momentum` | `:flow` | Buy after a sustained upward move, betting it continues. |
| `mean_reversion` | `PolymarketStrategies.MeanReversion` | `:flow` | Buy a dip below the trailing mean, betting it snaps back. |
| `favorite_taker` | `PolymarketStrategies.FavoriteTaker` | `:taker` | Take the ask on moderate favorites when the spread is tight. |
| `market_maker` | `PolymarketStrategies.MarketMaker` | `:resting` | Quote two-sided around the mid and re-quote as it moves. |
| `stink_bid` | `PolymarketStrategies.StinkBid` | `:resting` | Rest one discounted limit buy below the market and wait. |
| `resolution_snipe` | `PolymarketStrategies.ResolutionSnipe` | `:taker` | Buy a near-certain outcome and collect the last few cents at resolution. |
| `basket_arb` | `PolymarketStrategies.BasketArb` | `:arb` | Buy 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:
```elixir
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:
```elixir
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:
```elixir
{: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:
```elixir
# 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.