Creating your own buy/sell signals: Coding up & visualising MACD indicators

Daryl
6 min readSep 27, 2020

--

As part of my quest to familiarise myself with financial time series analysis, i’ve tried reading up on the various techniques, and subsequently reproducing them here on Medium.

In the wise words of a famous scientist, Albert Einstein.

If you can’t explain it, you don’t understand it.

Hence the best way to ensure one understands these concepts, is to attempt to reproduce them from somebody who did before, as well as explain how they work.

These posts of mine, function as some sort of journal for me to track my learning, and hopefully provide insights to anybody on the same journey, who may chance across this post in the future.

I’ve learned plenty from the many authors who post regularly here on Medium, and in a way, I also try to pay it forward.

With that said, lets jump right in.

The MACD indicator

(Moving Average Convergence-Divergence)

The MACD here is a elementary technical analysis indicator, which find its use across numerous asset classes. Stocks, bonds, energy futures, you name it.

In order to explain it in a comprehensible manner, we need to break it down into the various core concepts and understand each one in a satisfactory manner.

The Exponential Moving Average

Understandably, times series data fluctuates constantly and is rarely stable.

To add some semblance of meaning, we work with some form of average.

Credits: Investopedia

However, to just simply take the average value as per elementary arithmetic, would be unwise as it fails to encapsulates the relative importance of more recent data.

Conventional wisdom dictates that recent data is more relevant, in comparison to older data.

Hence the practice of adding a weighted multiplier, to account for the greater relevance and influence of recent data.

Credits: school.stockcharts.com

For a 10 day window, the weightage given to the most recent day, is 18.2%. This is in contrast to an equal weightage of 10%, for each day in a 10 day period.

While the time period in the explanation here is taken as one day, the EMA could just as easily be scaled down to shorter time frames, such as hours, minutes, or seconds.

In financial markets, the most commonly used ones are 9, 12, 26 time periods.

MACD Line

We obtain the MACD line by subtracting the 26 Day EMA from the 12 Day EMA

Credits: Investopedia

Signal line

The signal line is a short term indicator created by creating a Nine Day EMA of the MACD line.

Credits: Ivestopedia; MACD

Most commercial trading software catering to retail investors, will have the MACD feature available.

By sliding the cursor back and forth, one can see the interaction of the MACD lines and signal lines.

For most retail investors, the tools provided by most trading software and smartphones should be adequate.

However, what if you wish to go further and develop your own automated trading strategies?

You might want to incrementally tweak the parameters and backtest your strategy each time.

That is where learning to code your own indicators comes in handy, and that is what we shall be discussing today.

For full disclosure, I completed the following code samples via assistance from this particular youtube video. The person in the video has used Google Colab and downloaded the CSV dataset onto his local set up, and he analyses Apple Stock (AAPL).

In my case, I am using Jupyter Lab, and I import the relevant data directly from the Yahoo Finance Library.

As per some of our previous posts, we shall be loading the stock performance of TESLA (TSLA) this year, 2020.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
tsla_df = yf.download('TSLA',
start='2020-01-01',
end='2020-09-25',
progress=False) #1st Jan 2020 - 25 Sept 2020
tsla_df.head()

Again, we restrict our analysis to the closing price, the column “Close”

df = tsla_df[['Close']]
df.head()

To get a quick look, we attempt to plot the closing prices for each day against the date.

plt.figure(figsize=(12,6))
df['Close'].plot(grid=True)
plt.ylabel('Price ($)')
plt.xlabel('Date')
plt.title('Tesla Price')
plt.show()

Coding and visualising the MACD and Signal lines

As I mentioned earlier, many retail trading apps provide MACD line visualisation. However, most will confine the trader to the standard 9, 12, 26 time periods.

Right below, we can see that coding the MACD line in Python allows one to explicitly state the time periods we wish to use in our employment of MACD.

## MACD Line ##
ShortEMA = df.Close.ewm(span=12, adjust=False).mean()
LongEMA = df.Close.ewm(span=26, adjust=False).mean()
MACD = ShortEMA - LongEMA
## Signal Line ##
signal = MACD.ewm(span=9, adjust=False).mean()
plt.figure(figsize=(12,6))
plt.plot(df.index, MACD, label="TSLA MACD",color='red')
plt.plot(df.index, signal, label='Signal Line',color='green')
plt.legend(loc='upper left')
plt.xticks(rotation=45)
plt.show()

For the most part, MACD and signal lines will be distinct from each other. The times that they cross, are the times which potentially present a buying/selling opportunity.

The following segment defines a function that identifies these points that the lines cross.

For each points that the lines cross, it presents an opportunity.

  1. If the MACD line exceeds the Signal line, from which it was previously below, it suggest the price is lower than usual and presents a chance to enter a position.
  2. If the MACD line falls below the Signal line, from which it was previously above, it suggest one may consider exiting their positions as the price is higher than usual and may fall soon.
  3. If lines do not cross, one should hold.
#function that indicates buy/sell signaldef buy_sell(signal):
Buy = []
Sell = []
flag = -1

for i in range(0, len(signal)):
if signal['MACD'][i] > signal['Signal Line'][i]:
Sell.append(np.nan)
if flag != 1:
Buy.append(signal["Close"][i])
flag = 1
else:
Buy.append(np.nan)
elif signal['MACD'][i] < signal['Signal Line'][i]:
Buy.append(np.nan)
if flag != 0:
Sell.append(signal['Close'][i])
flag = 0

else:
Sell.append(np.nan)

else:
Buy.append(np.nan)
Sell.append(np.nan)

return(Buy, Sell)

Appending our the appropriate indicators to the original dataframe with the raw, unprocessed prices.

df['MACD'] = MACD
df['Signal Line'] = signal
a = buy_sell(df)
df['Buy_Signal_Price'] = a[0]
df['Sell_Signal_Price'] = a[1]
#Show buy/sell signalsplt.figure(figsize=(12,6))
plt.scatter(df.index, df['Buy_Signal_Price'],
color='green',
label='Buy',
marker = '^',
alpha=1)
plt.scatter(df.index, df['Sell_Signal_Price'],
color='red',
label='Sell',
marker = 'v',
alpha=1)
plt.plot(df['Close'], label='Close Price', alpha = 0.9)
plt.title('Close Price; Buy & Sell signals')
plt.xticks(rotation = 45)
plt.xlabel('Date')
plt.ylabel('Close Price USD ($)')
plt.legend(loc='upper left')
plt.show()

Through overlaying the buy/sell indicators onto our price plot, we can see the points at which it suggests entering and exiting positions.

For the default indicators (9, 12, 26), we can see that they hold up surprisingly well.

Closing and next steps

For a human trader:

They will probably be satisfied with this much. If one does not wish to rely on machines for trading, one can probably identify the time periods where the indicators occur, and try to match them to fundamental information.

I.e to try and pin down, what are the possible real world developments that could influence said price movements.

For Automated Trading:

This is where the fun begins ;)

The final chart where the buy/sell indicators are overlaid against the price movements, form the basis of data which can be used to train a machine learning model to recognise signs in which to trade.

By continuously tweaking the parameters here, we can backtest our strategy and train multiple models to see which one gives the best performance.

That is the direction I intend to pursue, going forward.

And that shall be all, for now.

--

--

Daryl
Daryl

Written by Daryl

Graduated with a Physics degree, I write about physics, coding and quantitative finance.

Responses (1)