Pine Script

Pine Script Bid-Ask Spread Monitor for Tick Charts

How to use Pine Script bid and ask variables for real-time spread analysis, market microstructure, and tick-level trading strategies.

Tom Hartman

Marketing

Reviewed by Mike Christensen

Fact-checked by Mike Christensen

10 Min Read
BluSky — The Future of Trading. Prop firm futures trading. Sign up at BluSky.pro.

Bottom Line

  • Pine Script added bid and ask built-in variables in February 2025 providing real-time market prices
  • bid represents the highest price an active buyer will pay and ask represents the lowest price an active seller will accept
  • These variables are only available on the 1T tick timeframe and return na on all other timeframes
  • Use bid and ask to build spread monitors liquidity indicators and market microstructure analysis tools

Every financial market operates through a two-sided auction. Buyers post the highest price they are willing to pay and sellers post the lowest price they will accept. The gap between those two prices is the bid-ask spread, and it tells you more about market conditions than most indicators ever will. In February 2025 TradingView added two built-in variables to Pine Script that give you direct access to these prices on tick charts1.

This guide explains what the bid and ask variables are, how to use them on the 1T timeframe, and how to build practical spread analysis tools that monitor liquidity and market microstructure in real time.

What Are Bid and Ask Prices

Before diving into Pine Script code, it helps to understand what bid and ask prices represent in market microstructure. These two prices define the core mechanics of how every trade happens on an exchange.

Bid: The highest price that an active buyer is currently willing to pay for an instrument. If you want to sell immediately at the market price, you will receive the bid price. The bid represents current demand.

Ask: The lowest price that an active seller is currently willing to accept for an instrument. If you want to buy immediately at the market price, you will pay the ask price. The ask represents current supply.

Spread: The difference between the ask and the bid. A narrow spread indicates high liquidity and tight competition among market makers. A wide spread signals lower liquidity, higher trading costs, or increased uncertainty.

The spread is essentially the cost of immediacy. When you place a market order, you cross the spread. Understanding how the spread behaves throughout the trading day gives you an edge in timing entries and exits.

The New Variables

The February 2025 Pine Script update introduced two new built-in variables that provide direct access to real-time market prices at the tick level1.

bid

The bid variable returns a series float value representing the highest price an active buyer is willing to pay for the instrument at the time of the current tick2. It is a built-in variable that requires no function call or library import.

//@version=6
indicator("Bid Price Display", overlay = true)
plot(bid, "Bid", color.green)

ask

The ask variable returns a series float value representing the lowest price an active seller will accept for the instrument at the time of the current tick2. Like bid, it is a built-in variable available without any additional setup.

//@version=6
indicator("Ask Price Display", overlay = true)
plot(ask, "Ask", color.red)

Both variables update only when a new tick arrives. If the bid or ask values change between ticks without a new trade occurring, those changes will not be reflected until the next tick fires3. This is an important distinction for very fast markets where quote updates may happen more frequently than actual trades.

The 1T Timeframe Requirement

The bid and ask variables are only available on the 1T tick timeframe2. On every other timeframe, including seconds, minutes, daily, and weekly charts, both variables return na. This is not a bug or a limitation you can work around. Tick-level data is fundamentally different from time-based data, and bid-ask information only exists at the individual tick level.

You can verify whether your chart is on the correct timeframe before attempting to use these variables. The timeframe.isticks built-in variable returns true when the current resolution is a tick resolution2.

//@version=6
indicator("Timeframe Check", overlay = true)
if not timeframe.isticks
    runtime.error("This indicator requires the 1T tick timeframe. Bid and ask data is not available on other timeframes.")
plot(bid, "Bid", color.green)
plot(ask, "Ask", color.red)

This guard pattern prevents the indicator from displaying misleading empty plots on non-tick charts. Instead, it raises a clear runtime error telling the user what timeframe is required.

Why Only Tick Data

Time-based bars aggregate many ticks into a single candle. During that aggregation, the bid and ask prices change many times. A 1-minute bar might contain hundreds of individual ticks, each with different bid and ask values. There is no single bid or ask price that meaningfully represents an entire time-based bar3. The open, high, low, and close of a candle already capture the trade price movement, but those are transaction prices, not quote prices.

Tick data preserves the individual quote-level granularity that makes bid-ask analysis meaningful. Each tick represents a single moment where the market had specific bid and ask prices, and that precision is what makes spread analysis valuable.

Calculating the Spread

The bid-ask spread is simply the difference between the ask price and the bid price. In Pine Script, this calculation is straightforward.

//@version=6
indicator("Basic Spread", overlay = false)
float spread = ask - bid
plot(spread, "Spread", color.orange, 2)

