Sniffing Algorithm in Trading: What It Is and How It Works
A sniffing algorithm in trading is an informal label for software that detects other participants' orders or footprints, such as hidden parent orders or institutional flow, and trades in response. It is not a formal technique.
- 'Sniffing' and 'stalking' are loose labels covering two different jobs: finding hidden parent orders, and labelling flow as institutional.
- Detection needs tick-by-tick trades with aggressor side and at least L2 depth; MBO/L3 is far better, and daily OHLCV cannot show any of it.
- Size thresholds undercount institutions because parent orders are sliced into small child orders and much volume prints off-exchange.
- Institutional share of volume can only be bracketed with biased proxies (size buckets, signed volume, VPIN, FINRA ATS data), never measured exactly.
- Validate any detector against your own known parent orders, with strict time ordering, and report precision and recall rather than anecdotes.
What is a sniffing algorithm in trading?
"Sniffing" or "stalking" appears in popular lists of high-frequency or predatory strategies, but it is not a standard term in market microstructure papers or exchange rulebooks. Definitions conflict because the label is applied to two different engineering problems. Both are partly right: the software looks for other participants' footprints and reacts.
A sniffing algorithm in trading is therefore best read as a description of intent, not a specific model. Always ask which of the two meanings below the author has in mind.
| Meaning | What is detected | Typical data | Typical output |
|---|---|---|---|
| 1. Parent order detection | A large hidden order being worked by an execution algo (VWAP, TWAP, POV, iceberg) | L2/L3 order book events plus tick trades with aggressor side | Probability that a repeating pattern at a price level is one parent order, and its likely side |
| 2. Smart money / institutional flow | Net buying or selling pressure attributed to large participants | Tick trades, trade size, venue and condition codes, sometimes weekly ATS data | Signed volume, imbalance score, estimated institutional share |
How do algorithms detect institutional orders?
Detection works because execution algos must leave regular traces. To buy 500,000 shares without moving the price, the algo breaks the order into child orders, and those children obey rules about size, timing and price.
The table lists the main techniques, what each needs, and where it fails.
| Technique | How it works | Data needed | Main false positive |
|---|---|---|---|
| Pinging | Send tiny IOC (immediate-or-cancel) orders at or inside the spread; a fill reveals hidden liquidity | Order entry access, very low latency | Midpoint pegged orders from unrelated participants |
| Iceberg refill detection | A visible quantity at one price is executed, then the same price level shows a new quantity at once | L3/MBO, or L2 plus trades | Market makers re-quoting at a popular price |
| Repeated child size | Many prints or orders of identical size (for example 200 shares) at the same side | Tick trades with side | Round-lot habits of retail flow |
| Regular time slicing | Near-constant gaps between child orders (low coefficient of variation of inter-arrival time) | Timestamps with millisecond or better precision | Periodic data feed batching or auction timers |
| Quote/trade imbalance | Persistent one-sided executions while the quote stays stable | L2 quotes plus trades | Genuine news-driven directional flow |
What do execution algo footprints look like, and how are they classified?
Each common execution style has a distinct signature in time and size. The signature is what a classifier tries to match.
The usual tools are simple. Hand-built features (inter-arrival time variance, size entropy, share of volume per interval) feed a gradient-boosted or logistic classifier. A change-point model or hidden Markov model with states such as "quiet", "algo active" and "algo inactive" then smooths the output so that one odd print does not toggle the flag.
Fourier or wavelet decomposition can expose periodic slicing, and it is occasionally used for TWAP-like patterns. It is not the usual tool, because real schedules are jittered and the volume curve for VWAP is not periodic, so features plus a state model are easier to build and to explain.
| Algo type | Signature | Feature to compute |
|---|---|---|
| TWAP | Constant-interval slices of similar size | Coefficient of variation of inter-arrival times; size variance |
| VWAP | Participation follows the historical intraday volume curve (heavier at open and close) | Correlation of the trader's slice size with the average volume profile |
| POV | Fixed percent of market volume (for example 10%), so child size scales with tape activity | Rolling ratio of one side's volume to total volume; low variance of that ratio |
| Iceberg | Fixed displayed size that refills at the same price | Count of refills per price level after full execution |
How do I estimate institutional share of daily volume?
No public source gives an exact figure, because trades do not carry an "institution" flag. You can only bracket the answer with proxies, and each proxy is biased in a known direction.
Treat the result as a range, and say which proxy produced which bound.
| Proxy | What it measures | Bias |
|---|---|---|
| Trade-size buckets (for example prints of 10,000 shares or more) | Volume in large prints | Undercounts: institutions slice orders; also counts large non-institutional trades. The threshold is a convention, not a rule |
| Trade-size distribution | Shape change in the share of volume by size bucket over time | Reflects market-wide fragmentation trends as well as institutions |
| Tick rule / Lee-Ready | Assigns buy or sell to each trade, giving signed volume | Misclassifies at the midpoint, in fast markets and when quotes lag trades |
| VPIN / order flow imbalance | Average absolute buy-sell imbalance across equal-volume buckets | Shows imbalance, not who caused it; sensitive to bucket size and classification method |
| FINRA ATS weekly data | Shares and trades per symbol per dark pool ATS | Published with a delay, aggregated weekly, no side, and ATS volume is not the same as institutional volume |
Why do trade-size thresholds undercount institutions?
A single 1,000,000 share parent order may execute as thousands of 100 to 300 share child orders. A rule such as "flag prints above 10,000 shares" never sees it.
Venue matters too. Roughly 40 to 50 percent of US equity volume prints off-exchange, reported through a trade reporting facility (TRF) and tagged with a TRF venue code. Those prints can arrive with a different time stamp from the actual execution, so ordering against exchange quotes is imperfect.
Lot conventions add noise. Odd lots (fewer than a round lot, historically 100 shares) were once excluded from some consolidated data and condition codes mark them in many feeds. The definition of a round lot has also changed for higher-priced stocks, so avoid hardcoding 100. Filter by the sale condition codes that your vendor documents for odd lots, late reports, derivatively priced and out-of-sequence trades before computing anything.
A minimal Python example: classify trades and flag slicing
The script assumes a DataFrame with columns ts (datetime64), price, size, and optionally a quotes DataFrame with ts, bid, ask. It classifies trades, builds size buckets and signed volume, then flags runs of equal-sized same-side prints with regular spacing. Timestamps must all be in one timezone, ideally UTC, before you start.
import numpy as np
import pandas as pd
def tick_rule(trades):
d = trades["price"].diff()
side = np.sign(d).replace(0, np.nan).ffill().fillna(0)
return side.astype(int)
def lee_ready(trades, quotes, lag="0ms"):
t = trades.sort_values("ts")
q = quotes.sort_values("ts").copy()
q["ts"] = q["ts"] + pd.Timedelta(lag)
m = pd.merge_asof(t, q[["ts", "bid", "ask"]], on="ts")
mid = (m["bid"] + m["ask"]) / 2
side = np.where(m["price"] > mid, 1, np.where(m["price"] < mid, -1, 0))
tick = tick_rule(t).to_numpy()
return pd.Series(np.where(side == 0, tick, side), index=t.index)
def add_features(trades):
df = trades.sort_values("ts").copy()
df["side"] = tick_rule(df)
df["signed_vol"] = df["side"] * df["size"]
df["bucket"] = pd.cut(df["size"], [0, 99, 499, 999, 9999, np.inf],
labels=["odd", "100-499", "500-999", "1k-9.9k", "10k+"])
return df
def flag_slices(df, min_run=8, max_gap_s=30, cv_max=0.3):
out = []
for (size, side), g in df[df["side"] != 0].groupby(["size", "side"]):
if len(g) < min_run:
continue
dt = g["ts"].diff().dt.total_seconds()
run = (dt.isna() | (dt > max_gap_s)).cumsum()
for _, r in g.groupby(run):
gaps = r["ts"].diff().dt.total_seconds().dropna()
if len(r) >= min_run and gaps.mean() > 0:
cv = gaps.std() / gaps.mean()
if cv <= cv_max:
out.append({"size": size, "side": side, "n": len(r),
"start": r["ts"].iloc[0], "end": r["ts"].iloc[-1],
"cv": round(cv, 3)})
return pd.DataFrame(out)
# trades = pd.read_parquet("ticks.parquet") # cleaned: condition codes filtered
# df = add_features(trades)
# print(df.groupby("bucket", observed=True)["size"].sum() / df["size"].sum())
# print(flag_slices(df))How do institutions defend against detection, and what are the practical limits?
Execution algos are built with anti-gaming logic, which is why detection is noisy. Child sizes and release times are randomised, often around a mean with a configurable jitter. Orders carry a minimum quantity so that tiny probes cannot fill them. Flow is routed to dark pools and midpoint venues, and algos pause or switch venues when they see signs of pinging, such as many small fills followed by adverse price movement.
Practical reality is also a barrier. Genuine pinging competes at microsecond to millisecond latency and generally needs colocation, direct exchange feeds and venue-specific order types. A retail connection over the internet, with a broker API that rate-limits orders and reports fills asynchronously, cannot do it. Even passive pattern detection on a delayed feed will see the pattern after the price has moved.
The compliance boundary is simple to state. Reading public data is analysis. Sending orders to manipulate or provoke, or placing orders you do not intend to execute, is where spoofing, layering and quote stuffing rules apply. Have compliance review any design that places orders in order to learn something.
How do I validate a detector, and what mistakes should I avoid?
Validation needs ground truth. The cleanest source is your own executions: run known TWAP, VWAP or POV parent orders (in a paper or small live account, within your broker's terms), record parent and child order IDs, and treat those as labels. Then check whether the detector finds your orders in the public tape.
- Split data by time, never at random: train on earlier days, test on later days, and fit every threshold only on the training period.
- Build features using only data with timestamps before the decision time, accounting for the trade-reporting delay of off-exchange prints.
- Label each window as parent-active or not, using your own order logs.
- Measure precision (flagged windows that were real) and recall (real windows that were flagged), and report both with the base rate of active windows.
- Report results by symbol liquidity tier, because performance on a large cap rarely carries over to a thin stock.
- Include fees, slippage and the latency you actually have before claiming any downstream use.
Common questions
What is a stalking algorithm in high frequency trading?
It is another informal name for the same idea as sniffing: software that follows another participant's footprint, such as a large order being worked in slices, and positions around it. It is not a formal strategy class, and the term mostly appears in educational lists rather than in regulation or research.
How do I detect an iceberg order?
With L3/MBO data, look for a price level whose displayed quantity is fully executed and then reappears at the same price almost immediately, repeatedly. With L2 only, count trades at a price that exceed the displayed size, since the excess must have come from hidden quantity. Both can be confused by market makers re-quoting.
Can daily OHLCV data show smart money?
No. Daily bars collapse trade size, timing, venue and aggressor side, which are the features used to identify slicing and imbalance. Volume relative to its average can show unusual activity, but it cannot show who caused it or in what direction.
Is Lee-Ready or the tick rule more accurate?
Lee-Ready is generally better when you have quotes timestamped accurately, because it compares the price with the prevailing midpoint and falls back to the tick rule only at the midpoint. The tick rule is the fallback when you have trades only. Both degrade when quote and trade timestamps are misaligned, so test a small lag adjustment.
Does FINRA dark pool data tell me what institutions are doing?
No. The ATS transparency data shows weekly volume per venue and symbol, published with a delay, without trade direction or participant type. It helps estimate how much volume trades away from lit exchanges, which is one input into a share estimate, not a measure of institutional activity.