Pine Script Pivot Points

Master this foundational indicator in TradingView's Pine Script that identifies key potential support, resistance, and reversal levels for intraday and swing trading strategies.

Last Updated on: Expertise: Intermediate

What are Pivot Points?

Pivot Points are significant levels derived from the high, low, and closing prices of a previous trading period (e.g., previous day, week, or month). Traders use these levels to predict potential support and resistance zones for the current or upcoming trading period. They are particularly popular among intraday traders for identifying key turning points or areas where price action might react.

The core idea is that these calculated levels represent a consensus of past price action, and therefore, they are likely to influence future price movements. When price approaches a pivot point, traders watch for either a bounce (support/resistance) or a breakout (continuation).

There are several types of Pivot Points (Classic, Fibonacci, Woodie, Camarilla, Demark), each with slightly different calculation formulas. However, the Classic Pivot Points are the most widely used and provide a solid foundation for understanding the concept.

In Pine Script, Pivot Points are a powerful tool for visualizing key price levels that can inform your pine script strategies for entries, exits, and risk management.

Components and Calculation (Classic Pivot Points)

Classic Pivot Points consist of a central Pivot Point (PP), three resistance levels (R1, R2, R3), and three support levels (S1, S2, S3). These are calculated using the previous period's (e.g., yesterday's) High, Low, and Close prices:

  1. Pivot Point (PP): The central point, considered the "fair value" or balance point for the current period.
    `PP = (High[previous_period] + Low[previous_period] + Close[previous_period]) / 3`
  2. First Resistance (R1):
    `R1 = (2 * PP) - Low[previous_period]`
  3. First Support (S1):
    `S1 = (2 * PP) - High[previous_period]`
  4. Second Resistance (R2):
    `R2 = PP + (High[previous_period] - Low[previous_period])` `R2 = PP + (R1 - S1)` (Alternative calculation based on R1 and S1, known as Range)
  5. Second Support (S2):
    `S2 = PP - (High[previous_period] - Low[previous_period])` `S2 = PP - (R1 - S1)` (Alternative calculation based on R1 and S1, known as Range)
  6. Third Resistance (R3):
    `R3 = R1 + (High[previous_period] - Low[previous_period])` `R3 = R1 + (R2 - S1)` (Alternative using R2 and S1 range)
  7. Third Support (S3):
    `S3 = S1 - (High[previous_period] - Low[previous_period])` `S3 = S1 - (R1 - S2)` (Alternative using R1 and S2 range)

These levels remain constant throughout the trading day and are recalculated at the start of the next trading day (or chosen period, e.g., week, month).

Basic Pivot Points Implementation in Pine Script

Pine Script v5 provides a built-in function `ta.pivotpoints()` which simplifies the calculation and plotting of various types of Pivot Points. We can specify the type and the timeframe for the pivot calculation.

//@version=5
indicator("My Pivot Points", overlay=true, max_bars_back=500) // overlay=true to plot on price chart. max_bars_back for historical pivots.

// Input for the Pivot Point calculation timeframe
// Common options: "D" (Daily), "W" (Weekly), "M" (Monthly)
pivotTimeframe = input.string("D", title="Pivot Timeframe", options=["D", "W", "M"])

// Input for the type of Pivot Points
// Options: "Classic", "Fibonacci", "Woodie", "Camarilla", "Demark"
pivotType = input.string("Classic", title="Pivot Type", options=["Classic", "Fibonacci", "Woodie", "Camarilla", "Demark"])

// Get the Pivot Points values using ta.pivotpoints()
// This function returns a tuple: [pp, r1, r2, r3, s1, s2, s3]
[pp, r1, r2, r3, s1, s2, s3] = ta.pivotpoints(pivotType, pivotTimeframe, high, low, close, 1) // `1` indicates to look back 1 period for HLC

