HeyTraders Documentation

Multi-Asset & Arbitrage Patterns (Cross Mode)

Taker-Taker Cross-Exchange Arbitrage (LIVE/PAPER)

Tags: arbitrage, cross_exchange, orderbook, taker_taker, live Functions: get_data, round_qty, is_valid_qty, get_position, emit Description: Declare one exact two-venue pair, compare executable ask-to-bid spreads in both directions, and emit equal-quantity MARKET legs from the same evaluation. The legs are routed concurrently but are not cross-venue atomic. Use this as the simple default; extend multiple pairs with explicit {key, leg_a, leg_b} mappings and pair-local labels. Code:

leg_a = 'BINANCEFUTURES:BTC/USDT:USDT'
leg_b = 'HYPERLIQUID:BTC/USDC:USDC'
pair_key = 'btc_binance_hyperliquid'
target_notional = 25.0
entry_bps = 20.0

book_a = get_data(leg_a).book
book_b = get_data(leg_b).book

if book_a is not None and book_b is not None:
    bid_a = book_a.best_bid
    ask_a = book_a.best_ask
    bid_b = book_b.best_bid
    ask_b = book_b.best_ask
    ready = (
        bid_a is not None and ask_a is not None
        and bid_b is not None and ask_b is not None
        and bid_a > 0 and ask_a > bid_a
        and bid_b > 0 and ask_b > bid_b
    )
    if ready:
        edge_bps = (bid_b / ask_a - 1.0) * 10000.0
        common_quantity = round_qty(leg_a, target_notional / ask_a, mode='down')
        common_quantity = round_qty(leg_b, common_quantity, mode='down')
        quantity_ready = (
            common_quantity > 0
            and is_valid_qty(leg_a, common_quantity)
            and is_valid_qty(leg_b, common_quantity)
        )
        is_flat = abs(get_position(leg_a)) < 0.000001 and abs(get_position(leg_b)) < 0.000001
        enter = is_flat and quantity_ready and edge_bps >= entry_bps

        if enter:
            emit(True, entry(
                leg_a,
                'LONG',
                Quantity(common_quantity),
                execution='MARKET',
                label=pair_key + ':a_long',
                when=NoPosition(),
            ))
            emit(True, entry(
                leg_b,
                'SHORT',
                Quantity(common_quantity),
                execution='MARKET',
                label=pair_key + ':b_short',
                when=NoPosition(),
            ))

The compact example shows one direction. A deployed strategy should evaluate the reverse executable spread, paired exits, fees, slippage, stale books, and an unmatched-leg policy.

Fill-Linked Cross-Exchange Arbitrage (LIVE/PAPER)

Tags: arbitrage, cross_exchange, orderbook, hedge_on_fill, live Functions: get_data, tick_size, round_price, round_qty, is_valid_qty, get_position, get_open_order, emit_chain, HedgeOnFill Description: Advanced maker-to-taker form. Declare one explicit maker-source/hedge pair, rest the source order, and let Broker hedge authoritative source fills. Use the same rounded base quantity on both venues. Extend to multiple pairs with a list of explicit {key, source, hedge} mappings and pair-local labels; do not infer pair roles from universe ordering. Code:

source = 'POLYMARKETPERP:LIT/PUSD:PUSD'
hedge = 'LIGHTER:LIT/USDC:USDC'
pair_key = 'lit_poly_lighter'
target_notional = 25.0
entry_edge = 0.002

source_data = get_data(source)
hedge_data = get_data(hedge)
source_book = source_data.book
hedge_book = hedge_data.book

