DEV Community

Cover image for Polymarket TWAP Market Maker: Quote Engine Design
Nagi
Nagi

Posted on

Polymarket TWAP Market Maker: Quote Engine Design

Build a Polymarket TWAP market maker using time-aware fair value, inventory skew, dynamic spreads, order-book data, and risk controls.

By Nagi

Nagi writes about Polymarket bots, algorithmic trading, quantitative strategies, Python automation, Web3, and prediction-market infrastructure.

Github: https://github.com/NagiPoly/poly-maker
Telegram: https://t.me/nagi_777x

A market maker normally starts with a simple question: What is fair value right now?

For a prediction-market order book, using the current midpoint alone can be unstable. A single aggressive trade can move the visible price while the broader market has barely changed.

A Polymarket TWAP market maker can treat that short-term noise differently. Instead of quoting directly from the latest midpoint, it combines a time-weighted reference price with current order-book information and inventory.

The result is not necessarily a wider or tighter market. It is a quote engine that has memory.

The core question

Can a TWAP reference make passive quotes less sensitive to short-lived price movements without making them dangerously stale?

That is a market-microstructure problem rather than simply a bot-development problem.

Polymarket's current market-data stream provides book, price-change, last-trade, tick-size, and best-bid/ask events. The platform also documents market-making guidance around two-sided quotes, inventory skew, stale-order cancellation, real-time data, and order replacement. ([Polymarket Documentation][2])

A better definition of fair value

Let:

  • (M_t) = current midpoint
  • (T_t) = rolling TWAP
  • (I_t) = normalized inventory
  • (w) = TWAP weight

A simple reference model is:

F_t = (1-w)M_t + wT_t
Enter fullscreen mode Exit fullscreen mode

If (w=0), the market maker behaves like a pure spot-midpoint strategy.

If (w) increases, the quote engine becomes progressively more anchored to recent history.

That creates an important trade-off.

A high TWAP weight filters noise, but it can also make the market maker slow to react when information genuinely changes the probability.

So the useful variable is not simply TWAP window. It is how much authority the TWAP has over the quote.

Add inventory before calculating the spread

Suppose the strategy is holding too many YES shares.

The fair-value estimate might still be correct, but continuing to quote symmetrical prices increases directional exposure.

Introduce an inventory adjustment:

F'_t = F_t - \lambda I_t
Enter fullscreen mode Exit fullscreen mode

where (\lambda) controls inventory pressure.

Positive inventory shifts the effective fair value downward, encouraging more selling and less buying.

The final quote can then be represented conceptually as:

Bid = F'_t - S_t
Enter fullscreen mode Exit fullscreen mode
Ask = F'_t + S_t
Enter fullscreen mode Exit fullscreen mode

where (S_t) is the dynamic half-spread.

This gives the system three separate controls:

TWAP → price stability

Inventory → exposure control

Spread → compensation for execution risk

That separation is useful when debugging because each adjustment has a different purpose.

What should determine the spread?

A fixed spread is rarely enough.

A practical quote engine can expand (S_t) when:

  • the order book becomes thin;
  • recent price volatility increases;
  • inventory approaches a limit;
  • the market is approaching a known catalyst;
  • the TWAP and midpoint diverge substantially;
  • the system's market-data state becomes stale.

One possible model is:

S_t = S_0 + \alpha\sigma_t + \beta|M_t-T_t| + \gamma|I_t|
Enter fullscreen mode Exit fullscreen mode

Here, (\sigma_t) represents short-term volatility.

The interesting term is (|M_t-T_t|).

A large deviation means the current market has moved far away from its recent average. That does not mean the market must revert. Instead, it can be interpreted as a warning that quoting aggressively around the old TWAP carries more model risk.

Python prototype

The following is a synthetic quote calculation, not measured Polymarket performance:

from dataclasses import dataclass

@dataclass
class Quote:
    bid: float
    ask: float
    fair_value: float

def calculate_quote(
    midpoint: float,
    twap: float,
    inventory: float,
    twap_weight: float = 0.35,
    inventory_penalty: float = 0.02,
    base_spread: float = 0.01,
):
    fair = (
        (1.0 - twap_weight) * midpoint
        + twap_weight * twap
        - inventory_penalty * inventory
    )

    spread = base_spread + 0.5 * abs(midpoint - twap)

    return Quote(
        bid=max(0.001, fair - spread),
        ask=min(0.999, fair + spread),
        fair_value=fair,
    )
