Exponential Moving Average in Python
- Intrendias

- Jun 27, 2024
- 2 min read
Learn how to calculate one of the most popular technical analysis measurements in python! Similar to the Simple Moving Average (SMA), the Exponential Moving Average (EMA) is a rolling average value that adds some spice! The EMA has additional weight on values closer to the present day to increase the importance of most recent data. This blog post will show you how to perform Exponential Moving Averages in Python!

Import Needed Libraries
import yfinance as yf import pandas as pd import matplotlib.pyplot as plt from datetime import timedelta, datetime, dateCreate a Custom Yahoo Finance GET Data Function
def GetYahooFinanceData(ticker, start, end): formatDate = "%Y-%m-%d" # Add 1 day to end date end = datetime.strptime(end, formatDate) end = end + timedelta(days = 1) #add one day to end date to get desired result end = end.strftime(formatDate) #converts back to a string type date df = yf.download(ticker, start, end) return df symbol = 'AAPL'stock_data = GetYahooFinanceData(symbol,'2022-01-01','2024-02-15')stock_data[*********************100%%**********************] 1 of 1 completed
Out[1]:
Open | High | Low | Close | Adj Close | Volume | |
Date | ||||||
2022-01-03 | 177.830002 | 182.880005 | 177.710007 | 182.009995 | 179.724564 | 104487900 |
2022-01-04 | 182.630005 | 182.940002 | 179.119995 | 179.699997 | 177.443573 | 99310400 |
2022-01-05 | 179.610001 | 180.169998 | 174.639999 | 174.919998 | 172.723587 | 94537600 |
2022-01-06 | 172.699997 | 175.300003 | 171.639999 | 172.000000 | 169.840240 | 96904000 |
2022-01-07 | 172.889999 | 174.139999 | 171.029999 | 172.169998 | 170.008118 | 86709100 |
... | ... | ... | ... | ... | ... | ... |
2024-02-09 | 188.649994 | 189.990005 | 188.000000 | 188.850006 | 188.850006 | 45155200 |
2024-02-12 | 188.419998 | 188.669998 | 186.789993 | 187.149994 | 187.149994 | 41781900 |
2024-02-13 | 185.770004 | 186.210007 | 183.509995 | 185.039993 | 185.039993 | 56529500 |
2024-02-14 | 185.320007 | 185.529999 | 182.440002 | 184.149994 | 184.149994 | 54630500 |
2024-02-15 | 183.550003 | 184.490005 | 181.350006 | 183.860001 | 183.860001 | 65434500 |
533 rows × 6 columns
Now Calculate the EMA!
# Calculate EMA12, EMA128 EMA200 stock_data['EMA12'] = stock_data['Close'].ewm(span=12, min_periods=0, adjust=False).mean() stock_data['EMA128'] = stock_data['Close'].ewm(span=128, min_periods=0, adjust=False).mean() stock_data['EMA200'] = stock_data['Close'].ewm(span=200, min_periods=0, adjust=False).mean() stock_dataOpen | High | Low | Close | Adj Close | Volume | EMA12 | EMA128 | EMA200 | |
Date | |||||||||
2022-01-03 | 177.830002 | 182.880005 | 177.710007 | 182.009995 | 179.724564 | 104487900 | 182.009995 | 182.009995 | 182.009995 |
2022-01-04 | 182.630005 | 182.940002 | 179.119995 | 179.699997 | 177.443573 | 99310400 | 181.654610 | 181.974181 | 181.987009 |
2022-01-05 | 179.610001 | 180.169998 | 174.639999 | 174.919998 | 172.723587 | 94537600 | 180.618516 | 181.864813 | 181.916691 |
2022-01-06 | 172.699997 | 175.300003 | 171.639999 | 172.000000 | 169.840240 | 96904000 | 179.292591 | 181.711871 | 181.818017 |
2022-01-07 | 172.889999 | 174.139999 | 171.029999 | 172.169998 | 170.008118 | 86709100 | 178.196807 | 181.563935 | 181.722017 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2024-02-09 | 188.649994 | 189.990005 | 188.000000 | 188.850006 | 188.850006 | 45155200 | 188.726492 | 184.599864 | 180.690855 |
2024-02-12 | 188.419998 | 188.669998 | 186.789993 | 187.149994 | 187.149994 | 41781900 | 188.483954 | 184.639401 | 180.755125 |
2024-02-13 | 185.770004 | 186.210007 | 183.509995 | 185.039993 | 185.039993 | 56529500 | 187.954114 | 184.645612 | 180.797760 |
2024-02-14 | 185.320007 | 185.529999 | 182.440002 | 184.149994 | 184.149994 | 54630500 | 187.368865 | 184.637928 | 180.831116 |
2024-02-15 | 183.550003 | 184.490005 | 181.350006 | 183.860001 | 183.860001 | 65434500 | 186.829039 | 184.625867 | 180.861254 |
533 rows × 9 columns
Why Stop Here? Automate Buy and Sell Signals!
# Initialize buy and sell columns stock_data['Buy_Signal'] = 0 stock_data['Sell_Signal'] = 0#iterate through the dataframe using a for loop for i in range(1,len(stock_data)): if (stock_data['EMA12'][i] > stock_data['EMA128'][i]) and (stock_data['EMA12'][i-1] <= stock_data['EMA128'][i-1]): stock_data['Buy_Signal'][i] = 1 elif (stock_data['EMA12'][i] < stock_data['EMA128'][i]) and (stock_data['EMA12'][i-1] >= stock_data['EMA128'][i-1]): stock_data['Sell_Signal'][i] = -1Visualize Your New Trading Algorithm!
plt.figure(figsize=(20,8))#Lines - Close and EMA Linesplt.plot(stock_data.index, stock_data['Close'], label='Close Price', color = 'black')plt.plot(stock_data.index, stock_data['EMA12'], label='EMA12', color = 'blue')plt.plot(stock_data.index, stock_data['EMA128'], label='EMA128', color = 'red')plt.plot(stock_data.index, stock_data['EMA200'], label='EMA200', color = 'green')# Plot buy and sell signals buy_signals = stock_data[stock_data['Buy_Signal'] == 1]plt.scatter(buy_signals.index, buy_signals['Close'], marker='^', color='g', label='Buy Signal', s=100) sell_signals = stock_data[stock_data['Sell_Signal'] == -1]plt.scatter(sell_signals.index, sell_signals['Close'], marker='v', color='r', label='Sell Signal', s=100)plt.title(f'{symbol} Price with EMA and Trading Signals')plt.xlabel('Date')plt.ylabel(f'{symbol} Price')plt.legend() plt.show()But How Does the Algorithm Perform?
initial_capital = 10000position = 0capital = initial_capitalbought_and_held_capital = capital bought_and_held_shares = capital / stock_data['Close'][0]#Simulate trading for i in range(len(stock_data)): if stock_data['Buy_Signal'][i] == 1: #Buy 10,000 worth of the asset shares_to_buy = capital / stock_data['Close'][i] position += shares_to_buy capital -= shares_to_buy * stock_data['Close'][i] elif stock_data['Sell_Signal'][i] == -1: #Sell all shares capital += position * stock_data['Close'][i] position = 0 # Update bought and held strategy bought_and_held_capital = bought_and_held_shares * stock_data['Close'][i] #Calculate final value algorithm_final_value = capital + position * stock_data['Close'][-1]bought_and_held_final_value = bought_and_held_capitalalgorithm_final_percent = (algorithm_final_value - initial_capital)/initial_capitalbought_and_held_final_percent = (bought_and_held_final_value - initial_capital)/initial_capital# Print resultsprint("Algorithm Final Value: $", algorithm_final_value, "%: ", round(algorithm_final_percent*100,1))print("Bought and Held Final Value: $", bought_and_held_final_value, "%: ", round(bought_and_held_final_percent*100,1))Algorithm Final Value: $ 10217.106243115186 %: 2.2 Bought and Held Final Value: $ 10101.643105288162 %: 1.0
We see the algorithm slightly performing better on AAPL stock compared to a buy and held position with the algorithm up 2.2% while AAPL itself is up 1%. The algorithm is not perfect and not expected to outperform in each scenario. I hope you enjoy the EMA algorithm and the code! Happy trading!
*Intrendias is not financial advice.



Comments