Pine Script Murrey Math Lines

Master this unique system of horizontal price levels in TradingView's Pine Script, based on W.D. Gann's theories, used to identify potential support, resistance, and crucial turning points in the market.

Last Updated on: Expertise: Advanced

What are Murrey Math Lines?

Murrey Math Lines are a system of geometric price lines derived from the principles of W.D. Gann's squares. Developed by T. H. Murrey, this indicator simplifies Gann's complex theories into a practical set of equally spaced horizontal lines that divide price action into eight "octaves" or zones. These lines are intended to represent major and minor support and resistance levels where price is likely to find equilibrium, reverse, or accelerate.

The core idea behind Murrey Math is that price tends to move in predictable ranges and will often react strongly at specific, harmonically related levels. Each of the nine lines (from 0/8 to 8/8) has a specific interpretation regarding price behavior:

In Pine Script, implementing Murrey Math Lines involves defining a major price range (a "square") and then calculating these octave levels dynamically. They are a powerful tool for visual traders and can inform your pine script strategies for entries, exits, and understanding market structure.

Components and Calculation

The calculation of Murrey Math Lines begins by identifying a significant trading range, often called the "Major Square." This range's highest high and lowest low within a defined period (e.g., 64, 128, or 256 bars) forms the basis. The range is then divided into eight equal parts.


Let `HH` be the Highest High and `LL` be the Lowest Low over a specified `period`.
  1. Determine the Major Square Range: * Find the `Max_Price = ta.highest(high, period)` * Find the `Min_Price = ta.lowest(low, period)` * `Price_Range = Max_Price - Min_Price`
  2. Adjust Price Range to Nearest Power of 2 (for proper scaling): Murrey's method involves scaling the price range to a power of 2 (e.g., 1, 2, 4, 8, 16, 32, 64, 128, etc.) to fit it within a "square." This normalization helps maintain consistency across different assets and price scales. * `Scaled_Range = (math.pow(2, math.ceil(math.log(Price_Range) / math.log(2))))` * `Min_Price_Adjusted = Min_Price - (Scaled_Range - Price_Range) / 2` * `Max_Price_Adjusted = Min_Price_Adjusted + Scaled_Range`
  3. Calculate the Octave Step: * `Octave_Step = Scaled_Range / 8`
  4. Calculate Each Murrey Math Line: * `0/8 Line = Min_Price_Adjusted` * `1/8 Line = Min_Price_Adjusted + Octave_Step` * `2/8 Line = Min_Price_Adjusted + (2 * Octave_Step)` * `3/8 Line = Min_Price_Adjusted + (3 * Octave_Step)` * `4/8 Line = Min_Price_Adjusted + (4 * Octave_Step)` (Median Line) * `5/8 Line = Min_Price_Adjusted + (5 * Octave_Step)` * `6/8 Line = Min_Price_Adjusted + (6 * Octave_Step)` * `7/8 Line = Min_Price_Adjusted + (7 * Octave_Step)` * `8/8 Line = Max_Price_Adjusted`

These lines will remain constant for the period defined by the `lookbackPeriod` input until a new highest high or lowest low is established, forcing a recalculation of the "Major Square."

Basic Murrey Math Lines Implementation in Pine Script

Since Pine Script does not have a built-in `ta.murreyMathLines()` function, we will implement the calculation logic directly using standard Pine Script functions.

//@version=5
indicator("My Murrey Math Lines", overlay=true, max_bars_back=500) // overlay=true to plot on price chart.

// --- User Inputs ---
// Period for identifying the major square (highest high and lowest low)
lookbackPeriod = input.int(256, title="Lookback Period (Bars for Major Square)", minval=64, maxval=500)
lineTransparency = input.int(0, title="Line Transparency (0-100)", minval=0, maxval=100)
showLabels = input.bool(true, title="Show Level Labels")

// --- Calculate Murrey Math Levels ---
// 1. Find Highest High and Lowest Low over the lookback period
highestHigh = ta.highest(high, lookbackPeriod)
lowestLow = ta.lowest(low, lookbackPeriod)

// We only recalculate the base prices if a new significant high or low occurs.
// This makes the lines stable for periods and then shift.
var float mmHighest = na
var float mmLowest = na
var float mmRange = na

