If you've ever built a dashboard on top of crypto market data, you've probably sorted something by 24-hour volume. It's the default "is anyone actually using this?" signal. The uncomfortable part is that volume is one of the easiest numbers in crypto to fake.
The technique is called wash trading: one person or group trades with themselves, again and again, so a market looks busy. No ownership really changes hands. If you treat volume as ground truth in your app, scanner, or trading bot, you are ingesting manipulated data.
This post looks at wash trading the way a developer would: as a data quality problem you can partly detect.
What wash trading actually is
The CFTC describes wash trades as trades made to give the appearance of buying and selling without taking on market risk or changing the trader's position. You're on both sides, so nothing really happens except fees and a bigger volume number.
A toy version: a team controls Wallet A and Wallet B. A sells 100,000 tokens to B, then B sells them back a few seconds later. A bot loops that a couple of thousand times a day and the token suddenly "trades" tens of millions of dollars. The team still holds the same coins.
Why bother? Higher volume moves a token up trending and top-volume lists, can help with exchange listings, sets up pump-and-dumps, inflates exchange rankings, and farms volume-based rewards or airdrop points.
For the full breakdown of motives, real enforcement cases, and the legal side, see this plain-English guide to crypto wash trading and fake volume.
CEX vs DEX: different plumbing, same trick
On a centralized exchange, the manipulator uses multiple accounts or a market maker's bot to place matching buy and sell orders. You only see the exchange's reported numbers, so you're trusting their data feed.
On a DEX, every trade is on-chain and costs gas, which makes faking volume more expensive but not impossible. A common pattern is one controller wallet funding many fresh wallets, which then trade in the same pool so activity looks spread out.
One caution for anyone writing detection code: fast back-and-forth trading is not automatically wash trading. Arbitrage and MEV bots also hammer the same pairs within seconds, for legitimate (if competitive) reasons. That's why external heuristics produce red flags, not verdicts.
A quick red-flag check in Python
Here's a small script using CoinGecko's public API. It doesn't prove anything; it flags tokens where the numbers don't hang together.
import json
import urllib.request
def get(url):
req = urllib.request.Request(url, headers={"accept": "application/json"})
with urllib.request.urlopen(req, timeout=20) as r:
return json.load(r)
def red_flags(coin_id):
data = get(f"https://api.coingecko.com/api/v3/coins/{coin_id}"
"?localization=false&tickers=true&community_data=false&developer_data=false")
md = data["market_data"]
vol = md["total_volume"].get("usd") or 0
mcap = md["market_cap"].get("usd") or 0
flags = []
# 1. Volume far larger than the whole market cap
if mcap and vol / mcap > 1:
flags.append(f"24h volume is {vol / mcap:.1f}x market cap")
# 2. Volume concentrated on one venue
tickers = data.get("tickers", [])
by_venue = {}
for t in tickers:
name = t["market"]["name"]
by_venue[name] = by_venue.get(name, 0) + (t.get("converted_volume", {}).get("usd") or 0)
total = sum(by_venue.values())
if total:
top_venue, top_vol = max(by_venue.items(), key=lambda kv: kv[1])
if top_vol / total > 0.8:
flags.append(f"{top_vol / total:.0%} of ticker volume on {top_venue}")
return flags
if __name__ == "__main__":
for coin in ["bitcoin", "ethereum"]:
print(coin, red_flags(coin) or "no obvious red flags")
Swap in any CoinGecko coin ID. Note that the tickers list is paginated and the free API is rate-limited, so treat this as a sketch, not a production monitor.
The two checks mirror classic warning signs, and a third is worth doing by eye:
- Volume vs market cap. A small token trading several times its entire value daily, with few holders, deserves suspicion.
- Venue concentration. If nearly all activity sits on one small exchange and big regulated venues show little, the "demand" may not be real.
- Pair trust scores. CoinGecko's Trust Score on its website looks at things like spread, order book depth and trade patterns. In my testing the free API returned no trust score on tickers, so check it on the coin's markets page. Lots of volume on red or unrated pairs is worth noticing.
Other checks worth adding if you go further: compare volume to ±2% order book depth, look for volume spikes with no price movement, and on DEXs, cluster wallets by common funding source.
Don't confuse it with the wash sale rule
Different thing entirely. A wash sale is a tax rule about claiming a loss and rebuying within 30 days. If you're scripting tax tooling, that's a separate rabbit hole.
Takeaways
- Treat reported crypto volume as untrusted input, especially for small tokens on small venues.
- Combine several heuristics; no single one proves wash trading.
- Don't flag arbitrage and MEV activity as manipulation by default.
- Regulated, larger venues tend to show much cleaner data.
- If your product ranks or alerts on volume, show users the caveats.
Read the full guide on NutshellCrypto
This is educational content, not financial advice.
This post was written with AI assistance.
Top comments (0)