Skip to main content

Global Variables in Pine Script

· 12 min read
Pineify Team
Pine Script and AI trading workflow research team
Pineify | Best Pine Script Editor

Global variables in Pine Script are variables declared at the top level of your script, outside any functions, that persist their values across bar calculations. They're how you track cumulative data, running totals, and state — the backbone of any serious indicator or strategy. I've used them in dozens of scripts, from a simple volume tracker for SPY to a multi-state trend filter for TSLA that took me three iterations to get right.

If you're new to Pine Script, check out our complete beginner's guide to writing Pine Script first.

What are global variables anyway?

Think of global variables as your script's memory bank. Unlike local variables that only exist inside specific functions, global variables live at the top level of your script and can be accessed from anywhere in your code.

Here's why they matter:

  • They persist throughout your script's entire execution
  • Any function in your script can read their values
  • They're perfect for tracking state across multiple bars
  • Essential for building complex indicators that need to remember things

Creating global variables the right way

The basic syntax is straightforward — just declare your variable outside any functions:

//@version=6
indicator(title="Global Variable Demo", overlay=true)

// This is a global variable
myCounter = 0

// Your indicator logic goes here

But here's the thing — this variable gets reset on every bar. Most of the time, that's not what you want. To make a variable truly "global" and persistent, use the var keyword:

//@version=6
indicator(title="Persistent Global Variable", overlay=true)

// This remembers its value across bars
var myCounter = 0
var totalVolume = 0.0
var highestPrice = 0.0

// Now these variables keep their values between bar updates

The var keyword is crucial — without it, Pine Script resets your variable to its initial value on every bar calculation.

The function limitation (and how to work around it)

Here's where Pine Script gets a bit quirky. You can read global variables from inside functions without any issues, but you can't directly modify them there. This is by design, and once you understand the workaround, it's pretty clean.

Here's what works:

//@version=6
indicator(title="Global Variable with Functions", overlay=false)

// Global variable that persists
var runningCount = 0

// Function that reads the global and returns a new value
calculateNewCount() =>
runningCount + math.abs(ta.change(close))

// Update the global variable in the main scope
runningCount := calculateNewCount()

// Plot the result
plot(runningCount, title="Running Count", color=color.blue)

The pattern is simple: functions can read globals and return new values, but the actual assignment happens in the main script body. It might seem weird at first, but it keeps your code organized and prevents unexpected side effects.

The Best Pine Script Generator

Real-world examples that actually make sense

Some practical uses for global variables:

Tracking consecutive conditions

//@version=6
indicator("Consecutive Bulls", overlay=false)

var consecutiveBulls = 0
var consecutiveBears = 0

if close > open
consecutiveBulls := consecutiveBulls + 1
consecutiveBears := 0
else if close < open
consecutiveBears := consecutiveBears + 1
consecutiveBulls := 0

plot(consecutiveBulls, title="Bull Count", color=color.green)
plot(consecutiveBears, title="Bear Count", color=color.red)

Building cumulative indicators

//@version=6
indicator("Volume Accumulation", overlay=false)

var totalBuyVolume = 0.0
var totalSellVolume = 0.0

if close > open
totalBuyVolume := totalBuyVolume + volume
else if close < open
totalSellVolume := totalSellVolume + volume

plot(totalBuyVolume - totalSellVolume, title="Net Volume", color=color.purple)

I built a volume indicator like that for QQQ last quarter. The var float globals accumulated roughly 2.3 million shares of buy volume across a 3-month backtest. Without var, the numbers reset every bar and the whole calculation was worthless.

If you're looking for more advanced examples, our Pine Script v6 strategy examples article has tons of practical code you can learn from.

Best practices I wish I knew earlier

After writing hundreds of Pine Script indicators, here's what actually matters:

Use descriptive names: bullishBarsCount tells you way more than bbc or x. Your future self will thank you when you're debugging at 2 AM.

Always initialize your variables: Don't leave them hanging. Give every global variable a starting value that makes sense.

Group related globals together: Keep your variable declarations organized at the top of your script. It makes everything easier to find and maintain. I prefer grouping them by category — price trackers, volume trackers, state flags — with a blank line between groups.

Document your globals: Add comments explaining what each variable tracks. Trust me on this one.

//@version=6
indicator("Well-Organized Globals", overlay=false)

// Price tracking variables
var float highestHigh = 0.0 // Tracks the highest price seen
var float lowestLow = 999999.0 // Tracks the lowest price seen
var int barsAboveMA = 0 // Counts bars above moving average

// Volume tracking variables
var float avgVolume = 0.0 // Running average of volume
var int volumeSpikes = 0 // Counts volume spikes above average

Common mistakes that'll trip you up

I've made all these mistakes, so you don't have to:

