Self-match prevention e wash trade: come funzionano
Come la self-match prevention evita l’incrocio tra propri ordini nel matching engine e dove inizia il divieto di wash trade previsto dalla legge.
La self-match prevention è una funzione del matching engine che impedisce a due ordini della stessa società di eseguire tra loro. Gli ordini ricevono un identificativo al momento dell’inserimento. Quando due ordini con lo stesso identificativo stanno per incrociarsi, il motore cancella uno dei due, oppure entrambi, prima che qualsiasi trade venga registrato. La self-match prevention è una funzione infrastrutturale della venue che si attiva, mentre il divieto di wash trade è previsto dalla legge. I due strumenti non coprono lo stesso ambito.
La regola si applica nel momento in cui una seconda strategia quota uno strumento già quotato dalla prima. Un grid bot a due livelli sullo stesso symbol è soggetto alla regola esattamente come un trading desk bancario.
Come funziona la self-match prevention nel matching engine
Ogni ordine ricevuto da una venue contiene campi che il motore legge prima del matching: direzione, prezzo, size e time in force. La self-match prevention ne aggiunge altri due. Il primo è un identificativo, un numero o una stringa che indica a quale società, account o gruppo di strategie appartiene l’ordine. Il secondo è un’istruzione che indica al motore cosa fare quando due ordini attivi con lo stesso identificativo stanno per eseguire tra loro.
Il controllo viene eseguito nel momento in cui un ordine aggressivo raggiunge il prezzo di un ordine resting con cui potrebbe abbinarsi. Sono comuni quattro esiti:
- Cancellazione dell’ordine resting. L’ordine in entrata continua nel book e può eseguire contro gli ordini successivi a quel prezzo.
- Cancellazione dell’ordine in entrata. L’ordine resting mantiene la propria posizione in coda e l’ordine aggressivo viene eliminato.
- Cancellazione di entrambi gli ordini, l’impostazione più severa.
- Decrement and cancel. L’ordine più grande viene ridotto della size dell’ordine più piccolo, quello più piccolo viene cancellato e la parte residua resta attiva.
In nessuno dei quattro casi avviene un trade. Nulla viene registrato sul tape, nulla entra in un fill log e arriva invece un unsolicited cancel su una delle due gambe, oppure su entrambe.
La posizione in coda è il costo meno evidente. Un ordine resting cancellato con un’istruzione cancel-oldest perde tutto il vantaggio accumulato durante l’attesa. Con la priorità prezzo-tempo la perdita è totale: reinserendo l’ordine, questo finisce dietro a tutti gli ordini entrati in coda mentre era presente. La nostra guida a come stimare la posizione in coda spiega quanto vale quella posizione.
Un solo strumento, molti book
Il controllo opera a livello di venue. Un motore confronta solo gli ordini presenti nel proprio book. Due ordini della stessa società resting in due book diversi sono invisibili l’uno all’altro e nessun meccanismo del mercato azionario statunitense opera tra i due. Una singola azione statunitense può essere quotata contemporaneamente su molti book. Il pannello seguente conta le venue distinte in cui sei nomi molto trattati hanno ricevuto quotazioni ed eseguito prints durante una finestra di quindici minuti nella mattina del 10 giugno 2026.
L'esatto SQL dietro ogni numero
SELECT
q.ticker AS ticker,
q.quoting_venues AS quoting_venues,
t.printing_venues AS printing_venues
FROM
(
SELECT
ticker,
countDistinct(bid_exchange) AS quoting_venues
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'SPY', 'KO', 'JNJ')
AND sip_timestamp >= toDateTime('2026-06-10 14:00:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 14:15:00', 'UTC')
AND bid_price > 0
GROUP BY ticker
) AS q
INNER JOIN
(
SELECT
ticker,
countDistinct(exchange) AS printing_venues
FROM global_markets.stocks_trades
WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'SPY', 'KO', 'JNJ')
AND sip_timestamp >= toDateTime('2026-06-10 14:00:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 14:15:00', 'UTC')
GROUP BY ticker
) AS t ON t.ticker = q.ticker
ORDER BY quoting_venues DESC, tickerAAPL ha ricevuto bid da 16 venue distinte in quell’intervallo di quindici minuti, e i prints sono stati eseguiti su 17 di esse. Il nome meno liquido del pannello ha comunque ricevuto quotazioni da 11 venue. Un smart order router che suddivide deliberatamente gli ordini child collocherà spesso le tue due strategie su book diversi, dove non si applica alcun controllo a livello di matching engine. Le società colmano questa lacuna upstream, nel livello di order management, prima che gli ordini escano dalla struttura. Anche i tuoi ordini resting su lati opposti e allo stesso prezzo in due book diversi producono un mercato locked o crossed, soggetto a regole proprie.
Quanti abbinamenti esegue un book in una sessione
Il controllo self-match è nel percorso di ogni matching eseguito dal motore. Su un nome liquido, quel percorso resta attivo per tutta la giornata. Il pannello seguente suddivide una sessione completa di un titolo in intervalli di quindici minuti e conta i prints in ciascuno, mantenendo gli intervalli che ne contengono almeno 200.
L'esatto SQL dietro ogni numero
SELECT
formatDateTime(toStartOfInterval(toTimeZone(sip_timestamp, 'America/New_York'), INTERVAL 15 MINUTE), '%H:%i') AS et_time,
count() AS trade_count
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= toDateTime('2026-06-10 08:00:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-11 04:00:00', 'UTC')
GROUP BY et_time
HAVING count() >= 200
ORDER BY et_timeAlle 04:00 ET quel nome ha registrato 9402 trade in quindici minuti. Alle 19:45 ET ne ha registrati 1345, su un totale di 64 intervalli che hanno superato la soglia di 200 prints. Ogni print è una coppia di ordini abbinati dal motore. Prima di consentire l’esecuzione, il controllo legge gli identificativi su entrambi i lati. Ogni ordine che resta nel book può quindi incontrare più avanti nella giornata un altro ordine dello stesso account.
Cosa mostra il tape quando viene registrato un self-trade
Un self-match bloccato non lascia traccia. Il tape contiene solo le esecuzioni. Ogni print arriva con condition flags, cioè codici che la venue di reporting associa al trade per descriverne le modalità di esecuzione. Il pannello seguente suddivide una sessione completa di un titolo in base a questi flags.
L'esatto SQL dietro ogni numero
SELECT
condition_name,
print_count,
round(100 * print_count / sum(print_count) OVER (), 2) AS share_pct
FROM
(
SELECT
cc.id AS condition_id,
any(cc.name) AS condition_name,
count() AS print_count
FROM
(
SELECT toInt32(arrayJoin(conditions)) AS condition_id
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= toDateTime('2026-06-10 08:00:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-11 04:00:00', 'UTC')
) AS f
INNER JOIN
(
SELECT
toInt32(id) AS id,
any(name) AS name
FROM global_markets.stocks_condition_codes
WHERE asset_class = 'stocks'
AND has(data_types, 'trade')
GROUP BY id
) AS cc ON cc.id = f.condition_id
GROUP BY condition_id
)
ORDER BY print_count DESC
LIMIT 10Odd Lot Trade rappresenta 48.34% dei prints con flags registrati nella sessione. Il pannello elenca i 10 flags più comuni della giornata. Leggendo l’elenco, si nota ciò che manca. Nessun codice indica che due ordini provenivano dalla stessa società. Un self-trade che viene eseguito appare come qualsiasi altro trade a quel prezzo. Per questo la sorveglianza si basa sul tape, sugli identificativi dei partecipanti conservati dalla venue e sui numeri di account associati agli ordini.
Dove termina la self-match prevention e dove inizia la normativa sui wash trade
La self-match prevention è un servizio della venue. Si sceglie di attivarlo, lo si configura e, se non lo si imposta, il motore abbina senza problemi i tuoi due ordini. Il divieto di wash trade non è facoltativo e non dipende da alcuna impostazione.
La Section 9(a)(1) del Securities Exchange Act del 1934 si applica alle operazioni su securities che non comportano un cambiamento della beneficial ownership e che vengono inserite per creare un’apparenza fuorviante di attività di trading. Il Commodity Exchange Act prevede l’equivalente per i futures e la CME Rule 534 lo ribadisce nel rulebook della borsa. La FINRA Rule 5210 si applica ai broker-dealer e il relativo supplementary material tratta direttamente i self-trade: le operazioni tra due algoritmi non correlati della stessa società non costituiscono di per sé una violazione, ma la società deve adottare policy per monitorarle e ridurle.
Per chi gestisce più di una strategia ne derivano due conseguenze. Un self-cross può violare il divieto su una venue nella quale non hai impostato alcuna istruzione di self-match, perché la regola si applica alla transazione e all’intento che la determina. Un self-cross bloccato dalla self-match prevention non viola alcuna norma: impedirlo è esattamente lo scopo della funzione.
Come la configurano gli operatori: CME, ICE, LME e MiFID II
Su CME Globex, la self-match prevention utilizza un identificativo trasmesso al momento dell’inserimento dell’ordine. Le società registrano gli identificativi che intendono usare, ogni ordine ne contiene uno e un’istruzione associata stabilisce quale lato il motore debba cancellare quando due ordini con lo stesso identificativo si incontrano. Gli ordini inviati senza identificativo vengono abbinati normalmente. È questa la trappola per un nuovo operatore: per default la funzione è disattivata.
ICE utilizza la Self-Trade Prevention Functionality, configurata in base all’identificativo della trading firm anziché per singolo ordine, con la stessa famiglia di esiti di cancellazione. La London Metal Exchange offre la Self-Execution Prevention su LMEselect per gli identificativi di trading dei membri. In Europa, l’Article 17 di MiFID II impone a ogni investment firm che svolga algorithmic trading di adottare sistemi e controlli adeguati, inclusi testing, kill functionality e prevenzione del trading disordinato. L’Article 48 impone un obbligo analogo alla venue. Gli strumenti di prevenzione lato venue sono diventati dotazioni standard.
La configurazione viene gestita a livello di account o società, non symbol per symbol. La dimensione della superficie di opzioni di un singolo sottostante spiega il motivo.
L'esatto SQL dietro ogni numero
SELECT
toString(date) AS session_date,
countDistinct(ticker) AS contracts_traded,
countDistinct(strike_price) AS strikes_traded
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND date >= '2026-06-01'
AND date <= '2026-06-30'
AND volume > 0
AND iv_converged = 1
GROUP BY date
ORDER BY dateSu 2026-06-01, un sottostante aveva 1579 contratti negoziabili distinti con volume, distribuiti su 112 strike. Il pannello copre 21 sessioni con una struttura simile. Impostare una regola contratto per contratto è impraticabile a quei livelli. L’identificativo viene invece associato all’account e accompagna ogni ordine inviato da quell’account.
Il problema che i tuoi fill log non spiegheranno
Ecco come si manifesta nella pratica. Un’istruzione cancel-newest elimina all’arrivo l’ordine appena inviato, prima che possa eseguire contro un ordine resting. Dal punto di vista del bot, la sequenza appare come un nuovo ordine seguito da una cancellazione che nessuno ha richiesto. Non ci sono fill, reject o error string che indichino il motivo. Per questo gli operatori che lo incontrano per la prima volta tendono a cercare un bug nel proprio percorso di cancellazione.
Due abitudini rendono il problema leggibile. Registra verbatim i messaggi di order status della venue invece di usare un riepilogo normalizzato, perché il motivo della prevenzione viene normalmente trasmesso in un campo di quel messaggio. Genera un alert per ogni cancellazione non originata dal tuo codice. L’alert deve rientrare nei tuoi circuit breaker per il trading automatizzato, perché il problema appartiene alla stessa classe: la venue ha modificato lo stato dell’ordine, mentre il processo ha continuato a comportarsi come se non fosse successo nulla.
FAQ
Che cos’è la self-match prevention?
È un controllo del matching engine che impedisce a due ordini con lo stesso identificativo di società o account di eseguire tra loro. Quando gli ordini stanno per essere abbinati, il motore cancella l’ordine resting, quello in entrata o entrambi, in base all’istruzione associata all’ordine.
Un self-trade è la stessa cosa di un wash trade?
No. Un self-trade è qualsiasi esecuzione tra due ordini dello stesso beneficial owner. Un wash trade è un self-trade inserito senza assumere un reale rischio di mercato e con l’intento di creare un’apparenza fuorviante di attività. I self-trade non intenzionali tra algoritmi non correlati sono trattati diversamente da quelli organizzati. Le società devono comunque monitorarli.
La self-match prevention funziona tra exchange diversi?
No. Ogni matching engine applica il controllo solo agli ordini presenti nel proprio book. Due ordini della stessa società resting su due venue possono eseguire tra loro. Il controllo deve quindi essere svolto dalla società stessa, tramite i propri controlli pre-trade a monte delle venue.
Perché il mio ordine è stato cancellato senza fill e senza motivo?
Un’istruzione self-match cancel-newest è una possibile causa. La venue ha cancellato l’ordine all’arrivo, prima che potesse eseguire contro un ordine resting con il tuo identificativo. Il motivo compare di norma in un campo del messaggio di cancellazione della venue, non in un messaggio di rejection.
Quali venue richiedono un identificativo di self-match prevention?
I requisiti variano in base alla venue e al prodotto. CME richiede un identificativo al momento dell’inserimento dell’ordine, registrato in anticipo. ICE e la London Metal Exchange offrono configurazioni proprie a livello di società. Le venue europee sono inoltre soggette agli obblighi relativi a sistemi e controlli previsti da MiFID II. Fa fede il rulebook della venue per il prodotto trattato.
Ogni pannello contiene il codice SQL che lo ha prodotto. Espandilo e leggilo. Per contare le venue che quotano un nome che tratti, oppure per suddividere una sessione in base ai condition flags, formula la domanda in inglese semplice sul terminale Strasmore.