batteriesinfinity.com

Generating Trading Signals Using SMA, MACD, and Bollinger Bands

Written on

Chapter 1: Understanding the Basics of Trading Signals

In trading, there are primarily two philosophies that guide decisions on when to buy and sell stocks: Technical Analysis and Fundamental Analysis.

Technical Analysis focuses on examining price movements and patterns of a stock or ticker. In contrast, Fundamental Analysis assesses metrics such as cash flow, revenue, valuation, and industry trends.

While Technical Analysis relies heavily on numerical data—particularly price and volume—its effectiveness is often seen in the short term. Conversely, for long-term growth, the strength of the underlying business remains crucial.

In essence, Technical Analysis aims to predict the future prices of financial assets by analyzing historical market data, rooted in principles like the belief that history tends to repeat itself, all information is reflected in price, and trends can be identified in time-series data.

Technical Analysis is the foundation for:

Algorithmic, Automated, or Rule-Based Trading. Indicators such as the Relative Strength Index (RSI), Moving Averages, Oscillators, and Candlestick Patterns are employed to identify overbought or oversold conditions, trend strength, or potential reversals. This article will explore how to generate buy and sell signals using some of these indicators.

Module Utilized: Pandas TA

Pandas TA is a user-friendly library built on top of Pandas that offers over 130 indicators and utility functions, along with more than 60 candlestick patterns.

To install the library, simply open your terminal, activate your conda environment, and run the following command:

pip install pandas-ta

1.1 Importing Required Libraries

To begin, we need several packages including Pandas and NumPy. If these are not installed, you can do so using pip:

import numpy as np

import pandas as pd

import yfinance as yf

import pandas_datareader.data as web

import pandas_ta as ta

import matplotlib.pyplot as plt

from datetime import date

plt.style.use('fivethirtyeight')

yf.pdr_override()

1.2 Data Extraction

For our analysis, we will use TATAMOTORS, a highly liquid stock that is well-suited for our strategies. The following code extracts the necessary data:

stocksymbols = ['TATAMOTORS.NS']

startdate = date(2017, 8, 4)

end_date = date.today()

print(end_date)

def getMyPortfolio(stocks=stocksymbols, start=startdate, end=end_date):

data = web.get_data_yahoo(stocks, data_source='yahoo', start=start, end=end)

return data

data = getMyPortfolio(stocksymbols)

1.3 Strategy Implementation

#### Simple Moving Averages (SMA)

We will begin with a straightforward indicator, the Simple Moving Average. This involves averaging the closing prices over a specified period to smooth out trends and illustrate the general direction:

data['SMA 30'] = ta.sma(data['Close'], 30)

data['SMA 100'] = ta.sma(data['Close'], 100)

#### Buy and Sell Signal Function

Next, we implement a function to generate buy and sell signals based on the SMA strategy:

def buy_sell(data):

signalBuy = []

signalSell = []

position = False

for i in range(len(data)):

if data['SMA 30'][i] > data['SMA 100'][i]:

if not position:

signalBuy.append(data['Adj Close'][i])

signalSell.append(np.nan)

position = True

else:

signalBuy.append(np.nan)

signalSell.append(np.nan)

elif data['SMA 30'][i] < data['SMA 100'][i]:

if position:

signalBuy.append(np.nan)

signalSell.append(data['Adj Close'][i])

position = False

else:

signalBuy.append(np.nan)

signalSell.append(np.nan)

else:

signalBuy.append(np.nan)

signalSell.append(np.nan)

return pd.Series([signalBuy, signalSell])

data['Buy_Signal_price'], data['Sell_Signal_price'] = buy_sell(data)

1.4 Visualization

To visualize the buy and sell signals, we can create a plot:

fig, ax = plt.subplots(figsize=(14, 8))

ax.plot(data['Adj Close'], label=stocksymbols[0], linewidth=0.5, color='blue', alpha=0.9)

