How Polymarket Crypto Market Discovery Handles Timing Gates for Different Durations

Polymarket crypto market discovery uses the MarketScanner component in src/strategies/crypto-hft/market-scanner.ts to enforce dual timing gates—minRoundAgeSec and minTimeLeftSec—that dynamically adapt to any market duration by calculating round slots based on Unix timestamps.

Polymarket crypto market discovery in the CloddsBot repository relies on a sophisticated round-based scanning system that prevents trading during volatile opening periods or unsafe closing windows. The implementation centers on the MarketScanner class, which continuously monitors Gamma API markets across multiple durations—from 5-minute to daily contracts—while applying configurable timing constraints that scale automatically with each round length.

Core Architecture of the MarketScanner

The MarketScanner class serves as the central discovery engine for crypto High-Frequency Trading (HFT) strategies. Located in src/strategies/crypto-hft/market-scanner.ts, it bridges the Polymarket Gamma API with the trading engine by calculating temporal slots and filtering markets through strict timing validations.

Round-Based Slot Tracking

At the heart of the discovery system lies slot calculation. The scanner determines the current slot by dividing the Unix timestamp by the configured roundDurationSec:

// Conceptual implementation based on slot logic (lines 54-60)
const currentSlot = Math.floor(Date.now() / 1000 / config.roundDurationSec);

This slot calculation defines the market's expiry window and groups contracts belonging to the same trading round. Because the slot is derived from the configurable roundDurationSec, the same logic applies seamlessly whether tracking 5-minute binary options or daily prediction markets.

Duration Mapping for Polymarket Gamma API

Before querying the API, the scanner translates internal duration configurations into Polymarket's URL slug fragments. A static durationMap in src/strategies/crypto-hft/market-scanner.ts (lines 84-90) converts supported durations—5 minutes, 15 minutes, 1 hour, 4 hours, and daily—into their corresponding Gamma API identifiers:

  • 5 minutes: Maps to Polymarket's short-term contract slug format
  • 15 minutes: Mid-frequency trading identifier
  • 1 hour / 4 hours: Standard hourly range formats
  • Daily: Long-term contract grouping

This mapping ensures that fetchMarkets() constructs the correct deterministic query for each duration tier.

How Timing Gates Filter Markets

The canTrade() method implements the timing gate logic that protects the trading engine from entering positions during suboptimal market conditions. Two runtime constraints, defined in the CryptoHftConfig interface (src/strategies/crypto-hft/types.ts), govern market eligibility:

The minRoundAgeSec Gate (Early Round Protection)

Markets are explicitly blocked during the initial volatile phase of each round. The minRoundAgeSec parameter defines how many seconds must elapse after a round begins before trading is permitted:

// Timing gate check (lines 80-82)
if (roundAgeSec < config.minRoundAgeSec) {
  return { ok: false, reason: 'Round too young' };
}

This prevents the algorithm from capturing spreads during the chaotic opening moments when liquidity is still establishing.

The minTimeLeftSec Gate (Expiry Protection)

Conversely, the minTimeLeftSec gate rejects markets approaching resolution. This safety mechanism prevents last-second trades that carry heightened settlement risk:

// Expiry protection check (lines 83-85)
if (timeLeftSec < config.minTimeLeftSec) {
  return { ok: false, reason: 'Too close to expiry' };
}

Together, these gates create a trading window that only admits markets sufficiently mature yet comfortably distant from expiration.

Adaptive Logic Across Durations

Because both thresholds are expressed in absolute seconds rather than percentages, they adapt automatically to any market duration configured in presets.ts. A 5-minute market might use minRoundAgeSec: 30 (30 seconds), while a daily market might use minRoundAgeSec: 300 (5 minutes), yet both utilize the exact same validation logic in canTrade().

The 10-Second Refresh Cycle

The scanner maintains market freshness through a periodic refresh cycle triggered every 10 seconds. This loop, implemented in the main scanner logic (lines 31-34), performs three critical functions:

  1. Slot Change Detection: Monitors for round transitions by comparing the previous and current slot calculations
  2. Rate Limiting: Prevents Gamma API spam by enforcing cooldown periods between manual refreshes
  3. Market Hydration: Calls fetchMarkets() to retrieve contracts matching the durationLabel and current timing constraints

When fetchMarkets() executes, it first attempts a deterministic slug query based on the asset symbol and current slot, then falls back to a generic search if the specific contract is not yet indexed. Both paths respect the active timing gates.

Configuring Timing Gates via Strategy Presets

All timing parameters reside within CryptoHftConfig, with practical implementations demonstrated in src/strategies/crypto-hft/presets.ts (lines 95-332). These presets demonstrate how different strategies tune gates for various durations:

import { createMarketScanner } from './strategies/crypto-hft/market-scanner';
import { preset15m } from './strategies/crypto-hft/presets';

// Initialize scanner with 15-minute duration configuration
const scanner = createMarketScanner(preset15m);

// Start the automatic refresh loop
scanner.start();

// Check if trading is permitted under current timing constraints
const tradeStatus = scanner.canTrade();
if (!tradeStatus.ok) {
  console.log('Trading blocked:', tradeStatus.reason);
}

For manual testing or debugging, developers can trigger immediate refreshes:

// Force market refresh bypassing the 10-second timer
const markets = await scanner.refresh();
console.log(`Discovered ${markets.length} valid markets`);

Summary

  • Polymarket crypto market discovery centers on the MarketScanner class in src/strategies/crypto-hft/market-scanner.ts, which calculates temporal slots based on configurable roundDurationSec values.
  • Dual timing gates—minRoundAgeSec and minTimeLeftSec—prevent trading during volatile opening periods and unsafe pre-expiry windows by validating round age and remaining time in canTrade().
  • Duration mapping uses a static map to translate internal duration configurations (5m, 15m, 1h, 4h, daily) into Polymarket Gamma API slugs.
  • Adaptive validation allows the same timing gate logic to function across all market durations because constraints are expressed in seconds relative to the current round.
  • 10-second refresh cycles continuously hydrate market data while respecting rate limits and timing constraints defined in CryptoHftConfig.

Frequently Asked Questions

What is the purpose of minRoundAgeSec in Polymarket trading?

The minRoundAgeSec parameter prevents the trading engine from entering positions during the initial seconds of a new round when bid-ask spreads are typically widest and most volatile. By requiring a minimum number of seconds to elapse after the round timestamp, the scanner ensures liquidity has stabilized before risking capital.

How does the MarketScanner handle different market durations like 5-minute vs hourly?

The scanner uses the same slot calculation logic for all durations by dividing the Unix timestamp by the configurable roundDurationSec. A static durationMap translates these configurations into Polymarket-specific API slugs, while the timing gates (minRoundAgeSec and minTimeLeftSec) scale appropriately because they are defined in absolute seconds within each duration's preset configuration.

Where are the timing gate thresholds configured in CloddsBot?

Timing thresholds are defined in the CryptoHftConfig interface located in src/strategies/crypto-hft/types.ts and instantiated through strategy presets in src/strategies/crypto-hft/presets.ts. Each preset (e.g., preset5m, preset1h) specifies unique values for minRoundAgeSec and minTimeLeftSec optimized for that duration's volatility profile.

Why does the scanner refresh every 10 seconds?

The 10-second refresh interval balances market data freshness with API rate limiting constraints. This period allows the MarketScanner to detect new rounds (slot changes) and expired markets quickly while avoiding excessive requests to the Polymarket Gamma API, which could trigger IP throttling or bans.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →