HeyTraders Documentation

Grid Trading & Special Strategies

Grid Trading with Limit Orders (Fixed Range)

Tags: grid, limit_order, fixed_price, range, levels Functions: None Description: Grid trading with limit orders in a fixed price range. Buys at the lower bound and sells at the upper bound, filling at exact prices. Code:

ticker = context['ticker']

# Fixed grid parameters (e.g., BTC $90,000 ~ $100,000)
lower_price = 90000
upper_price = 100000
profit_pct = 0.02  # 2% profit target per grid

# Buy condition: price touches lower bound (bar's low reaches our buy price)
buy_zone = low <= lower_price
# Sell condition: price touches upper bound (bar's high reaches our sell price)
sell_zone = high >= upper_price

# LIMIT orders ensure execution at specified prices, not close
emit(buy_zone, entry(ticker, 'LONG', Weight(1.0),
                            execution='LIMIT', limit_price=lower_price))
emit(sell_zone, exit_position(ticker,
                                     execution='LIMIT', limit_price=upper_price))

Multi-Level Grid with Limit Orders

Tags: grid, limit_order, multi_level, accumulation Functions: None Description: Staggered buy and sell limit orders across multiple price levels, each filling at a different price. Code:

ticker = context['ticker']

# Grid levels (fixed prices)
grid_levels = [85000, 90000, 95000, 100000, 105000]

# Buy at each level when price drops there
buy_85 = low <= 85000
buy_90 = low <= 90000
buy_95 = low <= 95000

emit(buy_85, entry(ticker, 'LONG', Weight(1.0),
                          execution='LIMIT', limit_price=85000))
emit(buy_90, entry(ticker, 'LONG', Weight(0.6),
                          execution='LIMIT', limit_price=90000))
emit(buy_95, entry(ticker, 'LONG', Weight(0.3),
                          execution='LIMIT', limit_price=95000))

# Sell at upper levels
sell_100 = high >= 100000
sell_105 = high >= 105000

emit(sell_100, exit_position(ticker,
                                    execution='LIMIT', limit_price=100000))
emit(sell_105, exit_position(ticker,
                                    execution='LIMIT', limit_price=105000))

Note on Limit Orders vs Market Orders:

  • MARKET: Fills at bar's close price. Both buy/sell can execute at same price.
  • LIMIT: Fills at specified limit_price. Buy fills when low ≤ limit, sell when high ≥ limit.
  • For grid trading, LIMIT orders ensure different execution prices for buy vs sell.

Simple Grid Buy

Tags: grid, levels, accumulation, dip_buying Functions: ts_mean Description: Buys in stages at fixed percentage drops below the reference price. Grid-style accumulation. Code:

ticker = context['ticker']
reference = ts_mean(close, 50)  # Use the 50-day average as the reference price.

# Price levels relative to reference
level = close / reference

# Grid buy levels
grid_1 = (level < 0.98) & (level >= 0.95)  # -2% to -5%
grid_2 = (level < 0.95) & (level >= 0.90)  # -5% to -10%
grid_3 = (level < 0.90) & (level >= 0.85)  # -10% to -15%
grid_4 = level < 0.85                       # Below -15%

emit(grid_1, entry(ticker, 'LONG', Weight(0.25)))
emit(grid_2, entry(ticker, 'LONG', Weight(0.50)))
emit(grid_3, entry(ticker, 'LONG', Weight(0.75)))
emit(grid_4, entry(ticker, 'LONG', Weight(1.0)))

# Exit when price recovers above reference
exit_cond = close > reference * 1.02
emit(exit_cond, exit_position(ticker))

Grid Trading Long/Short (Perpetual)

Tags: grid, perpetual, levels, range, long_short Functions: ts_mean, ts_std_dev Description: Bidirectional grid on perpetual futures. Goes long at the lower range and short at the upper range. Code:

ticker = context['ticker']
mean = ts_mean(close, 50)
std = ts_std_dev(close, 50)

# Grid levels
upper_2 = mean + std * 2
upper_1 = mean + std
lower_1 = mean - std
lower_2 = mean - std * 2

# Long levels
long_1 = (close < lower_1) & (close >= lower_2)
long_2 = close < lower_2

# Short levels
short_1 = (close > upper_1) & (close <= upper_2)
short_2 = close > upper_2

# Center zone - close positions
center = (close >= lower_1) & (close <= upper_1)

emit(long_1, entry(ticker, 'LONG', Weight(0.5)))
emit(long_2, entry(ticker, 'LONG', Weight(1.0)))
emit(short_1, entry(ticker, 'SHORT', Weight(0.5)))
emit(short_2, entry(ticker, 'SHORT', Weight(1.0)))
emit(center, exit_position(ticker))