ax.plot(data['SMA 30'], label='SMA30', alpha=0.85)

ax.plot(data['SMA 100'], label='SMA100', alpha=0.85)

ax.scatter(data.index, data['Buy_Signal_price'], label='Buy', marker='^', color='green', alpha=1)

ax.scatter(data.index, data['Sell_Signal_price'], label='Sell', marker='v', color='red', alpha=1)

ax.set_title(f"{stocksymbols[0]} Price History with Buy and Sell Signals", fontsize=10, backgroundcolor='blue', color='white')

ax.set_xlabel(f'{startdate} - {end_date}', fontsize=18)

ax.set_ylabel('Close Price INR (₨)', fontsize=18)

legend = ax.legend()

ax.grid()

plt.tight_layout()

plt.show()

Output:

This code visualizes our buy and sell levels, indicating that moving averages are effective for identifying long-term trends, aiding in decisions to buy, sell, or hold.

1.5 Moving Average Convergence Divergence (MACD)

The MACD indicator utilizes two exponential moving averages (EMA)—a short-term and a long-term. It provides three columns: the MACD line, the Signal line (EMA of the MACD), and the MACD histogram.

macd = ta.macd(data['Close'])

data = pd.concat([data, macd], axis=1).reindex(data.index)

When the MACD line crosses above the Signal line, a long position is recommended. Conversely, a cross below indicates a potential short position.

1.6 MACD Strategy Implementation

The following function applies our MACD strategy with a risk factor:

def MACD_Strategy(df, risk):

MACD_Buy = []

MACD_Sell = []

position = False

for i in range(len(df)):

if df['MACD_12_26_9'][i] > df['MACDs_12_26_9'][i]:

MACD_Sell.append(np.nan)

if not position:

MACD_Buy.append(df['Adj Close'][i])

position = True

else:

MACD_Buy.append(np.nan)

elif df['MACD_12_26_9'][i] < df['MACDs_12_26_9'][i]:

MACD_Buy.append(np.nan)

if position:

MACD_Sell.append(df['Adj Close'][i])

position = False

else:

MACD_Sell.append(np.nan)

elif position and df['Adj Close'][i] < MACD_Buy[-1] * (1 - risk):

MACD_Sell.append(df["Adj Close"][i])

MACD_Buy.append(np.nan)

position = False

elif position and df['Adj Close'][i] < df['Adj Close'][i - 1] * (1 - risk):

MACD_Sell.append(df["Adj Close"][i])

MACD_Buy.append(np.nan)

position = False

else:

MACD_Buy.append(np.nan)

MACD_Sell.append(np.nan)

df['MACD_Buy_Signal_price'] = MACD_Buy

df['MACD_Sell_Signal_price'] = MACD_Sell

data = MACD_Strategy(data, 0.025)

1.7 MACD Visualization

To visualize the MACD signals:

plt.rcParams.update({'font.size': 10})

fig, ax1 = plt.subplots(figsize=(14, 8))

fig.suptitle(stocksymbols[0], fontsize=10, backgroundcolor='blue', color='white')

ax1.set_ylabel('Price in ₨')

ax1.plot('Adj Close', data=data, label='Close Price', linewidth=0.5, color='blue')

ax1.scatter(data.index, data['MACD_Buy_Signal_price'], color='green', marker='^', alpha=1)

ax1.scatter(data.index, data['MACD_Sell_Signal_price'], color='red', marker='v', alpha=1)

ax1.legend()

ax1.grid()

ax1.set_xlabel('Date', fontsize=8)

ax2 = plt.subplot2grid((14, 8), (10, 0), rowspan=6, colspan=14)

ax2.set_ylabel('MACD', fontsize=8)

ax2.plot('MACD_12_26_9', data=data, label='MACD', linewidth=0.5, color='blue')

ax2.plot('MACDs_12_26_9', data=data, label='Signal', linewidth=0.5, color='red')

