33 min read

> "The market is not a casino. When someone manipulates the order book, they steal from every participant who traded at a price that was never real."

Chapter 22: Trade Surveillance — Spoofing, Layering, and Front-Running Detection

"The market is not a casino. When someone manipulates the order book, they steal from every participant who traded at a price that was never real."

— Rafael Torres, speaking to Cornerstone Financial Group's Compliance Leadership Forum


Learning Objectives

By the end of this chapter, you will be able to:

  1. Define and distinguish the primary forms of market manipulation — spoofing, layering, front-running, marking the close, quote stuffing, pump and dump, and cross-asset manipulation.
  2. Explain the regulatory frameworks governing market manipulation across US, EU, and UK jurisdictions, including the intent standards required for enforcement.
  3. Describe the algorithmic detection approaches used for each manipulation typology, including the key metrics and thresholds that trigger surveillance alerts.
  4. Analyze evidence requirements in regulatory enforcement actions and articulate what distinguishes a confirmed manipulation from a false positive.
  5. Implement Python-based detection logic for layering, front-running, and marking-the-close patterns.
  6. Evaluate the operational challenges of deploying trade surveillance systems at scale, including false positive management and alert triage.

22.1 Introduction: The Order Book as a Battlefield

On the morning of 6 May 2010, something went wrong with the US equity market. The Dow Jones Industrial Average fell nearly 1,000 points — roughly 9% — in minutes, wiping out nearly $1 trillion in market value before recovering almost as rapidly. The event became known as the Flash Crash, and for years its causes were debated by regulators, academics, and market participants alike.

It was not until 2015 that a British futures trader named Navinder Singh Sarao was arrested in a suburban London home, charged by US authorities with having contributed to the chaos through a technique known as spoofing. Sarao had programmed his trading software to place enormous layered sell orders in E-mini S&P 500 futures — orders he had no intention of executing — to artificially depress prices. When prices fell, he bought. When they rose, he sold. When the market showed signs of reversing, his software automatically cancelled the sell orders. Rinse and repeat.

Sarao ultimately pleaded guilty in 2016 to wire fraud and spoofing. He had generated approximately $40 million in profits over several years. The Flash Crash, caused in part by a single trader with a modified trading algorithm operating from his parents' house in Hounslow, illustrated in stark terms what was already well understood by market structure specialists: the integrity of modern electronic markets depends critically on order book transparency, and that transparency can be weaponized.

Maya Osei first encountered this problem not in a US courtroom but in a risk committee meeting at Verdant Bank, the UK challenger bank where she had recently taken up her role as Chief Compliance Officer. The bank's equity trading desk had received a referral from their prime brokerage relationship — a query from their broker's surveillance team about a pattern of cancellations in UK gilt futures. "We were not the subject of the inquiry," Maya recalls, "but we might as well have been. I realized we had almost no systematic capacity to detect these patterns ourselves. We were entirely dependent on our counterparties to flag problems."

That realization set Maya on a path that would consume the next eighteen months: building Verdant Bank's trade surveillance infrastructure from the ground up.

This chapter maps the terrain she had to cover. We begin with the regulatory definitions and enforcement precedents that establish what manipulation is and how regulators prove it. We then work through each major manipulation typology — spoofing, layering, front-running, marking the close, quote stuffing, pump and dump, and cross-asset manipulation — with both conceptual analysis and practical detection logic. We close with the operational challenge that is, in many ways, harder than the detection problem itself: managing the false positives that result when legitimate trading behavior pattern-matches against the same algorithms that catch genuine manipulation.


22.2 Regulatory Framework: Defining Market Manipulation

22.2.1 The United States: Dodd-Frank and the Commodity Exchange Act

In the United States, the primary spoofing prohibition appears in Section 6(c)(5)(C) of the Commodity Exchange Act, as amended by Section 747 of the Dodd-Frank Wall Street Reform and Consumer Protection Act (2010). The provision prohibits any person from engaging in trading, practice, or conduct that:

  • Is, is of the character of, or is commonly known as spoofing; and
  • Involves bidding or offering with the intent to cancel the bid or offer before execution.

The intent standard is crucial. The statute requires that a trader place orders with the intent to cancel before those orders execute. This is not a strict liability offense — the government must prove that the trader never intended to honor the orders they placed. This has made spoofing prosecutions challenging: a trader who routinely cancels orders can argue that market conditions changed and the cancellations were legitimate.

The CFTC has developed what practitioners sometimes call the "holistic" approach to proving intent, looking at multiple behavioral signals simultaneously: the order-to-trade ratio (how many orders placed versus executed), the speed of cancellation relative to market response, the correlation between the manipulative orders and the trader's actual positions, and any communications evidence (chats, emails, voice recordings) that reveals intent.

For securities (equities and options), the SEC's primary manipulation prohibition is Section 9(a)(2) of the Securities Exchange Act of 1934, which prohibits transactions that create a false or misleading appearance of active trading or raise or depress prices. Rule 10b-5 under the Securities Exchange Act of 1934 also reaches manipulation as a form of fraud in connection with the purchase or sale of a security.

The CFTC has been notably more aggressive than the SEC in spoofing enforcement, partly because the statutory prohibition is more explicit and partly because futures markets — where many manipulation schemes originate — fall primarily within CFTC jurisdiction.

22.2.2 The European Union: Market Abuse Regulation (MAR)

In the EU, market manipulation is governed primarily by Regulation (EU) No 596/2014 (the Market Abuse Regulation, or MAR), which entered into force on 3 July 2016. MAR Article 12 provides the core definition of market manipulation, covering three broad categories:

Article 12(1)(a): Transactions or orders that give false or misleading signals as to the supply, demand, or price of a financial instrument, or which secure the price at an abnormal or artificial level. This captures most order book manipulation including spoofing and layering.

Article 12(1)(b): Transactions or orders that employ fictitious devices or any other form of deception or contrivance. This is the broader fraud-type provision.

Article 12(1)(c): Dissemination of information through the media (including the internet and social networks) which gives false or misleading signals. This provision specifically reaches modern pump-and-dump schemes operating through social media.

MAR Article 12(2) provides a non-exhaustive list of indicators of manipulative behavior. These include:

  • Representing a significant proportion of daily volume with the intent of raising or lowering prices (related to marking the close)
  • Transactions or orders resulting in reversals of position within short periods, accounting for a large portion of daily volume
  • Transactions or orders concentrated in a short period of the trading session, having a significant impact on price

Commission Delegated Regulation (EU) 2016/522 further elaborates on these indicators, providing what is sometimes called the "Annex I" list of non-exhaustive indicators of suspicious patterns. This delegated regulation is the practical handbook for compliance teams implementing MAR surveillance programs.

Unlike the US spoofing statute, MAR does not specify an explicit intent standard in the same way. However, the European Securities and Markets Authority (ESMA) has made clear through guidance and opinion that intent is still a relevant factor in determining whether behavior constitutes manipulation, particularly in distinguishing legitimate market-making from manipulative order placement.

22.2.3 The United Kingdom: UK MAR

Following Brexit, the UK retained and onshored the EU MAR framework as the UK Market Abuse Regulation (UK MAR), with the FCA as the supervising authority. The definitions of market manipulation in UK MAR Article 12 are substantially identical to those in EU MAR Article 12. The FCA has supplemented UK MAR with its own guidance in the Market Conduct Sourcebook (MAR) in the FCA Handbook.

The FCA's enforcement approach has historically emphasized firms' systems and controls obligations alongside direct manipulation cases. Under the Senior Managers and Certification Regime (SMCR), a firm that fails to detect and prevent manipulation by its employees can face regulatory action even if the firm itself was not the direct actor. This has made effective trade surveillance a board-level compliance concern for UK-regulated firms.

22.2.4 The Intent Standard in Practice

The intent standard — proving that orders were placed with the purpose of cancellation — is the central evidentiary challenge in manipulation enforcement. Regulators have developed several doctrines to infer intent circumstantially:

Behavioral pattern evidence: If a trader consistently places large orders that are cancelled before execution whenever their existing position would benefit from the artificial price movement, intent can be inferred from the pattern itself. This is the foundation of algorithmic detection.

Communications evidence: Chat messages, emails, and voice recordings remain the most persuasive direct evidence of intent. In the Sarao case, investigators found that Sarao had explicitly discussed his manipulation techniques with brokers and technology providers. In numerous CFTC enforcement actions, traders have used terms such as "spoof" and "jam" in communications referring to their own order activity.

Temporal correlation evidence: If a trader invariably cancels layered orders within seconds of achieving the desired price movement, and the cancellations are automated responses to price triggers, regulators can argue this demonstrates a pre-planned scheme.

Comparative execution analysis: Comparing the trader's execution rates on their manipulative orders versus their legitimate orders can reveal that the manipulative orders were never intended to execute — they had features (price, quantity, timing) designed to minimize execution risk.


22.3 Spoofing: Definition, Detection, and Landmark Cases

22.3.1 What Spoofing Is

Spoofing, at its simplest, is the placement of a large order on one side of the market with the intent to cancel it before execution, for the purpose of inducing other market participants to trade at an artificially moved price.

The mechanics are straightforward: a trader who wants to buy a security cheaply might place a large sell order (a "spoof" order) that signals selling pressure to the market. Algorithmic traders and human participants reading the order book see the apparent supply and adjust their bids downward. The price falls. The spoofing trader then executes a genuine buy order at the artificially depressed price, then cancels the large sell order. The price returns toward its natural level. The trader profits from the round trip.

Spoofing exploits a fundamental assumption embedded in modern electronic markets: that displayed orders represent genuine trading interest. When that assumption is violated at scale, price discovery is corrupted.

22.3.2 The Navinder Sarao Case

Navinder Singh Sarao's case is the most extensively documented spoofing enforcement action and provides the clearest example of how the behavior is constructed, detected, and prosecuted.

Sarao operated through a small company called Nav Sarao Futures Limited, trading E-mini S&P 500 futures on the Chicago Mercantile Exchange (CME). He used commercially available trading software that he had modified — with the assistance of a software developer — to automatically place large layered sell orders at multiple price levels above the market, cancel and replace those orders as the market moved (maintaining them consistently above the best ask to avoid accidental execution), and cancel the orders when conditions changed.

The CME first alerted Sarao to concerns about his trading in 2009. He responded dismissively, claiming his trading was legitimate. The CME referred the matter to the CFTC. US investigators, working with UK authorities, built a case over several years using order-level data from the CME showing:

  • Sarao's orders represented a disproportionate share of visible sell-side depth on many trading days
  • The orders were systematically modified to remain just above the best ask price, indicating he monitored their execution risk
  • On the day of the Flash Crash (6 May 2010), Sarao had placed his largest-ever spoofing orders in the morning session, contributing to a significant imbalance in the order book
  • Sarao's actual trading on the same days showed him consistently buying when prices fell (consistent with inducing price decline through spoofing) and selling when prices rose

Sarao pleaded guilty in November 2016 and was sentenced in January 2020 to time served plus a year of home confinement, having cooperated extensively with authorities. The criminal forfeiture was $12.9 million. The relative leniency of the sentence reflected both his cooperation and the court's finding that he suffered from Asperger's syndrome, which may have affected his appreciation of the social harm of his conduct.

The case established several important precedents for spoofing enforcement:

  1. Intent can be inferred algorithmically from order-level data without requiring communications evidence.
  2. Third-party software developers can face liability if they knowingly assist in the creation of spoofing tools.
  3. Spoofing enforcement has extraterritorial reach — US authorities can prosecute foreign nationals for manipulation on US exchanges.

22.3.3 The Jitesh Thakkar Case

The Thakkar case arose from the same Sarao investigation and raised a different question: could the developer of trading software be criminally liable for the spoofing his client used it to commit?

Jitesh Thakkar, head of a Chicago technology firm called Edge Financial Technologies, was indicted in 2018 for conspiracy to commit spoofing, based on his development of automated trading software for Sarao. The first trial ended in a hung jury in 2019. The government dismissed the charges before a retrial.

The Thakkar acquittal (or non-conviction) is significant for RegTech firms and technology vendors: it suggests that courts are reluctant to hold technology developers liable for how clients use their products, absent clear evidence that the developer specifically intended to facilitate manipulation. But it also illustrates that vendors in the trade surveillance and execution technology space must be careful about the customizations they build and the purposes for which they know their products will be used.

22.3.4 Spoofing Detection Algorithms

The core detection metrics for spoofing are:

Order-to-Trade Ratio (OTR): The ratio of orders submitted to orders executed. A legitimate market maker might have an OTR of 5:1 or 10:1 (placing multiple orders for each execution). A spoofing trader may have OTRs of 50:1 or higher on specific instruments during manipulation episodes. The relevant comparison is the trader's OTR versus market average and versus the trader's own historical baseline.

Time-Weighted Cancellation Ratio (TWCR): This refines OTR by weighting cancellations by how quickly they occur. An order placed and cancelled within 100 milliseconds has a different behavioral signature than one placed and cancelled after 30 seconds. Most genuine market-making cancellations reflect legitimate repricing; very fast cancellations — particularly when correlated with price movements — are more suspicious.

