Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board
HomeBy LayerIntelligence4.16 LiquidityDecayMonitor

4.16 LiquidityDecayMonitor

Intelligence Signal Observe PLANNED Spec ready capital · Indirect P2 · Data normalisation pending stub

Tracks how quickly inside liquidity decays after our orders rest on the book. The output is a per-market liquidity-decay signal (in USD/second) that the smart router and order shaper consume to size and slice future orders. Pure observer — never blocks anything.

v3 readiness

Docs27/27
donehow scored
Impl0/15
pendinghow scored
Backtest0/4
pendinghow scored
Runtime0/8
pendinghow scored

A bot is done when all four scores are. What does done mean?

1. Bot Identity

LayerIntelligence  Intelligence
Bot classSignal
AuthorityObserve
StatusPLANNED
ReadinessSpec ready
Runs before
Runs afterintel.orderflowanalyzer, exec.order_lifecycle_manager
Applies toContinuous
Default modeshadow
User-visibleNo
Developer ownerIntelligence pod

Operational profile

OwnershipIntelligence pod · on-call intel-oncall · #polytraders-intel · escalates to Head of Intelligence · P3
Latency budgetp50: 8ms · p99: 30ms
Modes supportedoffshadowadvisory
Data freshnessmax_market_data_age_ms=2000 · max_orderbook_age_ms=2000 · on stale → Suppress emission; emit confidence=null.
Human overrideno · by · logs · time-bound: — · scope: — · single approver

2. Purpose

Tracks how quickly inside liquidity decays after our orders rest on the book. The output is a per-market liquidity-decay signal (in USD/second) that the smart router and order shaper consume to size and slice future orders. Pure observer — never blocks anything.

3. Why This Bot Matters

  • Order shaping with no liquidity model

    Without a decay estimate, the order shaper either over-slices (paying spread many times) or under-slices (eating its own resting depth).

  • Static liquidity assumptions

    Polymarket markets have wildly different microstructure across event types; a single config does not fit all of them.

  • Hidden execution cost

    Decay is the dominant hidden cost on illiquid markets; making it observable is the first step to controlling it.

No worked examples on this bot yet. Worked examples are optional but strongly recommended — they turn an abstract failure mode into something a developer can verify in a fixture.

4. Required Polymarket Inputs

InputSourceRequired?Use
OrderBookSnapshot streamWebSocket / data-flowYesTop-of-book depth at high frequency.
Our resting orders + fillsOrderLifecycleManagerYesIdentify the windows where we were the dominant resting size.

5. Required Internal Inputs

InputSourceRequired?Use
Per-market trade tapeintel.orderflowanalyzerYesUsed to attribute decay to taker flow vs cancellations.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
window_seconds60120300Trailing window over which decay is estimated.
min_observations30155Minimum sample count before publishing a decay estimate (otherwise emit confidence=null).

7. Detailed Parameter Instructions

window_seconds

What it means

Trailing window over which decay is estimated.

Default

{ "window_seconds": 60 }

Why this default matters

60 seconds balances responsiveness and stability for typical Polymarket binary markets.

Threshold logic

ConditionAction
< 5sToo noisy
60sDefault
> 600sToo slow to react to regime changes

Developer check

decay = (depth_t0 - depth_now) / window_seconds;

User-facing English

(Internal — not shown to users.)

min_observations

What it means

Minimum sample count before publishing a decay estimate (otherwise emit confidence=null).

Default

{ "min_observations": 30 }

Why this default matters

Avoids emitting wildly noisy estimates from a handful of ticks.

Threshold logic

ConditionAction
< 30Suppressed
≥ 30Published

Developer check

if (samples >= p.min_observations) emit(decayUsdPerSecond, confidence);

User-facing English

(Internal — not shown to users.)

8. Default Configuration

{
  "window_seconds": 60,
  "min_observations": 30
}

9. Implementation Flow

— not yet authored —

10. Reference Implementation

Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. IF/THEN/ELSE = decision. Translate directly to TypeScript, Python, Go, or Rust.

for each book_tick:
  baseline = rolling_baseline(market_id, p.window_seconds)
  decay = max(0, baseline - book.top_depth_usd) / p.window_seconds
  if samples(market_id) >= p.min_observations:
    emit_signal('liquidity_decay', market_id, decay, confidence(samples))

