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 LayerStrategy3.14 Liquidity-Pulse

3.14 Liquidity-Pulse

Strategy Alpha Strategy Trade PLANNED Spec started capital · Direct P8 · Additional strategies pending stub

Liquidity-Pulse is a market-analytics tool that monitors emerging Polymarket markets for early liquidity opportunities. When a market's volume and attention signal crosses configured thresholds, the bot emits an OrderIntent for user-controlled maker quote placement. All execution decisions remain with the user; this bot provides structured analytics and sizing recommendations only.

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

LayerStrategy  Strategy
Bot classAlpha Strategy
AuthorityTrade
StatusPLANNED
ReadinessSpec started
Runs beforeRisk guardrail pipeline
Runs afterMarket scanner / Observation bus
Applies toPolymarket binary markets that are gaining attention but currently have wide spreads and thin depth, offering attractive conditions for early market-making analytics
Default modeshadow_only
User-visibleAdvanced details only
Developer ownerPolytraders core — Strategy pod

2. Purpose

Liquidity-Pulse is a market-analytics tool that monitors emerging Polymarket markets for early liquidity opportunities. When a market's volume and attention signal crosses configured thresholds, the bot emits an OrderIntent for user-controlled maker quote placement. All execution decisions remain with the user; this bot provides structured analytics and sizing recommendations only.

3. Why This Bot Matters

  • Quote placed before sufficient volume confirmation

    Early quotes on unproven markets may sit unmatched or attract adverse selection from informed traders who discovered the market first.

  • Spread tightening faster than quote updates

    Quotes placed at the initial wide spread become the worst price on the book as other makers tighten, leading to adverse selection.

  • Market resolves before position unwinds

    Short-lived markets may reach resolution before an early maker position can be exited, forcing settlement at a potentially unfavorable resolution price.

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
CLOB book depth, spread, and volumews_marketYesMeasure current spread width and depth; detect volume pickup above tighten_at_volume_usd.
Market metadata (creation time, category, status)gammaYesCompute market age; verify event_lead_time_h; confirm market is open.
Market status (open/closed)clob_publicYesSkip closed or resolved markets.

5. Required Internal Inputs

InputSourceRequired?Use
KillSwitch active flagKillSwitchYesAbort all intent emission if KillSwitch active.
Attention signal (volume trend, social mention rate)internal (market scanner)YesGate quote entry on attention signal exceeding threshold.
Builder code bytes32internal configYesInjected into builder field on every signed V2 OrderIntent.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
initial_spread_bps20010050Initial maker quote spread in bps around the current mid-price for early-liquidity quote recommendations.
tighten_at_volume_usd50002000500Total traded volume threshold in pUSD above which the bot recommends tightening the spread by 50%.
max_pre_event_position_usd300500750Maximum pUSD maker position recommended per market during the pre-event attention phase.
event_lead_time_h2461Minimum hours before the event for the bot to emit early-liquidity quote recommendations. Avoids posting too close to resolution.

7. Detailed Parameter Instructions

initial_spread_bps

What it means

Initial maker quote spread in bps around the current mid-price for early-liquidity quote recommendations.

Default

{ "initial_spread_bps": 200 }

Why this default matters

200 bps provides sufficient maker edge on thin, uncertain markets before volume develops.

Threshold logic

ConditionAction
>= 200 bpsStandard early-liquidity quote
100–200 bpsWARN LP_TIGHT_SPREAD; reduced confidence
< 50 bpsHARD_REJECT LP_SPREAD_BELOW_FLOOR

Developer check

if params.initial_spread_bps < params.hard: return skip('LP_SPREAD_BELOW_FLOOR')

User-facing English

The recommended spread is too tight for the current market conditions.

tighten_at_volume_usd

What it means

Total traded volume threshold in pUSD above which the bot recommends tightening the spread by 50%.

Default

{ "tighten_at_volume_usd": 5000 }

Why this default matters

5000 pUSD signals enough market activity to justify tighter spreads with lower adverse-selection risk.

Threshold logic

