Opportunity Scanner
What it does
Watches for unusually large long-liquidation cascades on eligible symbols. When the market setup passes all safety gates, it opens a new hedge-mode grid using your configured long and short seed sizes, then manages the position with a frozen hard stop and a frozen profit target.
The Opportunity Scanner is separate from your normal manually configured pairs. It only acts on symbols from the admin-approved scanner universe, and it only opens a scanner position when a liquidation event is both large enough and unusual enough for that symbol.
Your settings live in the
opportunityScanner block in Strategy Config. The /dashboard/opportunity-scanner page is observability only.For all config fields, see Config Reference → Opportunity Scanner.
How it works
Every scanner entry follows the same flow:
- Detect a long-liquidation cascade on a qualifying symbol.
- Check all safety gates: BTC regime, universe membership, allow/block lists, cooldown, concurrency cap, and pump guard.
- Open a hedge-mode seed with your configured
seedLongUsdandseedShortUsd. - Freeze the stop and profit thresholds at entry.
- Hold until either the hard stop or the time-gated profit take triggers.
The scanner does not add to an existing manual pair. If you already have that symbol configured in your normal grid config, the scanner skips it.
Detection logic
The scanner looks at long liquidations over a rolling time window.
It needs both of these to be true:
- Total long liquidation value inside the window is at least
cascadeThresholdUsd - The event is statistically unusual enough to meet
cascadeMinZScore
The default window is 10 minutes. After a symbol triggers,
cascadeDedupMs prevents it from retriggering again immediately.Safety gates
Even if a cascade is detected, the scanner still rejects the symbol unless all gates pass.
| Gate | What it checks |
|---|---|
| BTC regime | BTC must be in a ranging state, not a high-momentum move |
| Universe | Symbol must be in the admin-approved scanner universe |
| Allow / block lists | Your personal include and exclude lists |
| Pair conflict | Scanner will not open a symbol you already configured manually |
| Cooldown | Recently exited symbols are blocked until cooldownHours passes |
| Concurrency cap | Total open scanner positions must stay below maxConcurrentPositions |
| Pump guard | Rejects symbols still too extended on the 24h view |
This is why "cascade detected" does not always mean "position opened".
BTC regime details:
the scanner requires
abs(BTC 1h move) < 1.5%, abs(BTC 4h move) < 3%, and
15 minute BTC realized volatility only blocks entries when it is both in the
top decile of its trailing 7 day distribution and at least 0.10 percentage
points in absolute terms. That absolute floor keeps quiet-week noise from
tripping the regime gate.Tier system
The tier system lets you use different detection thresholds for high-liquidity and low-liquidity symbols.
Why this matters:
- A $750k liquidation event can be a major flush on a smaller coin
- The same $750k can be routine noise on a very large coin
cascadeTiers solves this by picking thresholds from the symbol's 24h turnover.Each tier has three fields:
| Field | Meaning |
|---|---|
minTurnover24hUsd | Minimum 24h turnover needed for the tier to apply |
cascadeThresholdUsd | Minimum liquidation value required for detection |
cascadeMinZScore | Minimum statistical abnormality required |
How the picker works:
- The bot looks at the symbol's 24h turnover
- It finds the highest matching tier where
turnover24hUsd >= minTurnover24hUsd - That tier overrides the top-level
cascadeThresholdUsdandcascadeMinZScore - If no tier metadata is available, the bot falls back to the top-level values
Worked example: tier selection
Using this tier table:
| Tier | minTurnover24hUsd | cascadeThresholdUsd | cascadeMinZScore |
|---|---|---|---|
| Very high liquidity | 5,000,000,000 | 5,000,000 | 3.0 |
| High liquidity | 1,000,000,000 | 2,000,000 | 3.0 |
| Medium liquidity | 200,000,000 | 1,500,000 | 3.0 |
| Low liquidity | 50,000,000 | 1,000,000 | 3.5 |
| Small liquidity | 0 | 750,000 | 4.0 |
Example symbol resolution:
| Symbol | 24h turnover | Chosen tier | Threshold used | Z-score used |
|---|---|---|---|---|
| BTC-sized symbol | $7.2B | Very high liquidity | $5.0M | 3.0 |
| Mid-liquidity alt | $320M | Medium liquidity | $1.5M | 3.0 |
| Small alt | $18M | Small liquidity | $750k | 4.0 |
This keeps the scanner strict on small noisy symbols while still demanding a meaningful liquidation event on the largest markets.
Worked example: entry and exits
Settings:
| Field | Value |
|---|---|
seedLongUsd | $300 |
seedShortUsd | $100 |
hardStop | percent_net: -10 |
profitTake | percent_net: 10 |
profitTakeMinAgeHours | 1 |
At entry:
| Calculation | Result |
|---|---|
| Net exposure | $300 - $100 = $200 |
| Hard stop | -10% of $200 = -$20 |
| Profit take | +10% of $200 = +$20 |
What that means:
- If total PnL falls to
-$20or worse, the scanner exits immediately - If total PnL reaches
+$20before 1 hour, it does not exit yet - Once the position is at least 1 hour old,
+$20or better triggers the profit-take exit
Recommended starting point
For most users, this is a sensible starting setup:
| Setting | Recommended value | Why |
|---|---|---|
maxConcurrentPositions | 3 to 5 | Limits how many scanner trades can stack at once |
seedLongUsd / seedShortUsd | Start with a modest gap, such as $300 / $100 | Keeps the thesis directional without making one entry too large |
hardStop | percent_net: -10 | Simple risk cap tied to the actual entry size |
profitTake | percent_net: 10 | Symmetric exit target, easy to reason about |
profitTakeMinAgeHours | 1 | Avoids immediately closing a noisy bounce |
cascadeWindowMs | 600000 | Good default for spotting real flushes without being too slow |
cooldownHours | 1 | Prevents immediate re-entry on the same symbol |
pumpGuard.enabled | true | Good protection against late pump-and-dump reversals |
Recommended tier table:
| Liquidity bucket | Threshold | Z-score |
|---|---|---|
>= $5B turnover | $5.0M | 3.0 |
>= $1B turnover | $2.0M | 3.0 |
>= $200M turnover | $1.5M | 3.0 |
>= $50M turnover | $1.0M | 3.5 |
< $50M turnover | $750k | 4.0 |
Why I recommend this shape:
- Large markets need larger raw liquidation values before the move is meaningful
- Small markets need a higher z-score to avoid noisy false positives
- The lowest tier still allows smaller symbols to qualify, but only if the move is clearly abnormal
When to adjust the tiers
| If you want... | Change |
|---|---|
| Fewer trades overall | Raise cascadeThresholdUsd, raise cascadeMinZScore, or lower maxConcurrentPositions |
| More large-cap focus | Raise the low-liquidity thresholds or remove weaker low tiers |
| More small-cap participation | Lower the bottom-tier threshold slightly, but keep the z-score strict |
| Less pump-chasing | Keep pumpGuard on and consider tightening maxPrice24hPct |
| Faster symbol recycling | Lower cooldownHours carefully |
Troubleshooting
| Symptom | Likely cause |
|---|---|
| No scanner trades open | Feature disabled, warm-up still building baseline, or gates are rejecting all symbols |
| A liquidation spike did not open a trade | The symbol failed regime, universe, cooldown, concurrency, or pump-guard checks |
| The scanner never touches a symbol you trade manually | This is expected. Pair conflict protection blocks it |
| Profit target hit but no exit happened | The position was still younger than profitTakeMinAgeHours |
| Config changes do not affect a running bot | Scanner config is restart-scoped |