How CloddsBot's Circuit Breaker Works: Architecture, Configuration, and Implementation
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), 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 constraintsrecordTrade()– Updates P&L and consecutive loss counters after each traderecordError()– Tracks system errors for error-rate calculationstrip(reason)– Manually or automatically triggers the breakerreset()– Clears the tripped state and resets countersgetState()– Returns the currentCircuitBreakerStateobject
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). 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) 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) andmaxLossPct(percentage of initial balance) - Consecutive-loss limit –
maxConsecutiveLossestriggers a trip after a streak of failed trades - Error-rate limit –
maxErrorRatewithminTradesForErrorRateto prevent trading during system instability - Position-size cap –
maxPositionSizeprevents oversized exposures - Daily trade limit –
maxDailyTradescaps total activity - Timing controls –
resetTimeoutMs(auto-reset delay),cooldownMs, andcheckIntervalMs
Trip Logic and State Management
The checkConditions() method (lines 86-115) evaluates trip criteria after each trade or error record:
- Maximum USD loss – Trips with reason
'max_loss'whensessionPnLfalls below the negative threshold (lines 90-93) - Maximum loss percentage – Trips with reason
'max_loss_pct'relative to initial balance (lines 95-99) - Consecutive losses – Trips with reason
'consecutive_losses'when the loss streak exceeds the limit (lines 101-103) - 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 (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:
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:
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:
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:
// 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, with enforcement points insrc/trading/pre-trade.tsandsrc/risk/engine.ts. - Architecture: EventEmitter-based singleton with
createCircuitBreaker()factory andgetGlobalCircuitBreaker()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 (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.
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 →