Price Impact Correlation: The key signature of spoofing is that the large order moves the price, then is cancelled after the move. A detection algorithm can measure the correlation between (a) the appearance of a large order on one side of the book, (b) price movement in the direction consistent with that order, and (c) subsequent cancellation of that order. High correlation across multiple instances is a strong spoofing signal.

Layered-Order Profile: A sophisticated variant (discussed further in section 22.4) involves multiple orders at different price levels — the detection algorithm must identify whether orders appear at several price levels in a coordinated pattern.


22.4 Layering: Multiple Orders, Multiple Levels

22.4.1 Layering Versus Spoofing

Layering is a close relative of spoofing but involves a specific structural feature: the placement of orders at multiple price levels on one side of the order book, creating the appearance of deep liquidity (or supply) where none genuinely exists. While spoofing may involve a single large order, layering constructs a stack of orders — hence the name — at progressively worse prices, amplifying the apparent market imbalance.

The practical distinction matters for detection because layering creates a specific order book pattern: a cascade of orders on one side of the book that appears at multiple price levels within a short time window, followed by cancellation of those orders after the price has moved. A spoofing detection algorithm looking for a single large order will miss layering. A layering detector must identify the coordinated multi-level structure.

Regulators have treated layering as a form of market manipulation under the same statutory frameworks that apply to spoofing, but enforcement cases have sometimes drawn the distinction explicitly. The FCA's 2013 action against Swift Trade Inc. (a firm that employed traders operating layering strategies) was among the first significant UK enforcement actions specifically addressing layering as a distinct pattern, resulting in a £8 million fine.

22.4.2 How Layering Creates Artificial Order Book Pressure

Consider a hypothetical EUR/USD futures order book. A natural (untampered) book might show:

ASK: 1.0855 x 100 lots | 1.0856 x 80 lots | 1.0857 x 60 lots
BID: 1.0854 x 100 lots | 1.0853 x 80 lots | 1.0852 x 60 lots

A layering trader who wants to buy cheaply might insert:

ASK: 1.0855 x 100 lots | 1.0856 x 80 lots | 1.0857 x 60 lots
           + SPOOF LAYERS:
ASK: 1.0858 x 500 lots | 1.0859 x 800 lots | 1.0860 x 1,000 lots
BID: 1.0854 x 100 lots | 1.0853 x 80 lots | 1.0852 x 60 lots

The appearance of 2,300 lots of fictitious sell orders at 1.0858 through 1.0860 signals enormous selling pressure to the market. Algorithmic traders observing this book update their models to reflect a price likely to fall. Passive buyers reduce their bids. The market price moves down. The layering trader then executes genuine buy orders at a price depressed by their own false signals, then rapidly cancels the 2,300 layered sell orders.

The harm is not merely to the counterparty of the layering trader — it corrupts price discovery for all participants who observed the false book and adjusted their behavior accordingly.

22.4.3 The Cornerstone Financial Group Surveillance Case

At Cornerstone Financial Group, the compliance technology team had recently implemented a new order book analytics module as part of their trade surveillance platform upgrade. The module ingested order-level data from Cornerstone's Euribor futures desk in near real-time, applying a set of behavioral metrics developed with input from Rafael Torres, who had been engaged as an external adviser.

It was during a routine Tuesday morning alert review that a junior surveillance analyst named Deepa Krishnamurthy flagged something unusual. The system had generated a "Level 2" alert on a trader — identified in the platform only by an internal ID — with an elevated layering score for the previous six trading days. Level 2 alerts were meant to be reviewed within 24 hours; Deepa had discovered that this trader's alerts had been queuing unreviewed for nearly two weeks because the original analyst responsible for that desk segment had been on leave.

The pattern was striking: for approximately 90 minutes each morning in the period leading up to the 10am ECB rate decision window, the trader's account showed a consistent sequence. First, a cascade of sell orders would appear at three to five price levels above the current best ask in the March Euribor futures contract. These orders collectively represented several thousand lots — far larger than the trader's typical working order size. The market would show a measurable downward price response within 60 to 90 seconds. Then, within a roughly 30-second window, the trader would execute genuine buy orders in adjacent months. Then, in the following 2 to 5 minutes, the layered sell orders would be cancelled. All of it.

"What struck me," Deepa later told the investigation committee, "was the consistency. The pattern was nearly identical across six trading days. The orders were always placed at the same relative distance above the market. The cancel timing was always within the same window. No legitimate trading strategy I can think of would have that kind of mechanical regularity."

Rafael was called in to review the pattern independently. His assessment was unequivocal: this was a textbook layering scheme, and it had been running for at least six weeks based on the historical data review that followed.

22.4.4 Layering Detection: Python Implementation

The following code implements a layering detector that captures the structural features of the pattern Deepa identified at Cornerstone.

from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Optional
import pandas as pd
import numpy as np
from collections import defaultdict


@dataclass
class OrderBookEntry:
    order_id: str
    price: float
    quantity: float
    side: str          # 'bid' or 'ask'
    timestamp: datetime
    trader_id: str
    status: str = 'active'  # 'active', 'cancelled', 'executed'


@dataclass
class OrderEvent:
    event_type: str       # 'place', 'cancel', 'execute', 'modify'
    order_id: str
    price: float
    quantity: float
    side: str
    timestamp: datetime
    trader_id: str
    instrument_id: str


@dataclass
class SurveillanceAlert:
    alert_id: str
    alert_type: str
    trader_id: str
    instrument_id: str
    detected_at: datetime
    window_start: datetime
    window_end: datetime
    severity: str          # 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'
    details: dict = field(default_factory=dict)
    score: float = 0.0