Enter fullscreen mode Exit fullscreen mode

The important design choice is that the TWAP is not directly used as the bid or ask.

It modifies fair value, while market conditions determine how far quotes sit from that value.

Polymarket-specific execution constraints

A production implementation must use the market's current tick size and minimum order size. Polymarket documents that these constraints can change and that integrations should process tick_size_change events rather than permanently caching the initial tick size. ([Polymarket Documentation][3])

For passive market making, Polymarket currently documents GTC and GTD orders as the primary resting order types and supports post-only behavior when the strategy specifically needs an order to add liquidity rather than execute immediately. Orders cannot simply be edited in place; changing a quote requires cancellation and replacement. ([Polymarket Documentation][1])

That makes the quote engine a state-management problem:

Market events
      ↓
Local book
      ↓
TWAP calculator
      ↓
Fair-value model
      ↓
Inventory adjustment
      ↓
Quote generator
      ↓
Cancel / replace
      ↓
Order updates
Enter fullscreen mode Exit fullscreen mode

The local state must survive reconnects and reconcile against open orders before quoting again. Polymarket explicitly recommends fetching open orders and recent trades after reconnecting. ([Polymarket Documentation][1])

What can go wrong?

The most dangerous failure is TWAP anchoring during a genuine regime change.

Imagine a market trading around 0.55 for several minutes. New information arrives and the executable midpoint jumps to 0.70.

A slow TWAP remains near 0.55.

A naive TWAP market maker continues quoting around the historical reference and can become liquidity for informed traders.

Therefore, a TWAP-aware system needs a divergence circuit breaker:

|M_t-T_t| > D_{max}
\Rightarrow
reduce\ size\ or\ stop\ quoting
Enter fullscreen mode Exit fullscreen mode

This is more important than finding the “perfect” TWAP window.

Testing methodology

Use synthetic and historical replay separately.

Hypothesis: TWAP anchoring reduces unnecessary quote movement.

Experiment: Compare midpoint-only and TWAP-aware quote engines on identical replayed market data.

Observed result: Measure quote churn, inventory variance, fill distribution, spread capture, and adverse selection.

Interpretation: Determine whether the reduction in quote movement actually improves risk-adjusted execution.

Do not evaluate the strategy using midpoint fills alone. Real order-book depth, executable prices, partial fills, cancellations, and inventory must be represented.

Polymarket notes that desired trade size can move the market when liquidity is insufficient, making order-book depth a practical constraint rather than an optional metric. ([Polymarket Help Center][4])

Advanced extensions

An experienced implementation could extend the model with:

  1. Adaptive TWAP windows based on volatility.
  2. Microprice inputs from bid/ask depth instead of midpoint alone.
  3. Regime detection that temporarily disables TWAP anchoring.
  4. Cross-market references for correlated prediction markets.
  5. Rebate-aware quoting, where expected maker incentives become part of quote economics.

Polymarket currently operates maker-rebate and liquidity-reward programs, with eligibility and calculations depending on the applicable program and market. ([Polymarket Help Center][5])

Key takeaways

  • TWAP should be an anchor, not a substitute for live market data.
  • Inventory should modify fair value independently from the TWAP.
  • Large TWAP/midpoint divergence is a risk signal, not automatically a mean-reversion opportunity.
  • Quote width should respond to volatility, liquidity, inventory, and model uncertainty.
  • The production challenge is maintaining synchronized market, order, and inventory state.

FAQ

What is a Polymarket TWAP market maker?
A market-making system that uses a time-weighted historical price as one component of its fair-value model.

Should TWAP replace the current midpoint?
Usually not. A hybrid reference can retain current information while reducing sensitivity to isolated price movements.

What happens when price moves sharply away from TWAP?
The divergence can trigger wider quotes, smaller sizes, or a temporary quoting halt.

Can TWAP guarantee better market-making performance?
No. It is a filtering and reference technique, not a profitability guarantee.

What data does the system need?
At minimum, time-stamped market prices, order-book state, inventory, active orders, and market constraints such as tick size and minimum order size.

Trading disclaimer

This article is for educational and research purposes only. Trading prediction markets involves market, liquidity, execution, model, and capital risk. No strategy discussed here guarantees profit.

Conclusion

The interesting part of a TWAP-aware market maker is not the moving-average calculation. It is deciding when historical price information should influence a quote and when it should be ignored.

Top comments (0)