Circuit Breakers and Market Event Handling
Prepare your algo trading systems for circuit breakers, trading halts, and extreme market events in NSE and BSE.
March 2020: Nifty crashes 13% in a day. Circuit breakers trigger. Your algo keeps sending orders into a halted market. Positions stuck. Losses mounting. Sound familiar?
Market events—circuit breakers, trading halts, flash crashes—happen. This guide ensures your system handles them gracefully, protecting capital when markets go crazy.
Understanding Circuit Breakers in India
NSE/BSE Circuit Breaker Rules
Index-Level (Nifty 50/Sensex):
- 10% move: 45-minute halt
- 15% move: Additional 1.75-hour halt
- 20% move: Trading suspended for the day
Stock-Level:
- 5% circuit (90% of stocks)
- 10% circuit (actively traded)
- 20% circuit (highly liquid)
class CircuitBreakerMonitor:
"""
Monitor circuit breakers and trading halts
"""
def __init__(self, broker_api):
self.broker = broker_api
self.circuit_breaker_status = {}
self.halted_symbols = set()
def check_circuit_breaker(self, symbol: str, current_price: float, reference_price: float) -> dict:
"""Check if stock near circuit limits"""
price_change_pct = (current_price - reference_price) / reference_price
# Get circuit limit for symbol
circuit_limit = self.get_circuit_limit(symbol)
# Check proximity to limits
upper_limit = reference_price * (1 + circuit_limit)
lower_limit = reference_price * (1 - circuit_limit)
distance_to_upper = (upper_limit - current_price) / current_price
distance_to_lower = (current_price - lower_limit) / current_price
status = {
'symbol': symbol,
'current_price': current_price,
'price_change_pct': price_change_pct,
'circuit_limit': circuit_limit,
'upper_limit': upper_limit,
'lower_limit': lower_limit,
'distance_to_upper_pct': distance_to_upper,
'distance_to_lower_pct': distance_to_lower
}
# Warning if within 1% of circuit
if distance_to_upper < 0.01:
status['warning'] = 'NEAR_UPPER_CIRCUIT'
elif distance_to_lower < 0.01:
status['warning'] = 'NEAR_LOWER_CIRCUIT'
else:
status['warning'] = None
return status
def get_circuit_limit(self, symbol: str) -> float:
"""Get circuit limit for symbol"""
# Simplified: most stocks have 5% or 10% circuits
# In practice, fetch from broker API
return 0.05 # 5% default
def emergency_close_positions(self):
"""Emergency position closure during market event"""
positions = self.broker.get_positions()
for position in positions:
try:
# Close position at market price
order = {
'symbol': position['symbol'],
'quantity': abs(position['quantity']),
'side': 'sell' if position['quantity'] > 0 else 'buy',
'order_type': 'MARKET',
'product': position['product']
}
self.broker.place_order(order)
print(f"Emergency close: {position['symbol']}")
except Exception as e:
print(f"Failed to close {position['symbol']}: {e}")
monitor = CircuitBreakerMonitor(broker_api=None)
status = monitor.check_circuit_breaker('RELIANCE', 2450, 2500)
print(f"Circuit Status: {status}")