ConditionAction
>= 5000 pUSD volumeTighten spread recommendation by 50%
< 500 pUSDMaintain wide initial spread

Developer check

if total_volume >= params.tighten_at_volume_usd: spread = initial_spread_bps * 0.5

User-facing English

Volume has reached the threshold for a tighter spread recommendation.

max_pre_event_position_usd

What it means

Maximum pUSD maker position recommended per market during the pre-event attention phase.

Default

{ "max_pre_event_position_usd": 300 }

Why this default matters

300 pUSD limits adverse-selection exposure on thin pre-event markets.

Threshold logic

ConditionAction
<= 300 pUSDNormal pre-event sizing
> 750 pUSDReject config — PARAMETER_CHANGE_REQUIRES_APPROVAL

Developer check

if params.max_pre_event_position_usd > params.hard: raise ConfigError('PARAMETER_CHANGE_REQUIRES_APPROVAL')

User-facing English

Position size was capped at the configured pre-event maximum.

event_lead_time_h

What it means

Minimum hours before the event for the bot to emit early-liquidity quote recommendations. Avoids posting too close to resolution.

Default

{ "event_lead_time_h": 24 }

Why this default matters

24h lead time ensures the market has time to develop depth before resolution risk dominates.

Threshold logic

ConditionAction
>= 24hStandard lead time
6–24hWARN LP_SHORT_LEAD_TIME; halve max position
< 1hHARD_REJECT LP_TOO_CLOSE_TO_RESOLUTION

Developer check

if hours_to_event < params.hard: return skip('LP_TOO_CLOSE_TO_RESOLUTION')

User-facing English

The market is too close to its resolution time for an early liquidity position.

8. Default Configuration

{
  "bot_id": "strat.liquidity_pulse",
  "version": "0.1.0",
  "mode": "shadow_only",
  "defaults": {
    "initial_spread_bps": 200,
    "tighten_at_volume_usd": 5000,
    "max_pre_event_position_usd": 300,
    "event_lead_time_h": 24
  },
  "locked": {
    "initial_spread_bps": {
      "min": 50
    },
    "max_pre_event_position_usd": {
      "max": 750
    },
    "event_lead_time_h": {
      "min": 1
    }
  }
}

9. Implementation Flow

  1. Check KillSwitch; if active, emit no OrderIntents.
  2. FETCH gamma market metadata; compute hours_to_event.
  3. IF hours_to_event < hard (1h): skip LP_TOO_CLOSE_TO_RESOLUTION.
  4. FETCH attention signal from market scanner; if below threshold, skip.
  5. FETCH ws_market book; compute current spread and total_volume.
  6. Compute recommended spread: initial_spread_bps * (0.5 if total_volume >= tighten_at_volume_usd else 1.0).
  7. IF recommended_spread < spread_hard (50 bps): skip LP_SPREAD_BELOW_FLOOR.
  8. Compute position_size = min(max_pre_event_position_usd, available_capital).
  9. Adjust size down 50% if hours_to_event < warning (6h).
  10. EMIT OrderIntent: post_only=true, bid=mid-spread/2, ask=mid+spread/2, size=position_size, builder=code.
  11. EMIT DecisionReport with intent_emitted=true, reason=LP_QUOTE_EMITTED.

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.