class LayeringDetector:
    """
    Detects layering: placing multiple orders at different price levels
    on one side of the book to create artificial order book imbalance,
    then canceling those orders after the price moves in the intended
    direction and genuine orders on the opposite side have been filled.

    The detector looks for the three-phase pattern:
      Phase 1 — ORDER PLACEMENT: 3+ orders at distinct price levels,
                same side, within a short time window.
      Phase 2 — PRICE IMPACT:    Market price moves in direction
                consistent with the artificial imbalance.
      Phase 3 — CANCELLATION:    >= cancellation_threshold of the
                layered orders are cancelled after the price moves.
    """

    def __init__(
        self,
        min_layers: int = 3,
        cancellation_threshold: float = 0.80,
        max_layer_spread_bps: float = 50.0,   # max price spread across layers
        price_impact_min_bps: float = 2.0,    # min price movement to qualify
        phase2_window_seconds: int = 120,
        phase3_window_seconds: int = 300,
    ):
        self.min_layers = min_layers
        self.cancellation_threshold = cancellation_threshold
        self.max_layer_spread_bps = max_layer_spread_bps
        self.price_impact_min_bps = price_impact_min_bps
        self.phase2_window_seconds = phase2_window_seconds
        self.phase3_window_seconds = phase3_window_seconds

    def _extract_placement_clusters(
        self,
        events: list[OrderEvent],
        window_start: datetime,
        window_end: datetime,
        trader_id: str,
    ) -> dict[str, list[OrderEvent]]:
        """
        Group order placement events by trader and side within a time window.
        Returns {trader_id + side: [events]} for clusters meeting min_layers.
        """
        clusters: dict[str, list[OrderEvent]] = defaultdict(list)
        for event in events:
            if (
                event.event_type == 'place'
                and event.trader_id == trader_id
                and window_start <= event.timestamp <= window_end
            ):
                key = f"{event.trader_id}:{event.side}"
                clusters[key].append(event)

        # Keep only clusters with enough distinct price levels
        valid_clusters = {}
        for key, cluster_events in clusters.items():
            distinct_prices = set(round(e.price, 6) for e in cluster_events)
            if len(distinct_prices) >= self.min_layers:
                valid_clusters[key] = cluster_events

        return valid_clusters

    def _compute_price_spread_bps(self, prices: list[float]) -> float:
        """Spread of layered order prices in basis points relative to min price."""
        if not prices or min(prices) == 0:
            return 0.0
        return (max(prices) - min(prices)) / min(prices) * 10_000

    def _measure_price_impact(
        self,
        market_prices: pd.Series,   # indexed by datetime
        cluster_events: list[OrderEvent],
        phase2_window_seconds: int,
    ) -> tuple[float, str]:
        """
        Measure price movement (bps) after cluster placement.
        Returns (price_change_bps, direction).
        direction is 'down' for ask-side layering pressure (sell pressure),
        'up' for bid-side layering pressure (buy pressure).
        """
        if market_prices.empty or not cluster_events:
            return 0.0, 'none'

        placement_start = min(e.timestamp for e in cluster_events)
        placement_end = max(e.timestamp for e in cluster_events)
        impact_end = placement_start + timedelta(seconds=phase2_window_seconds)

        # Baseline: price at start of placement cluster
        try:
            price_at_placement = market_prices.asof(placement_start)
        except Exception:
            return 0.0, 'none'

        # Price window after placement
        post_placement = market_prices[
            (market_prices.index >= placement_end) &
            (market_prices.index <= impact_end)
        ]

        if post_placement.empty or price_at_placement == 0:
            return 0.0, 'none'

        min_price = post_placement.min()
        max_price = post_placement.max()
        down_move_bps = (price_at_placement - min_price) / price_at_placement * 10_000
        up_move_bps = (max_price - price_at_placement) / price_at_placement * 10_000

        # The side tells us expected direction: ask layers → sell pressure → price down
        side = cluster_events[0].side
        if side == 'ask':
            return down_move_bps, 'down'
        else:
            return up_move_bps, 'up'

    def _measure_cancellation_rate(
        self,
        cluster_events: list[OrderEvent],
        all_events: list[OrderEvent],
        price_impact_end: datetime,
        phase3_window_seconds: int,
    ) -> float:
        """
        Of the orders placed in the layering cluster, what fraction
        were cancelled (rather than executed) within phase3_window_seconds
        after the price impact window?
        """
        cluster_order_ids = {e.order_id for e in cluster_events}
        phase3_end = price_impact_end + timedelta(seconds=phase3_window_seconds)

        cancelled = set()
        executed = set()

        for event in all_events:
            if event.order_id not in cluster_order_ids:
                continue
            if not (price_impact_end <= event.timestamp <= phase3_end):
                continue
            if event.event_type == 'cancel':
                cancelled.add(event.order_id)
            elif event.event_type == 'execute':
                executed.add(event.order_id)

        total_dispositions = len(cancelled) + len(executed)
        if total_dispositions == 0:
            return 0.0

        return len(cancelled) / total_dispositions

    def analyze_order_book_sequence(
        self,
        order_events: list[OrderEvent],
        instrument_id: str,
        market_prices: pd.Series,   # mid-price time series, datetime-indexed
        trader_id: str,
        window_minutes: int = 5,
        alert_id_prefix: str = "LYR",
    ) -> list[SurveillanceAlert]:
        """
        Main detection method. Scans order events for a given trader
        and instrument, applying the three-phase layering test.

        Parameters
        ----------
        order_events : list[OrderEvent]
            All order events for the instrument (all traders) in the
            analysis period.
        instrument_id : str
            The instrument being analyzed.
        market_prices : pd.Series
            Mid-price time series with datetime index.
        trader_id : str
            The trader under review.
        window_minutes : int
            Rolling window within which Phase 1 cluster must complete.
        alert_id_prefix : str
            Prefix for generated alert IDs.

        Returns
        -------
        list[SurveillanceAlert]
            Alerts generated by the analysis.
        """
        alerts: list[SurveillanceAlert] = []
        instrument_events = [
            e for e in order_events if e.instrument_id == instrument_id
        ]
        trader_placements = [
            e for e in instrument_events
            if e.trader_id == trader_id and e.event_type == 'place'
        ]
        if not trader_placements:
            return alerts

        # Scan in rolling windows
        sorted_placements = sorted(trader_placements, key=lambda e: e.timestamp)
        checked_windows: set[datetime] = set()

        for anchor_event in sorted_placements:
            window_start = anchor_event.timestamp
            window_end = window_start + timedelta(minutes=window_minutes)

            if window_start in checked_windows:
                continue
            checked_windows.add(window_start)

            # Phase 1: Find placement clusters
            clusters = self._extract_placement_clusters(
                instrument_events, window_start, window_end, trader_id
            )
            if not clusters:
                continue

            for cluster_key, cluster_events in clusters.items():
                prices_in_cluster = [e.price for e in cluster_events]
                spread_bps = self._compute_price_spread_bps(prices_in_cluster)
                if spread_bps > self.max_layer_spread_bps:
                    continue  # Layers too spread out to be coherent

                # Phase 2: Measure price impact
                impact_bps, direction = self._measure_price_impact(
                    market_prices, cluster_events, self.phase2_window_seconds
                )
                if impact_bps < self.price_impact_min_bps:
                    continue  # Insufficient price movement

                impact_end = max(e.timestamp for e in cluster_events) + timedelta(
                    seconds=self.phase2_window_seconds
                )

                # Phase 3: Measure cancellation rate
                cancel_rate = self._measure_cancellation_rate(
                    cluster_events, instrument_events, impact_end,
                    self.phase3_window_seconds
                )
                if cancel_rate < self.cancellation_threshold:
                    continue  # Too many orders actually executed — not spoofing

                # All three phases confirmed: generate alert
                distinct_levels = len(set(round(e.price, 6) for e in cluster_events))
                total_spoofed_qty = sum(e.quantity for e in cluster_events)

                score = self._compute_layering_score(
                    distinct_levels, impact_bps, cancel_rate, spread_bps
                )

                severity = (
                    'CRITICAL' if score >= 0.85
                    else 'HIGH' if score >= 0.70
                    else 'MEDIUM' if score >= 0.50
                    else 'LOW'
                )

                alert = SurveillanceAlert(
                    alert_id=f"{alert_id_prefix}-{len(alerts)+1:04d}",
                    alert_type='LAYERING',
                    trader_id=trader_id,
                    instrument_id=instrument_id,
                    detected_at=datetime.utcnow(),
                    window_start=window_start,
                    window_end=impact_end + timedelta(seconds=self.phase3_window_seconds),
                    severity=severity,
                    score=score,
                    details={
                        'num_layers': distinct_levels,
                        'layering_side': cluster_events[0].side,
                        'total_spoofed_quantity': total_spoofed_qty,
                        'price_spread_bps': round(spread_bps, 2),
                        'price_impact_bps': round(impact_bps, 2),
                        'impact_direction': direction,
                        'cancellation_rate': round(cancel_rate, 4),
                        'num_orders_in_cluster': len(cluster_events),
                    }
                )
                alerts.append(alert)

        return alerts

    def _compute_layering_score(
        self,
        distinct_levels: int,
        impact_bps: float,
        cancel_rate: float,
        spread_bps: float,
    ) -> float:
        """
        Composite score 0–1 combining:
          - Number of distinct price levels (more = more suspicious)
          - Magnitude of price impact
          - Cancellation rate (higher = more suspicious)
        """
        level_score = min(distinct_levels / 8.0, 1.0)         # normalise to 8+ levels
        impact_score = min(impact_bps / 20.0, 1.0)            # normalise to 20bps
        cancel_score = (cancel_rate - self.cancellation_threshold) / (
            1.0 - self.cancellation_threshold
        ) if cancel_rate > self.cancellation_threshold else 0.0
        cancel_score = max(0.0, min(cancel_score, 1.0))

        # Weighted composite
        return round(0.35 * level_score + 0.35 * impact_score + 0.30 * cancel_score, 4)