Always-On Bidirectional Grid with Limit Orders (Perpetual)

Tags: grid, perpetual, limit_order, replace_order, bidirectional, always_on, maker Functions: ts_mean, has_open_order, replace_order Description: Always-on bidirectional grid on perpetual futures using limit orders. Both long and short grid orders are always active regardless of current position. Opposite-side fills naturally serve as take-profit. Uses replace_order to update prices without cancelling. Code:

ticker = context['ticker']
reference = ts_mean(close, 50)[-1]
grid_step = 0.5 / 100.0

# Long grid - always active (buy below reference)
long_price_1 = reference * (1 - grid_step * 1)
if has_open_order('grid_long_1'):
    replace_order('grid_long_1', price=long_price_1)
else:
    emit(True, entry(ticker, 'LONG', Notional(50), leverage=5, execution='LIMIT', limit_price=long_price_1, label='grid_long_1', accumulate=True))

long_price_2 = reference * (1 - grid_step * 2)
if has_open_order('grid_long_2'):
    replace_order('grid_long_2', price=long_price_2)
else:
    emit(True, entry(ticker, 'LONG', Notional(50), leverage=5, execution='LIMIT', limit_price=long_price_2, label='grid_long_2', accumulate=True))

long_price_3 = reference * (1 - grid_step * 3)
if has_open_order('grid_long_3'):
    replace_order('grid_long_3', price=long_price_3)
else:
    emit(True, entry(ticker, 'LONG', Notional(50), leverage=5, execution='LIMIT', limit_price=long_price_3, label='grid_long_3', accumulate=True))

# Short grid - always active (sell above reference)
short_price_1 = reference * (1 + grid_step * 1)
if has_open_order('grid_short_1'):
    replace_order('grid_short_1', price=short_price_1)
else:
    emit(True, entry(ticker, 'SHORT', Notional(50), leverage=5, execution='LIMIT', limit_price=short_price_1, label='grid_short_1', accumulate=True))

short_price_2 = reference * (1 + grid_step * 2)
if has_open_order('grid_short_2'):
    replace_order('grid_short_2', price=short_price_2)
else:
    emit(True, entry(ticker, 'SHORT', Notional(50), leverage=5, execution='LIMIT', limit_price=short_price_2, label='grid_short_2', accumulate=True))

short_price_3 = reference * (1 + grid_step * 3)
if has_open_order('grid_short_3'):
    replace_order('grid_short_3', price=short_price_3)
else:
    emit(True, entry(ticker, 'SHORT', Notional(50), leverage=5, execution='LIMIT', limit_price=short_price_3, label='grid_short_3', accumulate=True))

Range Trading

Tags: range, support_resistance, bounce, levels Functions: ts_mean Description: Buys at support and sells at resistance. Designed for sideways, range-bound markets. Code:

ticker = context['ticker']

# 20-day support and resistance
support = lowest(low, 20)
resistance = highest(high, 20)

# Near support: buy
near_support = (close - support) / support < 0.02
# Near resistance: sell
near_resistance = (resistance - close) / resistance < 0.02

emit(near_support, entry(ticker, 'LONG', Weight(1.0)))
emit(near_resistance, exit_position(ticker))

Candlestick Pattern - Hammer

Tags: pattern, candle, hammer, reversal Functions: None Description: Detects the hammer candlestick pattern as a reversal signal after a downtrend. Code:

ticker = context['ticker']

# Hammer pattern detection
body = (close - open).abs()
lower_shadow = iff(open < close, open, close) - low  # min(open, close) - low
upper_shadow = high - iff(open > close, open, close)

# Hammer: small body, long lower shadow, small upper shadow
small_body = body < (high - low) * 0.3
long_lower = lower_shadow > body * 2
small_upper = upper_shadow < body * 0.5

hammer = small_body & long_lower & small_upper

# Confirm with prior downtrend
downtrend = close < close.shift(5)
hammer_signal = hammer & downtrend

emit(hammer_signal, entry(ticker, 'LONG', Weight(1.0)))

Candlestick Pattern - Engulfing

Tags: pattern, candle, engulfing, reversal Functions: None Description: Bullish engulfing pattern. A bullish candle that fully engulfs the previous bearish candle. Code:

ticker = context['ticker']

# Previous candle was bearish
prev_bearish = close.shift(1) < open.shift(1)

# Current candle is bullish and engulfs previous
curr_bullish = close > open
engulfs = (open < close.shift(1)) & (close > open.shift(1))

bullish_engulfing = prev_bearish & curr_bullish & engulfs

