Properly Using Heikin-Ashi Candles in Pine Script
Heikin-Ashi candles are a popular way to display price in TradingView, helping reduce market noise and make trend identification easier. Although these candles look similar to regular candlesticks, there is one very important difference:
The Open, High, Low, and Close values of Heikin-Ashi candles are not necessarily actual market prices.
This distinction becomes especially important when developing indicators and, in particular, trading strategies and backtests. If a programmer uses Heikin-Ashi values in their code without taking this difference into account, the indicator or strategy may behave differently from what they expect.
In this tutorial, we first examine how Heikin-Ashi candles are calculated, then explain how to access this data in Pine Script, and finally discuss one of the most important topics: using Heikin-Ashi in trading strategies and backtesting.
Regular Candles vs. Heikin-Ashi
In a standard candlestick chart, each candle has four main values:
- Open: Opening price
- High: Highest price
- Low: Lowest price
- Close: Closing price
These values come directly from market data. So, for example, if the Open of a candle is $3,145, that represents the actual market price when that candle opened.
With Heikin-Ashi, however, things are different.
Heikin-Ashi is a type of non-standard price chart whose OHLC values are calculated using specific formulas based on actual market data and the Heikin-Ashi values of previous candles. Therefore, these values are synthetic prices, not prices at which the market necessarily traded. (TradingView)
As a result, when we examine the same candle on a standard chart and a Heikin-Ashi chart, the Open, High, Low, and Close values may be different.
Heikin-Ashi Calculation Formula
To properly understand how Heikin-Ashi behaves in Pine Script, it is useful to first understand how these candles are calculated.
We can represent the Heikin-Ashi values using HA. The formulas are as follows.
Close
The Heikin-Ashi closing price is calculated as the average of the four actual prices of the same candle:
HA Close = (Open + High + Low + Close) / 4
Therefore, calculating HA Close does not require data from the previous Heikin-Ashi candle.
Open
The Open is calculated differently:
HA Open = (HA Open[1] + HA Close[1]) / 2
In other words, the Open of the current Heikin-Ashi candle is calculated from the average of the Open and Close of the previous Heikin-Ashi candle.
Therefore, calculating the Open of each candle requires information from the previous candle.
This sequential dependency is an important consideration when implementing Heikin-Ashi in Pine Script.
High
The High is calculated as follows:
HA High = max(High, HA Open, HA Close)
In other words, the highest value among:
- The actual High of the candle
- Heikin-Ashi Open
- Heikin-Ashi Close
is used as the High of the Heikin-Ashi candle.
Low
Similarly:
HA Low = min(Low, HA Open, HA Close)
The lowest value among the actual Low, Heikin-Ashi Open, and Heikin-Ashi Close is selected as the Low of the Heikin-Ashi candle.
Therefore, the formulas can be summarized as follows:
HA Open = (HA Open[1] + HA Close[1]) / 2
HA High = max(High, HA Open, HA Close)
HA Low = min(Low, HA Open, HA Close)
HA Close = (Open + High + Low + Close) / 4
Of course, for the first candle, there is no previous candle, so an initial value for HA Open must be defined appropriately.
The First-Candle Problem in Heikin-Ashi Calculations
As mentioned above, HA Open depends on HA Open[1] and HA Close[1].
However, there is no previous candle when calculating the first candle.
Therefore, we need to define an initial value. There are several ways to do this. The important point is that once the calculation begins, the HA Open value of subsequent candles is calculated sequentially.
In Pine Script, we can use barstate.isfirst to identify the first candle or use a var variable to initialize a value only once.
For example, the general concept can be implemented as follows:
haOpen = barstate.isfirst ? (open + close) / 2 : (haOpen[1] + haClose[1]) / 2
Here, the average of the actual Open and Close of the first candle is used, and from the second candle onward, the standard Heikin-Ashi formula is applied.
An important point is that the initial value has only a very limited effect further along the series because HA Open is continuously recalculated based on subsequent candles.
Implementing Heikin-Ashi in Pine Script
After defining the four OHLC values, we can use plotcandle to display the calculated candles on the chart.
The general structure can look like this:
//@version=6
indicator("Custom Heikin-Ashi", overlay = true)
haClose = (open + high + low + close) / 4
var float haOpen = na
haOpen := barstate.isfirst ? (open + close) / 2 :
(haOpen[1] + haClose[1]) / 2
haHigh = math.max(high, math.max(haOpen, haClose))
haLow = math.min(low, math.min(haOpen, haClose))
haColor = haClose >= haOpen ? color.green : color.red
plotcandle(haOpen, haHigh, haLow, haClose, color = haColor)
With this approach, we can calculate the Heikin-Ashi candles ourselves in Pine Script and display them on a standard chart without changing the chart type to Heikin-Ashi.
This provides an important advantage: the main chart remains a Standard Candles chart, while our calculations can still be based on Heikin-Ashi data.
Using TradingView’s Built-in Functionality
We do not always need to implement the Heikin-Ashi formulas ourselves in Pine Script.
TradingView provides a built-in function for accessing Heikin-Ashi data:
ticker.heikinashi
This function creates a special ticker identifier for Heikin-Ashi data, which can then be passed to request.security to retrieve Heikin-Ashi values. (TradingView)
For example:
haTicker = ticker.heikinashi(syminfo.tickerid)
haClose = request.security(haTicker, timeframe.period, close)
Here:
ticker.heikinashicreates a Heikin-Ashi ticker identifier for the current symbol.request.securityretrieves the corresponding data.closereturns the Heikin-Ashi Close value.
The Open, High, and Low can be retrieved in the same way.
For example:
haOpen = request.security(haTicker, timeframe.period, open)
haHigh = request.security(haTicker, timeframe.period, high)
haLow = request.security(haTicker, timeframe.period, low)
haClose = request.security(haTicker, timeframe.period, close)
TradingView also allows all four OHLC values to be retrieved within a single request.security call using a tuple. (TradingView)
Why Isn’t request.security Always the Best Choice?
request.security is very useful, but in complex scripts, it is important to pay attention to the number of request calls being made.
Suppose that, in addition to Heikin-Ashi data, you also need data from several symbols and multiple timeframes. If you create several separate requests for each calculation, the number of required requests can quickly increase.
For example, if we use four separate requests to retrieve the OHLC values of Heikin-Ashi and repeat the same process for several symbols or timeframes, the total number of requests can increase significantly.
Therefore, if the goal is simply to calculate Heikin-Ashi using data from the same chart and timeframe, directly implementing the formulas at the beginning of the script can sometimes be a better choice.
On the other hand, when you actually need Heikin-Ashi data from another symbol or timeframe, ticker.heikinashi together with request.security is a suitable approach. request.security is specifically designed to retrieve data from different symbol and timeframe contexts. (TradingView)
An Important Point About Indicators
One important consideration when using Heikin-Ashi is its effect on indicators.
Suppose we calculate a 9-period Moving Average using close:
ma = ta.sma(close, 9)
If the chart is using standard candles, close represents the actual market Close.
However, if the chart is using Heikin-Ashi, close represents the synthetic Heikin-Ashi Close.
As a result: SMA on Standard Candles ≠ SMA on Heikin-Ashi
Even if both indicators use exactly the same formula and period.
This is not limited to Moving Averages. Any indicator that uses OHLC data may produce different results when the chart type is changed from Standard Candles to Heikin-Ashi.
A Better Approach: Analyze with Heikin-Ashi, Execute at Actual Market Prices
In many projects, we may want signals to be generated based on Heikin-Ashi, while entry and exit prices remain based on actual market prices.
In such cases, it is generally better to keep the chart on standard candles and retrieve or calculate Heikin-Ashi data inside the script.
For example:
Main chart → Standard Candles
↓
Actual market price
+
Heikin-Ashi data
↓
Indicator calculations
↓
Signal generation
↓
Entry/exit at real prices
This approach is particularly important for strategies.
TradingView also recommends exercising caution when backtesting on non-standard charts such as Heikin-Ashi, because the prices represented by these candles are not actual market prices, while real-world orders are executed at actual market prices. (TradingView)
Why Can Direct Backtesting on Heikin-Ashi Be Problematic?
Suppose our strategy enters a long position whenever two Moving Averages cross upward.
If we run the strategy on a standard chart, the order is simulated using actual market prices.
However, if we switch the chart to Heikin-Ashi, the Open, High, Low, and Close values of the candles are no longer necessarily actual market prices.
As a result, the strategy may assume that a trade was executed at a price that was never actually traded in the market.
This can affect:
- Entry price
- Exit price
- Stop loss
- Take profit
- Profit and loss
- Number of trades
- Risk-to-reward ratio
- Overall backtest results
Therefore, a strategy may show very attractive performance on a Heikin-Ashi chart but fail to produce the same results when actually executed using real market prices.
TradingView also explicitly explains that Heikin-Ashi OHLC values are synthetic and are not suitable for backtesting or automated trading because orders are executed at actual market prices, not Heikin-Ashi prices. (TradingView)
Recommended Approach for Heikin-Ashi Strategies
If your strategy is based on Heikin-Ashi, one suitable approach is to:
1. Keep the chart on Standard Candles.
2. Calculate the Heikin-Ashi values directly in Pine Script or retrieve them using ticker.heikinashi.
3. Calculate your indicators and entry/exit logic using the Heikin-Ashi data.
4. Simulate the orders in the standard chart environment using actual market prices.
For example, if two EMAs are supposed to be calculated based on the Heikin-Ashi Close, instead of changing the chart type, we can first obtain the Heikin-Ashi Close in the script:
haClose = ...
and then:
ema1 = ta.ema(haClose, 9)
ema2 = ta.ema(haClose, 50)
In this case, the analysis logic is based on Heikin-Ashi, while the main chart remains a standard chart.
Conclusion
Heikin-Ashi is not simply a different visual representation of regular candles. It is a set of OHLC values calculated using specific formulas based on actual and historical data. Therefore, the prices displayed by a Heikin-Ashi candle are not necessarily actual market prices.
This distinction is particularly important when programming in Pine Script.
If the goal is simply to make trends easier to identify and reduce market noise, using a Heikin-Ashi chart can be useful. However, if we want to develop an indicator or, especially, a trading strategy based on Heikin-Ashi, we need to distinguish between the data used for analysis and the actual prices used for trading.
There are two main approaches to working with Heikin-Ashi in Pine Script:
Method 1: Calculate Heikin-Ashi Directly
We can implement the Open, High, Low, and Close formulas ourselves in Pine Script.
The advantage of this approach is that we have full control over the data. When we only need Heikin-Ashi data for the same symbol and timeframe, we can also avoid creating multiple request.security calls.
Method 2: Use TradingView’s Built-in Functionality
Using:
ticker.heikinashi
and:
request.security
we can retrieve Heikin-Ashi data directly from TradingView. This approach is particularly useful when we need Heikin-Ashi data for another symbol or timeframe. (TradingView)
But the most important point is:
If your analysis is based on Heikin-Ashi, you do not necessarily need to change the chart itself to Heikin-Ashi.
For many strategies, it is better to keep the chart on Standard Candles, calculate the Heikin-Ashi data inside the script, and perform the analysis using those values. This way, the signals can be based on Heikin-Ashi while entry and exit prices remain tied to actual market prices.
This distinction between analytical data and actual trading prices is one of the key considerations when developing Pine Script strategies and avoiding misleading backtest results.