# How CloddsBot Computes Derived Signals: Feature Engine Deep Dive

> Explore how CloddsBot's feature engine computes derived signals by combining primitive metrics into actionable indicators like buy pressure and trend strength using pure functions.

- Repository: [AL/CloddsBot](https://github.com/alsk1992/CloddsBot)
- Tags: deep-dive
- Published: 2026-09-13

---

**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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/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**

```typescript
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**

```typescript
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**

```bash

# 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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/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`](https://github.com/alsk1992/CloddsBot/blob/main/src/services/feature-engineering/indicators.ts), following the pattern of `computeBuyPressure` or `computeTrendStrength`. Integrate these into the `getFeatures` workflow in [`index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/index.ts) to maintain separation between mathematical logic and stateful orchestration.