11. Wire Examples

Input — what arrives on the wire

{
  "market_id": "0xabc",
  "ts_ms": 1715260000000,
  "top_depth_usd": 87.5
}

Output — what the bot emits

{
  "kind": "liquidity_decay",
  "market_id": "0xabc",
  "value": 12.4,
  "confidence": 0.62
}

12. Decision Logic

APPROVE

Maintain rolling baseline depth and decayed depth. Attribute decay to (taker_volume, cancel_volume) using trade tape. Emit signal when sample count clears the threshold.

RESHAPE_REQUIRED

This bot does not reshape orders.

REJECT

No reject path defined for this bot — it is observe-only.

WARNING_ONLY

No warn-only path defined.

13. Standard Decision Output

This bot returns a RiskVote object. See RiskVote schema.

{
  "kind": "liquidity_decay",
  "market_id": "0xabc",
  "value": 12.4,
  "unit": "usd_per_second",
  "confidence": 0.62,
  "ts_ms": 1715260000000
}

14. Reason Codes

CodeSeverityMeaningActionUser-facing message
INTEL_DECAY_PUBLISHEDinfoIntel Decay PublishedSee decision output and developer log for context.(Internal signal — not user-facing.)
INTEL_DECAY_SUPPRESSED_LOW_SAMPLESinfoIntel Decay Suppressed Low SamplesSee decision output and developer log for context.(Internal signal — not user-facing.)
INTEL_DECAY_SUPPRESSED_HALTEDinfoIntel Decay Suppressed HaltedSee decision output and developer log for context.(Internal signal — not user-facing.)

15. Metrics & Logs

Metrics emitted

MetricTypeUnitLabelsMeaning
decay_emissions_totalcountereventbot_idDecay emissions total.
decay_suppressed_totalcountereventbot_idDecay suppressed total.
decay_value_histogramcountereventbot_idDecay value histogram.

Dashboards

  • 4.16 overview dashboard

16. Developer Reporting

"Per emission: market_id, window_seconds, samples, baseline_depth_usd, current_depth_usd, decay_usd_per_second, confidence."

17. Plain-English Reporting

SituationUser-facing explanation
When this bot acts(Internal signal — not user-facing.)

18. Failure-Mode Block

main_failure_modeMis-attributing depth changes to decay when the underlying event is a market-wide spread blowout.
false_positive_riskSudden venue-wide spread widening looks like decay; mitigation: gate emission on MarketHaltDetector status.
false_negative_riskSlow, smooth decay across a long event window may not register as significant; mitigation: also publish a long-window estimate alongside the short-window one.
safe_fallbackOn any sensor failure, suppress emission and emit confidence=null. Consumers default to a conservative slice size.
required_dependencies

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
Drop one in 10 book ticks and assert no spurious decay spikesDrop one in 10 book ticks and assert no spurious decay spikes.Bot detects within its latency budget and emits the corresponding reason code.Remove the injected fault; bot returns to healthy state within one debounce window.
Inject a halt and assert emission suppressionInject a halt and assert emission suppression.Bot detects within its latency budget and emits the corresponding reason code.Remove the injected fault; bot returns to healthy state within one debounce window.

20. State & Persistence

Per-market rolling buffers (baseline depth + sample count). In-memory; reseeds on restart.

State stores

NameKindKeyValue shapeTTLDurability
liquidity_decay_monitor_statein-memory + fast KV mirrormarket_idPer-market rolling buffers (baseline depth + sample count). In-memory; reseeds on restart.24hcrash-safe via KV mirror

Cold-start recovery

Cold-start hydrates from fast KV; missing keys default to safe fallback.

On restart

All in-flight decisions are re-evaluated; no bot decision is trusted across restart without re-emit.

21. Concurrency & Idempotency

AspectSpecification
Execution modelOne worker per market_id; lock-free ring buffer per series.
Max in-flight32
Idempotency keyorder_intent_id
Replay-safeTrue
DeduplicationBy idempotency_key within a 60s window.
Ordering guaranteesPer-market_id FIFO; cross-market unordered.
Per-call timeout (ms)250
Backpressure strategyBounded queue; oldest-dropped with metric increment when full.
Locking / mutual exclusionPer-market_id mutex; no global locks.

