Extract basic stock information to advanced technical indicators seamlessly
Technical indicators are very intriguing and never fail to grab my attention. I study vigorously about them and I got to know that the important part of studying technical indicators are applying them to the real-world market but before proceeding with that, we need to do something called backtesting which is nothing but the process of identifying a strategy’s performance by testing it on the past historical data.
Now to conduct backtesting processes, several platforms are there but I couldn’t find the flexibility I need. So I started using Python (and I still am) to code the whole program which is by the way super-flexible and interesting too.
The only drawback while using Python to code the whole program to me is to create the technical indicator from scratch. In order to do that, we must first understand the underlying idea of the indicator followed by its mathematical formulae (some have two or more). So, I decided to use Python packages to make the work done but was still not able to find a note-worthy library because of two reasons. The first was the installation and the documentation are poor, and the second was its irregularities in the readings.
I started following my conventional method which is building the indicator from scratch until I came across this Python library. Behold, Stockstats. It is a wrapper for Pandas dataframes and offers data ranging from basic stock information to advanced technical indicators. In this article, we will dive deep into this library and explore its functionalities. Without further ado, let’s get going!
Importing Packages
Importing the required packages into our python environment is an unskippable step. In this article, we would need a sum of five packages which are Pandas to deal with dataframes, Requests to make API calls and extract stock data, NumPy for advanced functions, Matplotlib for visualization, and finally the StockStats package for accessing technical indicators and other basic stock information. For those who haven’t yet installed these packages, copy this code into your terminal:
pip install pandas
pip install requests
pip install numpy
pip install matplotlib
pip install stockstats
After finished installing the packages, it’s time to import those into our python environment.
import requests
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from stockstats import StockDataFrame
plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (20, 10)
Extracting Stock Data
Now, that we have imported all the essential packages. Let’s pull the historical stock data of Apple using an API endpoint provided by twelvedata.com. Before that, a note on twelvedata.com: Twelve Data is one of the leading market data providers having an enormous amount of API endpoints for all types of market data. It is very easy to interact with the APIs provided by Twelve Data and has one of the best documentation ever. Also, ensure that you have an account on twelvedata.com, only then, you will be able to access your API key (vital element to extract data with an API).
Python Implementation:
def get_historical_data(symbol, start_date):
api_key = 'YOUR API KEY'
api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}'
raw_df = requests.get(api_url).json()
df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float)
df = df[df.index >= start_date]
df.index = pd.to_datetime(df.index)
return df
aapl = get_historical_data('AAPL', '2020-01-01')
aapl.tail()
Output:
In the above code, the first thing we did is to define a function named 'get_historical_data' that takes the stock’s symbol ('symbol') and the starting date of the historical data ('start_date') as parameters.
Inside the function, we are defining the API key and the URL and stored them into their respective variable. Next, we are extracting the historical data in JSON format using the 'get' function and stored it into the 'raw_df' 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 historical data of Apple from the starting of 2020 and stored it into the 'aapl' variable.
Pandas dataframe to Stockstats dataframe
One of the most important things to do before proceeding with anything is to change the Pandas dataframe into a Stockstats dataframe. In the previous step where we extracted Apple’s historical data using an API endpoint, we converted the JSON response and stored it in the form of Pandas dataframe. So, we first have to change it to a Stockstats dataframe which can be done easily by calling the main class of the package 'StockDataFrame' and pass the dataframe into it. Follow the code snippet to do it:
aapl = StockDataFrame(aapl)
After implementing the above code, you would notice less to zero changes to your dataframe unless if your columns are named in capital letters they would be transformed into small letters. But it doesn't mean this step is optional and in fact, converting the dataframe to the format of Stockstats is mandatory to perform any kind of task.
Accessing Technical Indicators
Now, we are all set to focus on the main part of this article. As I mentioned in the title, Stockstats offers technical indicators in such a way that we have to code just a line and we can get the desired result which is by the way not a false hope but a real thing. All we have to do is just select the column name like how we access columns in a Pandas dataframe and Stockstats will take care of the rest. To show how simple it is, let’s look at an example where we will access the readings of SMAs with different timeframes:
aapl[['close_10_sma', 'close_20_sma', 'close_50_sma']]
The above code will provide us with the SMA values for timeframes 10, 20, and 50. Along with that, the values will be appended to the original Apple dataframe which is really great and not offered by another technical analysis library out there. The output for the code will be a Stockstats dataframe that looks like this:
Stockstats expects us to follow a specific structure for accessing technical indicators which is '{columnName_window_statistics}' where 'columnName' is the column in our dataframe which we want to take into account for calculating the indicator, 'window' is the lookback period and 'statistics' is the indicator we want to access. In the above example, we mentioned 'close' as the 'columnName' meaning that we want to take into account the closing price of Apple, '10,20,50' as the lookback periods, and 'sma' as the statistics or the technical indicator we want to access.
Stockstats not only allows us to access basic technical indicators like the Simple Moving Average but also opens the door to many other advanced indicators such as the Bollinger Bands, Relative Strength Index, Williams %R, Moving Average Convergence/Divergence, Commodity Channel Index, and so on. The following code snippet will access all the advanced technical indicators mentioned above following the same structure as the SMA code.
# 1. BOLLINGER BANDS
aapl[['boll', 'boll_ub', 'boll_lb']]
# 2. RSI
aapl[['rsi_11', 'rsi_14', 'rsi_21']]
# 3. WILLIAMS %R
aapl[['wr_11', 'wr_14', 'wr_21']]
# 4. MACD
aapl[['macd', 'macdh', 'macds']]
# 5. COMMODITY CHANNEL INDEX
aapl[['cci_11', 'cci_14', 'cci_21']]
Each line on the above code will access the indicator being mentioned for different timeframes and append the values to the original dataframe. It can be noticed that I have used double brackets while accessing technical indicators which is because of the reason that Stockstats is built on top of the Pandas dataframe class and still retains its functionalities, so, when single brackets are used, the output will be in the form of a Pandas series. Since I want the output to be in a Pandas dataframe, I’ve used double brackets.
Generating Trade Signals
One of the unique features of Stockstats is its ability to generate signals from a mentioned trading strategy. This is awesome because algorithmic trading is all about generating trade signals and without that the created trading strategies will become obsolete. Like how we accessed the technical indicators, this also takes just a line of code but the structure differs. The following code snippet generates entry trade signals when the SMA 20 crosses above the SMA 50:
aapl[‘close_20_sma_xd_close_50_sma’]
The above code gives a series of boolean values as output which turns 'True' if the condition gets satisfied, or else, the value is 'False'. The following code will take this to the next level by generating both entry and exit trade signals hence making the strategy more realistic in nature:
buy_signals = aapl['close_20_sma_xd_close_50_sma']
sell_signals = aapl['close_50_sma_xd_close_20_sma']
for i in range(len(buy_signals)):
if buy_signals.iloc[i] == True:
buy_signals.iloc[i] = aapl.close[i]
else:
buy_signals.iloc[i] = np.nan
for i in range(len(sell_signals)):
if sell_signals.iloc[i] == True:
sell_signals.iloc[i] = aapl.close[i]
else:
sell_signals.iloc[i] = np.nan
plt.plot(aapl['close'], linewidth = 2.5, label = 'AAPL')
plt.plot(aapl.index, buy_signals, marker = '^', markersize = 15, color = 'green', linewidth = 0, label = 'BUY SIGNAL')
plt.plot(aapl.index, sell_signals, marker = 'v', markersize = 15, color = 'r', linewidth = 0, label = 'SELL SIGNAL')
plt.legend(loc = 'upper left')
plt.title('AAPL SMA 20,50 CROSSOVER STRATEGY SIGNALS')
plt.show()
Let’s break down the code by each line. In the first two lines of code, we are using Stockstats to generate both entry and exit trade signals and saved the values into their respective variables. After that, we are creating two for-loops that will replace the trade signals with the closing price of the stock if the value is 'True', or else, the 'False' values will be replaced by NaN. The following lines plot the created trading signals along with the closing price of Apple and the calculated SMA 20, 50 which will produce an output that looks like this:
From the above chart, it can be observed that whenever the red line (SMA 20) crosses above the golden line (SMA 50), a buy signal is plotted in green color, similarly, whenever the golden line crosses above the red line, a sell signal is plotted in red color.
Final Thoughts!
In this article, we had a brief look into the Stockstats library, and not to mention, it really is a wonderful one. It is also worth mentioning that Stockstats not only supports technical indicators and generating trading signals but also allows us to access basic stock information like the change in price, returns, and so on.
The only drawback of this package right now is its poor documentation that takes a millennium for one to understand completely. Though the package is not that huge as others like Pandas and NumPy, it is essential to maintain perfect documentation as the functions provided are complex and different from others since it is a wrapper library.
In conclusion, Stockstats is one of a kind and is a great library for anyone starting out in the field of technical analysis, and provides powerful functions that can be accessed with just a line of code which ultimately reduces a programmer’s effort and saves time. With that being said, you’ve reached the end of the article. Hope you learned something useful and new from this article.