What it does
Heikin-Ashi candles smooth price action and make trends easier to read, but switching the whole chart to them hides the real open and close prices. This indicator works out Heikin-Ashi candles in the background and uses them only to color your normal candles. Real prices stay on the chart, and you still get the cleaner trend picture. Markers and alerts show when the trend changes.
How it works
The standard Heikin-Ashi formulas are used:
- HA close = (open + high + low + close) ÷ 4
- HA open = (previous HA open + previous HA close) ÷ 2 (on the first bar, (open + close) ÷ 2)
- HA high = the highest of high, HA open and HA close; HA low = the lowest of low, HA open and HA close
If the pre-smoothing length is above 1, the regular open, high, low and close are first smoothed with an EMA of that length.
A Heikin-Ashi candle is bullish when HA close is above HA open and bearish when below. The trend flips to up after the set number of consecutive bullish HA candles, and to down after the same number of bearish ones. Candles in an uptrend whose HA candle has a lower wick (or in a downtrend, an upper wick) are drawn in a lighter shade to show weaker momentum. Trend changes are confirmed on candle close.
How to use it
- Use the color as a trend filter: favor long setups while candles are teal and short setups while they are red, using your own entry method.
- Strong, solid-color runs (no opposite wick) usually mark the steadier parts of a trend. A run of light candles often appears as momentum fades.
- Raise "candles needed to flip" to 3 to cut down on flips in choppy markets, at the cost of later signals.
- It pairs well with a level-based tool. The trendlines and moving averages lessons cover common companions.
Alerts: trend turned up, trend turned down.
Settings
| Input | Default | What it changes |
|---|---|---|
| Pre-smoothing EMA length | 1 | Extra smoothing before the HA formula |
| Candles needed to flip trend | 2 | Confirmation needed for a trend change |
| Color chart candles by trend | On | Candle coloring |
| Lighter color for candles with an opposite wick | On | Weak-candle shading |
| Also draw Heikin-Ashi candles | Off | HA overlay |
| Show trend-change markers | On | Triangles on flips |
| Bullish / bearish colors | Teal / red | Appearance only |
Limitations
Heikin-Ashi is a smoothed average, so it lags. Trend changes come after the turn has started, and the confirmation setting adds more delay. In ranges the color flips back and forth. The colors on the live candle can change until it closes; markers and alerts only appear on closed candles. Heikin-Ashi values are not real traded prices, so never use them for stop or target levels.
Pine Script source
In TradingView open Pine Editor, paste the code, click Save and then Add to chart.
FXP_HeikinAshiTrend.pine
69 lines
// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/heikin-ashi-trend/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
// Calculates Heikin-Ashi candles in the background and colors the regular candles by the
// Heikin-Ashi trend, so real prices stay on the chart. A trend change needs a set number
// of consecutive Heikin-Ashi candles in the new direction and is confirmed on bar close.
indicator("FXP Heikin-Ashi Trend", shorttitle = "FXP HA Trend", overlay = true)
// ── Inputs ─────────────────────────────────────────────────────────────
grpCalc = "Calculation"
smoothLen = input.int(1, "Pre-smoothing EMA length", minval = 1, maxval = 50, group = grpCalc, tooltip = "1 = classic Heikin-Ashi. Higher values smooth the open/high/low/close before the Heikin-Ashi formula.")
confirmN = input.int(2, "Candles needed to flip trend", minval = 1, maxval = 10, group = grpCalc)
grpDisp = "Display"
colorBars = input.bool(true, "Color chart candles by trend", group = grpDisp)
shadeWeak = input.bool(true, "Lighter color for candles with an opposite wick", group = grpDisp)
showHa = input.bool(false, "Also draw Heikin-Ashi candles", group = grpDisp)
showSig = input.bool(true, "Show trend-change markers", group = grpDisp)
colBull = input.color(#26a69a, "Bullish", group = grpDisp)
colBear = input.color(#ef5350, "Bearish", group = grpDisp)
// ── Heikin-Ashi ────────────────────────────────────────────────────────
float o = ta.ema(open, smoothLen)
float h = ta.ema(high, smoothLen)
float l = ta.ema(low, smoothLen)
float c = ta.ema(close, smoothLen)
float haClose = (o + h + l + c) / 4
float haOpen = na
haOpen := na(haOpen[1]) ? (o + c) / 2 : (haOpen[1] + haClose[1]) / 2
float haHigh = math.max(h, math.max(haOpen, haClose))
float haLow = math.min(l, math.min(haOpen, haClose))
bool haBull = haClose > haOpen
bool haBear = haClose < haOpen
// "strong" candles have no wick on the side opposite to their direction
bool strongBull = haBull and haLow >= haOpen
bool strongBear = haBear and haHigh <= haOpen
// ── Trend state ────────────────────────────────────────────────────────
var int bullRun = 0
var int bearRun = 0
bullRun := haBull ? bullRun + 1 : 0
bearRun := haBear ? bearRun + 1 : 0
var int trend = 0
int prevTrend = trend
if bullRun >= confirmN
trend := 1
else if bearRun >= confirmN
trend := -1
bool flipUp = barstate.isconfirmed and trend == 1 and prevTrend != 1
bool flipDown = barstate.isconfirmed and trend == -1 and prevTrend != -1
// ── Display ────────────────────────────────────────────────────────────
color trendCol = trend == 1 ? colBull : trend == -1 ? colBear : color.gray
bool weak = (trend == 1 and not strongBull) or (trend == -1 and not strongBear)
color barCol = shadeWeak and weak ? color.new(trendCol, 50) : trendCol
barcolor(colorBars ? barCol : na, title = "Trend candle color")
plotcandle(showHa ? haOpen : na, showHa ? haHigh : na, showHa ? haLow : na, showHa ? haClose : na, "Heikin-Ashi", color = haBull ? color.new(colBull, 60) : color.new(colBear, 60), wickcolor = color.new(color.gray, 60), bordercolor = color.new(color.gray, 80))
plotshape(showSig and flipUp, "Trend up", shape.triangleup, location.belowbar, colBull, size = size.small)
plotshape(showSig and flipDown, "Trend down", shape.triangledown, location.abovebar, colBear, size = size.small)
// ── Alerts ─────────────────────────────────────────────────────────────
alertcondition(flipUp, "Heikin-Ashi trend up", "{{ticker}} {{interval}}: Heikin-Ashi trend turned up at {{close}}")
alertcondition(flipDown, "Heikin-Ashi trend down", "{{ticker}} {{interval}}: Heikin-Ashi trend turned down at {{close}}")