if source_book is not None and hedge_book is not None:
    source_bid = source_book.best_bid
    source_ask = source_book.best_ask
    hedge_bid = hedge_book.best_bid
    hedge_ask = hedge_book.best_ask
    ready = (
        source_bid is not None and source_ask is not None
        and hedge_bid is not None and hedge_ask is not None
        and source_bid > 0 and source_ask > source_bid
        and hedge_bid > 0 and hedge_ask > hedge_bid
    )
    if ready:
        source_tick = tick_size(source)
        source_mid = (source_bid + source_ask) / 2.0
        common_quantity = round_qty(source, target_notional / source_mid, mode='down')
        common_quantity = round_qty(hedge, common_quantity, mode='down')
        source_label = pair_key + ':entry_buy'
        source_price = round_price(
            source,
            min(hedge_bid / (1.0 + entry_edge), source_ask - source_tick),
            side='BUY',
        )
        is_flat = abs(get_position(source)) < 0.000001 and abs(get_position(hedge)) < 0.000001
        quantity_ready = (
            common_quantity > 0
            and is_valid_qty(source, common_quantity)
            and is_valid_qty(hedge, common_quantity)
        )

        if is_flat and quantity_ready and get_open_order(source_label) is None:
            emit_chain(True, [
                entry(
                    source,
                    'LONG',
                    Quantity(common_quantity),
                    execution='LIMIT',
                    limit_price=source_price,
                    label=source_label,
                    auto_cancel_on_close=True,
                ),
                entry(
                    hedge,
                    'SHORT',
                    Quantity(common_quantity),
                    execution='MARKET',
                    when=HedgeOnFill(source_label),
                    label=pair_key + ':entry_sell_hedge',
                ),
            ])

The compact example shows the execution contract. A deployed strategy must also implement the opposite direction, pair-local requoting, paired closes, partial-fill handling, and an unmatched-state policy.

Cointegration Z-Score (Pair Trading)

Tags: arbitrage, pair_trading, cross_mode, zscore, spread, statistical_arbitrage Functions: get_data, ts_mean, ts_std_dev, ts_zscore Description: Enter when the price spread between two assets (e.g. BTC, ETH) deviates more than 2 standard deviations from the mean, targeting mean reversion. Code:

# Cross Mode for pair trading
btc = get_data('BINANCEFUTURES:BTC/USDT:USDT')
eth = get_data('BINANCEFUTURES:ETH/USDT:USDT')

# Spread using ratio (simpler than log spread)
spread = eth.close / btc.close
z_score = ts_zscore(spread, 30)
prev_z = z_score.shift(1)

# Entry Conditions
long_spread = (z_score < -2.0) & (prev_z >= -2.0)  # ETH undervalued -> Long ETH, Short BTC
short_spread = (z_score > 2.0) & (prev_z <= 2.0)  # ETH overvalued -> Short ETH, Long BTC

# Exit when z-score normalizes
exit_cond = (z_score > -0.5) & (z_score < 0.5)

# Both intents are emitted from the same evaluation and execute independently.
emit(long_spread, entry('BINANCEFUTURES:ETH/USDT:USDT', 'LONG', Weight(0.5), when=NoPosition()))
emit(long_spread, entry('BINANCEFUTURES:BTC/USDT:USDT', 'SHORT', Weight(0.5), when=NoPosition()))
emit(short_spread, entry('BINANCEFUTURES:ETH/USDT:USDT', 'SHORT', Weight(0.5), when=NoPosition()))
emit(short_spread, entry('BINANCEFUTURES:BTC/USDT:USDT', 'LONG', Weight(0.5), when=NoPosition()))
emit(exit_cond, exit_position('BINANCEFUTURES:ETH/USDT:USDT', when=HasPosition()))
emit(exit_cond, exit_position('BINANCEFUTURES:BTC/USDT:USDT', when=HasPosition()))

Spot-Perp Basis Arbitrage

Tags: arbitrage, basis, spot_perp, cross_mode, funding_rate, market_neutral Functions: get_data Description: When the basis (price gap) between spot and perpetual futures widens, sell the expensive side and buy the cheap side to collect funding fees or profit from basis convergence. Code:

spot = get_data('BINANCE:BTC/USDT')
perp = get_data('BINANCEFUTURES:BTC/USDT:USDT')

# Basis percentage
basis = (perp.close - spot.close) / spot.close * 100
prev_basis = basis.shift(1)

# Entry: Perp premium > 0.1%
open_arb = (basis > 0.1) & (prev_basis <= 0.1)
# Exit: Basis normalized < 0.01%
close_arb = basis < 0.01

