Simple Moving Average (SMA) vs Exponential Moving Average (EMA) in Pine Script & Python

emasma.png

Moving averages are commonly used in analyzing stock prices. They can be used on their own, in combination with other indicators, and in calculations of many widely known indicators. There are different kinds of moving averages. The most commonly used ones are Simple Moving Average (SMA) and Exponential Moving Average (EMA).

SMA is an average price of an asset for a given time period. It is calculated by dividing the sum of the prices in the desired time period or amount of candles on the chart. Following is the formula for SMA:

sma.png

Unlike SMA, calculating EMA is not that simple and each price in the chosen range doesn't have the same weight. The most recent prices have greater weight and EMA reacts faster to the more recent price changes.

An exponential moving average (EMA) is a type of moving average (MA) that places a greater weight and significance on the most recent data points. An exponentially weighted moving average reacts more significantly to recent price changes than a simple moving average (SMA), which applies an equal weight to all observations in the period. ~ Investopedia

Here is the formula for EMA:

ema.png

I don't want to bore you with the actual calculation of the EMA. Luckily for us, we don't have do the calculations ourselves when using Pine Script or Python. They provide functions to do the calculations for us already. However, one thing I would note to remember is that previous day's EMA is used to calculated present day's EMA. This piece of information will become useful when using EMA in python.

Pine Script is a native scripting language build by and for Tradingview. Pine Script tries to make it super easy for traders to build their own indicators, strategies, perform backtesting, etc. Let's explore how to plot SMAs and EMAs with Pine Script and build something completely useless.

The top screenshot shows two lines on the chart: blue and yellow. Yellow line is an SMA-50 and blue line is an EMA-20. When yellow line or SMA-50 crosses over blue line EMA-20 we get a red triangle with 'Sell' label on top of it. Similarly when the yellow line crosses below blue line we get a green triangle with 'Buy' label below. While these signals make seem ok on the chart, they are completely useless. They do not work for price prediction. I am using this just as example of how we can utilize EMAs and SMAs on Pine Script. Let's take a look at the code now.

//@version=4
study("EMA20-SMA50", overlay=true)

ema20 = ema(close,20)
sma50 = sma(close,50)

buy = crossover(ema20, sma50)
sell = crossover(sma50, ema20)

plot(ema20, color=color.blue, linewidth=2)
plot(sma50, color=color.yellow, linewidth=2)

plotshape(buy, style=shape.triangleup, size=size.normal, title='SMA25', color=color.green,text='Buy',location=location.belowbar, transp=0)
plotshape(sell, style=shape.triangledown, size=size.normal, title='SMA25', color=color.red,text='Sell',location=location.abovebar, transp=0)

As you can see from the code above moving averages can easily be calculated using built-in Pine Script functions like ema() and sma(). Then we can plot the lines with plot() annotation function. Another useful built-in function is crossover(), which returns boolean value and we can easily identify when values in two separate series intersect. That's how we can know where to plot our buy and sell signals. Finally we use plotshape()function to display buy sell signals.

Using these simple built in functions we can create and experiment with various price actions scenarios. Following screenshot is another completely useless buy sell signal indicator using 33 EMAs and one SMA. Signals are displayed when SMA-25 crosses above or below all 33 EMAs (ema-1 to ema-33).

emasma2.png

Now, let's explore how we can calculate SMAs and EMAs using python. Pine Script and Tradingview are great, I use them all the time. However, python gives more flexibility in automating repetitive tasks and applying strategies to thousands of assets in minutes, and narrowing down list of assets for manual review and analysis. Using both Pine Script and Python to simplify trading strategies can be really useful.

When I get historical price data for a given asset, I normally get in a form of pandas dataframe. In cases when data is returned in other formats like json, it can be converted to pandas dataframe to apply further calculations. Pandas makes really easy to work with series of data like prices.

Consider we have a dataframe for Bitcoin and is named df. Normally this dataframe will have collums like df['Open'], df['High'], df['Low'], df['Close'] which represent open, high, low, close prices for a given day or candlestick. We can create a new column for our SMA-50 as following:

df['SMA50'] = df['Close'].rolling(window=50).mean()

That's it. That's how easy it is to calculate SMAs in python.

When it comes to calculating EMA, it is not that simple. Although pandas does provide a function for calculating EMA, its original use doesn't behave as expected. Remember EMA formula uses the previous EMA? Feel free to scroll up to see the formula again. This is where the challenge is. Let's say we need EMA-20. Our first EMA value will need to be based on first twenty prices in the list, and since we don't have an EMA yet we need to calculate SMA for the very first 20 prices. Then we can continue calculating rest of the EMAs results. Let's look at the code.

sma = df['Close'].rolling(window=20, min_periods=20).mean[:20]
rest = df['Close'][20:]
ema = pd.concat([sma,rest]).ewm(span=20, adjust=False).mean()

Changing the number 20, we can calculate EMA for different ranges. What the first line is doing is getting an SMA value only for the first 20 prices and creating a series for the first 20 values. In essence first 19 values have value of None, and the 20th one has the average of first 20.

Then the second line creating another series starting with prices at the 21st value. After that we concatenate the two to apply the EMA functions. The last line is where the EMA is calculate is done by ewm() functions, which stands for 'exponentially weighted moving average'. Using EMA by itself without the first two lines creates unexpected results. I did try to use emw() by itself and compared the results on Tradingview and didn't get the expected results. With the above solution of splitting the series of price data, calculating first SMA, then concatenating the back before applying ewm() seem to work just fine. Splitting and concatenating the parts of the series is important because the length of the original data series from the dataframe column must remain same.

H2
H3
H4
3 columns
2 columns
1 column
4 Comments
Ecency