Skip to content

Intraday Momentum Index (IMI)

The Intraday Momentum Index (IMI) is a momentum oscillator that combines aspects of RSI and candlestick analysis. Unlike RSI which uses closing prices, IMI uses the relationship between open and close prices to measure intraday momentum. It oscillates between 0 and 100, making it particularly useful for identifying overbought and oversold conditions based on intraday price action.

Usage

require 'sqa/tai'

open_prices = [44.50, 44.25, 44.75, 44.00, 44.50, 45.00,
               45.25, 45.50, 45.75, 46.00, 46.25, 46.50,
               46.75, 47.00, 46.50, 46.75, 47.00, 47.25]

close_prices = [44.34, 44.09, 44.15, 43.61, 44.33, 44.83,
                45.10, 45.42, 45.84, 46.08, 46.03, 46.41,
                46.22, 45.64, 46.21, 46.25, 46.08, 46.46]

# Calculate 14-period IMI
imi = SQA::TAI.imi(open_prices, close_prices, period: 14)

puts "Current IMI: #{imi.last.round(2)}"

Parameters

Parameter Type Required Default Description
open_prices Array Yes - Array of open price values
close_prices Array Yes - Array of close price values
period Integer No 14 Number of periods for calculation

Returns

Returns an array of IMI values ranging from 0 to 100. The first period values will be nil.

Interpretation

IMI Value Interpretation
70-100 Overbought - strong intraday buying pressure
50-70 Bullish momentum
30-50 Bearish momentum
0-30 Oversold - strong intraday selling pressure
50 Neutral - balanced intraday action

Note: Array elements should be ordered from oldest to newest (chronological order)

Example: Basic IMI Trading Signals

open_prices = load_historical_data('AAPL', field: :open)
close_prices = load_historical_data('AAPL', field: :close)

imi = SQA::TAI.imi(open_prices, close_prices, period: 14)
current_imi = imi.last

case current_imi
when 0...30
  puts "IMI Oversold (#{current_imi.round(2)}) - Potential BUY"
  puts "Strong intraday selling pressure may be exhausted"
when 70..100
  puts "IMI Overbought (#{current_imi.round(2)}) - Potential SELL"
  puts "Strong intraday buying pressure may be exhausted"
when 45...55
  puts "IMI Neutral (#{current_imi.round(2)}) - No clear signal"
  puts "Balanced intraday momentum"
else
  puts "IMI at #{current_imi.round(2)}"
end

# Check trend
if current_imi > 50
  puts "Bullish intraday momentum"
else
  puts "Bearish intraday momentum"
end

Example: IMI Divergence Detection

open_prices = load_historical_data('TSLA', field: :open)
close_prices = load_historical_data('TSLA', field: :close)

imi = SQA::TAI.imi(open_prices, close_prices, period: 14)

# Find recent highs in price and IMI
price_high_1 = close_prices[-20..-10].max
price_high_2 = close_prices[-9..-1].max

imi_high_1 = imi[-20..-10].compact.max
imi_high_2 = imi[-9..-1].compact.max

# Bearish divergence: price makes higher high, IMI makes lower high
if price_high_2 > price_high_1 && imi_high_2 < imi_high_1
  puts "Bearish Divergence detected!"
  puts "Price higher high: #{price_high_1.round(2)} -> #{price_high_2.round(2)}"
  puts "IMI lower high: #{imi_high_1.round(2)} -> #{imi_high_2.round(2)}"
  puts "Intraday momentum weakening despite higher prices"
end

# Bullish divergence: price makes lower low, IMI makes higher low
price_low_1 = close_prices[-20..-10].min
price_low_2 = close_prices[-9..-1].min

imi_low_1 = imi[-20..-10].compact.min
imi_low_2 = imi[-9..-1].compact.min

if price_low_2 < price_low_1 && imi_low_2 > imi_low_1
  puts "Bullish Divergence detected!"
  puts "Price lower low: #{price_low_1.round(2)} -> #{price_low_2.round(2)}"
  puts "IMI higher low: #{imi_low_1.round(2)} -> #{imi_low_2.round(2)}"
  puts "Intraday selling pressure weakening"
end

Example: IMI vs RSI Comparison

open_prices = load_historical_data('MSFT', field: :open)
close_prices = load_historical_data('MSFT', field: :close)

# Calculate both indicators
imi = SQA::TAI.imi(open_prices, close_prices, period: 14)
rsi = SQA::TAI.rsi(close_prices, period: 14)

current_imi = imi.last
current_rsi = rsi.last

puts "IMI: #{current_imi.round(2)}"
puts "RSI: #{current_rsi.round(2)}"
puts "Difference: #{(current_imi - current_rsi).round(2)}"

