# How CloddsBot's Circuit Breaker Works: Architecture, Configuration, and Implementation

> Learn how CloddsBot's circuit breaker protects your capital by halting trading on loss limits, error rates, or position size breaches. Discover its architecture, configuration, and implementation.

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

---

**CloddsBot's circuit breaker is an EventEmitter-based safety system that automatically halts trading when loss limits, error rates, or position sizes exceed configured thresholds, protecting capital from runaway losses and system failures.**

The CloddsBot trading system implements a robust **circuit breaker pattern** to prevent catastrophic losses during volatile market conditions or technical failures. According to the source code in `alsk1992/CloddsBot`, this safety mechanism operates as a singleton service that gates all trading decisions through a centralized pre-trade validation layer.

## Core Architecture and Implementation Files

The circuit breaker implementation spans multiple modules across the execution, trading, and risk layers. Understanding these file relationships is essential for proper configuration and debugging.

### Main Circuit Breaker Implementation

The primary logic resides in [[`src/execution/circuit-breaker.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/circuit-breaker.ts)](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/circuit-breaker.ts), which exports the `createCircuitBreaker()` factory function and global accessor methods. This file defines the `CircuitBreaker` class with these core methods:

- `canTrade()` – Checks if trading is permitted based on current constraints
- `recordTrade()` – Updates P&L and consecutive loss counters after each trade
- `recordError()` – Tracks system errors for error-rate calculations
- `trip(reason)` – Manually or automatically triggers the breaker
- `reset()` – Clears the tripped state and resets counters
- `getState()` – Returns the current `CircuitBreakerState` object

Lines 24-40 provide singleton management through `getGlobalCircuitBreaker()` and `initGlobalCircuitBreaker()`, ensuring consistent state across the application.

### Pre-Trade Gate Integration

The central enforcement point appears in [[`src/trading/pre-trade.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/pre-trade.ts)](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/pre-trade.ts). The `validatePreTrade()` function (lines 59-84) consults the configured breaker via `checkSource()` before any order submission. If `circuitBreaker.canTrade()` returns `false`, the gate rejects the trade and includes the specific trip reason via `stateReason()`.

### Risk Engine Integration