22.5 Front-Running: Trading Ahead of Client Orders

22.5.1 Definition and Mechanics

Front-running occurs when a broker, dealer, or investment manager trades in its own account — or in accounts of favored clients — based on advance knowledge of pending client orders that will move the market. The front-runner effectively uses non-public information about order flow to position themselves advantageously before the order is executed.

The classic case involves a large asset manager placing an order to buy a significant position in a thinly traded stock. A broker handling that order who buys the same stock for their own account before executing the client's order is front-running. When the client's order moves the price up (as large buy orders tend to do), the broker's own position profits at the client's expense.

Electronic front-running is a more contemporary and contested variant, involving high-frequency trading firms that detect institutional order flow through multiple exchange routing patterns and race to trade ahead of incoming orders across venues. This practice, which Michael Lewis brought to mainstream attention in "Flash Boys" (2014), is legally more ambiguous than traditional front-running because the HFT firms are not typically acting as agents for the clients whose orders they detect.

In the traditional (clear-cut) regulatory framework:

  • US: Front-running by a broker-dealer violates Sections 9 and 10(b) of the Securities Exchange Act of 1934 and FINRA Rule 5270 ("Front Running of Block Transactions").
  • EU/UK: Front-running is captured by MAR Article 12 as a form of market manipulation and potentially also by the insider dealing provisions of MAR Article 8 if the knowledge of the pending order constitutes inside information (relevant particularly for large block orders that are reasonably expected to move the market significantly).

22.5.2 Information Barriers as a Control

The primary structural control against front-running is the information barrier (commonly called a Chinese wall), which separates business units that have access to client order information from those that engage in proprietary trading. An effective information barrier means that the trader placing orders in the firm's own account cannot access information about pending client orders before they are executed.

Information barriers are not always effective in practice. Common failures include:

  • Physical proximity: Prop traders and client execution desks physically adjacent, enabling inadvertent or deliberate information leakage.
  • Systems integration: Order management systems that expose client order queues to users who should not have access.
  • Management information sharing: Senior managers who receive consolidated P&L or position reports that reveal client order information.
  • Pre-hedging ambiguity: The legitimate practice of "pre-hedging" — a dealer taking positions in anticipation of a client order they are about to receive — is legally permitted in many jurisdictions but creates gray areas that can mask front-running.

22.5.3 FIFO and Pro-Rata Execution

Two exchange-level mechanisms provide partial mitigation of front-running risk:

First In, First Out (FIFO): Orders at the same price are executed in the sequence in which they were received. A front-runner who places their order after seeing the client order cannot get ahead of the client's order in the queue at the same price level — they would need to bid higher, which defeats the purpose.

Pro-Rata Allocation: In some markets (notably interest rate futures), execution is allocated proportionally among all orders at the best price, rather than sequentially. While this does not prevent front-running at better prices, it limits the advantage a front-runner can obtain by placing an order at the same price level.

22.5.4 Front-Running Detection Implementation

@dataclass
class TradeEvent:
    trade_id: str
    order_id: str
    price: float
    quantity: float
    side: str
    timestamp: datetime
    trader_id: str
    account_type: str   # 'proprietary', 'client', 'agency'
    client_id: Optional[str]
    instrument_id: str