You can also express the spread as a percentage of the mid-price, which normalizes it across instruments with different price levels. A 0.01 spread on a $10 stock is very different from a 0.01 spread on a $500 stock.

//@version=6
indicator("Spread Percentage", overlay = false)
float midPrice = (bid + ask) / 2.0
float spreadPct = midPrice > 0 ? ((ask - bid) / midPrice) * 100.0 : na
plot(spreadPct, "Spread %", color.purple, 2)

This percentage-based spread calculation is especially useful when comparing liquidity conditions across different instruments or when monitoring how spread behavior changes relative to price movements.

Building a Spread Monitor

A practical spread monitor indicator combines the raw spread calculation with a moving average to show how the current spread compares to its recent history. Spikes above the average often signal increased volatility or reduced liquidity.

//@version=6
indicator("Spread Monitor", overlay = false)

//@variable The lookback period for the average spread calculation.
int lengthInput = input.int(50, "Average Length", minval = 1)
//@variable The multiplier for the high-spread threshold.
float multInput = input.float(2.0, "Threshold Multiplier", minval = 0.5, step = 0.5)

// Ensure we are on a tick timeframe.
if not timeframe.isticks
    runtime.error("Switch to the 1T timeframe to use this indicator.")

//@variable The current bid-ask spread in price units.
float spread = ask - bid

//@variable The simple moving average of the spread over the lookback period.
float avgSpread = ta.sma(spread, lengthInput)

//@variable The threshold above which the spread is considered elevated.
float threshold = avgSpread * multInput

//@variable Color changes based on whether spread exceeds the threshold.
color spreadColor = spread > threshold ? color.red : color.green

// Plot the spread and its average.
plot(spread, "Spread", spreadColor, 2)
plot(avgSpread, "Average Spread", color.gray, 1, plot.style_line)
plot(threshold, "Threshold", color.new(color.red, 70), 1, plot.style_line)

// Highlight the background when spread is elevated.
bgcolor(spread > threshold ? color.new(color.red, 90) : na, title = "Wide Spread Alert")

This indicator plots three lines. The green or red line is the current tick-by-tick spread. The gray line is the rolling average spread. The faded red line is the threshold, set at a configurable multiple of the average. When the spread exceeds the threshold, the plot turns red and the background highlights, alerting you to unusual conditions.

Building a Spread Histogram

A histogram view can make spread changes easier to read at a glance. By plotting the deviation of the current spread from its average, you get a clear visual of when spreads are tighter or wider than normal.

//@version=6
indicator("Spread Histogram", overlay = false)

int lengthInput = input.int(100, "Lookback Length", minval = 1)

if not timeframe.isticks
    runtime.error("This indicator requires the 1T tick timeframe.")

float spread = ask - bid
float avgSpread = ta.sma(spread, lengthInput)

//@variable The deviation of the current spread from the average. Positive means wider than normal.
float deviation = spread - avgSpread

//@variable Green when the spread is tighter than average, red when wider.
color histColor = deviation > 0 ? color.red : color.green

// Plot the deviation as a histogram.
plot(deviation, "Spread Deviation", histColor, 2, plot.style_histogram)
// Plot a zero line for reference.
hline(0, "Zero", color.gray)

Green bars below the zero line mean the spread is tighter than average, which generally indicates good liquidity and lower trading costs. Red bars above zero mean the spread is wider than average, suggesting reduced liquidity or increased volatility. This visual pattern helps you quickly identify the best and worst times to execute trades.

Monitoring Spread Changes

Beyond static measurement, tracking how the spread changes over time reveals patterns in market behavior. Spreads tend to widen at market open, narrow during peak trading hours, and widen again near the close. Monitoring these transitions helps you understand the rhythm of the market you are trading.

//@version=6
indicator("Spread Change Tracker", overlay = false)

int fastLen = input.int(20, "Fast MA Length", minval = 1)
int slowLen = input.int(100, "Slow MA Length", minval = 1)

if not timeframe.isticks
    runtime.error("This indicator requires the 1T tick timeframe.")

float spread = ask - bid
float fastMA = ta.sma(spread, fastLen)
float slowMA = ta.sma(spread, slowLen)

//@variable True when the fast moving average of spread crosses above the slow, signaling widening.
bool widening = ta.crossover(fastMA, slowMA)
//@variable True when the fast moving average of spread crosses below the slow, signaling tightening.
bool tightening = ta.crossunder(fastMA, slowMA)

plot(fastMA, "Fast Spread MA", color.orange, 2)
plot(slowMA, "Slow Spread MA", color.blue, 1)
fill(plot(fastMA, display = display.none), plot(slowMA, display = display.none),
     fastMA > slowMA ? color.new(color.red, 85) : color.new(color.green, 85),
     title = "Spread Zone")