The risk evaluation system in [[`src/risk/engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts)](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts) integrates the breaker into feasibility calculations. The engine calls `deps.circuitBreaker?.canTrade()` during trade evaluation and reports the breaker's state to the monitoring dashboard.

## Configuration and Trip Conditions

The circuit breaker's behavior is controlled through the `CircuitBreakerConfig` interface, with sensible defaults defined in `DEFAULT_CONFIG` (lines 17-28 of the implementation file).

### CircuitBreakerConfig Options

You can customize these thresholds when instantiating the breaker:

- **Loss limits** – `maxLossUsd` (absolute dollar loss) and `maxLossPct` (percentage of initial balance)
- **Consecutive-loss limit** – `maxConsecutiveLosses` triggers a trip after a streak of failed trades
- **Error-rate limit** – `maxErrorRate` with `minTradesForErrorRate` to prevent trading during system instability
- **Position-size cap** – `maxPositionSize` prevents oversized exposures
- **Daily trade limit** – `maxDailyTrades` caps total activity
- **Timing controls** – `resetTimeoutMs` (auto-reset delay), `cooldownMs`, and `checkIntervalMs`

### Trip Logic and State Management

The `checkConditions()` method (lines 86-115) evaluates trip criteria after each trade or error record:

1. **Maximum USD loss** – Trips with reason `'max_loss'` when `sessionPnL` falls below the negative threshold (lines 90-93)
2. **Maximum loss percentage** – Trips with reason `'max_loss_pct'` relative to initial balance (lines 95-99)
3. **Consecutive losses** – Trips with reason `'consecutive_losses'` when the loss streak exceeds the limit (lines 101-103)
4. **High error rate** – Trips with reason `'high_error_rate'` when system errors exceed the configured ratio (lines 105-108)

Additional guards in `canTrade()` check **position size** (`'max_position'`, lines 22-25) and **daily trade count** (`'max_daily_trades'`, lines 28-31) before each order.

When tripped, the `trip()` method (lines 58-71) sets `isTripped = true`, logs the event, emits a `'tripped'` event, and schedules an automatic reset after `resetTimeoutMs`.

## Event-Driven Design

The circuit breaker extends Node.js `EventEmitter`, enabling reactive integration with monitoring systems. Key events include:

- `'tripped'` – Emitted with `{ reason, state }` when the breaker activates
- `'reset'` – Emitted when trading resumes after a manual or automatic reset
- `'trade'` – Fired after each recorded trade for external logging
- `'error'` – Signals system errors that affect error-rate calculations
- `'started'` / `'stopped'` – Lifecycle hooks for initialization and shutdown

The risk dashboard in [`src/risk/dashboard.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/dashboard.ts) (lines 11-29) listens to these events to display real-time status updates.

## Practical Implementation Guide

### Creating and Starting a Breaker

Instantiate a circuit breaker with custom limits and start the monitoring timers:

```typescript
import { createCircuitBreaker } from './execution/circuit-breaker';

const cb = createCircuitBreaker({
  maxLossUsd: 2000,
  maxConsecutiveLosses: 3,
  maxErrorRate: 0.1,
  resetTimeoutMs: 300000  // 5 minutes
}, 10000);  // initialBalance: $10,000

cb.start();  // Begins periodic checks and daily reset timer

```

### Integrating with Pre-Trade Validation

Configure the trading gate to use the global breaker instance:

```typescript
import { configurePreTradeGate } from './trading/pre-trade';
import { getGlobalCircuitBreaker } from './execution/circuit-breaker';

configurePreTradeGate({
  circuitBreaker: getGlobalCircuitBreaker(),
  // additional safety sources...
});

```

Once configured, `validatePreTrade()` automatically rejects orders while the breaker is tripped, returning the specific trip reason to the caller.

### Recording Trades and Errors

Update the breaker after each trading event to drive the trip logic:

```typescript
const breaker = getGlobalCircuitBreaker();

// After trade completion:
breaker.recordTrade({
  pnlUsd: -150,
  success: false,
  sizeUsd: 500,
  error: 'Slippage too high'
});

// After system errors:
breaker.recordError('Websocket disconnect');
breaker.recordError('API timeout');

```

These calls update `consecutiveLosses`, `sessionPnL`, `dailyTrades`, and `errorRate`, triggering `checkConditions()` automatically.

### Manual Control and Status Monitoring

Administrators can manually intervene or query status:

```typescript
// Emergency stop
getGlobalCircuitBreaker().trip('manual');

// Resume after investigation
getGlobalCircuitBreaker().reset();

// Check current state
const state = getGlobalCircuitBreaker().getState();
console.log(`Tripped: ${state.isTripped}`);
console.log(`Reason: ${state.tripReason}`);
console.log(`Session P&L: ${state.sessionPnL}`);

```

## Summary

- **Location**: The complete implementation lives in [`src/execution/circuit-breaker.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/circuit-breaker.ts), with enforcement points in [`src/trading/pre-trade.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/pre-trade.ts) and [`src/risk/engine.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/risk/engine.ts).
- **Architecture**: EventEmitter-based singleton with `createCircuitBreaker()` factory and `getGlobalCircuitBreaker()` accessor.
- **Trip conditions**: Configurable limits for USD loss, percentage loss, consecutive losses, error rates, position size, and daily trade counts.
- **Integration**: Centralized pre-trade gate (`validatePreTrade()`) ensures no orders pass while tripped.
- **Observability**: Emits `'tripped'`, `'reset'`, and lifecycle events for dashboard integration and automated monitoring.

## Frequently Asked Questions

### What triggers the CloddsBot circuit breaker to trip automatically?

The breaker trips automatically when any configured threshold is breached in `checkConditions()`: absolute USD loss (`maxLossUsd`), percentage of initial balance (`maxLossPct`), consecutive losing trades (`maxConsecutiveLosses`), or excessive system error rates (`maxErrorRate`). Additional guards in `canTrade()` block trades exceeding `maxPositionSize` or `maxDailyTrades`.

### How do I manually reset the circuit breaker after it trips?

Call `reset()` on the breaker instance. For the global breaker, use `getGlobalCircuitBreaker().reset()`. This clears the `isTripped` flag, resets all counters (`consecutiveLosses`, `sessionPnL`, `errorRate`), clears the auto-reset timer, and emits a `'reset'` event. Manual reset is useful after investigating the root cause of the trip condition.

### Can I customize the automatic reset timeout?

Yes. Pass `resetTimeoutMs` in the configuration object when calling `createCircuitBreaker()`. The default value from `DEFAULT_CONFIG` can be overridden (e.g., `resetTimeoutMs: 600000` for 10 minutes). After this duration, the breaker automatically calls `reset()` unless manually cleared first.

### Where does the circuit breaker check occur in the trade execution flow?

The check happens in `validatePreTrade()` within [`src/trading/pre-trade.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/pre-trade.ts) (lines 59-84). This function runs before any order reaches the exchange, querying `circuitBreaker.canTrade()`. If the breaker is tripped, the validation fails immediately with the trip reason, preventing the trade from proceeding to the execution layer.