Skip to content

Pair Selector

The pair selector automatically picks which trading pairs your bot trades. Instead of manually listing pairs in your config, the selector filters and ranks all available pairs on the exchange based on volume, price momentum, and other metrics — then subscribes to the top ones.

This means your bot always trades the most active or fastest-moving pairs without manual intervention.

How It Works

The pair selector runs a three-step pipeline:

All exchange pairs
  → Filter (remove pairs that don't meet criteria)
  → Sort (rank remaining pairs by a metric)
  → Limit (take the top N)
  → Bot trades these pairs

This pipeline runs periodically (configurable interval). When the selected pairs change, the bot automatically stops trading pairs that dropped off the list and starts trading newly selected pairs.

Pairs with open positions are always preserved — they stay active even if they no longer meet the filter criteria. The bot won't abandon a position just because volume dropped.

Enabling Pair Selection

Add a pairSelector object to your strategy parameters:

json
{
  "pairSelector": {
    "minVolume24h": 5000000,
    "sortBy": "volume24h",
    "sortDesc": true,
    "maxPairs": 10,
    "updateIntervalSecs": 300
  }
}

If no pairSelector key is present, the bot trades the pairs listed in your config file as usual.

Filtering

Filters remove pairs that don't meet your criteria. All filters are optional — only set the ones you care about. Pairs must pass all active filters to be selected.

Whitelist and Blacklist

ParameterTypeDefaultDescription
whiteliststring[][]Only consider these pairs. Empty = all pairs
blackliststring[][]Exclude these pairs. Applied after whitelist

If whitelist is non-empty, only those pairs are considered. Blacklist is then applied on top.

All pairs: BTCUSDT, ETHUSDT, SOLUSDT, DOGEUSDT, XRPUSDT

whitelist: ["BTCUSDT", "ETHUSDT", "SOLUSDT"]
  → only BTCUSDT, ETHUSDT, SOLUSDT considered

blacklist: ["SOLUSDT"]
  → SOLUSDT removed

Result: BTCUSDT, ETHUSDT

If whitelist is empty, all pairs on the exchange are considered (minus blacklisted ones).

Volume Filter

ParameterTypeDefaultDescription
minVolume24hUSDnoneMinimum 24-hour quote volume
maxVolume24hUSDnoneMaximum 24-hour quote volume

Quote volume is the total USD value traded in the last 24 hours. Use minVolume24h to skip low-liquidity pairs.

minVolume24h: 5000000  ($5M daily volume minimum)

  BTCUSDT   volume: $2.1B  →  passes
  ETHUSDT   volume: $890M  →  passes
  XYZUSDT   volume: $1.2M  →  filtered out (below $5M)

Price Change Filter

ParameterTypeDefaultDescription
minPriceChangePctpercentnoneMinimum 24-hour price change %
maxPriceChangePctpercentnoneMaximum 24-hour price change %

Use these to filter by daily price movement. For example, skip pairs that barely moved or that pumped/dumped too hard.

minPriceChangePct: -5.0
maxPriceChangePct: 5.0

  BTCUSDT   change: +1.2%   →  passes
  ETHUSDT   change: -3.8%   →  passes
  DOGEUSDT  change: +12.4%  →  filtered out (above +5%)
  XYZUSDT   change: -8.1%   →  filtered out (below -5%)

Momentum Delta Filters

Delta filters measure short-term price momentum — how much a pair's price moved in the last 1 minute, 5 minutes, 15 minutes, 1 hour, 2 hours, or 3 hours.

ParameterTypeDefaultDescription
minDelta1m / maxDelta1mpercentnone1-minute price change %
minDelta5m / maxDelta5mpercentnone5-minute price change %
minDelta15m / maxDelta15mpercentnone15-minute price change %
minDelta1h / maxDelta1hpercentnone1-hour price change %
minDelta2h / maxDelta2hpercentnone2-hour price change %
minDelta3h / maxDelta3hpercentnone3-hour price change %

Deltas are calculated as: ((current_price - price_N_ago) / price_N_ago) * 100

minDelta5m: 0.1  (only pairs that moved up at least 0.1% in last 5 min)

  BTCUSDT   5m delta: +0.3%  →  passes
  ETHUSDT   5m delta: -0.1%  →  filtered out (negative, below +0.1%)
  SOLUSDT   5m delta: +0.05% →  filtered out (below +0.1%)

Pairs without enough price history for a delta timeframe are excluded if that filter is active.

Sorting

After filtering, remaining pairs are sorted by a metric. The sort determines which pairs end up in your top-N list.

ParameterTypeDefaultDescription
sortBystring"volume24h"Metric to sort by (see table below)
sortDescbooleantrueSort order. true = highest first

Sort Metrics

ValueDescription
volume24h24-hour quote volume (default — trades the most liquid pairs)
delta1m1-minute price momentum
delta5m5-minute price momentum
delta15m15-minute price momentum
delta1h1-hour price momentum
delta2h2-hour price momentum
delta3h3-hour price momentum
sortBy: "delta5m", sortDesc: true

  SOLUSDT   5m delta: +1.2%  →  rank 1
  BTCUSDT   5m delta: +0.3%  →  rank 2
  ETHUSDT   5m delta: +0.1%  →  rank 3

Limiting

After sorting, take the top N pairs.

ParameterTypeDefaultDescription
maxPairsnumbernoneMaximum pairs to trade. No limit if unset
maxPairs: 5
Sorted pairs: SOL, BTC, ETH, DOGE, XRP, AVAX, MATIC, ...
  → Bot trades: SOL, BTC, ETH, DOGE, XRP (top 5 only)

Update Interval

The selector re-evaluates pairs on a schedule.

ParameterTypeDefaultDescription
updateIntervalSecsseconds0How often to re-run the selection pipeline. 0 = only on startup

Each update cycle:

  1. Fetches fresh 24-hour statistics from the exchange
  2. Updates 1-minute kline data for momentum deltas
  3. Runs the filter → sort → limit pipeline
  4. Compares new list with current list
  5. Stops tasks for removed pairs (unless they have open positions)
  6. Starts tasks for newly added pairs
updateIntervalSecs: 300 (every 5 minutes)

  14:00  selected: BTC, ETH, SOL, DOGE, XRP
  14:05  re-evaluate → SOL dropped (volume fell), AVAX added
         selected: BTC, ETH, AVAX, DOGE, XRP
         → SOL task stopped (if no open positions), AVAX task started

Momentum Data Collection

The pair selector uses a metrics collector that maintains a rolling 3-hour window of 1-minute price data for each pair. This data powers the delta calculations.

On startup:

  1. Loads 180 one-minute candles (3 hours of history) per pair from the exchange
  2. Calculates all 6 delta timeframes from the loaded history

On each update cycle:

  1. Fetches new kline data since last update
  2. Prunes entries older than 3 hours
  3. Recalculates deltas

Pairs new to the exchange (or with very recent listings) may not have enough data for longer delta timeframes. Those deltas will be None, and any active filter for that timeframe will exclude the pair.

Preserved Pairs

Pairs with open positions are always included in the selected list, even if they no longer meet any filter criteria. This prevents the bot from orphaning positions.

maxPairs: 3, minVolume24h: 10M

Current positions: DOGEUSDT (open long)
Filter results: BTC, ETH, SOL (DOGE didn't pass volume filter)

Final selected: BTC, ETH, SOL, DOGE
  → DOGE kept because it has an open position
  → Once the position closes, DOGE will be dropped on next update

Examples

High-Volume Trader

Trade the top 10 most liquid pairs, re-evaluated every 5 minutes:

json
{
  "pairSelector": {
    "minVolume24h": 10000000,
    "sortBy": "volume24h",
    "sortDesc": true,
    "maxPairs": 10,
    "updateIntervalSecs": 300
  }
}

Momentum Chaser

Trade the top 5 pairs with the strongest 5-minute momentum, skip extreme movers:

json
{
  "pairSelector": {
    "minVolume24h": 5000000,
    "minDelta5m": 0.1,
    "maxDelta5m": 5.0,
    "minPriceChangePct": -10.0,
    "maxPriceChangePct": 10.0,
    "sortBy": "delta5m",
    "sortDesc": true,
    "maxPairs": 5,
    "updateIntervalSecs": 60
  }
}

Curated List with Filters

Only trade from a fixed list of pairs, but still apply momentum filters:

json
{
  "pairSelector": {
    "whitelist": ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT"],
    "minDelta15m": 0.05,
    "sortBy": "delta15m",
    "sortDesc": true,
    "updateIntervalSecs": 120
  }
}

All Parameters

ParameterTypeDefaultDescription
whiteliststring[][]Only consider these pairs. Empty = all
blackliststring[][]Exclude these pairs
minVolume24hUSDnoneMinimum 24h quote volume
maxVolume24hUSDnoneMaximum 24h quote volume
minPriceChangePctpercentnoneMinimum 24h price change %
maxPriceChangePctpercentnoneMaximum 24h price change %
minDelta1m / maxDelta1mpercentnone1-minute momentum range
minDelta5m / maxDelta5mpercentnone5-minute momentum range
minDelta15m / maxDelta15mpercentnone15-minute momentum range
minDelta1h / maxDelta1hpercentnone1-hour momentum range
minDelta2h / maxDelta2hpercentnone2-hour momentum range
minDelta3h / maxDelta3hpercentnone3-hour momentum range
sortBystring"volume24h"Sort metric: volume24h, delta1m, delta5m, delta15m, delta1h, delta2h, delta3h
sortDescbooleantrueSort descending (highest first)
maxPairsnumbernoneMaximum pairs to select
updateIntervalSecsseconds0Re-evaluation interval. 0 = startup only

tradectl — Automate Crypto Trading