{"id":1382,"date":"2023-08-01T17:25:58","date_gmt":"2023-08-01T17:25:58","guid":{"rendered":"https:\/\/eodhd.com\/financial-academy\/?p=1382"},"modified":"2024-03-14T09:38:38","modified_gmt":"2024-03-14T09:38:38","slug":"trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","status":"publish","type":"post","link":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","title":{"rendered":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python"},"content":{"rendered":"\n<p id=\"1ded\">Each of the indicators Bollinger Bands, Keltner Channel, and Relative Strength Index are unique in nature and powerful when used individually. But what if we try to combine all these three indicators and create one effective trading strategy out of them? The results would be substantial, and we could be able to eradicate one of the most common problems associated with using technical indicators, which is false signals.<\/p>\n\n\n\n<p id=\"966f\">That\u2019s exactly what we aim to do today. In this article, we will first build some basic intuitions on the indicators, then we will use Python to build them from scratch, construct a trading strategy out of them, backtest the strategy with real-world historical stock data, and compare the results with those of SPY ETF (an ETF specifically designed to track the movement of the S&amp;P 500 market index).<\/p>\n\n\n\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-text-align-center\"><a class=\"maxbutton-1 maxbutton maxbutton-subscribe-to-api external-css btn\" href=\"https:\/\/eodhd.com\/register\"><span class='mb-text'>Register &amp; Get Data<\/span><\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"f405\">Bollinger Bands<\/h1>\n\n\n\n<p id=\"d0d6\">Before jumping on to explore Bollinger Bands, it is essential to know what a simple moving average (SMA) is. A simple moving average is just the average price of a stock given a specified period of time. Now, Bollinger Bands are trend lines plotted above and below the SMA of the given stock at a specific standard deviation level. To understand Bollinger Bands better, have a look at the following chart that represents the Bollinger Bands of the Apple stock calculated with SMA 20.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1801\" height=\"884\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-34.png\" alt=\"A graph of Apple's Bollinger Bands from 2020 to 2023 \" class=\"wp-image-1384\"\/><\/figure>\n\n\n\n<p id=\"d8dc\">Bollinger Bands are great to observe the volatility of a given stock over a period of time. The volatility of a stock is observed to be lower when the space or distance between the upper and lower band is less. Similarly, when the space or distance between the upper and lower band is more, the stock has a higher level of volatility. While observing the chart, you can observe a trend line named \u2018MIDDLE BB 20\u2019 which is the SMA 20 of the Apple stock. The formula to calculate both upper and lowers bands of stock is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>UPPER_BB = STOCK SMA + SMA STANDARD DEVIATION * 2<br>LOWER_BB = STOCK SMA - SMA STANDARD DEVIATION * 2<\/strong><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"defd\">Keltner Channel (KC)<\/h1>\n\n\n\n<p id=\"7cd3\">First introduced by Chester Keltner, the Keltner Channel is a technical indicator that is often used by traders to identify volatility and the direction of the market.&nbsp;The Keltner Channel is composed of three components: The upper band, the lower band, and the middle line.&nbsp;Now, let\u2019s discuss how each of the components is calculated.<\/p>\n\n\n\n<p id=\"e3ce\">Before diving into the calculation of the Keltner Channel it is essential to know about the three important inputs involved in the calculation.&nbsp;First is the ATR (Average True Range) lookback period,&nbsp;which is the number of periods that are taken into account for the calculation of ATR. Secondly, the Keltner Channel lookback period. This input is more or less similar to the first one but here, we are determining the number of periods that are taken into account for the calculation of the Keltner Channel itself.&nbsp;The final input is the multiplier which is a value determined to multiply with the ATR.&nbsp;The typical values that are taken as inputs are 10 as the ATR lookback period, 20 as the Keltner Channel lookback period, and 2 as the multiplier. Keeping these inputs in mind, let\u2019s calculate the readings of the Keltner Channel\u2019s components.<\/p>\n\n\n\n<p id=\"b978\">The first step in calculating the components of the Keltner Channel is determining the ATR values with 10 as the lookback period.<\/p>\n\n\n\n<p id=\"db43\">The next step is calculating the middle line of the Keltner Channel. This component is the 20-day Exponential Moving Average of the closing price of the stock.&nbsp;The calculation can be represented as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>MIDDLE LINE 20<\/strong> = <strong>EMA 20<\/strong> [ <strong>C.STOCK<\/strong> ]\n\nwhere,\nEMA 20 = 20-day Exponential Moving Average \nC.STOCK = Closing price of the stock<\/pre>\n\n\n\n<p id=\"0e2e\">The final step is calculating the upper and lower bands. Let\u2019s start with the upper band. It is calculated by first adding the 20-day Exponential Moving Average of the closing price of the stock by the multiplier (two) and then, multiplied by the 10-day ATR.&nbsp;The lower band calculation is almost similar to that of the upper band but instead of adding, we will be subtracting the 20-day EMA by the multiplier. The calculation of both upper and lower bands can be represented as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>UPPER BAND 20<\/strong> = <strong>EMA 20 <\/strong>[ <strong>C.STOCK <\/strong>] + <strong>MULTIPLIER <\/strong>* <strong>ATR 10\nLOWER BAND 20<\/strong> = <strong>EMA 20 <\/strong>[ <strong>C.STOCK <\/strong>] - <strong>MULTIPLIER <\/strong>* <strong>ATR 10<\/strong>\n\nwhere,\nEMA 20 = 20-day Exponential Moving Average \nC.STOCK = Closing price of the stock\nMULTIPLIER = 2\nATR 10 = 10-day Average True Range<\/pre>\n\n\n\n<p id=\"8490\">That\u2019s the whole process of calculating the components of the Keltner Channel. Now, let\u2019s analyze a chart of the Keltner Channel to build more understanding of the indicator.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1801\" height=\"884\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-35.png\" alt=\"\" class=\"wp-image-1385\"\/><\/figure>\n\n\n\n<p id=\"6663\">The above chart is a graphical representation of Apple\u2019s 20-day Keltner Chanel. We could notice that two bands are plotted on either side of the closing price line and those are the upper and lower band, and the grey-colored line running in between the two bands is the middle line, or the 20-day EMA. The Keltner Channel can be used in an extensive number of ways but the most popular usages are identifying the market volatility and direction.<\/p>\n\n\n\n<p id=\"7140\">The volatility of the market can be determined by the space that exists between the upper and lower band. If the space between the bands is wider, then the market is said to be volatile or showing greater price movements. On the other hand, the market is considered to be in a state of non-volatile or consolidating if the space between the bands is narrow. The other popular usage is identifying the market direction. The market direction can be determined by following the direction of the middle line as well as the upper and lower band.<\/p>\n\n\n\n<p id=\"7aa7\">While looking at the chart of the Keltner Channel,&nbsp;it might resemble the Bollinger Bands. The only difference between these two indicators is the way each of them is calculated. The Bollinger Bands use standard deviation for its calculation, whereas, the Keltner Channel utilizes ATR to calculate its readings.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"0ad5\">Relative Strength Index<\/h1>\n\n\n\n<p id=\"89a3\">Before moving on, let\u2019s first gain an understanding of what an oscillator means in the stock trading space. An oscillator is a technical tool that constructs a trend-based indicator whose values are bound between a high and low band. Traders use these bands along with the constructed trend-based indicator to identify the market state and make potential buy and sell trades. Also, oscillators are widely used for short-term trading purposes, but there are no restrictions in using them for long-term investments.<\/p>\n\n\n\n<p id=\"0f8b\">Founded and developed by J. Welles Wilder in 1978, the Relative Strength Index is a momentum oscillator that is used by traders to identify whether the market is in a state of overbought or oversold. Before moving on, let\u2019s explore what overbought and oversold is. A market is considered to be in the state of overbought when an asset is constantly bought by traders, moving it to an extremely bullish trend and bound to consolidate. Similarly, a market is considered to be in the state of oversold when an asset is constantly sold by traders, moving it to a bearish trend and tends to bounce back.<\/p>\n\n\n\n<p id=\"b248\">Being an oscillator, the values of RSI are bound between 0 to 100. The traditional way to evaluate a market state using the Relative Strength Index is that an RSI reading of 70 or above reveals a state of overbought, and similarly, an RSI reading of 30 or below represents the market is in the state of oversold. These overbought and oversold can also be tuned concerning which stock or asset you choose. For example, some assets might have constant RSI readings of 80 and 20. So in that case, you can set the overbought and oversold levels to be 80 and 20 respectively. The standard setting of RSI is 14 as the lookback period.<\/p>\n\n\n\n<p id=\"62ac\">RSI might sound more similar to Stochastic Oscillator in terms of value interpretation, but the way it\u2019s being calculated is quite different.&nbsp;There are three steps involved in the calculation of RSI:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Calculating the Exponential Moving Average (EMA) of the gain and loss of an asset:<\/strong>&nbsp;A word on Exponential Moving Average. EMA is a type of Moving Average (MA) that automatically allocates greater weighting (nothing but importance) to the most recent data point and lesser weighting to data points in the distant past. In this step, we will first calculate the returns of the asset and separate the gains from losses. Using these separated values, the two EMAs for a specified number of periods are calculated.<\/li>\n\n\n\n<li><strong>Calculating the Relative Strength of an asset:<\/strong>&nbsp;The Relative Strength of an asset is determined by&nbsp;dividing the Exponential Moving Average of the gain of an asset from the Exponential Moving Average of the loss of an asset for a specified number of periods. It can be mathematically represented as follows:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>RS = GAIN EMA \/ LOSS EMA<\/strong>\n\nwhere,\nRS = Relative Strength\nGAIN EMA = Exponential Moving Average of the gains\nLOSS EMA = Exponential Moving Average of the losses<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Calculating the RSI values:<\/strong>&nbsp;In this step, we will calculate the RSI itself by making use of the Relative Strength values we calculated in the previous step. To calculate the values of RSI of a given asset for a specified number of periods, there is a formula that we need to follow:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>RSI = 100.0 - (100.0 \/ (1.0 + RS))<\/strong>\n\nwhere,\nRSI = Relative Strength Index\nRS = Relative Strength<\/pre>\n\n\n\n<p id=\"9050\">Now let\u2019s analyze a chart of RSI plotted along with Apple\u2019s historical stock data to gain a strong understanding of the indicator.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1801\" height=\"884\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-36.png\" alt=\"\" class=\"wp-image-1386\"\/><\/figure>\n\n\n\n<p id=\"7d42\">The above chart is separated into two panels: The above panel with the closing price of Apple and the lower panel with the calculated RSI 14 values of Apple. While analyzing the panel plotted with the RSI values, it can be seen that the trend and movement of the calculated values follow the same as the closing price of Apple. So, we can consider that RSI is a directional indicator. Some indicators are non-directional meaning that their movement will be inversely proportional to the actual stock movement and this can sometimes confuse traders and be hard to understand too.<\/p>\n\n\n\n<p id=\"c510\">While observing the RSI chart, we are able to&nbsp;see that the plot of RSI reveals trend reversals even before the market does. Simply speaking, the RSI shows a downtrend or an uptrend right before the actual market does. This shows that RSI is a leading indicator. A leading indicator is an indicator that takes into account the current value of a data series to predict future movements. RSI being a leading indicator helps in warning the traders about potential trend reversions before in time. The opposite of leading indicators is called lagging indicators. Lagging indicators are indicators that represent the current value by taking into account the historical values of a data series.<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a class=\"maxbutton-1 maxbutton maxbutton-subscribe-to-api external-css btn\" href=\"https:\/\/eodhd.com\/register\"><span class='mb-text'>Register &amp; Get Data<\/span><\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"bd5d\">Trading Strategy<\/h1>\n\n\n\n<p id=\"1517\">Now that we have built some basic understanding of the three indicators, let\u2019s discuss the trading strategy that we are going to implement in this article. Basically,&nbsp;our strategy is a squeeze trading strategy which is confirmed by RSI. We will go long (buy the stock) whenever the Lower Keltner Channel is below the Lower Band, the Upper Keltner Channel is above the Upper Band,&nbsp;and&nbsp;the RSI shows a reading of below 30.&nbsp;Similarly, we go short (sell the stock) whenever the Lower Keltner Channel is below the Lower Band, the Upper Keltner Channel is above the Upper Band, and the RSI shows a reading of above 70. Our strategy can be represented as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\">IF <strong>LOWER_KC &lt; LOWER_BB<\/strong> AND <strong>UPPER_KC &gt; UPPER_BB<\/strong> AND <strong>RSI &lt; 30<\/strong> ==&gt; <strong>BUY<\/strong>\nIF <strong>LOWER_KC &lt; LOWER_BB<\/strong> AND<strong> UPPER_KC &gt; UPPER_BB <\/strong>AND <strong>RSI &gt; 70<\/strong> ==&gt; <strong>SELL<\/strong><\/pre>\n\n\n\n<p id=\"d53a\">That\u2019s it! This concludes our theory part and let\u2019s move on to the programming part where we will use Python to first build the indicators from scratch, construct the discussed trading strategy,&nbsp;backtest the strategy on Apple stock data, and finally compare the results with that of SPY ETF.&nbsp;Let\u2019s do some coding!&nbsp;<strong>Before moving on, a disclaimer: This article\u2019s sole purpose is to educate people and must be considered as an information piece, but not as investment advice.<\/strong><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"5aaa\">Implementation in Python<\/h1>\n\n\n\n<p id=\"4884\">The coding part is classified into various steps as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>1. Importing Packages\n2. Extracting Stock Data using EODHD\n3. Bollinger Bands Calculation\n4. Keltner Channel Calculation\n5. RSI Calculation\n6. Creating the Trading Strategy\n7. Creating our Position\n8. Backtesting\n9. SPY ETF Comparison<\/strong><\/pre>\n\n\n\n<p id=\"4101\">We will be following the order mentioned in the above list and buckle up your seat belts to follow every upcoming coding part.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"c7b1\">Step-1: Importing Packages<\/h2>\n\n\n\n<p id=\"aedc\">Importing the required packages into the Python environment is a non-skippable step. The primary packages are going to be Pandas to work with data, NumPy to work with arrays and for complex functions, Matplotlib for plotting purposes, and Requests to make API calls. The secondary packages are going to be Math for mathematical functions and Termcolor for font customization (optional).<\/p>\n\n\n\n<p id=\"094e\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># IMPORTING PACKAGES<br><\/strong><br>import numpy as np<br>import requests<br>import pandas as pd<br>import matplotlib.pyplot as plt<br>from math import floor<br>from termcolor import colored as cl<br><br>plt.style.use('fivethirtyeight')<br>plt.rcParams['figure.figsize'] = (20,10)<\/pre>\n\n\n\n<p id=\"9595\">Now that we have imported all the required packages into our Python. Let\u2019s pull the historical data of Apple with EODHD&#8217;s OHLC split-adjusted data API endpoint.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"9f73\">Step-2: Extracting Stock Data using EODHD<\/h2>\n\n\n\n<p id=\"3fbf\">In this step, we are going to pull the historical stock data of Apple using the <a href=\"https:\/\/eodhd.com\/financial-apis\/technical-indicators-api\/#Split_Adjusted_Data\">OHLC split-adjusted API endpoint<\/a> provided by&nbsp;<a href=\"https:\/\/eodhd.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">EODHD<\/a>. Before that, a note on&nbsp;<a href=\"https:\/\/eodhd.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">EOD Historical Data<\/a>: EOD Historical Data (EODHD) is a reliable provider of financial APIs covering a huge variety of market data ranging from historical data to economic and financial news data. Also, ensure that you have an <a href=\"https:\/\/eodhd.com\/register\">EODHD account<\/a>, only then you will be able to access your personal API key (a vital element to extract data with an API).<\/p>\n\n\n\n<p id=\"79f5\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># EXTRACTING STOCK DATA\n<\/strong>\n# EXTRACTING STOCK DATA\n\ndef get_historical_data(symbol, start_date):\n    api_key = 'YOUR API KEY'\n    api_url = f'https:\/\/eodhistoricaldata.com\/api\/technical\/{symbol}?order=a&amp;fmt=json&amp;from={start_date}&amp;function=splitadjusted&amp;api_token={api_key}'\n    raw_df = requests.get(api_url).json()\n    df = pd.DataFrame(raw_df)\n    df.date = pd.to_datetime(df.date)\n    df = df.set_index('date')\n    return df\n\naapl = get_historical_data('AAPL', '2010-01-01')\naapl.tail()<\/pre>\n\n\n\n<p id=\"8973\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"842\" height=\"452\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-37.png\" alt=\"\" class=\"wp-image-1387\"\/><\/figure>\n\n\n\n<p id=\"65c0\"><strong>Code Explanation:<\/strong>&nbsp;The first thing we did is to define a function named \u2018get_historical_data\u2019 that takes the stock\u2019s symbol (\u2018symbol\u2019) and the starting date of the historical data (\u2018start_date\u2019) as parameters. Inside the function, we are defining the API key and the URL and stored them in their respective variable. Next, we are extracting the historical data in JSON format using the \u2018get\u2019 function and stored it in the \u2018raw_df\u2019 variable. After doing some processes to clean and format the raw JSON data, we are returning it in the form of a clean Pandas dataframe. Finally, we are calling the created function to pull the historic data of Apple from the start of 2010 and stored it into the \u2018aapl\u2019 variable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"e863\">Step-3: Bollinger Bands calculation<\/h2>\n\n\n\n<p id=\"02f7\">In this step, we are going to calculate the components of the Bollinger Bands by following the methods and formulas we discussed before.<\/p>\n\n\n\n<p id=\"3eec\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># BOLLINGER BANDS CALCULATION\n<\/strong>\ndef sma(data, lookback):\n    sma = data.rolling(lookback).mean()\n    return sma\n\ndef get_bb(data, lookback):\n    std = data.rolling(lookback).std()\n    upper_bb = sma(data, lookback) + std * 2\n    lower_bb = sma(data, lookback) - std * 2\n    middle_bb = sma(data, lookback)\n    return upper_bb, middle_bb, lower_bb\n\naapl['upper_bb'], aapl['middle_bb'], aapl['lower_bb'] = get_bb(aapl['close'], 20)\naapl.tail()<\/pre>\n\n\n\n<p id=\"dfe7\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1229\" height=\"426\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-38.png\" alt=\"\" class=\"wp-image-1388\"\/><\/figure>\n\n\n\n<p id=\"98e6\"><strong>Code Explanation:<\/strong>&nbsp;The above can be classified into two parts: SMA calculation, and the Bollinger Bands calculation.<\/p>\n\n\n\n<p id=\"358d\">SMA calculation: Firstly, we are defining a function named \u2018sma\u2019 that takes the stock prices (\u2018data\u2019), and the number of periods (\u2018lookback\u2019) as the parameters. Inside the function, we are using the \u2018rolling\u2019 function provided by the Pandas package to calculate the SMA for the given number of periods. Finally, we are storing the calculated values in the \u2018sma\u2019 variable and returned them.<\/p>\n\n\n\n<p id=\"1c18\">Bollinger Bands calculation: We are first defining a function named \u2018get_bb\u2019 that takes the stock prices (\u2018data\u2019), and the number of periods as parameters (\u2018lookback\u2019). Inside the function, we are using the \u2018rolling\u2019 and the \u2018std\u2019 function to calculate the standard deviation of the given stock data and stored the calculated standard deviation values in the \u2018std\u2019 variable. Next, we are calculating Bollinger Bands values using their respective formulas, and finally, we are returning the calculated values. We are storing the Bollinger Bands values into our \u2018aapl\u2019 dataframe using the created \u2018bb\u2019 function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"9a18\">Step-4: Keltner Channel Calculation<\/h2>\n\n\n\n<p id=\"6225\">In this step, we are going to calculate the components of the Keltner Channel indicator by following the methods we discussed before.<\/p>\n\n\n\n<p id=\"922e\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># KELTNER CHANNEL CALCULATION<br><\/strong><br>def get_kc(high, low, close, kc_lookback, multiplier, atr_lookback):<br>    tr1 = pd.DataFrame(high - low)<br>    tr2 = pd.DataFrame(abs(high - close.shift()))<br>    tr3 = pd.DataFrame(abs(low - close.shift()))<br>    frames = [tr1, tr2, tr3]<br>    tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1)<br>    atr = tr.ewm(alpha = 1\/atr_lookback).mean()<br>    <br>    kc_middle = close.ewm(kc_lookback).mean()<br>    kc_upper = close.ewm(kc_lookback).mean() + multiplier * atr<br>    kc_lower = close.ewm(kc_lookback).mean() - multiplier * atr<br>    <br>    return kc_middle, kc_upper, kc_lower<br>    <br>aapl['kc_middle'], aapl['kc_upper'], aapl['kc_lower'] = get_kc(aapl['high'], aapl['low'], aapl['close'], 20, 2, 10)<br>aapl.tail()<\/pre>\n\n\n\n<p id=\"d09a\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1235\" height=\"299\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-39.png\" alt=\"\" class=\"wp-image-1389\"\/><\/figure>\n\n\n\n<p id=\"0364\"><strong>Code Explanation:<\/strong>&nbsp;We are first defining a function named \u2018get_kc\u2019 that takes a stock\u2019s high (\u2018high\u2019), low (\u2018low\u2019), and closing price data (\u2018close\u2019), the lookback period for the Keltner Channel (\u2018kc_lookback\u2019), the multiplier value (\u2018multiplier), and the lookback period for the ATR (\u2018atr_lookback\u2019) as parameters. The code inside the function can be separated into two parts: ATR calculation, and the Keltner Channel calculation.<\/p>\n\n\n\n<p id=\"513b\">ATR calculation: To determine the readings of the Average True Range, we are first calculating the three differences and storing them in their respective variables. Then we are combining all three differences into one dataframe using the \u2018concat\u2019 function and took the maximum values out of the three collective differences to determine the True Range. Then, using the \u2018ewm\u2019 and \u2018mean\u2019 functions, we are taking the customized Moving Average of True Range for a specified number of periods to get the ATR values.<\/p>\n\n\n\n<p id=\"5e53\">Keltner Channel calculation: Utilizing the previously calculated ATR values, we are first calculating the middle line of the Keltner Channel by taking the EMA of ATR for a specified number of periods. Then comes the calculation of both the upper and lower bands. We are substituting the ATR values into the upper and lower bands formula we discussed before to get the readings of each of them. Finally, we are returning and calling the created function to get the Keltner Channel values of Apple.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"e413\">Step-5: RSI Calculation<\/h2>\n\n\n\n<p id=\"076d\">In this step, we are going to calculate the values of RSI with 14 as the lookback period using the RSI formula we discussed before.<\/p>\n\n\n\n<p id=\"688e\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># RSI CALCULATION<\/strong>\ndef get_rsi(close, lookback):\n    ret = close.diff()\n    up = []\n    down = []\n    for i in range(len(ret)):\n        if ret[i] &lt; 0:\n            up.append(0)\n            down.append(ret[i])\n        else:\n            up.append(ret[i])\n            down.append(0)\n    up_series = pd.Series(up)\n    down_series = pd.Series(down).abs()\n    up_ewm = up_series.ewm(com = lookback - 1, adjust = False).mean()\n    down_ewm = down_series.ewm(com = lookback - 1, adjust = False).mean()\n    rs = up_ewm\/down_ewm\n    rsi = 100 - (100 \/ (1 + rs))\n    rsi_df = pd.DataFrame(rsi).rename(columns = {0:'rsi'}).set_index(close.index)\n    rsi_df = rsi_df.dropna()\n    return rsi_df[3:]\n\naapl['rsi_14'] = get_rsi(aapl['close'], 14)\naapl = aapl.dropna()\naapl.tail()<\/pre>\n\n\n\n<p id=\"ac5d\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1337\" height=\"299\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-40.png\" alt=\"\" class=\"wp-image-1390\"\/><\/figure>\n\n\n\n<p id=\"e5cf\"><strong>Code Explanation:<\/strong>&nbsp;Firstly, we are defining a function named \u2018get_rsi\u2019 that takes the closing price of a stock (\u2018close\u2019) and the lookback period (\u2018lookback\u2019) as parameters. Inside the function, we are first calculating the returns of the stock using the \u2018diff\u2019 function provided by the Pandas package and stored it in the \u2018ret\u2019 variable. This function basically subtracts the current value from the previous value. Next, we are passing a for-loop on the \u2018ret\u2019 variable to distinguish gains from losses and append those values to the concerning variable (\u2018up\u2019 or \u2018down\u2019).<\/p>\n\n\n\n<p id=\"c268\">Then, we are calculating the Exponential Moving Averages for both the \u2018up\u2019 and \u2018down\u2019 using the \u2018ewm\u2019 function provided by the Pandas package and storing them in the \u2018up_ewm\u2019 and \u2018down_ewm\u2019 variables respectively. Using these calculated EMAs, we are determining the Relative Strength by following the formula we discussed before and storing it into the \u2018rs\u2019 variable.<\/p>\n\n\n\n<p id=\"d6bb\">By making use of the calculated Relative Strength values, we are calculating the RSI values by following its formula. After doing some data processing and manipulations, we are returning the calculated Relative Strength Index values in the form of a Pandas dataframe. Finally, we are calling the created function to store the RSI values of Apple with 14 as the lookback period.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2a33\">Step-6: Creating the Trading Strategy:<\/h2>\n\n\n\n<p id=\"ed13\">In this step, we are going to implement the discussed Bollinger Bands, Keltner Channel, and Relative Strength Index trading strategy in Python.<\/p>\n\n\n\n<p id=\"2140\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># TRADING STRATEGY<\/strong><br><br>def bb_kc_rsi_strategy(prices, upper_bb, lower_bb, kc_upper, kc_lower, rsi):<br>    buy_price = []<br>    sell_price = []<br>    bb_kc_rsi_signal = []<br>    signal = 0<br>    <br>    for i in range(len(prices)):<br>        if lower_bb[i] &lt; kc_lower[i] and upper_bb[i] &gt; kc_upper[i] and rsi[i] &lt; 30:<br>            if signal != 1:<br>                buy_price.append(prices[i])<br>                sell_price.append(np.nan)<br>                signal = 1<br>                bb_kc_rsi_signal.append(signal)<br>            else:<br>                buy_price.append(np.nan)<br>                sell_price.append(np.nan)<br>                bb_kc_rsi_signal.append(0)<br>                <br>        elif lower_bb[i] &lt; kc_lower[i] and upper_bb[i] &gt; kc_upper[i] and rsi[i] &gt; 70:<br>            if signal != -1:<br>                buy_price.append(np.nan)<br>                sell_price.append(prices[i])<br>                signal = -1<br>                bb_kc_rsi_signal.append(signal)<br>            else:<br>                buy_price.append(np.nan)<br>                sell_price.append(np.nan)<br>                bb_kc_rsi_signal.append(0)<br>        else:<br>            buy_price.append(np.nan)<br>            sell_price.append(np.nan)<br>            bb_kc_rsi_signal.append(0)<br>                        <br>    return buy_price, sell_price, bb_kc_rsi_signal<br><br>buy_price, sell_price, bb_kc_rsi_signal = bb_kc_rsi_strategy(aapl['close'], aapl['upper_bb'], aapl['lower_bb'], aapl['kc_upper'], aapl['kc_lower'], aapl['rsi_14'])<\/pre>\n\n\n\n<p id=\"17d8\"><strong>Code Explanation:<\/strong>&nbsp;First, we are defining a function named \u2018bb_kc_rsi_strategy\u2019 which takes the stock prices (\u2018prices\u2019), Upper Keltner Channel (\u2018kc_upper\u2019), Lower Keltner Channel (\u2018kc_lower\u2019), Upper Bollinger band (\u2018upper_bb\u2019), Lower Bollinger band (\u2018lower_bb\u2019), and the Relative Strength Index readings (\u2018rsi\u2019) as parameters.<\/p>\n\n\n\n<p id=\"28c5\">Inside the function, we are creating three empty lists (buy_price, sell_price, and bb_kc_rsi_signal) in which the values will be appended while creating the trading strategy.<\/p>\n\n\n\n<p id=\"6e19\">After that, we are implementing the trading strategy through a for-loop. Inside the for-loop, we are passing certain conditions, and if the conditions are satisfied, the respective values will be appended to the empty lists. If the condition to buy the stock gets satisfied, the buying price will be appended to the \u2018buy_price\u2019 list, and the signal value will be appended as 1 representing buying the stock. Similarly, if the condition to sell the stock gets satisfied, the selling price will be appended to the \u2018sell_price\u2019 list, and the signal value will be appended as -1 representing to sell the stock. Finally, we are returning the lists appended with values. Then, we are calling the created function and stored the values in their respective variables.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"324a\">Step-7: Creating our Position<\/h2>\n\n\n\n<p id=\"f6c4\">In this step, we are going to create a list that indicates 1 if we hold the stock or 0 if we don\u2019t own or hold the stock.<\/p>\n\n\n\n<p id=\"b443\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># POSITION<\/strong>\n\nposition = []\nfor i in range(len(bb_kc_rsi_signal)):\n    if bb_kc_rsi_signal[i] &gt; 1:\n        position.append(0)\n    else:\n        position.append(1)\n        \nfor i in range(len(aapl['close'])):\n    if bb_kc_rsi_signal[i] == 1:\n        position[i] = 1\n    elif bb_kc_rsi_signal[i] == -1:\n        position[i] = 0\n    else:\n        position[i] = position[i-1]\n        \nkc_upper = aapl['kc_upper']\nkc_lower = aapl['kc_lower']\nupper_bb = aapl['upper_bb'] \nlower_bb = aapl['lower_bb']\nrsi = aapl['rsi_14']\nclose_price = aapl['close']\nbb_kc_rsi_signal = pd.DataFrame(bb_kc_rsi_signal).rename(columns = {0:'bb_kc_rsi_signal'}).set_index(aapl.index)\nposition = pd.DataFrame(position).rename(columns = {0:'bb_kc_rsi_position'}).set_index(aapl.index)\n\nframes = [close_price, kc_upper, kc_lower, upper_bb, lower_bb, rsi, bb_kc_rsi_signal, position]\nstrategy = pd.concat(frames, join = 'inner', axis = 1)<\/pre>\n\n\n\n<p id=\"9890\"><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1326\" height=\"354\" src=\"https:\/\/eodhistoricaldata.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-41.png\" alt=\"\" class=\"wp-image-1391\"\/><\/figure>\n\n\n\n<p id=\"3a51\"><strong>Code Explanation:<\/strong>&nbsp;First, we are creating an empty list named \u2018position\u2019. We are passing two for-loops, one is to generate values for the \u2018position\u2019 list to just match the length of the \u2018signal\u2019 list. The other for-loop is the one we are using to generate actual position values.<\/p>\n\n\n\n<p id=\"64af\">Inside the second for-loop, we are iterating over the values of the \u2018signal\u2019 list, and the values of the \u2018position\u2019 list get appended concerning which condition gets satisfied. The value of the position remains 1 if we hold the stock or remains 0 if we sold or don\u2019t own the stock. Finally, we are doing some data manipulations to combine all the created lists into one dataframe.<\/p>\n\n\n\n<p id=\"f894\">From the output being shown, we can see that in the first four rows, our position in the stock has remained at 1 (since there isn\u2019t any change in the trading signal) but our position suddenly turned to 0 as we sold the stock when the trading signal represents a buy signal (-1). Our position will remain -1 until some changes in the trading signal occur. Now it\u2019s time to implement some backtesting processes!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"6796\">Step-8: Backtesting<\/h2>\n\n\n\n<p id=\"d7d7\">Before moving on, it is essential to know what backtesting is. Backtesting is the process of seeing how well our trading strategy has performed on given stock data. In our case, we are going to implement a backtesting process for our trading strategy over the Apple stock data.<\/p>\n\n\n\n<p id=\"9068\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># BACKTESTING<\/strong>\n\naapl_ret = pd.DataFrame(np.diff(aapl['close'])).rename(columns = {0:'returns'})\nbb_kc_rsi_strategy_ret = []\n\nfor i in range(len(aapl_ret)):\n    returns = aapl_ret['returns'][i]*strategy['bb_kc_rsi_position'][i]\n    bb_kc_rsi_strategy_ret.append(returns)\n    \nbb_kc_rsi_strategy_ret_df = pd.DataFrame(bb_kc_rsi_strategy_ret).rename(columns = {0:'bb_kc_rsi_returns'})\ninvestment_value = 100000\nbb_kc_rsi_investment_ret = []\n\nfor i in range(len(bb_kc_rsi_strategy_ret_df['bb_kc_rsi_returns'])):\n    number_of_stocks = floor(investment_value\/aapl['close'][i])\n    returns = number_of_stocks*bb_kc_rsi_strategy_ret_df['bb_kc_rsi_returns'][i]\n    bb_kc_rsi_investment_ret.append(returns)\n\nbb_kc_rsi_investment_ret_df = pd.DataFrame(bb_kc_rsi_investment_ret).rename(columns = {0:'investment_returns'})\ntotal_investment_ret = round(sum(bb_kc_rsi_investment_ret_df['investment_returns']), 2)\nprofit_percentage = floor((total_investment_ret\/investment_value)*100)\nprint(cl('Profit gained from the BB KC RSI strategy by investing $100k in AAPL : {}'.format(total_investment_ret), attrs = ['bold']))\nprint(cl('Profit percentage of the BB KC RSI strategy : {}%'.format(profit_percentage), attrs = ['bold']))<\/pre>\n\n\n\n<p id=\"d425\"><strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>Profit gained from the BB KC RSI strategy by investing $100k in AAPL : 165737.51<\/strong>\n<strong>Profit percentage of the BB KC RSI strategy : 165%<\/strong><\/pre>\n\n\n\n<p id=\"a41f\"><strong>Code Explanation:<\/strong>&nbsp;First, we are calculating the returns of the Apple stock using the \u2018diff\u2019 function provided by the NumPy package and we have stored it as a dataframe in the \u2018aapl_ret\u2019 variable. Next, we are passing a for-loop to iterate over the values of the \u2018aapl_ret\u2019 variable to calculate the returns we gained from our RVI trading strategy, and these returns values are appended to the \u2018bb_kc_rsi_strategy_ret\u2019 list. Next, we are converting the \u2018bb_kc_rsi_strategy_ret\u2019 list into a dataframe and storing it into the \u2018bb_kc_rsi_strategy_ret_df\u2019 variable.<\/p>\n\n\n\n<p id=\"229f\">Next comes the backtesting process. We are going to backtest our strategy by investing a hundred thousand USD into our trading strategy. So first, we are storing the amount of investment into the \u2018investment_value\u2019 variable. After that, we are calculating the number of Apple stocks we can buy using the investment amount. You can notice that I\u2019ve used the \u2018floor\u2019 function provided by the Math package because, while dividing the investment amount by the closing price of Apple stock, it spits out an output with decimal numbers. The number of stocks should be an integer but not a decimal number. Using the \u2018floor\u2019 function, we can cut out the decimals. Remember that the \u2018floor\u2019 function is way more complex than the \u2018round\u2019 function. Then, we are passing a for-loop to find the investment returns followed by some data manipulation tasks.<\/p>\n\n\n\n<p id=\"b171\">Finally, we are printing the total return we got by investing a hundred thousand into our trading strategy and it is revealed that we have made an approximate profit of 165K USD in around thirteen-and-a-half years with a profit percentage of 165%. That\u2019s great! Now, let\u2019s compare our returns with SPY ETF (an ETF designed to track the S&amp;P 500 stock market index) returns.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"df56\">Step-8: SPY ETF Comparison<\/h2>\n\n\n\n<p id=\"20e3\">This step is optional but it is highly recommended as we can get an idea of how well our trading strategy performs against a benchmark (SPY ETF). In this step, we will extract the SPY ETF data using the \u2018get_historical_data\u2019 function we created and compare the returns we get from the SPY ETF with our trading strategy returns on Apple.<\/p>\n\n\n\n<p id=\"602b\"><strong>Python Implementation:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-white-color has-black-background-color has-text-color has-background\"><strong># SPY ETF COMPARISON<\/strong>\n\ndef get_benchmark(start_date, investment_value):\n    spy = get_historical_data('SPY', start_date)['close']\n    benchmark = pd.DataFrame(np.diff(spy)).rename(columns = {0:'benchmark_returns'})\n    \n    investment_value = investment_value\n    benchmark_investment_ret = []\n    \n    for i in range(len(benchmark['benchmark_returns'])):\n        number_of_stocks = floor(investment_value\/spy[i])\n        returns = number_of_stocks*benchmark['benchmark_returns'][i]\n        benchmark_investment_ret.append(returns)\n\n    benchmark_investment_ret_df = pd.DataFrame(benchmark_investment_ret).rename(columns = {0:'investment_returns'})\n    return benchmark_investment_ret_df\n\nbenchmark = get_benchmark('2010-01-01', 100000)\ninvestment_value = 100000\ntotal_benchmark_investment_ret = round(sum(benchmark['investment_returns']), 2)\nbenchmark_profit_percentage = floor((total_benchmark_investment_ret\/investment_value)*100)\nprint(cl('Benchmark profit by investing $100k : {}'.format(total_benchmark_investment_ret), attrs = ['bold']))\nprint(cl('Benchmark Profit percentage : {}%'.format(benchmark_profit_percentage), attrs = ['bold']))\nprint(cl('BB KC RSI Strategy profit is {}% higher than the Benchmark Profit'.format(profit_percentage - benchmark_profit_percentage), attrs = ['bold']))<\/pre>\n\n\n\n<p id=\"ced3\"><strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#abb7c217\"><strong>Benchmark profit by investing $100k : 159541.51<\/strong>\n<strong>Benchmark Profit percentage : 159%<\/strong>\n<strong>BB KC RSI Strategy profit is 6% higher than the Benchmark Profit<\/strong><\/pre>\n\n\n\n<p id=\"e939\"><strong>Code Explanation:<\/strong>&nbsp;The code used in this step is almost similar to the one used in the previous backtesting step but, instead of investing in Apple, we are investing in SPY ETF by not implementing any trading strategies. From the output, we can see that our trading strategy has outperformed the SPY ETF by 6%. That\u2019s awesome!<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a class=\"maxbutton-1 maxbutton maxbutton-subscribe-to-api external-css btn\" href=\"https:\/\/eodhd.com\/register\"><span class='mb-text'>Register &amp; Get Data<\/span><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Final Thoughts!<\/h2>\n\n\n\n<p id=\"ae1b\">After the immense process of crushing both theory and coding parts, we have successfully learned what the three indicators are all about and built a killer trading strategy out of them that manages to surpass the returns of the SPY ETF in a 13-year timeframe. From the results, it is notable that by consolidating two or more indicators, we can gain better returns out of our investment than we could with a single indicator trading strategy. Also, we can erase non-authentic signals from our strategy as much as possible.<\/p>\n\n\n\n<p id=\"e7e3\">With that being said, you\u2019ve reached the end of the article. Hope you learned something new and useful from this article!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Each of the indicators Bollinger Bands, Keltner Channel, and Relative Strength Index are unique in nature and powerful when used individually. But what if we try to combine all these three indicators and create one effective trading strategy out of them? The results would be substantial, and we could be able to eradicate one of [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":1383,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[59],"tags":[],"coding-language":[30],"ready-to-go-solution":[],"qualification":[31,32],"financial-apis-category":[36],"financial-apis-manuals":[39,40],"class_list":["post-1382","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technical-analysis-examples","coding-language-python","qualification-experienced","qualification-guru","financial-apis-category-stock-market-prices","financial-apis-manuals-end-of-day","financial-apis-manuals-technical-indicators","has_thumb"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.9 (Yoast SEO v26.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python | EODHD APIs Academy<\/title>\n<meta name=\"description\" content=\"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python\" \/>\n<meta property=\"og:description\" content=\"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading\" \/>\n<meta property=\"og:url\" content=\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\" \/>\n<meta property=\"og:site_name\" content=\"Financial Academy\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/eodhistoricaldata\" \/>\n<meta property=\"article:published_time\" content=\"2023-08-01T17:25:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-14T09:38:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png\" \/>\n\t<meta property=\"og:image:width\" content=\"828\" \/>\n\t<meta property=\"og:image:height\" content=\"552\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Nikhil Adithyan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@EOD_data\" \/>\n<meta name=\"twitter:site\" content=\"@EOD_data\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nikhil Adithyan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#article\",\"isPartOf\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\"},\"author\":{\"name\":\"Nikhil Adithyan\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/67681e71050cf7d8d0efb91fee5f0402\"},\"headline\":\"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python\",\"datePublished\":\"2023-08-01T17:25:58+00:00\",\"dateModified\":\"2024-03-14T09:38:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\"},\"wordCount\":4038,\"publisher\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage\"},\"thumbnailUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png\",\"articleSection\":[\"Technical Analysis Examples\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\",\"name\":\"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python | EODHD APIs Academy\",\"isPartOf\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage\"},\"thumbnailUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png\",\"datePublished\":\"2023-08-01T17:25:58+00:00\",\"dateModified\":\"2024-03-14T09:38:38+00:00\",\"description\":\"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading\",\"breadcrumb\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png\",\"contentUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png\",\"width\":828,\"height\":552,\"caption\":\"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/eodhd.com\/financial-academy\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#website\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/\",\"name\":\"Financial APIs Academy | EODHD\",\"description\":\"Financial Stock Market Academy\",\"publisher\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/eodhd.com\/financial-academy\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\",\"name\":\"EODHD (EOD Historical Data)\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png\",\"contentUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png\",\"width\":159,\"height\":82,\"caption\":\"EODHD (EOD Historical Data)\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/eodhistoricaldata\",\"https:\/\/x.com\/EOD_data\",\"https:\/\/www.reddit.com\/r\/EODHistoricalData\/\",\"https:\/\/eod-historical-data.medium.com\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/67681e71050cf7d8d0efb91fee5f0402\",\"name\":\"Nikhil Adithyan\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/eb53ce41bde412555cee22b8b4c09c2ff51625fff05ba3696b20cac7a7c0d938?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/eb53ce41bde412555cee22b8b4c09c2ff51625fff05ba3696b20cac7a7c0d938?s=96&d=mm&r=g\",\"caption\":\"Nikhil Adithyan\"},\"description\":\"Founder at BacktestZone | Streamlit Student Ambassador | FinTech &amp; Quantitative Finance enthusiast\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/author\/nikhiladithyan\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python | EODHD APIs Academy","description":"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","og_locale":"en_US","og_type":"article","og_title":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python","og_description":"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading","og_url":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","og_site_name":"Financial Academy","article_publisher":"https:\/\/www.facebook.com\/eodhistoricaldata","article_published_time":"2023-08-01T17:25:58+00:00","article_modified_time":"2024-03-14T09:38:38+00:00","og_image":[{"width":828,"height":552,"url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","type":"image\/png"}],"author":"Nikhil Adithyan","twitter_card":"summary_large_image","twitter_creator":"@EOD_data","twitter_site":"@EOD_data","twitter_misc":{"Written by":"Nikhil Adithyan","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#article","isPartOf":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python"},"author":{"name":"Nikhil Adithyan","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/67681e71050cf7d8d0efb91fee5f0402"},"headline":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python","datePublished":"2023-08-01T17:25:58+00:00","dateModified":"2024-03-14T09:38:38+00:00","mainEntityOfPage":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python"},"wordCount":4038,"publisher":{"@id":"https:\/\/eodhd.com\/financial-academy\/#organization"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage"},"thumbnailUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","articleSection":["Technical Analysis Examples"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","url":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python","name":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python | EODHD APIs Academy","isPartOf":{"@id":"https:\/\/eodhd.com\/financial-academy\/#website"},"primaryImageOfPage":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage"},"thumbnailUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","datePublished":"2023-08-01T17:25:58+00:00","dateModified":"2024-03-14T09:38:38+00:00","description":"Learn how to trade stocks using Bollinger Bands in Python. Discover effective strategies to optimize your trading","breadcrumb":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#primaryimage","url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","contentUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","width":828,"height":552,"caption":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python"},{"@type":"BreadcrumbList","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/trading-stocks-using-bollinger-bands-keltner-channel-and-rsi-in-python#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/eodhd.com\/financial-academy\/"},{"@type":"ListItem","position":2,"name":"Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python"}]},{"@type":"WebSite","@id":"https:\/\/eodhd.com\/financial-academy\/#website","url":"https:\/\/eodhd.com\/financial-academy\/","name":"Financial APIs Academy | EODHD","description":"Financial Stock Market Academy","publisher":{"@id":"https:\/\/eodhd.com\/financial-academy\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/eodhd.com\/financial-academy\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/eodhd.com\/financial-academy\/#organization","name":"EODHD (EOD Historical Data)","url":"https:\/\/eodhd.com\/financial-academy\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/","url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png","contentUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png","width":159,"height":82,"caption":"EODHD (EOD Historical Data)"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/eodhistoricaldata","https:\/\/x.com\/EOD_data","https:\/\/www.reddit.com\/r\/EODHistoricalData\/","https:\/\/eod-historical-data.medium.com\/"]},{"@type":"Person","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/67681e71050cf7d8d0efb91fee5f0402","name":"Nikhil Adithyan","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/eb53ce41bde412555cee22b8b4c09c2ff51625fff05ba3696b20cac7a7c0d938?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/eb53ce41bde412555cee22b8b4c09c2ff51625fff05ba3696b20cac7a7c0d938?s=96&d=mm&r=g","caption":"Nikhil Adithyan"},"description":"Founder at BacktestZone | Streamlit Student Ambassador | FinTech &amp; Quantitative Finance enthusiast","url":"https:\/\/eodhd.com\/financial-academy\/author\/nikhiladithyan"}]}},"jetpack_featured_media_url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/07\/image-33.png","jetpack_shortlink":"https:\/\/wp.me\/pdOdVT-mi","jetpack_sharing_enabled":true,"acf":[],"_links":{"self":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/1382","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/comments?post=1382"}],"version-history":[{"count":23,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/1382\/revisions"}],"predecessor-version":[{"id":3069,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/1382\/revisions\/3069"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/media\/1383"}],"wp:attachment":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/media?parent=1382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/categories?post=1382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/tags?post=1382"},{"taxonomy":"coding-language","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/coding-language?post=1382"},{"taxonomy":"ready-to-go-solution","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/ready-to-go-solution?post=1382"},{"taxonomy":"qualification","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/qualification?post=1382"},{"taxonomy":"financial-apis-category","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/financial-apis-category?post=1382"},{"taxonomy":"financial-apis-manuals","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/financial-apis-manuals?post=1382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}