// Mark transitions with shapes.
plotshape(widening, "Widening", shape.triangleup, location.bottom, color.red, size = size.small)
plotshape(tightening, "Tightening", shape.triangledown, location.top, color.green, size = size.small)

This dual moving average approach to spread monitoring works similarly to how traders use price crossovers. When the fast spread MA crosses above the slow, spreads are widening. The opposite crossover signals tightening. The filled zone between the two lines gives you an instant visual read on the current spread regime.

Limitations

The bid and ask variables are powerful additions to Pine Script, but they come with specific constraints you should understand before building strategies around them.

  • The variables return na on all timeframes except 1T, including other tick multiples like 5T or 10T2
  • Values update only on new ticks, so bid-ask changes between ticks are not captured3
  • Tick data availability varies by broker and instrument, and historical tick data may be limited3
  • Strategies running on tick charts consume significantly more computational resources than those on time-based charts
  • Not all instruments provide bid and ask data through TradingView data feeds3

These constraints mean that bid-ask analysis in Pine Script is best suited for real-time monitoring and intraday analysis rather than long-term backtesting3. Historical tick data is often limited to a few days or weeks depending on the data provider.

Conclusion

The bid and ask variables introduced in the February 2025 Pine Script update1 open up an entire category of market microstructure analysis that was previously impossible in TradingView. By providing direct access to real-time quote prices on the 1T tick timeframe2, these variables let you build spread monitors, liquidity indicators, and execution timing tools that go far beyond traditional price-based analysis.

The key concepts to remember are that bid represents demand and ask represents supply, the spread between them measures liquidity and trading costs, and all of this data is only available on the 1T timeframe. Start with the basic spread calculation and then layer on moving averages and threshold alerts to build a monitoring system that fits your trading style.

Once you have built indicators that identify favorable spread conditions, you can connect your TradingView alerts to automated execution through TradersPost4. By sending webhook signals from your tick-based spread analysis to TradersPost, you can automate entries and exits that account for real-time liquidity conditions, helping you avoid executing trades during periods of unusually wide spreads.

References

1 Pine Script Release Notes — February 2025
2 Pine Script v6 Language Reference
3 Pine Script User Manual
4 TradersPost — Automated Trading Platform

All In Pine Script
  • Pine Script Mar 9, 2026

    Export Constants from Pine Script Libraries (v6)

    How to export constant variables from Pine Script libraries to share reusable values like ratios, thresholds, and configuration across multiple scripts.

  • Pine Script Mar 9, 2026

    How to Automate Pine Script Strategies

    How to automate your Pine Script v6 strategies with TradersPost webhooks, from alert setup to live broker execution with supported brokers.

  • Pine Script Mar 9, 2026

    What Changed in the Pine Script Editor in 2025

    Pine Script developer experience improvements from 2025: unlimited scopes, 10x longer strings, the new Pine Editor layout, and flexible line wrapping.

  • Pine Script Mar 9, 2026

    Pine Script Multi-Symbol Screener Tutorial

    How to build a multi-symbol dashboard in Pine Script v6 using dynamic requests to compare prices, RSI, and volume across multiple tickers.

Start trading at scale today. Sign up for free.

Free 7-day trial

Set-up in 3 minutes

Paper account for testing

TradersPost operates as a non-custodial automated trading platform, enabling users to connect alerts from their preferred trading platforms to their selected brokerage or exchange accounts. It abstains from the transmission, custody, or management of customer funds, covering both traditional and cryptocurrency assets. Typically, registration requirements set by regulatory entities such as the SEC, FINRA, or FinCEN apply to entities that hold or transmit customer funds. To ensure ongoing compliance, TradersPost regularly engages with regulatory authorities to confirm its adherence to all relevant local and federal laws.

TradersPost does not provide alerts, signals, research, analysis, or trading advice of any kind. It is designed to assist traders and investors in making their own trading decisions based on their alerts. The platform does not offer recommendations regarding securities to buy or sell, nor does it provide trading or investing advice. The platform and its features, capabilities, and tools are provided 'as-is' without any warranty.

Risk Disclosure: The use of automated trading systems involves inherent risks, including the potential for significant financial loss. These systems operate based on predetermined algorithms that may not fully adapt to changing market conditions, possibly making them unsuitable for some investors. Individuals are advised to thoroughly assess their financial situation and risk tolerance before using this platform.

Testimonials appearing on this website may not be representative of other clients or customers and is not a guarantee of future performance or success.

© 2026 TradersPost, Inc. All rights reserved.