// Plotting the Pivot Points levels
plot(pp,   title="Pivot Point",    color=color.purple,   linewidth=2, style=plot.style_stepline)
plot(r1,   title="Resistance 1",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r2,   title="Resistance 2",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r3,   title="Resistance 3",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(s1,   title="Support 1",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s2,   title="Support 2",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s3,   title="Support 3",      color=color.green,    linewidth=1, style=plot.style_stepline)

// Optional: Add labels to the pivot lines for clarity
var label pp_label = na
var label r1_label = na
var label r2_label = na
var label r3_label = na
var label s1_label = na
var label s2_label = na
var label s3_label = na

// Only draw labels on the first bar of a new pivot period (e.g., start of new day)
if ta.change(time(pivotTimeframe))
    label.delete(pp_label)
    label.delete(r1_label)
    label.delete(r2_label)
    label.delete(r3_label)
    label.delete(s1_label)
    label.delete(s2_label)
    label.delete(s3_label)

    pp_label := label.new(bar_index, pp, text="PP", style=label.style_label_left, color=color.new(color.purple, 70), textcolor=color.white)
    r1_label := label.new(bar_index, r1, text="R1", style=label.style_label_left, color=color.new(color.red, 70), textcolor=color.white)
    r2_label := label.new(bar_index, r2, text="R2", style=label.style_label_left, color=color.new(color.red, 70), textcolor=color.white)
    r3_label := label.new(bar_index, r3, text="R3", style=label.style_label_left, color=color.new(color.red, 70), textcolor=color.white)
    s1_label := label.new(bar_index, s1, text="S1", style=label.style_label_left, color=color.new(color.green, 70), textcolor=color.white)
    s2_label := label.new(bar_index, s2, text="S2", style=label.style_label_left, color=color.new(color.green, 70), textcolor=color.white)
    s3_label := label.new(bar_index, s3, text="S3", style=label.style_label_left, color=color.new(color.green, 70), textcolor=color.white)

// Extend labels horizontally if on higher timeframes to be visible
label.set_x(pp_label, bar_index)
label.set_x(r1_label, bar_index)
label.set_x(r2_label, bar_index)
label.set_x(r3_label, bar_index)
label.set_x(s1_label, bar_index)
label.set_x(s2_label, bar_index)
label.set_x(s3_label, bar_index)

Static Levels: Unlike moving averages, Pivot Points are static levels for the entire trading period, calculated based on the previous period's high, low, and close. This makes them predictable.

Practical Pivot Points Trading Strategies

1. Support and Resistance Trading (Reversals)

This is the most common use of Pivot Points. Traders look for price to react to these levels, either bouncing off them or failing to break through, signaling potential reversals.

//@version=5
strategy("Pivot Point Reversal Strategy", overlay=true)

pivotTimeframe = input.string("D", title="Pivot Timeframe", options=["D", "W", "M"])
pivotType = input.string("Classic", title="Pivot Type", options=["Classic", "Fibonacci", "Woodie", "Camarilla", "Demark"])
[pp, r1, r2, r3, s1, s2, s3] = ta.pivotpoints(pivotType, pivotTimeframe, high, low, close, 1)

// Plotting (removed labels for brevity in strategy example, but you'd keep them for visual trading)
plot(pp,   title="Pivot Point",    color=color.purple,   linewidth=2, style=plot.style_stepline)
plot(r1,   title="Resistance 1",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r2,   title="Resistance 2",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r3,   title="Resistance 3",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(s1,   title="Support 1",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s2,   title="Support 2",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s3,   title="Support 3",      color=color.green,    linewidth=1, style=plot.style_stepline)


// Simple reversal logic: price touches a support/resistance and closes back
// (Needs to be more sophisticated for production, e.g., bullish/bearish candle confirmation)
longCondition = close > s1 and close[1] <= s1[1] // Price bounces from S1
shortCondition = close < r1 and close[1] >= r1[1] // Price rejected from R1

// Add conditions to ensure it's a new pivot period to avoid multiple entries on same pivot
isNewPeriod = ta.change(time(pivotTimeframe))

if (longCondition and not isNewPeriod) // only enter if not the very start of the pivot period
    strategy.entry("Long Reversal S1", strategy.long)

if (shortCondition and not isNewPeriod)
    strategy.entry("Short Reversal R1", strategy.short)

// Basic exit logic: exit on opposite pivot or fixed profit/loss
strategy.exit("Long Reversal S1 Exit", from_entry="Long Reversal S1", profit=r1, stop=s2)
strategy.exit("Short Reversal R1 Exit", from_entry="Short Reversal R1", profit=s1, stop=r2)

2. Breakout Trading (Continuation)

If price decisively breaks through a pivot level with strong momentum and volume, it can signal a continuation of the trend towards the next pivot level.

//@version=5
strategy("Pivot Point Breakout Strategy", overlay=true)

pivotTimeframe = input.string("D", title="Pivot Timeframe", options=["D", "W", "M"])
pivotType = input.string("Classic", title="Pivot Type", options=["Classic", "Fibonacci", "Woodie", "Camarilla", "Demark"])
[pp, r1, r2, r3, s1, s2, s3] = ta.pivotpoints(pivotType, pivotTimeframe, high, low, close, 1)

// Plotting (as above)
plot(pp,   title="Pivot Point",    color=color.purple,   linewidth=2, style=plot.style_stepline)
plot(r1,   title="Resistance 1",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r2,   title="Resistance 2",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r3,   title="Resistance 3",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(s1,   title="Support 1",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s2,   title="Support 2",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s3,   title="Support 3",      color=color.green,    linewidth=1, style=plot.style_stepline)

// Breakout logic: Price closes decisively above/below a pivot level
// Check for prior bar close below/above the level to confirm a true breakout
longBreakoutCondition = close > r1 and close[1] <= r1[1] and volume > volume[1] * 1.5 // Break above R1 with higher volume
shortBreakoutCondition = close < s1 and close[1] >= s1[1] and volume > volume[1] * 1.5 // Break below S1 with higher volume

if (longBreakoutCondition)
    strategy.entry("Long Breakout R1", strategy.long)

if (shortBreakoutCondition)
    strategy.entry("Short Breakout S1", strategy.short)

// Exit: Target next pivot level or fixed profit/loss
strategy.exit("Long Breakout R1 Exit", from_entry="Long Breakout R1", profit=r2, stop=pp)
strategy.exit("Short Breakout S1 Exit", from_entry="Short Breakout S1", profit=s2, stop=pp)

3. Trend Bias with Pivot Point (PP)

The central Pivot Point (PP) can act as an excellent indicator of the intraday trend bias. Its position relative to the current price tells you if buyers or sellers are in control for the day.

//@version=5
indicator("Pivot Point Trend Bias", overlay=true)

pivotTimeframe = input.string("D", title="Pivot Timeframe", options=["D", "W", "M"])
pivotType = input.string("Classic", title="Pivot Type", options=["Classic", "Fibonacci", "Woodie", "Camarilla", "Demark"])
[pp, r1, r2, r3, s1, s2, s3] = ta.pivotpoints(pivotType, pivotTimeframe, high, low, close, 1)

// Plotting (as above)
plot(pp,   title="Pivot Point",    color=color.purple,   linewidth=2, style=plot.style_stepline)
plot(r1,   title="Resistance 1",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r2,   title="Resistance 2",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(r3,   title="Resistance 3",   color=color.red,      linewidth=1, style=plot.style_stepline)
plot(s1,   title="Support 1",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s2,   title="Support 2",      color=color.green,    linewidth=1, style=plot.style_stepline)
plot(s3,   title="Support 3",      color=color.green,    linewidth=1, style=plot.style_stepline)

// Determine intraday bias based on price relative to PP
isBullishBias = close > pp
isBearishBias = close < pp

// Color background to easily visualize bias
bgcolor(isBullishBias ? color.new(color.teal, 95) : na, title="Bullish Intraday Bias")
bgcolor(isBearishBias ? color.new(color.maroon, 95) : na, title="Bearish Intraday Bias")

// Plot arrows on price crossing PP to show bias shift
plotarrow(ta.crossover(close, pp) ? close : na, title="Bias Shift Up", colorarrow=color.new(color.aqua, 0), style=plot.style_circles, offset=-bar_index+bar_index[1])
plotarrow(ta.crossunder(close, pp) ? close : na, title="Bias Shift Down", colorarrow=color.new(color.orange, 0), style=plot.style_circles, offset=-bar_index+bar_index[1])

Optimizing Pivot Points Performance

To get the most from Pivot Points in Pine Script:

Predictable Levels: Pivot Points are unique because they are fixed and known at the beginning of the trading period, allowing traders to plan their strategies in advance.

Common Pivot Points Pitfalls

Conclusion

Pivot Points are a foundational and highly valued technical indicator available in Pine Script for TradingView. By providing pre-calculated levels of potential support, resistance, and reversals, they offer traders a clear framework for navigating intraday and short-term price movements. While their primary strength lies in identifying these static levels, their true power is unlocked when combined with price action, volume analysis, and other confirming indicators. By understanding their calculation, thoughtfully selecting the appropriate timeframe and type, and integrating them strategically into your pine script strategies, you can leverage Pivot Points to enhance your decision-making, improve your entry/exit timing, and better manage risk in dynamic markets.