Skip to main content

RSI (Relative Strength Index)

Usage

// In your run() loop
btc := s.w.Asset("BTC")
usdt := s.w.Asset("USDT")
pair := s.w.Pair(btc, usdt)

// Basic usage - 14-period RSI
rsi := s.w.Indicators().RSI(pair, 14)

// With options - specific exchange or timeframe
rsi := s.w.Indicators().RSI(pair, 14, indicators.IndicatorOptions{
Exchange: connector.Binance,
Interval: "4h",
})

In a Strategy

// In your run() loop
func (s *Strategy) run(ctx context.Context) {
ticker := time.NewTicker(1 * time.Hour)
defer ticker.Stop()

btc := s.w.Asset("BTC")
usdt := s.w.Asset("USDT")
pair := s.w.Pair(btc, usdt)

for {
select {
case <-ticker.C:
// Get 14-period RSI (standard)
rsi := s.w.Indicators().RSI(pair, 14)

// Oversold: RSI < 30
if rsi.LessThan(decimal.NewFromInt(30)) {
signal := s.w.Spot().Signal(s.name).
BuyMarket(pair, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
s.w.Emit(signal)
s.w.Log().Opportunity(string(s.name), "BTC",
"RSI oversold at %.2f", rsi)
}

// Overbought: RSI > 70
if rsi.GreaterThan(decimal.NewFromInt(70)) {
signal := s.w.Spot().Signal(s.name).
SellMarket(pair, connector.Binance, decimal.NewFromFloat(0.1)).
Build()
s.w.Emit(signal)
s.w.Log().Opportunity(string(s.name), "BTC",
"RSI overbought at %.2f", rsi)
}
}
}
}

Parameters

RSI(asset, period, ...options) decimal.Decimal
ParameterTypeDescription
assettypes.AssetAsset to calculate for
periodintNumber of periods (typically 14)
options...IndicatorOptionsOptional exchange/interval

Return Value

Returns a decimal.Decimal value between 0 and 100.

Common Patterns

Basic Oversold/Overbought

rsi := s.k.Indicators().RSI(btc, 14)

// Buy when oversold
if rsi.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(btc).Build()
}

// Sell when overbought
if rsi.GreaterThan(decimal.NewFromInt(70)) {
return s.Signal().Sell(btc).Build()
}

With Trend Filter

price := s.k.Market().Price(btc)
sma200 := s.k.Indicators().SMA(btc, 200)
rsi := s.k.Indicators().RSI(btc, 14)

// Only buy oversold signals in uptrend
if price.GreaterThan(sma200) && rsi.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(btc).Reason("Oversold in uptrend").Build()
}

Multi-Timeframe

// Higher timeframe for trend
rsi4h := s.k.Indicators().RSI(btc, 14, indicators.IndicatorOptions{
Interval: "4h",
})

// Lower timeframe for entry
rsi1h := s.k.Indicators().RSI(btc, 14, indicators.IndicatorOptions{
Interval: "1h",
})

// 4h not overbought, 1h oversold
if rsi4h.LessThan(decimal.NewFromInt(70)) &&
rsi1h.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(btc).Build()
}

Divergence Detection

// Bullish divergence: price makes lower lows, RSI makes higher lows
prevPrice := s.k.Market().PricePrevious(btc, 1)
prevRSI := s.k.Indicators().RSIPrevious(btc, 14, 1)

price := s.k.Market().Price(btc)
rsi := s.k.Indicators().RSI(btc, 14)

if price.LessThan(prevPrice) && rsi.GreaterThan(prevRSI) {
// Bullish divergence detected
return s.Signal().Buy(btc).Reason("RSI bullish divergence").Build()
}

Interpretation Guide

Levels

RSI ValueConditionAction
> 70OverboughtConsider selling
50-70BullishHold/accumulate
30-50BearishCautious
< 30OversoldConsider buying

Advanced Levels

Some traders use tighter levels:

// Extreme oversold/overbought
if rsi.LessThan(decimal.NewFromInt(20)) {
// Extremely oversold - strong buy
}

if rsi.GreaterThan(decimal.NewFromInt(80)) {
// Extremely overbought - strong sell
}

What It Measures

RSI measures the magnitude of recent price changes to evaluate overbought or oversold conditions.

Formula

RS = Average Gain / Average Loss
RSI = 100 - (100 / (1 + RS))

Where:

  • Average Gain = Average of gains over the period
  • Average Loss = Average of losses over the period

The Theory

  • RSI > 70: Momentum is strong to the upside, potentially overbought
  • RSI < 30: Momentum is strong to the downside, potentially oversold
  • RSI = 50: Neutral, no clear momentum

Best Practices

✅ Do

// Use with trend confirmation
price := s.k.Market().Price(btc)
ema200 := s.k.Indicators().EMA(btc, 200)
rsi := s.k.Indicators().RSI(btc, 14)

// Only buy oversold in uptrend
if price.GreaterThan(ema200) && rsi.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(btc).Build()
}
// Combine with other indicators
rsi := s.k.Indicators().RSI(btc, 14)
macd := s.k.Indicators().MACD(btc, 12, 26, 9)

// Both confirm bullish
if rsi.GreaterThan(decimal.NewFromInt(50)) &&
macd.MACD.GreaterThan(macd.Signal) {
return s.Signal().Buy(btc).Build()
}

❌ Don't

// Don't trade solely on RSI
if rsi.LessThan(decimal.NewFromInt(30)) {
// ❌ Can stay oversold in downtrend
return s.Signal().Buy(btc).Build()
}
// Don't use same levels for all assets
// ❌ Volatile assets may need different thresholds
rsi := s.k.Indicators().RSI(volatileAsset, 14)
if rsi.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(volatileAsset).Build()
}

// ✅ Adjust for asset characteristics
if rsi.LessThan(decimal.NewFromInt(20)) { // Tighter threshold
return s.Signal().Buy(volatileAsset).Build()
}

Common Periods

PeriodUse Case
14Standard, balanced
9More sensitive, faster signals
21Less sensitive, smoother
7Day trading, very responsive
// Standard
rsi14 := s.k.Indicators().RSI(btc, 14)

// More sensitive
rsi9 := s.k.Indicators().RSI(btc, 9)

// Smoother
rsi21 := s.k.Indicators().RSI(btc, 21)

Common Pitfalls

Problem: RSI can remain overbought/oversold during strong trends.

Solution:

// Add trend filter
ema := s.k.Indicators().EMA(btc, 200)
price := s.k.Market().Price(btc)
rsi := s.k.Indicators().RSI(btc, 14)

inUptrend := price.GreaterThan(ema)

if inUptrend {
// Only take buy signals in uptrend
if rsi.LessThan(decimal.NewFromInt(30)) {
return s.Signal().Buy(btc).Build()
}
}

2. Ignoring Market Context

Problem: Using same levels in all market conditions.

Solution:

// Adjust levels based on volatility
vol := s.k.Analytics().Volatility(btc, 24)
rsi := s.k.Indicators().RSI(btc, 14)

oversoldLevel := decimal.NewFromInt(30)
if vol.GreaterThan(decimal.NewFromInt(50)) {
// High volatility - use tighter levels
oversoldLevel = decimal.NewFromInt(20)
}

if rsi.LessThan(oversoldLevel) {
return s.Signal().Buy(btc).Build()
}

Complete Example

See the RSI Strategy Example for a complete, production-ready implementation using the Start/run/Emit pattern.

See Also

References