How CloddsBot Computes Derived Signals: Feature Engine Deep Dive

CloddsBot's Feature Engineering Service computes derived signals by combining primitive metrics like momentum, imbalance, and spread changes into actionable indicators—buy pressure, sell pressure, trend strength, and liquidity scores—using pure functions in indicators.ts.

CloddsBot is an open-source trading intelligence system that transforms raw market microstructure into trading decisions through its dedicated Feature Engineering Service. Located in src/services/feature-engineering/, this module continuously ingests tick and order-book updates to generate derived signals that drive arbitrage execution, copy-trading, and smart routing strategies.

The Data Pipeline: From Raw Ticks to Primitive Metrics

The engine maintains per-market state using a Map<string, MarketState> keyed by platform:marketId[:outcomeId], implemented in getOrCreateMarket within src/services/feature-engineering/index.ts. This persistent state enables rolling statistical calculations across temporal windows.

Processing raw market data occurs through two primary entry points:

Tick Processing via processTick The processTick function updates rolling price windows and computes low-level metrics including return, momentum, velocity, volatility, and tick intensity. These values are stored in tick.lastFeatures, creating the numerical foundation for subsequent signal derivation.

Order-Book Processing via processOrderbook Complementing tick data, processOrderbook analyzes depth and liquidity conditions. It calculates spread percentage, mid-price, total depth, order-book imbalance, and weighted prices, persisting results in orderbook.lastFeatures.

Computing Derived Signals from Primitive Metrics

The transformation from raw inputs to derived signals is orchestrated by the getFeatures function in src/services/feature-engineering/index.ts. This layer retrieves the latest tick and order-book feature objects, extracts primitive values, and delegates higher-order mathematics to pure helper functions in src/services/feature-engineering/indicators.ts.

Buy Pressure and Sell Pressure Calculations

The engine quantifies directional market pressure using computeBuyPressure and computeSellPressure. These pure functions accept three parameters:

  • momentum (extracted from tick?.momentum)
  • imbalance (from orderbook?.imbalance)
  • spreadChange (the delta between the latest spread and previous values from state.orderbook.spreads)

Buy pressure increases with positive momentum, bid-heavy imbalance, and narrowing spreads. Sell pressure escalates with negative momentum and ask-heavy imbalance.

Trend Strength and Liquidity Scoring

Beyond directional pressure, the system calculates trend strength via computeTrendStrength(momentum, imbalance), evaluating the persistence of price movements. For execution quality assessment, computeLiquidityScore(orderbook.totalDepth, orderbook.spreadPct) synthesizes depth and tightness into a normalized liquidity metric.

The resulting CombinedFeatures object encapsulates raw tick data, order-book snapshots, and the four computed derived signals for downstream strategy modules.

Real-Time Signal Emission and Threshold Monitoring

The feature engine actively monitors for exceptional market conditions beyond passive computation. Within processTick, the service compares absolute momentum and volatility against configurable thresholds: signalMomentumThreshold and signalVolatilityThreshold.

When thresholds are breached, the engine emits a 'signal' event containing the signal type, direction, and strength. Downstream modules—including the arbitrage executor and smart router—subscribe via the EventEmitter interface for sub-second strategy adjustments.

Accessing Derived Signals: Implementation Examples

Fetching Market Features Programmatically

import { getMarketFeatures } from '../services/feature-engineering';

// Retrieve derived signals for a Polymarket prediction market
const features = getMarketFeatures('polymarket', '0x1234');
if (features) {
  console.log('Buy pressure:', features.signals.buyPressure);
  console.log('Sell pressure:', features.signals.sellPressure);
  console.log('Liquidity score:', features.signals.liquidityScore);
}

Subscribing to Real-Time Signal Events

import { createFeatureEngineering } from '../services/feature-engineering';
import { EventEmitter } from 'events';

const fe = createFeatureEngineering();
fe.setEmitter(new EventEmitter());

fe.emitter?.on('signal', (sig) => {
  console.log(`Signal: ${sig.type} – ${sig.direction} (strength ${sig.strength})`);
});

CLI Inspection


# Display all derived signals for a specific market

./clodds features signals polymarket 0x1234abcd

Summary

  • State Architecture: Per-market state is maintained in src/services/feature-engineering/index.ts via getOrCreateMarket, enabling isolated temporal calculations across multiple trading pairs.
  • Primitive Extraction: processTick and processOrderbook compute low-level metrics including momentum, imbalance, and spread percentages, storing them in lastFeatures objects.
  • Signal Derivation: The getFeatures function orchestrates computation of derived signals using pure mathematical models in indicators.ts, yielding buy pressure, sell pressure, trend strength, and liquidity scores.
  • Threshold Alerts: Configurable momentum and volatility thresholds trigger 'signal' events for real-time strategy reactions.
  • Integration Pattern: The accessor.ts module exposes getMarketFeatures as a singleton accessor, allowing arbitrary bot modules to consume derived signals without direct service instantiation.

Frequently Asked Questions

What primitive metrics feed into CloddsBot's derived signals?

The system derives signals from four primary primitives: momentum (calculated from rolling price windows in processTick), order-book imbalance (bid/ask ratio from processOrderbook), spread change (delta from historical spread arrays), and composite liquidity data (total depth paired with spread percentage).

How does the feature engine handle state for multiple concurrent markets?

The service isolates market data within a Map<string, MarketState> structure keyed by composite identifiers (platform:marketId[:outcomeId]). This prevents cross-market contamination while enabling parallel processing of numerous prediction markets and trading pairs.

Can signal sensitivity thresholds be adjusted without code changes?

Yes. The emission logic in processTick references signalMomentumThreshold and signalVolatilityThreshold parameters that are externally configurable. These values can be modified through the bot's configuration system to adjust signal sensitivity without requiring source modification or redeployment.

Where should custom derived signals be implemented?

New signal calculations should be added as pure functions in src/services/feature-engineering/indicators.ts, following the pattern of computeBuyPressure or computeTrendStrength. Integrate these into the getFeatures workflow in index.ts to maintain separation between mathematical logic and stateful orchestration.

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 →