FUNCTION onAttentionSignal(market_id, attentionSignal):
  ks = FETCH internal.killswitch.status
  IF ks.active: RETURN

  // Resolve event lead time
  meta = FETCH gamma.GET('/markets/' + market_id)
  hoursToEvent = (meta.end_date_ms - now_ms()) / 3600000
  IF hoursToEvent < params.event_lead_time_h_hard:  // 1h
    EMIT DecisionReport(intent_emitted=false, reason='LP_TOO_CLOSE_TO_RESOLUTION')
    RETURN

  // Book and volume snapshot
  book = FETCH ws_market.book(market_id)
  totalVolume = book.total_traded_volume_usd
  mid = (book.best_bid + book.best_ask) / 2

  // Spread computation
  spreadBps = params.initial_spread_bps
  IF totalVolume >= params.tighten_at_volume_usd:
    spreadBps = spreadBps * 0.5

  IF spreadBps < params.initial_spread_bps_hard:  // 50 bps
    EMIT DecisionReport(intent_emitted=false, reason='LP_SPREAD_BELOW_FLOOR')
    RETURN

  IF spreadBps < params.initial_spread_bps_warn:  // 100 bps
    WARN('LP_TIGHT_SPREAD')

  // Sizing
  sizeMultiplier = 0.5 IF hoursToEvent < params.event_lead_time_h_warn ELSE 1.0  // < 6h
  orderSize = toPusdUnits(params.max_pre_event_position_usd * sizeMultiplier)

  bidPrice = mid - (spreadBps / 20000)
  askPrice = mid + (spreadBps / 20000)

  EMIT OrderIntent(market=market_id, outcome='YES', side='buy', price=bidPrice,
                   size_pUSD=orderSize, tif='GTC', post_only=true, builder=internalBuilderCode)
  EMIT DecisionReport(intent_emitted=true, spread_bps=spreadBps, reason='LP_QUOTE_EMITTED')

SDK calls used

  • ws_market.subscribe('book', [market_id])
  • gamma.GET('/markets/' + market_id)
  • fetchClobPublic('/markets/' + market_id)
  • internal.killswitch.status()
  • buildOrderTypedData(orderParams, {name:'CTFExchange', version:'2', chainId:137})

Complexity: O(1) per attention signal per market

11. Wire Examples

Input — what arrives on the wire

Attention signal — market gaining volumeinternal (market scanner)

{
  "market_id": "0xlp000000000000000000000000000000000000000000000000000000000000001",
  "attention_score": 0.72,
  "total_volume_usd": "850.0",
  "hours_to_event": "36.0",
  "received_at_ms": 1746790800000
}

Output — what the bot emits

OrderIntent — LP GTC post-only maker YES

{
  "intent_id": "oi_01HLP0000001A",
  "market_id": "0xlp000000000000000000000000000000000000000000000000000000000000001",
  "outcome": "YES",
  "side": "buy",
  "price": "0.490",
  "size_pUSD": "150.00",
  "tif": "GTC",
  "post_only": true,
  "builder": {
    "code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
    "fee_bps": 10
  },
  "decision": {
    "spread_bps": 200,
    "reasons": [
      "LP_QUOTE_EMITTED"
    ]
  }
}

12. Decision Logic

APPROVE

hours_to_event >= 1h, attention signal above threshold, spread >= 50 bps, market open, KillSwitch inactive.

RESHAPE_REQUIRED

Not applicable — reshaping handled by downstream Risk guardrail.

REJECT

hours_to_event < 1h; spread < 50 bps; KillSwitch active.

WARNING_ONLY

hours_to_event 6–24h triggers warning and 50% position reduction; spread 100–200 bps triggers tight-spread warning.

13. Standard Decision Output

This bot returns a OrderIntent object. See OrderIntent schema.

{
  "intent_id": "oi_01HLP0000001A",
  "trace_id": "tr_01HLP000TR001",
  "market_id": "0xlp000000000000000000000000000000000000000000000000000000000000001",
  "outcome": "YES",
  "side": "buy",
  "price": "0.490",
  "size_pUSD": "150.00",
  "tif": "GTC",
  "post_only": true,
  "builder": {
    "code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
    "fee_bps": 10
  },
  "negrisk_aware": false,
  "decision": {
    "spread_bps": 200,
    "hours_to_event": 36.0,
    "total_volume_usd": 850.0,
    "reasons": [
      "LP_QUOTE_EMITTED"
    ]
  },
  "comment": "fees are operator-set at match time in V2 \u2014 feeRateBps is NOT on the signed order"
}

14. Reason Codes

CodeSeverityMeaningActionUser-facing message
LP_QUOTE_EMITTEDINFOAttention signal fired, spread viable, hours_to_event OK. GTC post-only maker OrderIntent emitted.Emit GTC maker OrderIntent.An early-liquidity maker quote was placed.
LP_TOO_CLOSE_TO_RESOLUTIONHARD_REJECThours_to_event < 1h hard floor. Resolution risk too high for new maker positions.Skip; no OrderIntent.Too close to the event time for a new maker position.
LP_TIGHT_SPREADWARNRecommended spread between 100 and 200 bps; adverse selection risk elevated.Emit with lower confidence; log warning.The spread is tighter than ideal for early liquidity.
LP_SPREAD_BELOW_FLOORHARD_REJECTComputed spread < 50 bps hard floor.Skip; no OrderIntent.The spread was below the minimum required.
KILL_SWITCH_ACTIVEHARD_REJECTGlobal kill switch is active.Skip all markets; no OrderIntents emitted.Trading is currently paused.

15. Metrics & Logs

Metrics emitted

MetricTypeUnitLabelsMeaning
polytraders_strat_liquiditypulse_decisions_totalcountercountverdict, reason_codeTotal evaluation cycles by verdict and reason.
polytraders_strat_liquiditypulse_spread_bpshistogrambasis_pointsDistribution of recommended spreads at quote emission.
polytraders_strat_liquiditypulse_intents_emitted_totalcountercountspread_tierTotal maker OrderIntents by spread tier (wide/tight).
polytraders_strat_liquiditypulse_eval_latency_mshistogrammillisecondsLatency from attention signal to OrderIntent emit.

Alerts

AlertConditionSeverityRunbook
LiquidityPulseHighAdverseSelectionrate(polytraders_strat_liquiditypulse_decisions_total{reason_code='LP_TIGHT_SPREAD'}[5m]) > 0.3warn#runbook-lp-spread
LiquidityPulseKillSwitchrate(polytraders_strat_liquiditypulse_decisions_total{reason_code='KILL_SWITCH_ACTIVE'}[1m]) > 0page#runbook-killswitch
LiquidityPulseStaleFeedrate(polytraders_strat_liquiditypulse_decisions_total{reason_code='STALE_MARKET_DATA'}[5m]) > 0.1warn#runbook-lp-stale

16. Developer Reporting

{
  "bot_id": "strat.liquidity_pulse",
  "market_id": "0xlp000000000000000000000000000000000000000000000000000000000000001",
  "spread_bps": 200,
  "hours_to_event": 36.0,
  "total_volume_usd": 850.0,
  "intent_emitted": true,
  "reason": "LP_QUOTE_EMITTED",
  "emitted_at_ms": 1746790800000
}

17. Plain-English Reporting

SituationUser-facing explanation
Early-liquidity quote placedThis market is attracting attention but still has a wide spread. A maker quote was placed to provide early liquidity at an attractive spread.
Market too close to resolutionLess than 1 hour remains before the event. No new maker positions were opened to avoid resolution-time risk.
Volume threshold reached — spread tightenedTraded volume crossed the threshold. The recommended spread was narrowed to remain competitive.

18. Failure-Mode Block

main_failure_modeAdverse selection: informed traders arrive first and take liquidity at the initial wide spread before the market develops, leaving the maker with a systematically mispriced position.
false_positive_riskAttention signal fires on markets that spike briefly but have no underlying trading interest, producing wasted quote placement.
false_negative_riskevent_lead_time_h too large misses genuine early-liquidity windows on rapidly developing markets.
safe_fallbackIf ws_market feed stale or gamma metadata unavailable, skip without emitting any OrderIntent.
required_dependenciesws_market, clob_public, gamma, internal market scanner, KillSwitch, internal builder code

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
GAMMA_METADATA_UNAVAILABLETake gamma API offline; bot cannot compute hours_to_eventAutomatic when gamma API returns.
NEAR_RESOLUTION_BLOCKSet hours_to_event=0.5 (< 1h hard)Automatic — bot resumes after market resolves or resets.
KILL_SWITCH_ONSet killswitch.active=trueAutomatic on manual KillSwitch reset.