// Recalculate MM base levels when a new highest high or lowest low is found within the lookback
// Use `ta.highestbars` and `ta.lowestbars` to find if the current high/low is the period's extreme
if (high[0] == highestHigh and bar_index == bar_index[ta.highestbars(high, lookbackPeriod)]) or
   (low[0] == lowestLow and bar_index == bar_index[ta.lowestbars(low, lookbackPeriod)])

    // 2. Adjust Price Range to Nearest Power of 2 (for proper scaling)
    priceRange = highestHigh - lowestLow
    
    // Handle cases where priceRange might be zero or too small
    if priceRange == 0
        priceRange := 0.000000001 // Small non-zero value to prevent issues
    
    // Calculate the power of 2 that covers the price range
    pow2 = math.ceil(math.log(priceRange) / math.log(2))
    scaledRange = math.pow(2, pow2)

    // Adjust the lowest price so that the range fits perfectly within the scaledRange
    adjustedLowest = lowestLow - (scaledRange - priceRange) / 2
    
    // Store these values to use for plotting all subsequent bars until a new extreme
    mmHighest := adjustedLowest + scaledRange
    mmLowest := adjustedLowest
    mmRange := scaledRange

// Use `nz()` to carry forward the last calculated levels
mmHighest := nz(mmHighest[1], mmHighest)
mmLowest := nz(mmLowest[1], mmLowest)
mmRange := nz(mmRange[1], mmRange)

// 3. Calculate the Octave Step
octaveStep = mmRange / 8.0

// 4. Calculate Each Murrey Math Line
mm_8_8 = mmHighest
mm_7_8 = mmHighest - octaveStep
mm_6_8 = mmHighest - (2 * octaveStep)
mm_5_8 = mmHighest - (3 * octaveStep)
mm_4_8 = mmHighest - (4 * octaveStep) // Median Line
mm_3_8 = mmLowest + (3 * octaveStep)
mm_2_8 = mmLowest + (2 * octaveStep)
mm_1_8 = mmLowest + octaveStep
mm_0_8 = mmLowest

// --- Plotting Murrey Math Levels ---
// Define colors and styles for each line for easier interpretation
color_8_0 = color.new(color.red, lineTransparency)
color_7_1 = color.new(color.orange, lineTransparency)
color_6_2 = color.new(color.maroon, lineTransparency) // Stronger resistance/support
color_5_3 = color.new(color.gray, lineTransparency)
color_4_4 = color.new(color.purple, lineTransparency) // Median line, strongest
color_line = color.new(color.blue, lineTransparency)

plot(mm_0_8, title="0/8", color=color_8_0, linewidth=1, style=plot.style_stepline)
plot(mm_1_8, title="1/8", color=color_7_1, linewidth=1, style=plot.style_stepline)
plot(mm_2_8, title="2/8", color=color_6_2, linewidth=2, style=plot.style_stepline) // Stronger
plot(mm_3_8, title="3/8", color=color_5_3, linewidth=1, style=plot.style_stepline)
plot(mm_4_8, title="4/8", color=color_4_4, linewidth=3, style=plot.style_stepline) // Strongest
plot(mm_5_8, title="5/8", color=color_5_3, linewidth=1, style=plot.style_stepline)
plot(mm_6_8, title="6/8", color=color_6_2, linewidth=2, style=plot.style_stepline) // Stronger
plot(mm_7_8, title="7/8", color=color_7_1, linewidth=1, style=plot.style_stepline)
plot(mm_8_8, title="8/8", color=color_8_0, linewidth=1, style=plot.style_stepline)

// --- Optional: Add Labels to Lines ---
if showLabels and bar_index == last_bar_index
    // Only draw labels on the current (last) bar for clarity
    label.new(x=bar_index, y=mm_0_8, text="0/8 - Extreme Oversold", style=label.style_label_left, color=color_8_0, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_1_8, text="1/8 - Weak Support", style=label.style_label_left, color=color_7_1, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_2_8, text="2/8 - Strong Support", style=label.style_label_left, color=color_6_2, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_3_8, text="3/8 - Minor Support", style=label.style_label_left, color=color_5_3, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_4_8, text="4/8 - Median Line (Major S/R)", style=label.style_label_left, color=color_4_4, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_5_8, text="5/8 - Minor Resistance", style=label.style_label_left, color=color_5_3, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_6_8, text="6/8 - Strong Resistance", style=label.style_label_left, color=color_6_2, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_7_8, text="7/8 - Weak Resistance", style=label.style_label_left, color=color_7_1, textcolor=color.white, size=size.small)
    label.new(x=bar_index, y=mm_8_8, text="8/8 - Extreme Overbought", style=label.style_label_left, color=color_8_0, textcolor=color.white, size=size.small)


// --- Simple Strategy Example (Conceptual) ---
// This strategy demonstrates how you might react to Murrey Math levels.
// It is highly simplified and for educational purposes only.
// Real trading strategies require more complex confirmation.

strategy("Murrey Math Strategy", overlay=true)

// Use the calculated Murrey Math levels for strategy logic
// Re-calculate the levels to ensure they are available to the strategy
// (This is redundant if the above indicator part is run first, but good practice for standalone strategy)
var float strat_mmHighest = na
var float strat_mmLowest = na
var float strat_mmRange = na