# Short Perp (expensive), Long Spot (cheap)
emit(open_arb, entry('BINANCE:BTC/USDT', 'LONG', Weight(0.5), when=NoPosition()))
emit(open_arb, entry('BINANCEFUTURES:BTC/USDT:USDT', 'SHORT', Weight(0.5), when=NoPosition()))
emit(close_arb, exit_position('BINANCE:BTC/USDT', when=HasPosition()))
emit(close_arb, exit_position('BINANCEFUTURES:BTC/USDT:USDT', when=HasPosition()))

Historical Cross-Exchange Spread Proxy

Tags: arbitrage, cross_exchange, hyperliquid, binance, price_spread, backtest_proxy Functions: get_data Description: Candle-only research proxy for a same-asset spread. Its independently emitted legs are not a LIVE execution template and do not provide fill-linked hedging. Code:

# Cross-Exchange Arbitrage: Hyperliquid vs Binance
hl_btc = get_data('HYPERLIQUID:BTC/USDC:USDC')
bn_btc = get_data('BINANCEFUTURES:BTC/USDT:USDT')

# Calculate price spread percentage
spread_pct = (hl_btc.close - bn_btc.close) / bn_btc.close * 100
prev_spread = spread_pct.shift(1)

# Open arbitrage when Hyperliquid is 0.5% more expensive than Binance
open_arb = (spread_pct > 0.5) & (prev_spread <= 0.5)
# Close when spread normalizes below 0.1%
close_arb = spread_pct < 0.1

# Short the expensive exchange, Long the cheap one
emit(open_arb, entry('HYPERLIQUID:BTC/USDC:USDC', 'SHORT', Weight(0.5), when=NoPosition()))
emit(open_arb, entry('BINANCEFUTURES:BTC/USDT:USDT', 'LONG', Weight(0.5), when=NoPosition()))
emit(close_arb, exit_position('HYPERLIQUID:BTC/USDC:USDC', when=HasPosition()))
emit(close_arb, exit_position('BINANCEFUTURES:BTC/USDT:USDT', when=HasPosition()))

Historical Bidirectional Cross-Exchange Spread Proxy

Tags: arbitrage, bidirectional, cross_exchange, hyperliquid, binance, backtest_proxy Functions: get_data Description: Candle-only bidirectional spread research. Do not deploy these independent legs as LIVE arbitrage; use the explicit source/hedge HedgeOnFill pattern above. Code:

# Bidirectional Cross-Exchange Arbitrage
hl_btc = get_data('HYPERLIQUID:BTC/USDC:USDC')
bn_btc = get_data('BINANCEFUTURES:BTC/USDT:USDT')

# Calculate spread in both directions
spread_pct = (hl_btc.close - bn_btc.close) / bn_btc.close * 100
prev_spread = spread_pct.shift(1)

# Hyperliquid expensive (spread > 0.5%) -> Short HL, Long Binance
hl_expensive = (spread_pct > 0.5) & (prev_spread <= 0.5)
# Binance expensive (spread < -0.5%) -> Short Binance, Long HL
bn_expensive = (spread_pct < -0.5) & (prev_spread >= -0.5)
# Exit when normalized
exit_cond = (spread_pct > -0.1) & (spread_pct < 0.1)

# Direction 1: HL expensive
emit(hl_expensive, entry('HYPERLIQUID:BTC/USDC:USDC', 'SHORT', Weight(0.5), when=NoPosition()))
emit(hl_expensive, entry('BINANCEFUTURES:BTC/USDT:USDT', 'LONG', Weight(0.5), when=NoPosition()))

# Direction 2: Binance expensive
emit(bn_expensive, entry('HYPERLIQUID:BTC/USDC:USDC', 'LONG', Weight(0.5), when=NoPosition()))
emit(bn_expensive, entry('BINANCEFUTURES:BTC/USDT:USDT', 'SHORT', Weight(0.5), when=NoPosition()))

# Exit both directions
emit(exit_cond, exit_position('HYPERLIQUID:BTC/USDC:USDC', when=HasPosition()))
emit(exit_cond, exit_position('BINANCEFUTURES:BTC/USDT:USDT', when=HasPosition()))