class FrontRunningDetector:
    """
    Detects potential front-running: the institution (or a specific
    trader) trades in a proprietary account shortly before executing
    a large client order in the same direction and instrument.

    The key signal is:
      1. Prop trade in instrument X, direction D, size >= threshold
      2. Within pre_trade_window_seconds, client order arrives in
         instrument X, direction D, size >= min_client_order_size
      3. Prop trade is closed or reversed shortly after client order
         execution (capturing the price impact profit)
    """

    def __init__(
        self,
        pre_trade_window_seconds: int = 60,
        post_trade_reversal_seconds: int = 300,
        min_client_order_size: float = 100_000,   # notional
        min_prop_order_size: float = 10_000,
    ):
        self.pre_trade_window_seconds = pre_trade_window_seconds
        self.post_trade_reversal_seconds = post_trade_reversal_seconds
        self.min_client_order_size = min_client_order_size
        self.min_prop_order_size = min_prop_order_size

    def check_own_account_vs_client(
        self,
        all_trades: list[TradeEvent],
        trader_id: str,
        instrument_id: str,
    ) -> list[SurveillanceAlert]:
        """
        Check whether a specific trader's proprietary trades precede
        large client orders in the same instrument and direction.
        """
        alerts: list[SurveillanceAlert] = []

        instrument_trades = [
            t for t in all_trades if t.instrument_id == instrument_id
        ]

        # Identify large client orders executed by this trader
        client_orders = [
            t for t in instrument_trades
            if t.trader_id == trader_id
            and t.account_type in ('client', 'agency')
            and (t.price * t.quantity) >= self.min_client_order_size
        ]

        # Identify this trader's proprietary trades
        prop_trades = [
            t for t in instrument_trades
            if t.trader_id == trader_id
            and t.account_type == 'proprietary'
            and (t.price * t.quantity) >= self.min_prop_order_size
        ]

        for client_order in client_orders:
            window_open = client_order.timestamp - timedelta(
                seconds=self.pre_trade_window_seconds
            )
            window_close = client_order.timestamp

            # Find prop trades in same direction, within pre-trade window
            preceding_prop = [
                p for p in prop_trades
                if p.side == client_order.side
                and window_open <= p.timestamp <= window_close
            ]

            if not preceding_prop:
                continue

            # Check for post-execution reversal (profit-taking)
            reversal_window_end = client_order.timestamp + timedelta(
                seconds=self.post_trade_reversal_seconds
            )
            opposite_side = 'ask' if client_order.side == 'bid' else 'bid'
            post_reversals = [
                p for p in prop_trades
                if p.side == opposite_side
                and client_order.timestamp <= p.timestamp <= reversal_window_end
            ]

            # Compute aggregated preceding prop quantity
            total_preceding_qty = sum(p.quantity for p in preceding_prop)
            has_reversal = len(post_reversals) > 0

            severity = 'HIGH' if has_reversal else 'MEDIUM'

            alert = SurveillanceAlert(
                alert_id=f"FRR-{len(alerts)+1:04d}",
                alert_type='FRONT_RUNNING',
                trader_id=trader_id,
                instrument_id=instrument_id,
                detected_at=datetime.utcnow(),
                window_start=window_open,
                window_end=reversal_window_end,
                severity=severity,
                score=0.8 if has_reversal else 0.5,
                details={
                    'client_order_id': client_order.order_id,
                    'client_order_size_notional': client_order.price * client_order.quantity,
                    'client_order_direction': client_order.side,
                    'num_preceding_prop_trades': len(preceding_prop),
                    'total_preceding_prop_qty': total_preceding_qty,
                    'reversal_detected': has_reversal,
                    'num_post_reversals': len(post_reversals),
                }
            )
            alerts.append(alert)

        return alerts

22.6 Marking the Close: Benchmark Manipulation

22.6.1 How Marking the Close Works

Marking the close refers to the practice of placing concentrated buy or sell orders near the end of the trading session — typically in the final minutes — with the intent to influence the closing price or fixing. The closing price is not merely the last trade of the day; it is a reference price used in a wide range of financial contracts, index calculations, portfolio valuations, and performance benchmarks.

A trader who holds a large long position in a stock that is approaching a performance review date has a financial incentive to ensure the closing price on that date is as high as possible. By placing a surge of buy orders in the last minutes of trading, they can push the closing price upward, improving their reported performance at the expense of those who must trade at that artificially inflated benchmark.

Marking the close is particularly relevant in:

  • Index rebalancing: Stocks being added to or deleted from major indices experience extremely high volume near the close on rebalancing dates, creating manipulation opportunities.
  • Options and futures expiry: Instruments settling against closing prices of the underlying create strong financial incentives to move those closing prices.
  • Fund performance measurement: Net asset value calculations using closing prices create incentives for fund managers with concentrated positions to mark up those prices.

22.6.2 The FCA's LIBOR Context

While LIBOR manipulation (discussed in earlier chapters of this textbook) involved benchmark rates rather than exchange-traded closing prices, the same economic logic applies: when a trader holds positions whose value depends on a reference rate or price, they have an incentive to manipulate that reference. The FCA's enforcement experience with LIBOR has significantly informed its approach to closing-price manipulation, including the application of MAR Article 12(1)(a) to patterns of concentrated end-of-session trading.

22.6.3 Marking the Close Detection

class MarkingTheCloseDetector:
    """
    Detects marking the close: concentrated trading volume near market
    close that is disproportionate to the trader's intraday activity
    and correlates with a position that benefits from price movement.
    """

    def __init__(
        self,
        closing_window_minutes: int = 30,
        concentration_threshold: float = 0.40,   # 40% of daily volume in window
        min_daily_volume_threshold: int = 1_000,  # minimum relevant daily volume
    ):
        self.closing_window_minutes = closing_window_minutes
        self.concentration_threshold = concentration_threshold
        self.min_daily_volume_threshold = min_daily_volume_threshold

    def analyze(
        self,
        orders: list[OrderEvent],
        market_close_time: datetime,
        trader_positions: dict[str, float],   # {instrument_id: net position (+ = long)}
        instrument_id: str,
        trader_id: str,
    ) -> list[SurveillanceAlert]:
        """
        Flag if trader's volume in closing window exceeds
        concentration_threshold of their daily volume, AND
        the direction is consistent with benefiting their position.
        """
        alerts: list[SurveillanceAlert] = []

        trader_orders = [
            o for o in orders
            if o.trader_id == trader_id and o.instrument_id == instrument_id
        ]

        if not trader_orders:
            return alerts

        day_start = market_close_time.replace(hour=0, minute=0, second=0, microsecond=0)
        closing_window_start = market_close_time - timedelta(
            minutes=self.closing_window_minutes
        )

        daily_volume = sum(
            o.quantity for o in trader_orders
            if day_start <= o.timestamp <= market_close_time
        )

        if daily_volume < self.min_daily_volume_threshold:
            return alerts  # Insufficient volume to be significant

        closing_window_orders = [
            o for o in trader_orders
            if closing_window_start <= o.timestamp <= market_close_time
        ]

        closing_volume = sum(o.quantity for o in closing_window_orders)
        concentration = closing_volume / daily_volume if daily_volume > 0 else 0.0

        if concentration < self.concentration_threshold:
            return alerts

        # Check directional consistency with position
        net_position = trader_positions.get(instrument_id, 0.0)
        closing_buy_volume = sum(
            o.quantity for o in closing_window_orders if o.side == 'bid'
        )
        closing_sell_volume = sum(
            o.quantity for o in closing_window_orders if o.side == 'ask'
        )

        direction_consistent = (
            (net_position > 0 and closing_buy_volume > closing_sell_volume) or
            (net_position < 0 and closing_sell_volume > closing_buy_volume)
        )

        severity = 'HIGH' if direction_consistent else 'MEDIUM'
        score = concentration * (1.2 if direction_consistent else 0.8)
        score = min(score, 1.0)

        alert = SurveillanceAlert(
            alert_id=f"MTC-0001",
            alert_type='MARKING_THE_CLOSE',
            trader_id=trader_id,
            instrument_id=instrument_id,
            detected_at=datetime.utcnow(),
            window_start=closing_window_start,
            window_end=market_close_time,
            severity=severity,
            score=round(score, 4),
            details={
                'daily_volume': daily_volume,
                'closing_window_volume': closing_volume,
                'concentration_ratio': round(concentration, 4),
                'net_position': net_position,
                'direction_consistent_with_position': direction_consistent,
                'closing_buy_volume': closing_buy_volume,
                'closing_sell_volume': closing_sell_volume,
            }
        )
        alerts.append(alert)
        return alerts