highestHigh_strat = ta.highest(high, lookbackPeriod)
lowestLow_strat = ta.lowest(low, lookbackPeriod)

if (high[0] == highestHigh_strat and bar_index == bar_index[ta.highestbars(high, lookbackPeriod)]) or
   (low[0] == lowestLow_strat and bar_index == bar_index[ta.lowestbars(low, lookbackPeriod)])

    priceRange_strat = highestHigh_strat - lowestLow_strat
    if priceRange_strat == 0
        priceRange_strat := 0.000000001
    
    pow2_strat = math.ceil(math.log(priceRange_strat) / math.log(2))
    scaledRange_strat = math.pow(2, pow2_strat)
    adjustedLowest_strat = lowestLow_strat - (scaledRange_strat - priceRange_strat) / 2
    
    strat_mmHighest := adjustedLowest_strat + scaledRange_strat
    strat_mmLowest := adjustedLowest_strat
    strat_mmRange := scaledRange_strat

strat_mmHighest := nz(strat_mmHighest[1], strat_mmHighest)
strat_mmLowest := nz(strat_mmLowest[1], strat_mmLowest)
strat_mmRange := nz(strat_mmRange[1], strat_mmRange)
strat_octaveStep = strat_mmRange / 8.0

strat_mm_0_8 = strat_mmLowest
strat_mm_1_8 = strat_mmLowest + strat_octaveStep
strat_mm_2_8 = strat_mmLowest + (2 * strat_octaveStep)
strat_mm_3_8 = strat_mmLowest + (3 * strat_octaveStep)
strat_mm_4_8 = strat_mmLowest + (4 * strat_octaveStep)
strat_mm_5_8 = strat_mmLowest + (5 * strat_octaveStep)
strat_mm_6_8 = strat_mmLowest + (6 * strat_octaveStep)
strat_mm_7_8 = strat_mmLowest + (7 * strat_octaveStep)
strat_mm_8_8 = strat_mmHighest


// Strategy Logic: Reversals at 0/8, 8/8, and 4/8 lines (Median Line)

// Buy at 0/8 or 1/8 (extreme oversold/weak support)
longCondition = ta.crossover(close, strat_mm_0_8) or ta.crossover(close, strat_mm_1_8)

// Sell at 8/8 or 7/8 (extreme overbought/weak resistance)
shortCondition = ta.crossunder(close, strat_mm_8_8) or ta.crossunder(close, strat_mm_7_8)

// Additional reversal at 4/8 (Median Line) - can be entry or exit
// If price crosses 4/8 from below, it's bullish. If from above, it's bearish.
long4_8 = ta.crossover(close, strat_mm_4_8)
short4_8 = ta.crossunder(close, strat_mm_4_8)

if (longCondition)
    strategy.entry("Long MM", strategy.long)

if (shortCondition)
    strategy.entry("Short MM", strategy.short)

// Exit logic: Using 4/8 line as profit target or reversal point
// Or using fixed stop loss and profit target based on levels
profitTargetLong = strat_mm_4_8 // Target 4/8 for long
stopLossLong = strat_mm_0_8 - (strat_octaveStep / 2) // Below 0/8, giving some buffer

profitTargetShort = strat_mm_4_8 // Target 4/8 for short
stopLossShort = strat_mm_8_8 + (strat_octaveStep / 2) // Above 8/8, giving some buffer

strategy.exit("Long MM Exit", from_entry="Long MM", profit=profitTargetLong, stop=stopLossLong)
strategy.exit("Short MM Exit", from_entry="Short MM", profit=profitTargetShort, stop=stopLossShort)

Optimizing Murrey Math Lines Performance

To get the most from Murrey Math Lines in Pine Script:

Geometric Harmony: Murrey Math Lines divide price into harmonically related octaves, based on Gann's theory that markets move in predictable, geometric patterns. This offers a unique perspective on price behavior.

Common Murrey Math Lines Pitfalls

Conclusion

Murrey Math Lines offer a fascinating and structured approach to technical analysis in Pine Script for TradingView. Derived from W.D. Gann's theories, these equally spaced horizontal lines provide a unique framework for identifying potential support, resistance, and crucial turning points within various "octaves" of price action. While their calculation requires a clear definition of the "Major Square" and their interpretation benefits from an understanding of each line's significance, mastering Murrey Math can significantly enhance your pine script strategies. By combining these powerful levels with price action confirmation, volume analysis, and other technical tools, you can leverage Murrey Math Lines to improve your decision-making, anticipate market reactions, and gain a deeper understanding of market harmony and equilibrium.