# The Ten Stages of the CloddsBot Risk Engine Pre-Trade Pipeline

> Explore the ten stages of the CloddsBot risk engine pre-trade pipeline. Learn how CloddsBot validates trades with kill switches, Kelly sizing, and more before orders hit the exchange.

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

---

**CloddsBot validates every trade through a unified RiskEngine that executes ten ordered checks—from kill switches to Kelly sizing—before any order reaches the exchange.**

The **RiskEngine** serves as the gatekeeper for all trading activity in the CloddsBot system, implemented in [`src/risk/engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts). This defensive layer ensures that no position violates firm-wide risk limits or user-specific constraints. Below is the complete technical breakdown of each validation stage as defined in the source code and documented in [`src/skills/bundled/risk/SKILL.md`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/bundled/risk/SKILL.md).

## Stage 1: Global Kill Switch

The pipeline begins with a **system-level halt check** using the `SafetyManager`. If the global kill switch is active, the engine rejects the trade immediately without further processing.

In [`src/risk/engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts) (lines 5‑6), the engine queries the safety manager to determine if the entire system is disabled. This serves as the first line of defense against catastrophic market events or operational emergencies.

## Stage 2: Circuit Breaker Validation

Next, the engine calls the execution-level `CircuitBreaker.canTrade()` method (lines 6‑7 in [`engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/engine.ts)). A tripped circuit breaker—triggered by excessive volatility or consecutive losses—blocks the trade at this stage.

This check operates independently from the global kill switch, allowing granular control over specific trading venues or strategies while maintaining system-wide safety.

## Stage 3: Maximum Order Size Enforcement

The engine enforces the user-defined `maxOrderSize` parameter through the `enforceMaxOrderSize` function (lines 14‑16). Any order exceeding the configured size limit is rejected outright, preventing accidental fat-finger errors or oversized positions.

## Stage 4: Exposure Limit Compliance

Per-user exposure checks occur via `enforceExposureLimits` (lines 36‑38), validating against `maxTotalExposure` and `maxPositionValue` thresholds. If the proposed trade would push the user's portfolio beyond either ceiling, the engine blocks execution.

This stage aggregates current positions from the `getPositions` and `getPositionValues` dependencies to calculate real-time exposure impact.

## Stages 5‑7: SafetyManager Validations

The engine batches three critical risk checks through `SafetyManager.validateTrade` (lines 60‑62):

- **Daily Loss Limit**: Rejects trades that would exceed the configured daily loss ceiling.
- **Maximum Drawdown**: Blocks orders that would push the account beyond the allowed percentage drawdown from peak equity.
- **Concentration Limit**: Prevents HHI-style concentration breaches that would over-weight the portfolio in a single asset or category.

All three validations share the same invocation point but evaluate distinct risk metrics from the safety context.

## Stage 8: Value‑at‑Risk (VaR) Calculation

The **VaR Limit** stage (lines 88‑99) calculates portfolio Value‑at‑Risk using the `VaRCalculator`. If the computed VaR exceeds the user-provided `varLimit` (typically set at 95% confidence), the trade is rejected.

This quantifies the potential loss in dollar terms under normal market conditions, adding a statistical safety layer beyond static exposure limits.

## Stage 9: Volatility Regime Detection

The `VolatilityDetector` analyzes current market conditions (lines 19‑28). If the detector flags an *extreme* regime via `shouldHalt`, the trade is disallowed. In elevated—but not extreme—volatility, the engine may approve the trade but append a warning flag for downstream logging.

The detector typically uses a configurable `lookbackWindow` (default 30 periods) to determine regime state.

## Stage 10: Kelly Sizing Recommendation

The final stage invokes the optional `DynamicKellyCalculator` (lines 41‑53) to compute a Kelly-optimal position size based on the trade's `estimatedEdge` and `confidence`. Unlike previous stages, this step **never blocks the trade**; instead, it may reduce the requested size through a volatility-regime multiplier.

The adjusted size appears in the `adjustedSize` field of the validation response, allowing the execution layer to submit a smaller, mathematically optimal order.

## Implementation Example

The following TypeScript demonstrates how to instantiate the risk engine with all ten stages configured:

```typescript
import { createRiskEngine } from 'clodds/risk';
import { getGlobalCircuitBreaker } from 'clodds/execution';

const riskEngine = createRiskEngine(
  {
    varLimit: 500,
    varConfidence: 0.95,
    volatilityConfig: { lookbackWindow: 30, haltOnExtreme: true },
  },
  {
    riskContext: { db: {/* … */} },
    safetyManager: {/* implements canTrade() & validateTrade() */},
    circuitBreaker: getGlobalCircuitBreaker(),
    kellyCalculator: {/* implements calculate() */},
    getPositions: () => [],
    getPositionValues: () => [],
  }
);

const decision = riskEngine.validateTrade({
  userId: 'user-123',
  platform: 'polymarket',
  marketId: 'abc-xyz',
  side: 'buy',
  size: 200,
  price: 0.65,
  estimatedEdge: 0.04,
  confidence: 0.8,
  category: 'politics',
});

if (decision.approved) {
  console.log('Trade passes all 10 checks. Adjusted size =', decision.adjustedSize);
} else {
  console.log('Trade blocked at stage:', decision.reason);
}

```

## Summary

- **Stages 1‑2** (`SafetyManager`, `CircuitBreaker`) provide system-wide emergency stops.
- **Stages 3‑4** (`enforceMaxOrderSize`, `enforceExposureLimits`) enforce hard position limits.
- **Stages 5‑7** (`validateTrade`) check daily loss, drawdown, and concentration via the safety manager.
- **Stage 8** (`VaRCalculator`) applies statistical risk metrics.
- **Stage 9** (`VolatilityDetector`) halts trading during extreme market regimes.
- **Stage 10** (`DynamicKellyCalculator`) optimizes sizing without blocking trades.

Each stage in [`src/risk/engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts) can independently reject the trade, creating a defense-in-depth architecture that prioritizes capital preservation over execution speed.

## Frequently Asked Questions

### What happens if the volatility regime is extreme but all other checks pass?

The trade is blocked at Stage 9. According to the `VolatilityDetector` implementation in [`engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/engine.ts) lines 19‑28, when `shouldHalt` returns true for an extreme regime, the engine returns a rejection decision regardless of VaR or exposure limit compliance. This prevents trading during market discontinuities.

### Can the Kelly sizing stage override previous rejection decisions?

No. The **DynamicKellyCalculator** runs only if the trade passes stages 1‑9. As implemented in [`engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/engine.ts) lines 41‑53, this stage only modifies the `adjustedSize` field downward; it cannot resurrect a rejected trade or increase the requested size beyond what earlier stages approved.

### Where are the specific risk limits configured?

User-defined limits like `maxOrderSize`, `maxTotalExposure`, and `varLimit` are passed as configuration parameters to `createRiskEngine` (shown in the implementation example above). System-wide defaults and safety thresholds reside in the `SafetyManager` implementation, while circuit breaker parameters are defined in [`src/execution/circuit-breaker.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/circuit-breaker.ts).

### How does the engine handle partial position closures?

The engine evaluates exposure limits using `getPositions` and `getPositionValues` (passed as dependencies), which return the current portfolio state. For closing trades, the logic in `enforceExposureLimits` (lines 36‑38) recognizes the delta effect and only blocks trades that would increase net exposure beyond limits, not those reducing it.