Pine Script – Lesson 8: Higher Timeframe EMA
Working With Higher Timeframes
& Security Function
Today’s lesson will cover how to access higher timeframe price data in your custom Pine Script indicators.
The reasons you might want to do this are too numerous to list, but in today’s lesson we’ll focus on creating an indicator that draws a higher timeframe’s EMA to our chart.
The functions and features that we’ll use to achieve this will give me a good opportunity to demonstrate a handful of Pine Script features we haven’t covered yet – such as the security() function and the resolution input.
As always, this lesson builds on the knowledge from previous lessons, so if anything doesn’t make sense here please go back through the other lessons where everything we’re using up until now should be explained.
So, without any further ado – let’s get started!
First of all, here’s the video version that compliments this lesson:
Step 1: Getting User Input
The first step as always is to get our script parameters (or settings) from the user.
We’re going to need to get 4 inputs for this lesson. The first one is the higher timeframe we want to reference, the second is the EMA period length we’d like to use, the third is whether or not to color the EMA based on price being above or below it, and the fourth is whether to smooth the EMA or not.
These settings will make more sense as we go, so I won’t spend any more time explaining them.
The way we get a timeframe input is using the input.resolution data type. So in Pine Script code, it would look something like this:
res = input(title="EMA Timeframe", type=input.resolution, defval="D")
This line of code will prompt the user to choose their timeframe from a drop-down box in the settings menu. By default, this “res” variable will be set to “D” – which is short for the Daily chart timeframe.
The other 3 inputs use data types we’ve already covered in previous lessons, so I won’t go into detail about them. We need the EMA Length as an integer, the Color EMA as a boolean, and the Smooth setting as a boolean (or checkbox).
They should look something like this:
len = input(title="EMA Length", type=input.integer, defval=50) col = input(title="Color EMA", type=input.bool, defval=true) smooth = input(title="Smooth", type=input.bool, defval=false)
Step 2: Get EMA Value Using HTF Data
The next step is to retrieve the EMA value using the timeframe input we just defined (with the variable name “res”).
To do this we need to first define our EMA variable, and then later we can input the EMA variable into the security() function to reference higher timeframe price data.
This probably sounds confusing, but don’t worry – as usual with Pine Script it’s extremely simple. It looks something like this:
ema = ema(close, len) emaSmooth = security(syminfo.tickerid, res, ema, barmerge.gaps_on, barmerge.lookahead_off) emaStep = security(syminfo.tickerid, res, ema, barmerge.gaps_off, barmerge.lookahead_off)
I’ll break down each line of code separately and explain what’s happening.
In line 1, we’re creating an EMA variable using the closing price and a period length of 50 – which is the default setting for our input variable named “len”.
If we plot this to our chart we will get the current 50 EMA for whatever timeframe we have our chart set to as any normal EMA would plot. But we don’t want this – we want this EMA variable to be calculated using the higher timeframe closing price.
So in line 2 we’re using the security() function to request higher timeframe data (in this case, the HTF closing price run through the inbuilt EMA function).
The security() function takes several input parameters.
1st Input: Symbol
The first is the “symbol” or instrument ID – such as “EUR/USD”, “AAPL”, or “BTC/ETH”. In this lesson we don’t want to access another instrument’s data, we just want to access the current instrument’s higher timeframe, so we can use syminfo (short for symbol info) to access its ticker name (syminfo.tickerid).
2nd Input: Resolution
The second input is the timeframe resolution we want to reference – in this case “res” which is a timeframe determined by the user in the settings menu.
3rd Input: Requested Data
The third input is what price action data we want to request from the higher timeframe – in this case, we want the “ema” variable to be calculated using higher timeframe data.
Because the “ema” is using the closing price to calculate its value, this means the security() function will return the EMA value based on the closing price from the timeframe “res” (Daily chart by default).
When using the security() function to calculate the HTF EMA value we have two options we can work with in order to deal with gaps in price.
4th Input: Gaps
One is to use barmerge.gaps_on, which will merge any price action gaps between plotting to the chart (in essence, smoothing the EMA – which is why we call this variable “emaSmooth”).
I’m sure this is confusing for many rookie coders, but I’ll do my best to explain what this means.
Remember that if we’re drawing the Daily chart’s EMA to our 1HR chart, it is not a smooth line by default. The reason for this is that the Daily chart EMA is calculated based on the closing price for each day.
So if you have an instrument that trades 24 hours per day such as crypto or forex, then the Daily EMA requires 24 hourly bars to close before the next EMA calculation is made.
What this results in is a “stepped” appearance to the EMA if we draw it to a lower timeframe, like so:
That is a Daily chart EMA being plotted to a 1HR chart.
Notice that each time a new day closes, the EMA “steps” down by several pips and then draws as a solid horizontal line throughout the next trading session.
This is the “natural” way to draw this EMA to the chart, because the Daily chart EMA is only calculated every 24 hours and so any smoothing that occurs on lower timeframes is not the “real” Daily EMA value but a 1HR average between each Daily close.
If we were to use barmerge.gaps_on, it will look like this:
Obviously this option looks much “better” in an aesthetic sense. We’re used to seeing moving averages smoothed like this, but the EMA value plotted to the chart on each 1HR bar is not the real Daily EMA but a predictive average.
It’s essentially averaging the steps into a smoothed line. Depending on your trading style and preferences, you may prefer one drawing style over the other – which is why I’ve included the option to choose one or the other.
I hope that makes sense. If not, feel free to leave a comment below or study the official TradingView documentation.
5th Input: Lookahead
The final input that the security() function takes is a lookahead boolean value.
If lookahead is set to true then the script will reference the current closing price on live data, and on historical data, it will essentially “cheat” by drawing that day’s daily EMA based on the day’s closing price – which ordinarily we would not know until after the day had closed.
By default “lookahead” is set to false, so you technically don’t need to set this parameter if you don’t want to, But it’s always a good idea to declare these parameters yourself as a beginner so that you know what it’s set to.
Now alternatively, if we set lookahead to be turned on, then the script will literally be looking ahead in time and time-travelling to the future to reference data from when that particular market’s higher timeframe already closed.
This means that historical bars will cheat and know the future, and currently active bars will “repaint”.
There are many reasons you might want this, but in today’s script, we do not want this to happen.
So if we set lookahead to false then on the lower timeframe the script will draw the previous day’s closing price over the top of current price action, which makes a lot more sense if you want to trade using this information.
Given the fact that yesterday’s Daily chart has already closed, it’s safe to reference that data in historical price action – whereas if our script is referencing the current day’s Daily closing price before it closes this can cause all kinds of trouble and give us a false reading on the accuracy of any strategies we try to backtest using this indicator.
So in this particular case, we want to set barmerge.lookahead to off. This will also help with “repainting”, but that’s another topic for another day.
Again – I know this is complex to understand and it’s difficult to explain, so if any of this didn’t make sense or you’d like to study it in further detail then I encourage you to read the official documentation about this topic.
I’ll go into more detail about repainting and how to circumvent it in the next lesson. For now, let’s just focus on understanding the security() function.
Step 3: Drawing the HTF EMA
The final step is to plot our higher timeframe EMA to the chart.
We created two EMA variables – one that is smooth using “barmerge.gaps_on”, and one that is stepped using “barmerge.gaps_off”.
We don’t want to draw both of these to the chart at the same time, so we can use the conditional operator (which looks something like this: “boolean ? codeIfTrue : codeIfFalse”).
We’ve also included an option to color the EMA based on whether price is above or below it. This can also be achieved using two conditional operators on the one line.
Therefore our final line of code will look something like this:
plot(smooth ? emaSmooth : emaStep, color=col ? close > emaStep ? color.green : color.red : color.black, style=plot.style_line, linewidth=2, title="EMA (HTF)")
Here we are saying if the smooth option is selected, plot the “emaSmooth” value to the chart – otherwise plot the “emaStep” value to the chart.
Then we’re saying:
If the color option “col” is set to true, then if the current closing price is above the “emaStep” value set the color to green, otherwise set it to red – and if the color option is set to false, then ignore price action and set the color to black.
Then we’re setting the plot style to style_line, the line width to 2, and we’re titling the drawing to “EMA (HTF)” so that our users can change these style settings in the options menu.
And that’s it! We’re done. If you save your script and add it to the chart, it should look something like this by default:
If you want to take your Pine Script coding to the next level, then I think you’ll be interested in my Pine Script Mastery Course.
If you liked this free content then I promise that you’ll love my premium content where I am able to go into much greater detail and help answer students’ questions!
//@version=4 study(title="Higher Timeframe EMA", shorttitle="EMA+", overlay=true) // Get user input res = input(title="EMA Timeframe", type=input.resolution, defval="D") len = input(title="EMA Length", type=input.integer, defval=50) col = input(title="Color EMA", type=input.bool, defval=true) smooth = input(title="Smooth", type=input.bool, defval=false) // Calculate EMA ema = ema(close, len) emaSmooth = security(syminfo.tickerid, res, ema, barmerge.gaps_on, barmerge.lookahead_off) emaStep = security(syminfo.tickerid, res, ema, barmerge.gaps_off, barmerge.lookahead_off) // Draw EMA plot(smooth ? emaSmooth : emaStep, color=col ? close > emaStep ? color.green : color.red : color.black, style=plot.style_line, linewidth=2, title="EMA (HTF)")