22. Dependencies

Depends on (must run first)

Requires (graph.requires)

intel.orderflowanalyzer exec.order_lifecycle_manager

ConsumesOrderBookSnapshot TradeTick FillEvent
EmitsSignalEnvelope(kind=liquidity_decay)
Blocks ordersno

23. Security Surfaces

Read-only on internal data-flow streams. Emits internal signals only.

Signing surface

Reads pending signed orders; never signs on user behalf.

Mitigations

  • Rate-limit per source
  • Audit-log every override
  • Require role-based authz on admin paths

24. Polymarket V2 Compatibility

AspectValue
CLOB versionV2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldyes
Aware of negative-risk marketsyes
Multi-chain readyyes
SDK usedPolymarket CLOB V2 SDK
Settlement contractCTFExchangeV2
NotesConsumes V2 OrderBookSnapshot and Fill events.

25. Versioning & Migration

FieldValue
current0.1.0
contract_version1.0.0
last_breaking_changenone
deprecation_window_days30

26. Acceptance Tests

Unit Tests

TestSetupExpected result
Synthetic 100→50 USD depth drop in 10s emits decay ≈ 5 USD/s.Synthetic fixture per template.Behaviour matches the rule described in the test name.
No depth change emits decay ≈ 0 with confidence trending to 1.0.Synthetic fixture per template.Behaviour matches the rule described in the test name.

Integration Tests

TestExpected result
Replay a recorded busy market for 10 minutes; assert emitted decay tracks observed taker volume within 20%.End-to-end behaviour matches the spec without manual intervention.

Property Tests

PropertyRequired behaviour
Decay estimate is in [0, baseline_depth/window_seconds] for any non-negative depth series.Always true across all generated inputs.

27. Operational Runbook

If consumers report wildly noisy slice sizes, raise window_seconds. If decay never publishes for a market, check sample count vs min_observations.

On-call actions

AlertFirst stepDiagnosisMitigationEscalate to
4.16_anomalyOpen the bot's reporting page and confirm the alert is real (not a metric hiccup).Inspect developer log entries for the affected market_id over the last 30 minutes.Force-clear via Admin UI if the rule is clearly stale; otherwise leave engaged and notify owner.Intelligence pod

Manual overrides

  • polytraders bot pause 4.16 — Disables the bot's enforcement layer; downstream consumers fall back to safe defaults.

Healthcheck

GET /healthz/liquidity_decay_monitor → 200 if last successful evaluation < 60s ago.

28. Promotion Gates

A bot does not advance to the next readiness state until every gate below is green. Gates are observable from production data — no subjective sign-off.

Promote to Shadow

GateHow measuredThreshold
Stubreplay test against a recorded market.Documented threshold met for the full window.

Promote to Limited live

GateHow measuredThreshold
Shadow14 days; consumers compare against baseline static decay.Documented threshold met for the full window.
Advisory14 days; consumers can adopt the signal voluntarily.Documented threshold met for the full window.

Promote to General live

GateHow measuredThreshold
Owner sign-offBot owner reviews 14 days of advisory data.No P1 incidents attributable to this bot.

29. Developer Checklist

Ready-to-ship score: 27/27 sections complete · 100%

RequirementStatus
Purpose defined✓ done
Required inputs listed✓ done
Parameters defined✓ done
Defaults defined✓ done
Warning thresholds defined✓ done
Hard thresholds defined✓ done
Safe fallback defined✓ done
Structured output defined✓ done
Developer log defined✓ done
Plain-English explanation✓ done
Unit tests defined✓ done
Integration tests defined✓ done
Property tests defined✓ done
Failure-mode block complete✓ done
Reference implementation pseudocode✓ done
Wire examples (input + output)✓ done
Reason codes listed✓ done
Metrics & logs defined✓ done
State & persistence defined✓ done
Concurrency & idempotency defined✓ done
Dependencies declared✓ done
Security surfaces declared✓ done
Polymarket V2 compatibility declared✓ done
Version & migration history declared✓ done
Operational runbook defined✓ done
Promotion gates defined✓ done
Failure-injection recipes defined✓ done