The Mechanism
The Mechanism
The feedback loop has three components: a sell algorithm that responds to volume, market makers that respond to price movement, and an order book with finite depth.
# RECONSTRUCTED FROM SEC/CFTC JOINT REPORT DESCRIPTION
# Illustrates the percentage-of-volume execution logic
class PercentageOfVolumeAlgorithm:
def __init__(self, total_quantity, target_pct):
self.remaining = total_quantity # 75,000 contracts
self.target_pct = target_pct # ~9% of market volume
def compute_order_size(self, market_volume_last_minute):
# FAILURE POINT: Order size increases when volume increases
# Volume increases during a sell-off because other participants
# are also selling. The algorithm interprets their panic as
# available liquidity and increases its own rate.
target = int(market_volume_last_minute * self.target_pct)
return min(target, self.remaining)
def execute(self, market):
while self.remaining > 0:
volume = market.get_volume_last_minute()
size = self.compute_order_size(volume)
# No price check. No spread check. No depth check.
# Sells 'size' contracts at whatever price is available.
market.sell(size)
self.remaining -= size
The algorithm has no feedback dampening. It does not check whether the price has moved adversely. It does not check whether the bid-ask spread has widened, which would indicate declining liquidity. It does not check whether market depth has fallen below a threshold. It has a single input (market volume) and a single behavior (sell a fixed percentage of that volume). When market volume increases because other participants are panic selling, the algorithm increases its own selling. When the algorithm’s increased selling causes more participants to sell, volume increases further. The loop has no brake.
The HFT market makers behave rationally but their collective behavior creates a vacuum:
# RECONSTRUCTED FROM SEC/CFTC BEHAVIORAL DESCRIPTION
# Illustrates HFT market maker risk management logic
class HFTMarketMaker:
def __init__(self):
self.inventory = 0
self.max_inventory = 1000 # Maximum position size
self.max_loss_per_minute = 50000 # Risk limit
def update_quotes(self, market_state):
# Check risk limits
if abs(self.inventory) > self.max_inventory:
self.withdraw_all_quotes() # Stop providing liquidity
return
if self.calculate_pnl_last_minute() < -self.max_loss_per_minute:
self.withdraw_all_quotes() # Stop providing liquidity
return
# If still within limits, post tighter quotes
# But with less size if conditions are volatile
spread = self.calculate_spread(market_state.volatility)
size = self.calculate_size(market_state.depth)
self.post_bid(market_state.mid - spread/2, size)
self.post_ask(market_state.mid + spread/2, size)
When HFT market makers withdraw, the order book empties. The remaining orders are stub quotes: orders posted at absurd prices ($0.01 bid, $100,000 ask) by firms that are required by regulation to maintain continuous quotes but do not expect those quotes to execute. Under normal conditions, these stub quotes are thousands of ticks away from the market price and are irrelevant. When the order book empties, they become the best available price.
This is why Accenture, a $40 billion company, traded at one cent per share. Not because anyone believed Accenture was worth a penny. Because the only remaining bid in the book was a stub quote at $0.01, and a sell order that needed to execute found no other buyer.
The circuit breaker that arrested the crash was the CME Group’s Stop Logic Functionality. It is a price-based circuit breaker: if the price of the E-mini moves more than a specified threshold in a specified time window, trading pauses for five seconds. Five seconds is not long. But it breaks the feedback loop. During the pause, the sell algorithm cannot sell. HFT firms can reassess conditions. Manual traders can enter orders. When trading resumes, the order book has repopulated and the feedback loop must restart from a state with more liquidity.
The equity market circuit breakers that existed in 2010 were not designed for this scenario. The NYSE’s Liquidity Replenishment Points (LRPs) slowed trading in individual stocks when prices moved rapidly, but they were exchange-specific. Orders that were slowed at the NYSE could be routed to other exchanges that had no such mechanism. The result was that some exchanges continued trading at dislocated prices while others were paused, creating further confusion and inconsistency.