22.7 Quote Stuffing, Pump and Dump, and Cross-Asset Manipulation

22.7.1 Quote Stuffing

Quote stuffing involves the rapid submission of large numbers of orders and cancellations to an exchange, with the purpose of slowing down competing trading systems and gaining a latency advantage. The practice exploits the fact that all market participants on a trading venue share the same message processing infrastructure — by flooding that infrastructure with quotes, a trader can temporarily impair rivals' ability to process market data and respond to price changes.

Quote stuffing is distinct from spoofing in that the primary harm mechanism is not false price signals — it is the degradation of market infrastructure for competitors. Detection focuses on abnormally high message rates from a single participant, particularly when those messages are concentrated in instruments where the participant has a directional position.

Regulators have addressed quote stuffing under the same manipulation statutes as spoofing (MAR Article 12, CFTC regulations under the CEA), but enforcement is complicated by the fact that many legitimate market-making strategies involve high message rates. The FCA's 2013 guidance on automated trading (ESMA Guidelines on Systems and Controls in an Automated Trading Environment) addresses quote stuffing as a specific risk of algorithmic trading.

22.7.2 Pump and Dump: The Social Media Dimension

Pump and dump is one of the oldest forms of securities fraud: artificially inflate the price of a thinly traded security through misleading promotional activity, then sell at the inflated price, leaving other investors holding overpriced shares as the price collapses.

The modern evolution of pump and dump has moved aggressively onto social media platforms. The 2021 GameStop and meme stock phenomena, while legally contested in terms of whether they constitute manipulation (coordinated activity by large numbers of independent retail investors raises genuine questions about the application of traditional manipulation doctrine), illustrated the potential for social media coordination to move markets. Unambiguous pump-and-dump schemes operate through:

  • Paid promoters posting misleading content on social media platforms (Twitter/X, Reddit, Discord, Telegram)
  • Anonymous accounts purchasing penny stocks, then promoting them through fabricated research or news
  • Coordinated messaging that creates artificial appearance of independent organic interest

MAR Article 12(1)(c) explicitly covers information dissemination that gives false or misleading signals, and ESMA has published guidance on the application of MAR to social media communications. The FCA has brought enforcement actions in this area, including against individuals who promoted unlicensed investments through social media.

Detection of social media pump-and-dump schemes requires integration of trading surveillance with alternative data sources: social media monitoring, web scraping of investment forums, and natural language processing to identify coordinated messaging patterns correlated with abnormal trading activity.

22.7.3 Cross-Asset Manipulation

Cross-asset manipulation involves manipulation in one instrument that is designed to create a benefit in a related instrument — exploiting the price relationships between markets.

Classic examples include:

Cash/Futures manipulation: Buying large quantities of a stock in the cash market near futures expiry to push up the settlement price of futures contracts on that stock. The trader may hold a large long position in the futures, and the manipulation in the cash market generates profit in the futures position.

Options/Underlying manipulation: Buying options that will become deeply in-the-money if the underlying price moves to a certain level, then buying the underlying aggressively to push it through that level. The profit on the options exceeds the cost of the manipulation in the underlying.

Bond/CDS manipulation: Taking a large position in credit default swaps on a company's debt, then engineering (or amplifying) negative information about the company to push down its bond prices and trigger CDS payouts.

Index/Component manipulation: Manipulating the price of a component stock at index rebalancing time to affect the index level, benefiting an index futures position.

Detection of cross-asset manipulation requires surveillance systems that can correlate position data across instruments, markets, and even asset classes. Priya Nair's work designing a cross-asset surveillance program for an EU investment bank (detailed in Case Study 2 at the end of this chapter) illustrates the architectural requirements for this kind of multi-dimensional analysis.


22.8 Evidence Requirements for Enforcement Actions

When a surveillance alert progresses to a formal investigation, whether internal or regulatory, the evidence needed to support an enforcement action follows a structured framework. Rafael Torres, drawing on his experience advising clients through both internal investigations and regulatory inquiries, describes the evidence hierarchy as follows:

22.8.1 Level 1: Behavioral Data (Necessary but Not Sufficient)

Order-level data showing the pattern of order placement, modification, and cancellation. This is the foundation of every surveillance-based investigation. At this level, the evidence demonstrates that a pattern occurred — but patterns consistent with manipulation also occur in legitimate trading. Behavioral data alone rarely supports an enforcement action.

Key data points at this level: - Complete order lifecycle records (submission, modification, cancellation, execution) - Timestamps with microsecond precision (or better) - Order attributes: price, quantity, order type, time-in-force - Position data before, during, and after the suspected manipulation period - Trade confirmations showing actual executions

22.8.2 Level 2: Correlation and Statistical Analysis

Statistical analysis demonstrating that the behavioral pattern is inconsistent with legitimate trading. This includes:

  • Cancellation rates compared to peer group and market averages
  • Price impact analysis showing correlation between the trader's orders and price movements
  • Temporal analysis of the sequence: order placement → price movement → cancellation → position benefit
  • Statistical significance testing showing the pattern is not consistent with random trading behavior

At Level 2, the evidence is sufficient to justify opening a formal investigation and may be sufficient to issue regulatory notices or compel testimony.

22.8.3 Level 3: Intent Evidence

The most powerful evidence in manipulation cases is direct or circumstantial evidence of intent. This includes:

  • Communications evidence: Chat messages, emails, voice recordings in which the trader discusses the manipulation strategy, refers to their own orders as "spoof orders," or coordinates with others. Communications evidence is obtained through regulatory compulsion (document requests, subpoenas) or from whistleblowers.
  • Technology evidence: Code review showing that trading software was deliberately configured to minimize execution probability (e.g., orders placed at prices far from the market with automatic modification to maintain that distance). In the Sarao case, the software was specifically designed to reprice orders to avoid accidental execution.
  • Pattern evidence over extended periods: A single episode might be explained away as legitimate market activity. A pattern of dozens or hundreds of substantially identical episodes over weeks or months is much harder to characterize as coincidental.
  • Post-trade analysis: Showing that the trader consistently profited from the manipulation — i.e., their genuine trades were consistently executed at favorable prices coinciding with their spoofing/layering activity.