# IMI measures intraday action, RSI measures closing momentum
if current_imi > current_rsi + 10
  puts "IMI > RSI: Strong intraday buying (closes > opens)"
  puts "Bullish candle pattern trend"
elsif current_rsi > current_imi + 10
  puts "RSI > IMI: Prices rising but weak intraday action"
  puts "Caution: May indicate buying exhaustion"
end

# Strong signals when both align
if current_imi < 30 && current_rsi < 30
  puts "Both oversold - high conviction BUY signal"
elsif current_imi > 70 && current_rsi > 70
  puts "Both overbought - high conviction SELL signal"
end

Advanced Techniques

1. Intraday Gap Analysis

IMI is particularly useful when combined with gap analysis: - Large gap up + IMI > 70 = Gap may fill - Large gap down + IMI < 30 = Potential reversal

2. Candlestick Pattern Confirmation

Use IMI to confirm candlestick patterns: - Bullish engulfing + IMI rising = Strong buy - Bearish engulfing + IMI falling = Strong sell

3. Timeframe Analysis

  • Daily IMI: Swing trading signals
  • Hourly IMI: Day trading signals
  • 15-min IMI: Scalping opportunities

4. IMI Zones

Customize zones based on market conditions: - Volatile markets: 80/20 instead of 70/30 - Quiet markets: 60/40 for earlier signals

Example: Intraday Trading Strategy

# For day trading with minute/hourly data
open_prices = load_intraday_data('SPY', field: :open, interval: '5min')
close_prices = load_intraday_data('SPY', field: :close, interval: '5min')

imi = SQA::TAI.imi(open_prices, close_prices, period: 14)

# Track intraday momentum
current_imi = imi.last
prev_imi = imi[-2]

# Entry signals
if current_imi < 30 && prev_imi >= 30
  puts "IMI crossed below 30 - SELL signal"
  puts "Short entry at: #{close_prices.last.round(2)}"
elsif current_imi > 70 && prev_imi <= 70
  puts "IMI crossed above 70 - BUY signal"
  puts "Long entry at: #{close_prices.last.round(2)}"
end

# Exit signals (mean reversion)
if current_imi > 50 && prev_imi < 50
  puts "IMI crossed above 50 - Exit short positions"
elsif current_imi < 50 && prev_imi > 50
  puts "IMI crossed below 50 - Exit long positions"
end

# Calculate strength of move
candle_strength = ((close_prices.last - open_prices.last).abs /
                   open_prices.last * 100).round(2)
puts "Candle Strength: #{candle_strength}%"
puts "IMI reflects intraday momentum: #{current_imi.round(2)}"

Example: Multi-Period IMI

open_prices = load_historical_data('NVDA', field: :open)
close_prices = load_historical_data('NVDA', field: :close)

# Calculate multiple periods
imi_7 = SQA::TAI.imi(open_prices, close_prices, period: 7)
imi_14 = SQA::TAI.imi(open_prices, close_prices, period: 14)
imi_21 = SQA::TAI.imi(open_prices, close_prices, period: 21)

puts "Short-term IMI (7): #{imi_7.last.round(2)}"
puts "Standard IMI (14): #{imi_14.last.round(2)}"
puts "Long-term IMI (21): #{imi_21.last.round(2)}"

# All periods aligned = strong signal
if imi_7.last > 70 && imi_14.last > 70 && imi_21.last > 70
  puts "All timeframes overbought - strong reversal candidate"
elsif imi_7.last < 30 && imi_14.last < 30 && imi_21.last < 30
  puts "All timeframes oversold - strong reversal candidate"
end

# Divergence between timeframes
if imi_7.last > 70 && imi_21.last < 50
  puts "Short-term overbought but longer-term neutral"
  puts "Potential pullback in uptrend"
elsif imi_7.last < 30 && imi_21.last > 50
  puts "Short-term oversold but longer-term bullish"
  puts "Buying opportunity in uptrend"
end

Common Settings

Period Use Case
7 Short-term, day trading
14 Standard (most common)
21 Swing trading
30 Position trading

Key Differences from RSI

Feature IMI RSI
Data Used Open and Close Close only
Focus Intraday momentum Overall momentum
Sensitivity More sensitive to candle patterns Smoother, trend-focused
Best For Day trading, intraday analysis Swing trading, trend analysis
Gap Sensitivity Affected by gaps Less affected by gaps
  • RSI - Similar oscillator using closes
  • Stochastic - Another overbought/oversold indicator
  • MFI - Money Flow Index (volume-weighted)
  • CCI - Commodity Channel Index

See Also