ax2.bar(data.index, 'MACDh_12_26_9', data=data, label='Volume', color=data.positive.map({True: 'g', False: 'r'}), width=1, alpha=0.8)

ax2.axhline(0, color='black', linewidth=0.5, alpha=0.5)

ax2.grid()

plt.show()

1.8 Bollinger Bands (BB)

Bollinger Bands are commonly used in trading due to their power and simplicity. They consist of three lines: the Upper Band, the Middle Band, and the Lower Band. The upper and lower bands are typically set two standard deviations away from the mean closing price, capturing over 80% of price action.

#### BB Strategy Function

def bb_strategy(data):

bbBuy = []

bbSell = []

position = False

bb = ta.bbands(data['Adj Close'], length=20, std=2)

data = pd.concat([data, bb], axis=1).reindex(data.index)

for i in range(len(data)):

if data['Adj Close'][i] < data['BBL_20_2.0'][i]:

if not position:

bbBuy.append(data['Adj Close'][i])

bbSell.append(np.nan)

position = True

else:

bbBuy.append(np.nan)

bbSell.append(np.nan)

elif data['Adj Close'][i] > data['BBU_20_2.0'][i]:

if position:

bbBuy.append(np.nan)

bbSell.append(data['Adj Close'][i])

position = False

else:

bbBuy.append(np.nan)

bbSell.append(np.nan)

else:

bbBuy.append(np.nan)

bbSell.append(np.nan)

data['bb_Buy_Signal_price'] = bbBuy

data['bb_Sell_Signal_price'] = bbSell

return data

data = bb_strategy(data)

1.9 BB Visualization

To visualize the Bollinger Bands:

fig, ax1 = plt.subplots(figsize=(14, 8))

fig.suptitle(stocksymbols[0], fontsize=10, backgroundcolor='blue', color='white')

ax1.set_ylabel('Price in ₨')

ax1.plot(data['Adj Close'], label='Close Price', linewidth=0.5, color='blue')

ax1.scatter(data.index, data['bb_Buy_Signal_price'], color='green', marker='^', alpha=1)

ax1.scatter(data.index, data['bb_Sell_Signal_price'], color='red', marker='v', alpha=1)

ax1.legend()

ax1.grid()

ax1.set_xlabel('Date', fontsize=8)

ax2 = plt.subplot2grid((14, 8), (10, 0), rowspan=6, colspan=14)

ax2.plot(data['BBM_20_2.0'], label='Middle', color='blue', alpha=0.35)

ax2.plot(data['BBU_20_2.0'], label='Upper', color='green', alpha=0.35)

ax2.plot(data['BBL_20_2.0'], label='Lower', color='red', alpha=0.35)

ax2.fill_between(data.index, data['BBL_20_2.0'], data['BBU_20_2.0'], alpha=0.1)

ax2.legend(loc='upper left')

ax2.grid()

plt.show()

Output:

Our strategy assumes that any closing price that breaches the Bollinger Bands signals a high probability of price reversion. However, caution is advised, as external events may influence stock behavior.

Conclusion

In conclusion, the realm of Technical Analysis is extensive, with numerous indicators available. Understanding the fundamental principles behind these indicators is vital for crafting a successful trading strategy, whether by combining them or developing entirely new indicators. As we delve deeper into Algorithmic Trading using these technical indicators, the complexity will inevitably increase. I hope you found this article informative!

Learn how to build a Bollinger Bands and RSI trading strategy using Python.

Discover how to create buy and sell signals with Bollinger Bands on the MACD indicator in TradingView PineScript V5.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Exploring the Connection Between Formaldehyde and Dementia

This article examines how formaldehyde, produced in the brain, may relate to dementia and cognitive decline, especially as we age.

Unlocking the Extraordinary Skill Most People Lack

Discover how to elevate your skills from average to extraordinary with effective learning strategies.

Understanding the Balance of Masculine and Feminine Energies

Exploring the interplay of masculine and feminine principles within us can enhance self-perception and relationships.