20. State & Persistence

Cold-start recovery

On cold start, attention signals re-polled from market scanner; spread recomputed from ws_market.

21. Concurrency & Idempotency

AspectSpecification
Execution modelactor-per-market
Max in-flight30
Idempotency keyintent_id
Per-call timeout (ms)300
Backpressure strategydrop oldest attention signal per market_id when queue > 2
Locking / mutual exclusionper-market_id mutex for spread-state

22. Dependencies

Depends on (must run first)

BotWhyContract
risk.kill_switchChecked first; blocks all intent emission when active.

Emits to (downstream consumers)

External services

ServiceEndpointSLA assumedOn failure
Polymarket CLOB WebSocket (ws_market)best-effort
Polymarket Gamma API (market metadata)99.9%

23. Security Surfaces

Abuse vectors considered

  • Attention signal injection to force quotes on low-quality markets
  • Front-running of posted GTC quotes by adversaries who monitor emerging markets

Mitigations

  • Attention signals sourced from authenticated internal market scanner only
  • Quote sizes bounded by max_pre_event_position_usd
  • GTC quotes can be cancelled by user at any time

24. Polymarket V2 Compatibility

AspectValue
CLOB versionv2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldyes
Aware of negative-risk marketsno
Multi-chain readyno
SDK usedpy-clob-client-v2
Settlement contractCTFExchangeV2
NotesBot not yet implemented; designed against V2 schema (pUSD, builder codes, V2 EIP-712 domain). feeRateBps not present on any signed OrderIntent.

API surfaces declared

clob_publicclob_authws_marketgammainternal

Networks supported

polygon

25. Versioning & Migration

FieldValue
spec2.0.0
implementation0.1.0
schema2
releasedNone
planned_releaseQ3-2026

Migration history

DateFromToReasonAction taken
2026-04-28n/av2-specSpec drafted post-CLOB-V2 cutover; bot not yet implementedDesigned against V2 schema (pUSD, builder codes, V2 EIP-712 domain)

26. Acceptance Tests

Unit Tests

TestSetupExpected result
Emit GTC post-only maker quote when attention signal fires, hours_to_event=36initial_spread_bps=200, max_pre_event_position_usd=300GTC post_only OrderIntent; reason=LP_QUOTE_EMITTED
Skip when hours_to_event < 1h hard floorhours_to_event=0.5No OrderIntent; reason=LP_TOO_CLOSE_TO_RESOLUTION
Tighten spread when total_volume >= 5000 pUSDtotal_volume=5500, initial_spread_bps=200OrderIntent with spread_bps=100

Integration Tests

TestExpected result
Full cycle: attention signal → quote → GTC post-only OrderIntent on Polygon testnetOrder has builder.code, post_only=true, no feeRateBps, EIP-712 domain v2

Property Tests

PropertyRequired behaviour
Bot never emits OrderIntent when hours_to_event < 1hAlways true
feeRateBps never present on any signed OrderIntentAlways true

27. Operational Runbook

Liquidity-Pulse incidents are typically gamma API outages (blocking event lead-time checks) or kill-switch activations. Near-resolution blocks are expected behavior.

On-call actions

AlertFirst stepDiagnosisMitigationEscalate to
LiquidityPulseHighAdverseSelection
LiquidityPulseKillSwitch
LiquidityPulseStaleFeed

Manual overrides

Healthcheck

GET /internal/health/liquidity-pulse -> 200 if Gamma API responding; ws_market feed age < 5s; KillSwitch inactive.. Red: Gamma API down or KillSwitch active..

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
Unit tests pass including near-resolution block and spread-below-floor blockCI test run100% pass

Promote to Limited live

GateHow measuredThreshold
p99 eval latency < 300ms over 24h shadow runpolytraders_strat_liquiditypulse_eval_latency_ms histogramp99 < 300ms

Promote to General live

GateHow measuredThreshold
E2E: attention signal → maker GTC quote on Polygon testnet with post_only=true, builder.code, no feeRateBpsE2E testPass

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