22.8.4 The Cornerstone Investigation Evidence Structure

In the Cornerstone case, the surveillance system's initial output constituted Level 1 and Level 2 evidence: a six-week pattern of order book behavior showing layering across multiple sessions, with statistically significant price impact and near-total cancellation rates. This was sufficient for the compliance team to escalate to legal counsel and open a formal internal investigation.

The internal investigation then obtained Level 3 evidence in the form of communications between the trader and a colleague on another desk, in which the colleague asked about the trader's consistent performance in the morning session and the trader replied with a message that, in context, described the layering strategy explicitly.

"That single message changed the character of the investigation entirely," Rafael told the subsequent review committee. "Before we found it, we had a pattern that was suspicious but explainable. After we found it, we had a pattern with a deliberate purpose attached. That's when we called the FCA."


22.9 False Positive Management: When Legitimate Trading Looks Like Manipulation

The single greatest operational challenge in trade surveillance is managing false positives — alerts generated by legitimate trading behavior that pattern-matches against manipulation detection algorithms. A surveillance program that generates hundreds of false positives for every genuine case of manipulation is not merely inefficient; it creates the risk of desensitization, where analysts begin to dismiss alerts reflexively because the signal-to-noise ratio is too low.

22.9.1 Behaviors That Generate False Positives

Market Making: Market makers are obligated or incentivized to provide continuous two-sided quotes. They frequently place and cancel large numbers of orders as the market moves, resulting in high OTRs and cancellation ratios. A spoofing detection algorithm configured without market-maker exemptions will generate constant alerts on market-making desks. The solution is to segment alert populations by trader function and apply differentiated thresholds — or to specifically exempt registered market makers from certain detection rules, reviewing their activity under a separate rule set focused on whether their market-making activity is genuinely bilateral.

Hedging Activity: A portfolio manager who places a large order in futures to hedge a position may cancel and replace that order multiple times as the underlying moves, generating apparent layering signals. Detecting whether the orders are genuine hedges requires access to position data across books — information that a surveillance system must be designed to ingest.

Testing and System Malfunctions: Trading systems send erroneous orders due to fat-finger errors, system malfunctions, or testing. These can generate order-cancel patterns that trigger manipulation alerts. Robust surveillance systems maintain awareness of system test windows and implement look-back reconciliation to identify orders flagged as errors by the trader's OMS.

News-Driven Volatility: During high-volatility periods driven by genuine news events (earnings releases, central bank announcements, geopolitical developments), order cancellation rates spike across all market participants as traders rapidly update their views. Absolute cancellation thresholds calibrated in normal market conditions will generate disproportionate alerts in volatile periods. Adaptive thresholds that adjust to market-wide volatility levels reduce this problem.

Algorithmic VWAP/TWAP Execution: Large institutional orders executed using volume-weighted average price (VWAP) or time-weighted average price (TWAP) algorithms involve placing and cancelling orders repeatedly throughout the session. A TWAP algorithm executing a large client order near the close might trigger both a front-running alert (for the prop position the desk holds as a hedge) and a marking-the-close alert (for the concentrated closing-period volume).

22.9.2 Alert Disposition Framework

A well-designed alert disposition workflow separates the technical detection output from the investigative determination. The key stages are:

  1. Automated Triage: Machine learning classifiers trained on historical alert dispositions can score new alerts by predicted true-positive probability, allowing analysts to prioritize higher-confidence cases.

  2. Level 1 Review (15–30 minutes per alert): An analyst reviews the raw behavioral data, checks against known legitimate activity (market-making designations, hedge exemptions, system test windows), and either closes the alert with documented rationale or escalates.

  3. Level 2 Investigation (hours to days): For escalated alerts, a more detailed investigation is conducted, including communications review, position data analysis, and comparison against the trader's historical activity.

  4. Regulatory Determination: If Level 2 investigation finds evidence sufficient to support a regulatory referral, internal legal counsel is engaged and the decision to make a Suspicious Transaction and Order Report (STOR) is made.

The STOR (or its US equivalent, a Suspicious Activity Report) is a regulatory obligation under UK MAR Article 16 and EU MAR Article 16. Firms that detect suspected market manipulation are required to submit a STOR to the relevant national competent authority — the FCA in the UK, or the relevant EU national authority (working through ESMA's TREM system for cross-border cases). The obligation exists independently of whether the firm has concluded that manipulation occurred; reasonable suspicion is sufficient to trigger the reporting obligation.


22.10 Summary: The Surveillance Program in Practice

The landscape of market manipulation detection presents compliance technology teams with a set of challenges that are simultaneously technical, legal, and operational. The technical challenge is constructing detection algorithms that are sensitive enough to catch genuine manipulation while generating a manageable false positive rate. The legal challenge is understanding the evidentiary standards required to support enforcement action and ensuring that the surveillance program is capable of generating the right categories of evidence. The operational challenge is building the human infrastructure — the analyst capacity, the escalation workflows, the governance frameworks — to translate technical output into actionable compliance determinations.

Maya's experience building Verdant Bank's surveillance infrastructure, and Cornerstone's experience responding to an internal surveillance alert that uncovered a genuine manipulation case, illustrate the same fundamental point: trade surveillance is not a technology problem with a technology solution. It is a compliance program problem that technology enables. The algorithms detect patterns. The humans determine what the patterns mean.

"The day we found the Cornerstone case," Rafael says, "was the day I stopped thinking about surveillance as a system you configure and leave alone. You have to keep asking the question: what would a trader do that we wouldn't see? Because they're asking that question too."


Key Terms

Spoofing: Placing orders with the intent to cancel before execution, to create false price signals that benefit genuine positions on the opposite side.

Layering: A variant of spoofing involving multiple orders at different price levels on one side of the book, creating the appearance of deep liquidity.

Front-running: Trading in a proprietary account ahead of known pending client orders in the same direction and instrument.

Marking the close: Concentrated end-of-session trading designed to influence closing prices or benchmark fixings.

Quote stuffing: Generating abnormally high message volumes on an exchange to impair competitors' systems and gain a latency advantage.

Pump and dump: Artificially inflating an asset's price through misleading promotional activity, then selling at the inflated price.

Cross-asset manipulation: Manipulating one instrument to generate a profit in a related instrument, exploiting price relationships across markets.

Order-to-trade ratio (OTR): The ratio of orders submitted to orders executed; a key metric for detecting manipulation.

Suspicious Transaction and Order Report (STOR): A regulatory report required under MAR Article 16 when a firm detects suspected market manipulation or insider dealing.

Information barrier (Chinese wall): Organizational and systems controls separating business units with access to client order information from proprietary trading units.


Next: Chapter 23 — Market Microstructure, High-Frequency Trading, and Regulatory Response