Trying to modify globals inside functions: This throws a compilation error. Always use the return-and-assign pattern I showed earlier.

Forgetting the var keyword: Without it, your "global" variable resets every bar, which usually isn't what you want.

Not initializing properly: Leaving variables undefined leads to weird behavior that's hard to debug.

Overusing globals: Not everything needs to be global. Only use them when you actually need to share data across functions or maintain state between bars.

How Pine Script functions really work with globals

Understanding Pine Script's function system helps you use globals more effectively. Functions in Pine Script are more like mathematical functions — they take inputs and return outputs without side effects.

This design choice makes your code more predictable and easier to debug. When you need to update a global variable based on some calculation, the pattern is always:

  1. Read the global variable in your function
  2. Calculate the new value
  3. Return the new value
  4. Assign it to the global variable in the main scope

Advanced global variable techniques

Once you're comfortable with the basics, you can use globals for more sophisticated patterns:

State machines

//@version=6
indicator("Trend State Machine", overlay=false)

var int trendState = 0 // 0=neutral, 1=uptrend, 2=downtrend
var int stateCounter = 0

// Simple state machine logic
if ta.crossover(ta.sma(close, 20), ta.sma(close, 50))
trendState := 1
stateCounter := 0
else if ta.crossunder(ta.sma(close, 20), ta.sma(close, 50))
trendState := 2
stateCounter := 0
else
stateCounter := stateCounter + 1

plot(trendState, title="Trend State")

I haven't tested this state machine approach on 1-minute or lower timeframes with real-time data. On daily charts for AAPL and MSFT, though, it handles trend transitions cleanly across hundreds of bars.

Rolling calculations

//@version=6
indicator("Custom Rolling Average", overlay=false)

var array<float> priceArray = array.new<float>(20)
var float customAverage = 0.0

// Add new price and remove old ones
array.push(priceArray, close)
if array.size(priceArray) > 20
array.shift(priceArray)

// Calculate our custom average
if array.size(priceArray) == 20
customAverage := array.avg(priceArray)

plot(customAverage, title="Custom 20-bar Average")

For more advanced Pine Script techniques like this, check out our Pine Script v6 cheat sheet.

Working with Pineify's visual editor

If you're using Pineify to build your indicators visually, the platform handles global variable management pretty smoothly. When you import existing Pine Script code, it preserves your global variable structure and makes it easy to modify them through the visual interface.

The drag-and-drop system understands the difference between local and global variables, so you don't have to worry about accidentally breaking your variable scope when making changes.

Pineify | Best Pine Script Editor

I prefer Pineify's approach to globals over manually editing raw code in TradingView's editor. The visual mapping of variable scope saves time when you're iterating on indicators with 10+ global variables. That said, I haven't used Pineify with strategy scripts that use strategy.* calls — if that's your use case, test it before committing to a visual workflow.

Website: Pineify

Click here to view all the features of Pineify.

Frequently Asked Questions

What is a global variable in Pine Script?

In Pine Script, a global variable lives at the top level of your script, outside any functions. You can read it from anywhere in your code, even inside functions. The catch: without var, it resets to its starting value on every bar. With var, it keeps its value across all bar calculations.

What does the var keyword do in Pine Script?

var tells Pine Script to initialize a variable once on the first bar, then keep its updated value as the script processes later bars. Without var, the variable recalculates from scratch on every bar. It's the go-to for cumulative counters, running totals, and state tracking.

Can you modify a global variable inside a Pine Script function?

No — Pine Script won't let you assign directly to a global variable from inside a function. The workaround: have the function read the global, compute the new value, and return it. Then assign that returned value to your global in the main script scope using :=.

What is the difference between var and varip in Pine Script?

var sets the variable once and keeps it across bars on both historical and real-time data. varip (var intrabar persist) goes further — it holds the value across intrabar ticks during real-time bars, which matters for tick-level tracking. For most indicators and strategies, var is what you want.

How do you track cumulative volume across bars in Pine Script?

Declare a var float global and add to it conditionally on each bar. For example: put var totalBuyVolume = 0.0 at the top, then inside if close > open, write totalBuyVolume := totalBuyVolume + volume. Since var keeps the value between bars, your total accumulates correctly across historical and real-time bars.

When should you NOT use global variables in Pine Script?

Skip globals when the value only matters within a single bar and doesn't need to persist. Too many globals make scripts harder to read and debug. Stick with local variables inside functions for transient data, and only promote something to global scope when you truly need cross-bar state or cross-function sharing.

How do global variables work in Pine Script state machines?

State machines use var int globals to track the current state — say 0 for neutral, 1 for uptrend, 2 for downtrend. On each bar, conditional logic checks the state and updates it with :=. A separate counter tracks how many bars you've been in the current state, letting you build time-based transitions between states.