# Additional filter: was in downtrend
in_downtrend = close.shift(1) < sma(close, 10).shift(1)

long_cond = bullish_engulfing & in_downtrend
exit_cond = close < sma(close, 10)

emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))

Volume Profile Strategy

Tags: volume, spike, accumulation, distribution Functions: ts_mean Description: Treats a volume spike with a bullish candle as an institutional accumulation signal to buy. Code:

ticker = context['ticker']
vol_avg = ts_mean(volume, 20)

# Volume spike (2x average)
vol_spike = volume > vol_avg * 2

# Bullish candle with volume
bullish = close > open
accumulation = vol_spike & bullish

# Exit: volume spike with bearish candle (distribution)
bearish = close < open
distribution = vol_spike & bearish

emit(accumulation, entry(ticker, 'LONG', Weight(1.0)))
emit(distribution, exit_position(ticker))

Relative Strength vs BTC

Tags: relative_strength, btc, outperform, cross_mode Functions: get_data, ts_zscore Description: Buys coins with high relative strength versus BTC. Outperformance strategy. Code:

ticker = context['ticker']
btc = get_data('BINANCE:BTC/USDT')

# Calculate relative returns
ticker_ret = (close - close.shift(10)) / close.shift(10)
btc_ret = (btc.close - btc.close.shift(10)) / btc.close.shift(10)

# Relative strength
rel_strength = ticker_ret - btc_ret
z_score = ts_zscore(rel_strength, 30)

# Strong relative performance
long_cond = z_score > 1.5
exit_cond = z_score < 0

emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))

Momentum Rotation

Tags: momentum, rotation, ranking, cross_mode Functions: get_data, ts_rank Description: Holds only the top-momentum assets across multiple candidates. Code:

btc = get_data('BINANCE:BTC/USDT')
eth = get_data('BINANCE:ETH/USDT')
sol = get_data('BINANCE:SOL/USDT')

# 20-day returns
btc_mom = (btc.close - btc.close.shift(20)) / btc.close.shift(20)
eth_mom = (eth.close - eth.close.shift(20)) / eth.close.shift(20)
sol_mom = (sol.close - sol.close.shift(20)) / sol.close.shift(20)

# Find best performer
btc_best = (btc_mom > eth_mom) & (btc_mom > sol_mom)
eth_best = (eth_mom > btc_mom) & (eth_mom > sol_mom)
sol_best = (sol_mom > btc_mom) & (sol_mom > eth_mom)

# Go long on best performer
emit(btc_best, entry('BINANCE:BTC/USDT', 'LONG', Weight(1.0)))
emit(eth_best, entry('BINANCE:ETH/USDT', 'LONG', Weight(1.0)))
emit(sol_best, entry('BINANCE:SOL/USDT', 'LONG', Weight(1.0)))

# Exit non-best
emit(~btc_best, exit_position('BINANCE:BTC/USDT'))
emit(~eth_best, exit_position('BINANCE:ETH/USDT'))
emit(~sol_best, exit_position('BINANCE:SOL/USDT'))

Dip Buying After Crash

Tags: dip_buying, crash, recovery, oversold Functions: ts_mean Description: Buys on recovery after a crash. Enters on a bullish candle following a day with a -10% or worse drop. Code:

ticker = context['ticker']

# Daily return
daily_ret = (close - close.shift(1)) / close.shift(1)

# Crash day: -10% or worse
crash = daily_ret < -0.10

# Recovery: next day is bullish
recovery = close > open

# Buy on recovery after crash
long_cond = crash.shift(1) & recovery
exit_cond = close > close.shift(5) * 1.10  # Exit on 10% recovery

emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))

All-Time High Breakout

Tags: breakout, ath, momentum, trend Functions: None Description: Buys on a breakout above the all-time high. Rides new-ATH momentum. Code:

ticker = context['ticker']

# Cumulative all-time high
ath = high.cum_max()

# New ATH: current high exceeds previous ATH
new_ath = high > ath.shift(1)

# Volume confirmation
vol_avg = ts_mean(volume, 20)
vol_confirm = volume > vol_avg * 1.5

long_cond = new_ath & vol_confirm
exit_cond = close < sma(close, 20)

emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))

Support Bounce with RSI

Tags: support, rsi, bounce, confirmation Functions: rsi Description: Combines proximity to the 20-day support level with RSI oversold confirmation. Code:

ticker = context['ticker']

support = lowest(low, 20)
rsi_val = rsi(close, 14)

# Near support AND oversold
near_support = (close - support) / support < 0.02
oversold = rsi_val < 30

long_cond = near_support & oversold
exit_cond = rsi_val > 60

emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))