Skip to main content
Ultra Feature. Requires an Ultra subscription. Get started at api.mathematicalcompany.com

Wallet Signals

Unified entry point for tracking wallets and extracting directional signals. Combines wallet scoring, position analysis, trade flow, and behavioral profiling into a single actionable signal per wallet per market.

Track Wallet

Given a wallet, compute signals for every market it holds.

Consensus

Aggregate top holders into a weighted directional signal.

Auto-Discover

Find high-signal wallets in a target market automatically.

Quick Start

Mode 1: Track a Wallet

import horizon as hz

signals = hz.track_wallet("0x1234...")
for s in signals:
    print(f"{s.market_id[:12]} signal={s.signal:.4f} regime={s.regime}")

Mode 2: Market Consensus

consensus = hz.compute_consensus("0xcondition...", market_price=0.65)
print(f"Signal: {consensus.signal:.4f}")
print(f"Agreement: {consensus.agreement:.2f}")
print(f"Wallets: {consensus.n_wallets}")

Mode 3: Auto-Discover

consensus = hz.scan_wallets(market_id="0xcondition...")
if consensus.is_actionable:
    print(f"Edge: {consensus.edge_bps:.0f} bps")

Pipeline Integration

hz.run(
    markets=[market],
    pipeline=[
        hz.wallet_tracker(wallets=["0xaaa...", "0xbbb..."]),
        my_quoter,
    ],
)

# In your quoter:
def my_quoter(ctx):
    sig = ctx.params.get("wallet_tracker_signal")
    if sig and sig.is_actionable:
        # Use sig.signal as directional bias
        ...

Signal Math

Each per-wallet signal is a 4-component decomposition:

Direction D(w,m)

Net position direction from wallet positions. YES positions contribute +1, NO contributes -1, size-weighted.
net = sum(size_i * direction_i) / total_size
D = (net + 1) / 2    # maps [-1, 1] to [0, 1]

Conviction C(w,m)

Position size in this market relative to the wallet’s average position across all markets.
ratio = market_size_usdc / avg_position_size_usdc
C = (tanh(ratio - 1) + 1) / 2
When ratio = 1 (average-sized position), C = 0.5. Larger than average positions push C toward 1.

Recency R(w,m)

Exponential decay from the most recent trade, using the Rust decay_weight() function.
R = decay_weight(age_secs, half_life)
Default half-life is 6 hours. No trades = R = 0.0, which kills the signal entirely.

Momentum M(w,m)

Volume-weighted buy ratio shift between the recent half and older half of trades.
M = 0.5 + (recent_buy_ratio - old_buy_ratio)
Detects direction changes. Needs 3+ trades; returns 0.5 otherwise.

Composition

deviation = D - 0.5
amplified = deviation * C * 2
with_momentum = amplified + (M - 0.5) * momentum_weight
decayed = with_momentum * R
quality_adjusted = decayed * Q
S = clamp(0.5 + quality_adjusted, 0.01, 0.99)
Where Q is the wallet’s composite_score from score_wallet(). Negative Q inverts the signal (fade bad wallets).

Consensus Aggregation

For multi-wallet consensus:
  1. Fetch top 20 holders via get_top_holders()
  2. Score each wallet via score_wallet() (cached 5 min)
  3. Filter by |composite_score| >= min_wallet_quality
  4. Compute WalletMarketSignal for each
  5. Weight: |quality| * sqrt(position_size) * recency
  6. Weighted average of signals
  7. Agreement = 1 - CV(signals) (coefficient of variation)
  8. Confidence interval from IQR of individual signals
Requires 3+ wallets by default; returns neutral otherwise.

Pipeline Mode

The wallet_tracker() factory creates a pipeline function that:
  • Refreshes signals every N cycles (default: 20)
  • EMA-smooths signal between refreshes
  • Detects regime changes and emits WalletRegimeChange events
  • Supports both explicit wallet lists and auto-discovery

Injected Context Parameters

ParameterTypeDescription
wallet_tracker_signalWalletMarketSignalBest signal for current market
wallet_tracker_consensusConsensusSignalMulti-wallet consensus (if available)
wallet_tracker_edge_bpsfloatSigned edge in basis points
wallet_tracker_regime_changeslist[WalletRegimeChange]Regime flips detected this cycle

Oracle Integration

The wallet tracker can optionally feed into the Oracle as a 7th signal:
config = hz.OracleConfig()
config.signal_weights["wallet_consensus"] = 0.20

fc = hz.forecast_market(
    "0xcondition...",
    market_price=0.65,
    config=config,
    include_wallet_signal=True,
)
The wallet_consensus signal weight defaults to 0.0 (disabled). You must explicitly set a non-zero weight and pass include_wallet_signal=True.

Configuration Reference

@dataclass
class TrackerConfig:
    decay_half_life_secs: float = 21600.0     # 6h for recency decay
    ema_alpha: float = 0.3                     # signal smoothing
    min_signal_strength: float = 0.05          # |signal - 0.5| threshold
    min_confidence: float = 0.3
    min_edge_bps: float = 200.0
    min_wallets_for_consensus: int = 3
    min_wallet_quality: float = 0.1            # smart money filter
    momentum_weight: float = 0.2              # max momentum shift
    regime_change_threshold: float = 0.4
    wallet_score_cache_ttl: float = 300.0      # 5 min
    poll_interval_cycles: int = 20

Types Reference

WalletMarketSignal

FieldTypeDescription
walletstrWallet address
market_idstrMarket condition ID
signalfloatComposite signal [0.01, 0.99]
directionfloatPosition direction D(w,m)
convictionfloatRelative sizing C(w,m)
recencyfloatDecay weight R(w,m)
momentumfloatTrade direction shift M(w,m)
wallet_qualityfloatComposite score [-1, 1]
confidencefloatSignal confidence [0, 1]
confidence_lowfloatLower bound
confidence_highfloatUpper bound
trade_countintTrades in this market
position_size_usdcfloatPosition value in USDC
regimestrbullish / bearish / neutral / flipping
edge_bpsfloatEdge vs market price
is_actionableboolPasses all thresholds

ConsensusSignal

FieldTypeDescription
market_idstrMarket condition ID
signalfloatWeighted consensus [0.01, 0.99]
confidencefloatAggregate confidence
agreementfloatWallet agreement [0, 1]
n_walletsintContributing wallets
edge_bpsfloatConsensus edge
wallet_signalslist[WalletMarketSignal]Individual signals
best_walletstrHighest-confidence wallet
is_actionableboolPasses thresholds

WalletRegimeChange

FieldTypeDescription
walletstrWallet address
market_idstrMarket condition ID
old_regimestrPrevious regime
new_regimestrNew regime
confidencefloatDetection confidence