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 fromtick?.momentum)imbalance(fromorderbook?.imbalance)spreadChange(the delta between the latest spread and previous values fromstate.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.tsviagetOrCreateMarket, enabling isolated temporal calculations across multiple trading pairs. - Primitive Extraction:
processTickandprocessOrderbookcompute low-level metrics including momentum, imbalance, and spread percentages, storing them inlastFeaturesobjects. - Signal Derivation: The
getFeaturesfunction orchestrates computation of derived signals using pure mathematical models inindicators.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.tsmodule exposesgetMarketFeaturesas 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →