Decode market indecision and potential reversals with this comprehensive guide to detecting and strategizing with Doji patterns in TradingView's Pinescript.
A Doji candlestick pattern is a crucial signal in technical analysis, characterized by a very small or non-existent real body, meaning the opening and closing prices are virtually the same. This indicates market indecision, where buyers and sellers are in a state of balance. While a single Doji candle alone may not be a definitive reversal signal, its appearance, especially after a prolonged trend or at key support/resistance levels, can indicate potential exhaustion of the current trend and a possible reversal. This makes Doji patterns invaluable for:
While all Doji share the characteristic of a small body, their wick lengths and positions create different variations, each conveying a slightly different message:
A cross shape, indicating perfect balance between buyers and sellers. Common in sideways markets.
Long upper and lower wicks, signifying strong indecision and volatility, but no clear direction.
Long lower wick, no upper wick. Price rejected lower levels. Bullish reversal signal if after downtrend.
Long upper wick, no lower wick. Price rejected higher levels. Bearish reversal signal if after uptrend.
Open, high, low, and close are all the same. Extremely rare, indicating extreme indecision or very low liquidity.
Small/Non-existent Real Body: Open and close prices are very close, often at the same level.
Indecision: Represents a balance between buying and selling forces.
Context is Crucial: A Doji's significance increases dramatically when it appears after a strong trend or at key support/resistance levels.
//@version=5
indicator("Doji Pattern Detector", overlay=true)
// User input for threshold to define a "small body"
bodyRatioThreshold = input.float(0.1, title="Doji Body Ratio Threshold (e.g., 0.1 for 10%)", minval=0.01, maxval=0.5)
// Calculate candle body size
bodySize = math.abs(close - open)
// Calculate total candle range
candleRange = high - low
// Check if it's a Doji (body size is very small relative to the candle's total range)
// Avoid division by zero if candleRange is 0 (occurs with Four Price Doji)
isDoji = if candleRange > 0
bodySize / candleRange <= bodyRatioThreshold
else // Handle Four Price Doji case (open==high==low==close)
true
// Plot signal on the chart
plotshape(isDoji, title="Doji Detected", location=location.belowbar, color=color.new(color.silver, 0), style=shape.circle, size=size.small)
// Alert condition (optional)
alertcondition(isDoji, title="Doji Detected", message="Doji Candlestick Pattern Detected!")
//@version=5
indicator("Specific Doji Patterns", overlay=true)
// Input for threshold to define a "small body"
bodyRatioThreshold = input.float(0.1, title="Doji Body Ratio Threshold (e.g., 0.1 for 10%)", minval=0.01, maxval=0.5)
// Input for wick ratio to define "long" or "short" wicks
wickRatioThreshold = input.float(0.4, title="Long Wick Ratio Threshold (e.g., 0.4 for 40%)", minval=0.1, maxval=0.9)
// Helper function to check for small body
isSmallBody(open_val, close_val, high_val, low_val) =>
bodySize = math.abs(close_val - open_val)
candleRange = high_val - low_val
candleRange > 0 ? (bodySize / candleRange <= bodyRatioThreshold) : true // Handles Four Price Doji
// Calculate wick lengths
upperShadow = high - math.max(open, close)
lowerShadow = math.min(open, close) - low
totalRange = high - low
// --- Standard Doji ---
// Small body, relatively balanced upper and lower shadows (or overall short wicks)
isStandardDoji = isSmallBody(open, close, high, low) and
(upperShadow / totalRange > 0.1 and lowerShadow / totalRange > 0.1) // Some wicks
// More balanced wick check: math.abs(upperShadow - lowerShadow) / totalRange < 0.2
// --- Long-Legged Doji ---
// Small body, very long upper and lower shadows
isLongLeggedDoji = isSmallBody(open, close, high, low) and
upperShadow / totalRange >= wickRatioThreshold and
lowerShadow / totalRange >= wickRatioThreshold
// --- Dragonfly Doji ---
// Small body (or non-existent) at the top of the candle, long lower shadow, little to no upper shadow
isDragonflyDoji = isSmallBody(open, close, high, low) and
lowerShadow / totalRange >= wickRatioThreshold and
upperShadow / totalRange < bodyRatioThreshold * 0.5 // Upper shadow is tiny
// --- Gravestone Doji ---
// Small body (or non-existent) at the bottom of the candle, long upper shadow, little to no lower shadow
isGravestoneDoji = isSmallBody(open, close, high, low) and
upperShadow / totalRange >= wickRatioThreshold and
lowerShadow / totalRange < bodyRatioThreshold * 0.5 // Lower shadow is tiny
// --- Four Price Doji ---
// Open, high, low, close are all the same
isFourPriceDoji = (open == high) and (high == low) and (low == close)
// Plot shapes for detected patterns
plotshape(isStandardDoji, title="Standard Doji", location=location.belowbar, color=color.new(color.gray, 0), style=shape.circle, size=size.small, text="SD")
plotshape(isLongLeggedDoji, title="Long-Legged Doji", location=location.belowbar, color=color.new(color.orange, 0), style=shape.circle, size=size.normal, text="LLD")
plotshape(isDragonflyDoji, title="Dragonfly Doji", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.normal, text="DFD")
plotshape(isGravestoneDoji, title="Gravestone Doji", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.normal, text="GSD")
plotshape(isFourPriceDoji, title="Four Price Doji", location=location.belowbar, color=color.new(color.purple, 0), style=shape.diamond, size=size.small, text="4PD")
// Alerts (optional)
alertcondition(isLongLeggedDoji, title="Long-Legged Doji Alert", message="Long-Legged Doji Detected!")
alertcondition(isDragonflyDoji, title="Dragonfly Doji Alert", message="Dragonfly Doji Detected!")
alertcondition(isGravestoneDoji, title="Gravestone Doji Alert", message="Gravestone Doji Detected!")
Doji patterns are powerful signals of indecision, but their true predictive value shines when combined with other indicators and market context. They act as "warnings" that a trend might be losing momentum, rather than direct entry signals.
//@version=5
strategy("Doji with Trend Reversal Confirmation", overlay=true)
// Input for Moving Average length
maLength = input(50, "MA Length (for trend)")
ma = ta.ema(close, maLength) // Using EMA for trend detection
// Doji Pattern Detection (using a general Doji definition for simplicity)
bodyRatioThreshold = 0.1
bodySize = math.abs(close - open)
candleRange = high - low
isDoji = if candleRange > 0
bodySize / candleRange <= bodyRatioThreshold
else
true
// Trend Context:
// Potential Bullish Reversal: Doji after a downtrend AND near MA support
isPotentialBullishReversal = isDoji and close < ma and close[1] < ma[1] and ma > ma[1] // price below MA, MA sloping down
// Potential Bearish Reversal: Doji after an uptrend AND near MA resistance
isPotentialBearishReversal = isDoji and close > ma and close[1] > ma[1] and ma < ma[1] // price above MA, MA sloping up
// Plot signals
plotshape(isPotentialBullishReversal, title="Doji (Bullish Reversal Context)", location=location.belowbar, color=color.new(color.blue, 0), style=shape.arrowup, size=size.normal)
plotshape(isPotentialBearishReversal, title="Doji (Bearish Reversal Context)", location=location.abovebar, color=color.new(color.purple, 0), style=shape.arrowdown, size=size.normal)
// Plot MA
plot(ma, "Trend MA", color.blue)
//@version=5
indicator("Doji with Volume Confirmation", overlay=true)
// Doji Pattern Detection (from basic example)
bodyRatioThreshold = input.float(0.1, title="Doji Body Ratio Threshold", minval=0.01, maxval=0.5)
bodySize = math.abs(close - open)
candleRange = high - low
isDoji = if candleRange > 0
bodySize / candleRange <= bodyRatioThreshold
else
true
// Volume Confirmation:
// Volume on the Doji candle should be higher than average volume, indicating significant indecision.
avgVolume = ta.sma(volume, 20) // 20-period Simple Moving Average of Volume
isVolumeConfirmed = volume > avgVolume * 1.5 // Volume is 1.5x average
// Combined signal
confirmedDoji = isDoji and isVolumeConfirmed
// Plot confirmed signals
barcolor(confirmedDoji ? color.new(color.teal, 60) : na)
plotshape(confirmedDoji, title="Doji (Vol Confirmed)", location=location.belowbar, color=color.new(color.yellow, 0), style=shape.labeldown, size=size.small, text="Doji Vol")
// Optional: Plot volume for visual check
plot(volume, title="Volume", color=color.gray, style=plot.style_columns)
plot(avgVolume, title="Avg Volume", color=color.orange, style=plot.style_line)
//@version=5
indicator("Doji at S/R Zones", overlay=true)
// User input for threshold to define a "small body"
bodyRatioThreshold = input.float(0.1, title="Doji Body Ratio Threshold", minval=0.01, maxval=0.5)
// Define sensitivity for S/R zone detection
srTolerance = input.float(0.005, title="S/R Zone Tolerance (as % of price)", minval=0.001, maxval=0.02)
// Calculate candle body size
bodySize = math.abs(close - open)
candleRange = high - low
isDoji = if candleRange > 0
bodySize / candleRange <= bodyRatioThreshold
else
true
// Simple S/R line detection (e.g., using previous swing highs/lows)
// This is a simplified example; real S/R can be complex.
lookback = input(20, "S/R Lookback Periods")
prevHigh = ta.highest(high[1], lookback)
prevLow = ta.lowest(low[1], lookback)
// Check if Doji is near Resistance
isNearResistance = isDoji and math.abs(high - prevHigh) / high <= srTolerance and close > open // Bullish close might be a breakout failure or test
// Check if Doji is near Support
isNearSupport = isDoji and math.abs(low - prevLow) / low <= srTolerance and close < open // Bearish close might be a breakdown failure or test
// Plot signals
plotshape(isNearResistance, title="Doji at Resistance", location=location.abovebar, color=color.new(color.red, 0), style=shape.square, size=size.normal, text="R-Doji")
plotshape(isNearSupport, title="Doji at Support", location=location.belowbar, color=color.new(color.green, 0), style=shape.square, size=size.normal, text="S-Doji")
// Plot S/R lines (for visual confirmation)
plot(prevHigh, "Previous High (Resistance)", color.red, linewidth=1, style=plot.style_stepline)
plot(prevLow, "Previous Low (Support)", color.green, linewidth=1, style=plot.style_stepline)
To maximize the effectiveness of Doji patterns in your Pinescript strategies:
The Doji candlestick pattern is a foundational concept in technical analysis, offering invaluable insights into market indecision and potential turning points. While simple in appearance, its various forms (Standard, Long-Legged, Dragonfly, Gravestone, Four Price) each convey nuanced messages when interpreted within the correct market context. By implementing Doji detection in Pinescript, you can automate the identification of these critical moments, integrate them into broader trading strategies with confirmation from other indicators, and enhance your ability to anticipate shifts in market sentiment on TradingView. Remember, the Doji is a signal of pause; the subsequent price action confirms the new direction.
Get a high-performance Pinescript analysis tool for actionable market insights, designed for traders on the move.
This strategy runs in live mode on TradingView, helping you identify potential opportunities.
Get Pinescript Strategy