The FinanceDatabase serves the role of providing anyone with any type of financial product categorisation entirely for free. To be able to achieve this, the FinanceDatabase relies on involvement from the community to add, edit and remove tickers over time. This is made easy enough that anyone, even with a lack of coding experience can contribute because of the usage of CSV files that can be manually edited. I'd like to invite you to go to the Contributing Guidelines to understand how you can help. Thank you!
As a private investor, the sheer amount of information that can be found on the internet is rather daunting. Trying to understand what type of companies or ETFs are available is incredibly challenging with there being millions of companies and derivatives available on the market. Sure, the most traded companies and ETFs can quickly be found simply because they are known to the public (for example, Microsoft, Tesla, S&P500 ETF or an All-World ETF). However, what else is out there is often unknown.
This database tries to solve that. It features 300.000+ symbols containing Equities, ETFs, Funds, Indices, Currencies, Cryptocurrencies and Money Markets. It therefore allows you to obtain a broad overview of sectors, industries, types of investments and much more.
The aim of this database is explicitly not to provide up-to-date fundamentals or stock data as those can be obtained with ease (with the help of this database) by using the FinanceToolkit. Instead, it gives insights into the products that exist in each country, industry and sector and gives the most essential information about each product. With this information, you can analyse specific areas of the financial world and/or find a product that is hard to find.
To install the FinanceDatabase and the FinanceToolkit it simply requires the following (the Finance Toolkit is a dependency):
pip install financedatabase -U
Then within Python use:
import financedatabase as fd
To be able to get started with the Finance Toolkit, you need to obtain an API Key from FinancialModelingPrep. This is used to gain access to 30+ years of financial statement both annually and quarterly. Note that the Free plan is limited to 250 requests each day, 5 years of data and only features companies listed on US exchanges.
Through the link you are able to subscribe for the free plan and also premium plans at a 15% discount. This is an affiliate link and thus supports the project at the same time. I have chosen FinancialModelingPrep as a source as I find it to be the most transparent, reliable and at an affordable price. When you notice that data is inaccurate or have any other issue related to the data, note that I simply provide the means to access this data and I am not responsible for the accuracy of the data itself. For this, use their contact form or provide the data yourself.
import financedatabase as fd
import matplotlib.pyplot as plt
import numpy as np
API_KEY = "FINANCIAL_MODELING_PREP_API_KEY"
Let's start off by obtaining the ETF dataset from the Finance Database.
etfs = fd.ETFs()
Then let's find Health Care ETFs that mention something about 'Biotech' in their description. This would indicate they are related to Biotechnology.
health_care_etfs_in_biotech = etfs.search(category='Health Care', summary='biotech', exclude_exchanges=True)
health_care_etfs_in_biotech
name | currency | summary | category_group | category | family | exchange | market | |
---|---|---|---|---|---|---|---|---|
symbol | ||||||||
AGNG | Global X Aging Population ETF | USD | The investment seeks results that correspond g... | Health Care | Health Care | Global X Funds | NMS | us_market |
BBC | Virtus LifeSci Biotech Clinical Trials ETF | USD | The investment seeks investment results that c... | Health Care | Health Care | Virtus | PCX | us_market |
BBH | VanEck Vectors Biotech ETF | USD | The investment seeks to replicate as closely a... | Health Care | Health Care | VanEck Asset Management | NMS | us_market |
BBP | Virtus LifeSci Biotech Products ETF | USD | The investment seeks investment results that c... | Health Care | Health Care | Virtus | PCX | us_market |
CNCR | Loncar Cancer Immunotherapy ETF | USD | The investment seeks to track the total return... | Health Care | Health Care | Loncar Investments | NGM | us_market |
FBT | First Trust NYSE Arca Biotechnology Index Fund | USD | The investment seeks investment results that c... | Health Care | Health Care | First Trust Advisors | PCX | us_market |
IBB | iShares Nasdaq Biotechnology ETF | USD | The investment seeks to track the investment r... | Health Care | Health Care | BlackRock Asset Management | NMS | us_market |
IBBJ | Defiance Nasdaq Junior Biotechnology ETF | USD | The investment seeks to track the total return... | Health Care | Health Care | Defiance ETFs | NGM | us_market |
IBBQ | Invesco Nasdaq Biotechnology ETF | USD | The investment seeks to track the investment r... | Health Care | Health Care | Invesco Investment Management | NMS | us_market |
IEIH | iShares Evolved U.S. Innovative Healthcare ETF | USD | The investment seeks to provide access to U.S.... | Health Care | Health Care | BlackRock Asset Management | BTS | us_market |
PBE | Invesco Dynamic Biotechnology & Genome ETF | USD | The investment seeks to track the investment r... | Health Care | Health Care | Invesco Investment Management | PCX | us_market |
SBIO | ALPS Medical Breakthroughs ETF | USD | The investment seeks investment results that c... | Health Care | Health Care | ALPS ETF Trust | PCX | us_market |
XBI | SPDR S&P Biotech ETF | USD | The investment seeks to provide investment res... | Health Care | Health Care | State Street Global Advisors | PCX | us_market |
XLV | Health Care Select Sector SPDR Fund | USD | The investment seeks investment results that, ... | Health Care | Health Care | State Street Global Advisors | PCX | us_market |
I initialize the FinanceToolkit with the tickers as found in the FinanceDatabase. This uses a the function to_toolkit
that uses the tickers as shown above to initalize the Finance Toolkit. Here a start and end date are also selected that match the period around the initial wave of the Coronacrisis. Then it's time to collect the historical data for each ETF found.
etfs_in_biotech = health_care_etfs_in_biotech.to_toolkit(api_key=API_KEY, start_date="2020-01-01", end_date="2020-06-01", benchmark_ticker=None)
etfs_in_biotech.get_historical_data()
Obtaining historical data: 100%|██████████| 14/14 [00:01<00:00, 9.45it/s]
No data found for the following tickers: IBBQ
Open | ... | Cumulative Return | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AGNG | BBC | BBH | BBP | CNCR | FBT | IBB | IBBJ | IBBQ | IEIH | ... | CNCR | FBT | IBB | IBBJ | IBBQ | IEIH | PBE | SBIO | XBI | XLV | |
2020-01-01 | 23.675 | 38.205 | 139.565 | 43.92 | 23.4522 | 148.745 | 120.635 | NaN | 0.0 | 27.8241 | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
2020-01-02 | 23.59 | 38.47 | 140.44 | 44.18 | 23.62 | 149.6 | 121.3 | NaN | 0.0 | 27.7942 | ... | 1.0 | 1.0 | 1.0 | NaN | 0.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 |
2020-01-03 | 23.41 | 36.9 | 137.24 | 42.88 | 23.11 | 145.9 | 118.2 | NaN | 0.0 | 27.74 | ... | 0.9888 | 0.987 | 0.9873 | NaN | 0.0 | 0.992 | 0.9925 | 0.9841 | 0.986 | 0.9913 |
2020-01-04 | 23.3533 | 36.79 | 137.1767 | 42.6867 | 23.1067 | 145.7567 | 118.03 | NaN | 0.0 | 27.7467 | ... | 0.9924 | 0.9906 | 0.9894 | NaN | 0.0 | 0.9934 | 0.9922 | 0.9843 | 0.9889 | 0.9934 |
2020-01-05 | 23.2967 | 36.68 | 137.1133 | 42.4933 | 23.1033 | 145.6133 | 117.86 | NaN | 0.0 | 27.7533 | ... | 0.996 | 0.9942 | 0.9915 | NaN | 0.0 | 0.9948 | 0.992 | 0.9846 | 0.9917 | 0.9954 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2020-05-28 | 23.77 | 41.7 | 156.56 | 46.75 | 26.39 | 163.43 | 132.14 | NaN | 0.0 | 29.145 | ... | 1.0991 | 1.1034 | 1.1044 | NaN | 0.0 | 1.0516 | 1.0253 | 0.9913 | 1.0829 | 1.0015 |
2020-05-29 | 23.99 | 40.68 | 157.9 | 45.95 | 26.06 | 163.6 | 132.46 | NaN | 0.0 | 29.42 | ... | 1.1293 | 1.116 | 1.1245 | NaN | 0.0 | 1.0691 | 1.0401 | 0.9971 | 1.0937 | 1.0136 |
2020-05-30 | 24.12 | 40.7833 | 159.0833 | 46.0167 | 26.3 | 164.09 | 133.0567 | NaN | 0.0 | 29.5333 | ... | 1.1331 | 1.1156 | 1.1228 | NaN | 0.0 | 1.0655 | 1.0376 | 0.9962 | 1.0957 | 1.0102 |
2020-05-31 | 24.25 | 40.8867 | 160.2667 | 46.0833 | 26.54 | 164.58 | 133.6533 | NaN | 0.0 | 29.6467 | ... | 1.1368 | 1.1152 | 1.121 | NaN | 0.0 | 1.0618 | 1.0351 | 0.9953 | 1.0976 | 1.0069 |
2020-06-01 | 24.38 | 40.99 | 161.45 | 46.15 | 26.78 | 165.07 | 134.25 | NaN | 0.0 | 29.76 | ... | 1.1405 | 1.1148 | 1.1193 | NaN | 0.0 | 1.0581 | 1.0326 | 0.9945 | 1.0995 | 1.0035 |
153 rows × 168 columns
Then, let's calculate the Bollinger Bands for each ETF.
bollinger_bands = etfs_in_biotech.technicals.get_bollinger_bands()
bollinger_bands
Close | ... | Upper Band | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AGNG | BBC | BBH | BBP | CNCR | FBT | IBB | IBBJ | IBBQ | IEIH | ... | CNCR | FBT | IBB | IBBJ | IBBQ | IEIH | PBE | SBIO | XBI | XLV | |
Date | |||||||||||||||||||||
2020-01-01 | 23.01 | 37.6 | 137.52 | 43.35 | 21.593 | 146.4542 | 118.94 | NaN | 0.0 | 27.9525 | ... | 22.6035 | 152.0311 | 122.2038 | NaN | NaN | 28.3852 | 56.7623 | 43.744 | 98.2908 | 96.8363 |
2020-01-02 | 23.06 | 37.28 | 137.62 | 43.17 | 21.6018 | 146.2076 | 118.63 | NaN | 0.0 | 27.948 | ... | 22.5898 | 152.0685 | 122.2395 | NaN | NaN | 28.3697 | 56.7613 | 43.8433 | 98.3066 | 96.7776 |
2020-01-03 | 22.95 | 36.71 | 136.02 | 42.71 | 21.3596 | 144.3137 | 117.12 | NaN | 0.0 | 27.7255 | ... | 22.5746 | 152.4669 | 122.5632 | NaN | NaN | 28.3644 | 56.7648 | 44.0395 | 98.5889 | 96.5248 |
2020-01-04 | 22.9533 | 36.6867 | 136.4433 | 42.8167 | 21.4375 | 144.8365 | 117.37 | NaN | 0.0 | 27.7642 | ... | 22.5694 | 152.413 | 122.6471 | NaN | NaN | 28.3653 | 56.8004 | 44.1126 | 98.6489 | 96.48 |
2020-01-05 | 22.9567 | 36.6633 | 136.8667 | 42.9233 | 21.5155 | 145.3593 | 117.62 | NaN | 0.0 | 27.8028 | ... | 22.5703 | 152.2766 | 122.6905 | NaN | NaN | 28.3652 | 56.8259 | 44.045 | 98.6095 | 96.3943 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2020-05-28 | 23.31 | 40.77 | 154.59 | 45.95 | 23.7427 | 161.3295 | 131.01 | NaN | 0.0 | 29.39 | ... | 25.6432 | 163.7218 | 132.9694 | NaN | 0.0 | 29.9723 | 58.9018 | 42.9823 | 106.3906 | 95.8946 |
2020-05-29 | 23.64 | 41.0 | 158.6 | 45.9 | 24.3956 | 163.1642 | 133.4 | NaN | 0.0 | 29.88 | ... | 25.6092 | 163.8551 | 133.5014 | NaN | 0.0 | 30.0247 | 58.8902 | 42.9449 | 106.3134 | 96.6528 |
2020-05-30 | 23.67 | 41.1533 | 158.3633 | 45.9833 | 24.476 | 163.1083 | 133.1933 | NaN | 0.0 | 29.7773 | ... | 25.608 | 164.0098 | 133.8478 | NaN | 0.0 | 30.0337 | 58.8959 | 42.9446 | 106.3122 | 97.0912 |
2020-05-31 | 23.7 | 41.3067 | 158.1267 | 46.0667 | 24.5564 | 163.0524 | 132.9867 | NaN | 0.0 | 29.6747 | ... | 25.5911 | 164.1846 | 134.0508 | NaN | 0.0 | 30.0046 | 58.8815 | 42.9584 | 106.2618 | 97.349 |
2020-06-01 | 23.73 | 41.46 | 157.89 | 46.15 | 24.6368 | 162.9966 | 132.78 | NaN | 0.0 | 29.572 | ... | 25.4983 | 164.3456 | 134.1176 | NaN | 0.0 | 29.936 | 58.7814 | 42.9544 | 106.0082 | 97.477 |
153 rows × 56 columns
Then, it's time to visually depict the Bollinger Bands for each ETF during the early stages of the Coronacrisis. This leads to the following graph which gives an indication whether Biotech ETFs were oversold or overbought and how this effect is neutralised (to some degree) in the months after. Read more about Bollinger Bands here.
figure, axis = plt.subplots(4, 3)
figure.set_size_inches(15, 10)
row = 0
column = 0
bollinger_bands_clean = bollinger_bands.replace(0, np.nan).dropna(axis=1)
for ticker in bollinger_bands_clean.columns.get_level_values(1).unique():
name = health_care_etfs_in_biotech.loc[health_care_etfs_in_biotech.index == ticker, 'name'].iloc[0]
bollinger_bands_clean.xs(ticker, level=1, axis=1).plot(
ax=axis[row, column],
xlabel='',
title=name,
legend=False
)
column += 1
if column == 3:
row += 1
column = 0
figure.suptitle('Technical Analysis of Biotech ETFs during Coronacrisis', fontweight='bold')
figure.tight_layout()
This would work with any kind of technical indicator. For example, the Relative Strength Index (RSI).
rsi = etfs_in_biotech.technicals.get_relative_strength_index()
rsi
AGNG | BBC | BBH | BBP | CNCR | FBT | IBB | IBBJ | IBBQ | IEIH | PBE | SBIO | XBI | XLV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||||||
2020-01-01 | 60.1449 | 64.9709 | 55.0317 | 54.4732 | 56.9261 | 51.7305 | 53.8308 | NaN | NaN | 52.65 | 62.3327 | 48.3146 | 53.2025 | 80.1058 |
2020-01-02 | 59.5588 | 57.6744 | 54.1166 | 45.9519 | 55.2684 | 48.9167 | 48.2218 | NaN | NaN | 44.3159 | 50.7995 | 39.2927 | 49.3048 | 76.3819 |
2020-01-03 | 47.2 | 54.7059 | 41.0602 | 40.9274 | 52.1853 | 39.8636 | 39.795 | NaN | NaN | 38.7326 | 49.6872 | 34.669 | 40.1777 | 64.135 |
2020-01-04 | 51.8936 | 51.1545 | 34.2903 | 37.0799 | 51.094 | 33.1496 | 35.0754 | NaN | NaN | 49.65 | 42.5031 | 32.4324 | 34.202 | 56.7066 |
2020-01-05 | 50.7477 | 49.2147 | 40.0002 | 40.7101 | 49.5761 | 36.7263 | 39.0397 | NaN | NaN | 50.0694 | 40.6282 | 27.8846 | 36.3057 | 60.2317 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2020-05-28 | 77.7273 | 62.2991 | 55.0615 | 60.3352 | 55.413 | 68.5793 | 60.0864 | NaN | NaN | 52.5399 | 60.1942 | 62.5364 | 59.3836 | 66.9935 |
2020-05-29 | 78.8793 | 50.3257 | 57.1879 | 47.7218 | 53.6946 | 63.7529 | 58.0143 | NaN | NaN | 54.4338 | 56.2665 | 53.0165 | 52.8435 | 68.8272 |
2020-05-30 | 76.8135 | 48.7395 | 54.8531 | 44.7626 | 50.744 | 61.3869 | 55.8127 | NaN | NaN | 50.8115 | 52.4555 | 50.0316 | 50.2581 | 64.2202 |
2020-05-31 | 74.3011 | 47.0486 | 52.3795 | 41.4514 | 47.3929 | 58.7473 | 53.5226 | NaN | NaN | 47.3235 | 48.3066 | 46.7431 | 47.3737 | 59.697 |
2020-06-01 | 71.1765 | 45.2424 | 49.7539 | 37.7143 | 43.5525 | 55.784 | 51.1371 | NaN | NaN | 43.9582 | 43.7694 | 43.0998 | 44.1332 | 55.2553 |
153 rows × 14 columns
Which if plotted would result in the following. In this graph, when the RSI is above 70 or below 30 this would indicate whether the ETF is overbought or oversold respectively.
figure, axis = plt.subplots(12, 1, figsize=(15, 20))
row = 0
column = 1
for ticker in bollinger_bands_clean.columns.get_level_values(1).unique():
name = health_care_etfs_in_biotech.loc[health_care_etfs_in_biotech.index == ticker, 'name'].iloc[0]
rsi[ticker].plot(
ax=axis[row],
xlabel='',
title=name,
legend=False,
)
axis[row].hlines(70, rsi.index[0], rsi.index[-1], color='red', linestyle='--')
axis[row].hlines(30, rsi.index[0], rsi.index[-1], color='green', linestyle='--')
row += 1
figure.tight_layout()