Finance Toolkit
<!-- mcp-name: io.github.JerBouma/financetoolkit -->
[](https://github.com/JerBouma/FinanceToolkit)
[](https://github.com/sponsors/JerBouma)
[](https://www.buymeacoffee.com/jerbouma)
[](https://www.linkedin.com/in/boumajeroen/)
[](https://www.jeroenbouma.com/projects/financetoolkit/mcp)
[](https://github.com/JerBouma/FinanceToolkit/releases/latest/download/financetoolkit.mcpb)
[](https://smithery.ai/servers/jer-bouma/financetoolkit)
[](https://glama.ai/mcp/servers/JerBouma/FinanceToolkit)
[](https://www.jeroenbouma.com/projects/financetoolkit/docs)
[](https://pypi.org/project/FinanceToolkit/)
[](https://pypi.org/project/FinanceToolkit/)
[](https://pepy.tech/project/financetoolkit)
While browsing a variety of websites, I repeatedly observed significant fluctuations in the same financial metric among different sources. Similarly, the reported financial statements often didn't line up, and there was limited information on the methodology used to calculate each metric.
For example, Microsoft's Price-to-Earnings (PE) ratio on the 6th of May, 2023 is reported to be 28.93 (Stockopedia), 32.05 (Morningstar), 32.66 (Macrotrends), 33.09 (Finance Charts), 33.66 (Y Charts), 33.67 (Wall Street Journal), 33.80 (Yahoo Finance) and 34.4 (Companies Market Cap). All of these calculations are correct, however the method of calculation varies leading to different results. Therefore, collecting data from multiple sources can lead to wrong interpretation of the results given that one source could apply a different definition than another. And that is, if that definition is even available as often the underlying methods are hidden behind a paid subscription.
**This is why I designed the FinanceToolkit**, this is an open-source toolkit in which all relevant financial methods ([500+](https://www.jeroenbouma.com/projects/financetoolkit/docs)) are written down in the most simplistic way allowing for complete transparency of the method of calculation ([proof](https://github.com/JerBouma/FinanceToolkit/blob/main/financetoolkit/ratios/valuation_model.py)). This enables you to avoid dependence on metrics from other providers that do not provide their methods. With a large selection of financial statements in hand, it facilitates streamlined calculations, promoting the adoption of a consistent and universally understood methods and formulas.
Beyond Equities, it supports Options, Currencies, Cryptocurrencies, ETFs, Mutual Funds, Indices, Money Markets, Commodities, Key Economic Indicators and more, allowing you to obtain historical data as well as important performance and risk measurements such as the Sharpe Ratio and Value at Risk.
Complementing this is the [Finance Database 🌎](https://github.com/JerBouma/FinanceDatabase), a database featuring 300.000+ symbols containing Equities, ETFs, Funds, Indices, Currencies, Cryptocurrencies and Money Markets. By utilising both, it is possible to do a fully-fledged competitive analysis with the tickers found from the FinanceDatabase inputted into the FinanceToolkit.
___
**🔌 The Finance Toolkit is also available as an [MCP Server](https://www.jeroenbouma.com/projects/financetoolkit/mcp)**
Query 500+ methods from Claude, Copilot, Cursor, Windsurf or any MCP-compatible client without writing code.
- **Hosted:** connect to `https://financetoolkit.jeroenbouma.com/mcp` — OAuth handles the rest on first use.
- **Local:** `uvx --from "financetoolkit[mcp]" financetoolkit-mcp-setup` — sets up your client config and API key automatically. See [MCP Server Documentation](https://www.jeroenbouma.com/projects/financetoolkit/mcp#local-clients) for manual setup.
Also on [Smithery](https://smithery.ai/servers/jer-bouma/financetoolkit), [Glama](https://glama.ai/mcp/servers/JerBouma/FinanceToolkit), [MCP Servers](https://mcpservers.org/servers/jerbouma/financetoolkit) and more.
___
# Table of Contents
1. [Installation](#installation)
2. [Functionality](#functionality)
- [Discovering the Sector](#discovering-the-sector)
- [Following the Market](#following-the-market)
- [Zooming in on Competitors](#zooming-in-on-competitors)
- [Weighing Risk and Return](#weighing-risk-and-return)
- [What the Option Market Expects](#what-the-option-market-expects)
- [The Economic Environment](#the-economic-environment)
- [Economic Relations](#economic-relations)
- [Comparing the Sector's ETFs](#comparing-the-sectors-etfs)
- [Building a Diversified Portfolio](#building-a-diversified-portfolio)
- [Following the Portfolio](#following-the-portfolio)
3. [MCP Server](#mcp-server)
4. [Questions & Answers](#questions--answers)
5. [Contributing](#contributing)
6. [Mentions](#mentions)
7. [Contact](#contact)
# Installation
Before installation, consider starring the project on GitHub which helps others find the project as well.
<a href="https://github.com/JerBouma/FinanceToolkit" target="_blank"><img width="1415" alt="image" src="https://github.com/JerBouma/FinanceToolkit/assets/46355364/014109fe-0c68-47d4-99bd-217c69dcea8d"></a>
To install the Finance Toolkit it simply requires the following:
```
pip install financetoolkit -U
````
Then within Python use:
```python
from financetoolkit import Toolkit
companies = Toolkit(
tickers=['AAPL', 'MSFT'],
api_key="FINANCIAL_MODELING_PREP_KEY", # replace with your actual API key
)
```
To be able to get started, 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.
___
<b><div align="center">Obtain an API Key from FinancialModelingPrep <a href="https://www.jeroenbouma.com/fmp" target="_blank">here</a>.</div></b>
___
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. I have yet to find a platform offering such low prices for the amount of data offered. When you notice that the 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](https://site.financialmodelingprep.com/contact) or provide the data yourself.
**By default, the Finance Toolkit prioritizes Financial Modeling Prep for data retrieval. If data acquisition from Financial Modeling Prep is unsuccessful (e.g., due to plan restrictions or API key issues), the toolkit automatically switches to Yahoo Finance as a secondary source.** To disable this fallback behavior and exclusively use Financial Modeling Prep, set `enforce_source="FinancialModelingPrep"` during Toolkit initialization. This configuration ensures that an error is raised if Financial Modeling Prep data cannot be accessed. Alternatively, you can set `enforce_source="YahooFinance"` to exclusively use Yahoo Finance as the data source.
The same `enforce_source` argument is also accepted per call on `get_historical_data`, `get_treasury_data` and the four statement functions (`get_balance_sheet_statement`, `get_income_statement`, `get_cash_flow_statement` and `get_statistics_statement`), where it overrides whatever the Toolkit was initialised with.
# Functionality
This section is an introduction to the Finance Toolkit. The documentation contains many more examples: every module page opens with a Getting Started section, from the basics to creating custom ratios and working with your own datasets.
___
<b><div align="center">Find the Documentation, including the Getting Started guides, <a href="https://www.jeroenbouma.com/projects/financetoolkit/docs">here</a>.</div></b>
___
The sections below follow one analysis of the semiconductor sector from start to finish, where each step answers the question the previous one raises: which companies make up the sector, how their shares did, what drives their profits, how much risk came with the returns, what the option market expects next, how the economy shaped all of it, whether a fund is the better way in and how the sector fits into a diversified portfolio. Every module of the Finance Toolkit appears once, but each holds far more than shown here: 500+ methods in total, all described with examples in the [documentation](https://www.jeroenbouma.com/projects/financetoolkit/docs).
## Discovering the Sector
An analysis starts with a set of companies. The [Discovery](https://www.jeroenbouma.com/projects/financetoolkit/docs/discovery) module finds them without needing any tickers yet, through stock screeners, sector performance, news and lists of companies, ETFs, indices, currencies, cryptocurrencies and commodities.
The screener below looks for semiconductor companies on NASDAQ that are worth more than $100 billion:
```python
from financetoolkit import Discovery
# Initialize the standalone Discovery module
discovery = Discovery(api_key="FINANCIAL_MODELING_PREP_KEY")
# Find US semiconductor companies worth more than $100 billion
semiconductors = discovery.get_stock_screener(
industry="Semiconductors",
country="US",
exchange="NASDAQ",
market_cap_higher=100_000_000_000,
is_etf=False,
)
# Show the five largest
semiconductors[["Name", "Market Cap", "Beta", "Price", "Dividend"]].head()
```
For example, the five largest companies the screener returns are shown below.
| Symbol | Name | Market Cap | Beta | Price | Dividend |
|:---------|:-----------------------------|--------------:|-------:|--------:|-----------:|
| NVDA | NVIDIA Corporation | 5084136000000 | 2.216 | 210.96 | 0.28 |
| AVGO | Broadcom Inc. | 1535581254973 | 1.476 | 321.68 | 2.6 |
| MU | Micron Technology, Inc. | 992877621000 | 2.226 | 877.55 | 0.565 |
| AMD | Advanced Micro Devices, Inc. | 843646776955 | 2.454 | 516.79 | 0 |
| INTC | Intel Corp. | 459679713584 | 2.23 | 86.96 | 0 |
And below all of them are ranked by market cap.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/discovery-dark.png">
<img alt="Discovering the Sector" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/discovery-light.png">
</picture>
## Following the Market
The rest of this walkthrough follows three of them: Nvidia, AMD and Intel. They are loaded into the Toolkit in one line, and the S&P 500 comes along as the benchmark:
```python
from financetoolkit import Toolkit
# Initialize the Toolkit for Nvidia, AMD and Intel from 2018 to 2025
companies = Toolkit(
["NVDA", "AMD", "INTC"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2017-12-31",
end_date="2025-12-31",
)
```
[Historical data](https://www.jeroenbouma.com/projects/financetoolkit/docs#get_historical_data) comes on a daily, weekly, monthly, quarterly or yearly basis, with the return and cumulative return of each period, and so do the [income statement](https://www.jeroenbouma.com/projects/financetoolkit/docs#get_income_statement), [balance sheet](https://www.jeroenbouma.com/projects/financetoolkit/docs#get_balance_sheet_statement) and [cash flow statement](https://www.jeroenbouma.com/projects/financetoolkit/docs#get_cash_flow_statement) on an annual or quarterly basis. How far a share has travelled is one thing; whether the rally was stretched is another. The [technicals](https://www.jeroenbouma.com/projects/financetoolkit/docs/technicals) module answers that with 50+ indicators, such as the Relative Strength Index (RSI), which moves between 0 and 100 and is commonly read as overbought above 70:
```python
# Obtain weekly market data for all tickers and the benchmark
historical_data = companies.get_historical_data(period="weekly")
# The 14-week Relative Strength Index
relative_strength_index = companies.technicals.get_relative_strength_index(period="weekly", window=14)
# Show the highest RSI of each year
relative_strength_index.groupby(relative_strength_index.index.start_time.year).max()
```
For example, the highest weekly RSI of each year is shown below.
| Date | NVDA | AMD | INTC | Benchmark |
|-------:|--------:|--------:|--------:|------------:|
| 2018 | 66.1087 | 90.9719 | 66.7363 | 66.0498 |
| 2019 | 73.8156 | 81.2446 | 69.8225 | 75.9305 |
| 2020 | 85.2337 | 82.1215 | 78.4827 | 80.2378 |
| 2021 | 85.1593 | 82.0983 | 71.5862 | 74.4751 |
| 2022 | 58.4343 | 58.9426 | 61.2806 | 59.9225 |
| 2023 | 87.5129 | 77.506 | 76.2332 | 71.4291 |
| 2024 | 91.0702 | 82.1403 | 67.6949 | 80.0566 |
| 2025 | 73.3514 | 82.5281 | 79.7429 | 71.6939 |
And below the cumulative returns of all three are plotted against the S&P 500, with the RSI underneath.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/historical-dark.png">
<img alt="Following the Market" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/historical-light.png">
</picture>
## Zooming in on Competitors
Nvidia's shares outran the other two by far, which raises the question whether its business did as well. From the financial statements the Toolkit calculates 80+ [ratios](https://www.jeroenbouma.com/projects/financetoolkit/docs/ratios) in five categories: efficiency, liquidity, profitability, solvency and valuation. Each ratio has its own function, and a `collect_` function returns a whole category at once:
```python
# Collect all Profitability Ratios for all tickers
profitability_ratios = companies.ratios.collect_profitability_ratios()
# Show the first ratios for Nvidia
profitability_ratios.loc["NVDA"].head()
```
For example, some of Nvidia's profitability ratios are shown below.
| | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |
|:----------------------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|
| Gross Margin | 0.5993 | 0.6121 | 0.6199 | 0.6234 | 0.6493 | 0.5693 | 0.7272 | 0.7499 | 0.7107 |
| Operating Margin | 0.3305 | 0.3247 | 0.2607 | 0.2718 | 0.3731 | 0.1566 | 0.5412 | 0.6242 | 0.6038 |
| Net Profit Margin | 0.3137 | 0.3534 | 0.2561 | 0.2598 | 0.3623 | 0.1619 | 0.4885 | 0.5585 | 0.556 |
| EBITDA Margin | 0.3509 | 0.347 | 0.2956 | 0.3376 | 0.4167 | 0.2138 | 0.566 | 0.6385 | 0.617 |
| Free Cash Flow Margin | 0.2995 | 0.2683 | 0.3913 | 0.2815 | 0.3021 | 0.1412 | 0.4435 | 0.4663 | 0.4477 |
And below a few of them are shown with their latest value and their course over the years.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/ratios-dark.png">
<img alt="Profitability Ratios" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/ratios-light.png">
</picture>
A high return on equity can come from margins, from turnover or from debt. [Models](https://www.jeroenbouma.com/projects/financetoolkit/docs/models) combine the ratios to tell these apart: the [Extended DuPont Analysis](https://www.jeroenbouma.com/projects/financetoolkit/docs/models#get_extended_dupont_analysis) splits the return on equity into five components that multiply into it: interest burden, tax burden, operating margin, asset turnover and equity multiplier.
```python
# Get the Extended DuPont Analysis for all tickers
extended_dupont_analysis = companies.models.get_extended_dupont_analysis()
# Show the results for Nvidia
extended_dupont_analysis.loc["NVDA"]
```
For example, the components for Nvidia are shown below.
| | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |
|:------------------------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|
| Interest Burden Ratio | 0.9956 | 1.0242 | 1.0436 | 0.9729 | 0.99 | 0.9898 | 1.0257 | 1.0316 | 1.0848 |
| Tax Burden Ratio | 0.9534 | 1.0629 | 0.9414 | 0.9825 | 0.981 | 1.0447 | 0.88 | 0.8674 | 0.8488 |
| Operating Profit Margin | 0.3305 | 0.3247 | 0.2607 | 0.2718 | 0.3731 | 0.1566 | 0.5412 | 0.6242 | 0.6038 |
| Asset Turnover | 0.9215 | 0.9551 | 0.7134 | 0.7233 | 0.7376 | 0.6319 | 1.1397 | 1.4718 | 1.3564 |
| Equity Multiplier | 1.5931 | 1.4592 | 1.4205 | 1.5846 | 1.6775 | 1.7525 | 1.6428 | 1.4499 | 1.3456 |
| Return on Equity | 0.4605 | 0.4926 | 0.2595 | 0.2978 | 0.4483 | 0.1793 | 0.9146 | 1.1918 | 1.0149 |
And below each component is shown for every fiscal year, with the latest value on top, multiplying into the return on equity.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/models-dark.png">
<img alt="Extended DuPont Analysis" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/models-light.png">
</picture>
Other models include the [Weighted Average Cost of Capital](https://www.jeroenbouma.com/projects/financetoolkit/docs/models#get_weighted_average_cost_of_capital), [Altman Z-Score](https://www.jeroenbouma.com/projects/financetoolkit/docs/models#get_altman_z_score), [Piotroski F-Score](https://www.jeroenbouma.com/projects/financetoolkit/docs/models#get_piotroski_score) and [Intrinsic Valuation](https://www.jeroenbouma.com/projects/financetoolkit/docs/models#get_intrinsic_valuation). Almost every function also accepts `growth=True` for the growth from one period to the next, `trailing=4` for trailing twelve-month figures and `standardize=True` for Z-Scores.
## Weighing Risk and Return
Strong businesses do not make for smooth shares. The market data feeds the [performance](https://www.jeroenbouma.com/projects/financetoolkit/docs/performance) and [risk](https://www.jeroenbouma.com/projects/financetoolkit/docs/risk) modules, which calculate their metrics for any period, from intraday to yearly:
```python
# The annualized Sharpe Ratio for each year
sharpe_ratio = companies.performance.get_sharpe_ratio(period="yearly", annualize=True)
# The deepest fall within each year
maximum_drawdown = companies.risk.get_maximum_drawdown(period="yearly", within_period=True)
# Show the Sharpe Ratios
sharpe_ratio
```
For example, the yearly Sharpe Ratios are shown below.
| Date | NVDA | AMD | INTC |
|:-------|--------:|--------:|--------:|
| 2018 | -0.613 | 1.1009 | 0.161 |
| 2019 | 1.5458 | 1.9143 | 1.048 |
| 2020 | 1.656 | 1.419 | -0.0445 |
| 2021 | 2.0003 | 1.2366 | 0.2976 |
| 2022 | -0.8393 | -1.0532 | -1.5306 |
| 2023 | 2.6986 | 1.9195 | 1.8358 |
| 2024 | 2.0851 | -0.2615 | -1.5749 |
| 2025 | 0.8325 | 1.1753 | 1.2061 |
And below both are plotted for each year, the maximum drawdown together with the S&P 500.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/risk-dark.png">
<img alt="Sharpe Ratio and Maximum Drawdown" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/risk-light.png">
</picture>
Together the two modules cover 70+ metrics, such as [Value at Risk](https://www.jeroenbouma.com/projects/financetoolkit/docs/risk#get_value_at_risk), [GARCH](https://www.jeroenbouma.com/projects/financetoolkit/docs/risk#get_garch), [Jensen's Alpha](https://www.jeroenbouma.com/projects/financetoolkit/docs/performance#get_jensens_alpha), the [Capital Asset Pricing Model](https://www.jeroenbouma.com/projects/financetoolkit/docs/performance#get_capital_asset_pricing_model) and the [Fama-French factors](https://www.jeroenbouma.com/projects/financetoolkit/docs/performance#get_fama_and_french_model). Most of them also accept `rolling=<n>` for a value that moves through time.
## What the Option Market Expects
The past shows how much risk came with the returns; the option market puts a price on the risk ahead. The [options](https://www.jeroenbouma.com/projects/financetoolkit/docs/options) module prices options with Black-Scholes, the Binomial Model and others, calculates the Greeks up to the third order and reads the live option chains: the put-call ratio, max pain, dealer gamma exposure, the volatility skew and term structure and the implied move. As the chains are those of today, the Toolkit below runs up to today, and the numbers are those of the day this README was last updated:
```python
# Initialize the Toolkit up to today, as the option chains are live
companies_today = Toolkit(["NVDA", "AMD", "INTC"], api_key="FINANCIAL_MODELING_PREP_KEY")
# The volatility the options imply for the next 30 days against that of the past 30 days
companies_today.options.get_volatility_risk_premium(days=30)
```
The implied volatility is model-free, read with the method behind the VIX from all out-of-the-money options around the horizon, and the realized volatility is that of the daily returns over the same number of days. For example, both are shown below for each company.
| | Implied Volatility | Realized Volatility | Volatility Risk Premium | Variance Risk Premium | Implied to Realized Ratio |
|:-----|---------------------:|----------------------:|--------------------------:|------------------------:|----------------------------:|
| NVDA | 0.4845 | 0.2795 | 0.2049 | 0.1566 | 1.7331 |
| AMD | 0.657 | 0.498 | 0.159 | 0.1836 | 1.3192 |
| INTC | 0.6991 | 0.5196 | 0.1795 | 0.2188 | 1.3456 |
Options usually price more risk than follows, as their sellers want to be paid for taking it on, and here they priced far more turbulence for the coming month than the past month delivered: Nvidia's options implied 1.7 times the volatility its shares showed. And below the implied and realized volatility of each company are plotted next to each other.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/options-market-dark.png">
<img alt="Implied and Realized Volatility" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/options-market-light.png">
</picture>
## The Economic Environment
All three are listed in the United States and valued on earnings that lie years ahead, which makes US inflation and interest rates the backdrop to their share prices. In 2022, the year the maximum drawdown above shows each of them falling by more than half, inflation reached 9% and the Federal Reserve raised its policy rate from 0.12% to 4.38%.
The [economics](https://www.jeroenbouma.com/projects/financetoolkit/docs/economics) module covers 60+ countries with 50+ indicators, from GDP and unemployment to money supply and interest rates, and the [fixed income](https://www.jeroenbouma.com/projects/financetoolkit/docs/fixedincome) module adds bond yields, yield curves, central bank rates and bond and derivative valuations. Both are reached through the same Toolkit instance, or on their own with `from financetoolkit import Economics, FixedIncome`:
```python
# Inflation on the same month a year earlier and the Federal Reserve's policy rate
inflation_rate = companies.economics.get_inflation_rate("United States", period="monthly")
policy_rate = companies.economics.get_central_bank_policy_rate("United States", period="monthly")
# The daily U.S. Treasury par yield curve
treasury_rates = companies.fixedincome.get_treasury_rates()
# Show the curve on the last trading day of each year
treasury_rates.groupby(treasury_rates.index.year).last()
```
For example, the yield curve at the end of each year is shown below.
| Date | 1 Month | 2 Month | 3 Month | 6 Month | 1 Year | 2 Year | 3 Year | 5 Year | 7 Year | 10 Year | 20 Year | 30 Year |
|-------:|----------:|----------:|----------:|----------:|---------:|---------:|---------:|---------:|---------:|----------:|----------:|----------:|
| 2018 | 0.0244 | 0.0245 | 0.0245 | 0.0256 | 0.0263 | 0.0248 | 0.0246 | 0.0251 | 0.0259 | 0.0269 | 0.0287 | 0.0302 |
| 2019 | 0.0148 | 0.0151 | 0.0155 | 0.016 | 0.0159 | 0.0158 | 0.0162 | 0.0169 | 0.0183 | 0.0192 | 0.0225 | 0.0239 |
| 2020 | 0.0008 | 0.0008 | 0.0009 | 0.0009 | 0.001 | 0.0013 | 0.0017 | 0.0036 | 0.0065 | 0.0093 | 0.0145 | 0.0165 |
| 2021 | 0.0006 | 0.0005 | 0.0006 | 0.0019 | 0.0039 | 0.0073 | 0.0097 | 0.0126 | 0.0144 | 0.0152 | 0.0194 | 0.019 |
| 2022 | 0.0412 | 0.0441 | 0.0442 | 0.0476 | 0.0473 | 0.0441 | 0.0422 | 0.0399 | 0.0396 | 0.0388 | 0.0414 | 0.0397 |
| 2023 | 0.056 | 0.0559 | 0.054 | 0.0526 | 0.0479 | 0.0423 | 0.0401 | 0.0384 | 0.0388 | 0.0388 | 0.042 | 0.0403 |
| 2024 | 0.044 | 0.0439 | 0.0437 | 0.0424 | 0.0416 | 0.0425 | 0.0427 | 0.0438 | 0.0448 | 0.0458 | 0.0486 | 0.0478 |
| 2025 | 0.0374 | 0.0367 | 0.0367 | 0.0359 | 0.0348 | 0.0347 | 0.0355 | 0.0373 | 0.0394 | 0.0418 | 0.0479 | 0.0484 |
And below the yield curve at the end of each year is plotted. It went from almost zero at the short end in 2021 to above 4% across all maturities a year later, and when short-term yields lie above long-term ones, as at the end of 2022 and 2023, the curve is inverted.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/economics-dark.png">
<img alt="US Inflation, Policy Rate and Yield Curve" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/economics-light.png">
</picture>
## Economic Relations
Rates rose and the shares fell, but a 10-year Treasury yield is made of two parts: the real yield, the return investors demand on top of inflation, and the inflation they expect over those ten years. The [econometrics](https://www.jeroenbouma.com/projects/financetoolkit/docs/econometrics) module tells such drivers apart with regressions, tests and forecasts built on `statsmodels` and `linearmodels` (`pip install financetoolkit[econometrics]`). Through the Toolkit it analyzes the returns of its tickers, and on its own, through `Econometrics(data=...)`, any data at all, here the monthly returns of the three next to the monthly change in the US 10-year real yield and in 10-year inflation expectations:
```python
import pandas as pd
from financetoolkit import Econometrics
# The US 10-year real yield and inflation expectations at the end of each month
real_yield = companies.economics.get_real_yield_curve("United States", period="monthly")
inflation_expectations = companies.economics.get_breakeven_inflation_expectations(
"United States", period="monthly"
)
# The monthly change in both next to the monthly returns
monthly_returns = companies.get_historical_data(period="monthly")["Return"][["NVDA", "AMD", "INTC"]]
monthly_returns["Real Yield"] = real_yield[("United States", "10Y")].diff()
monthly_returns["Inflation Expectations"] = inflation_expectations[("United States", "10Y")].diff()
# The data are changes already
econometrics = Econometrics(data=monthly_returns, changes=None)
# Regress the return of each company on the change in the real yield and inflation expectations
regressions = pd.concat(
{
ticker: econometrics.get_ols(
dependent_ticker=ticker, independent_tickers=["Real Yield", "Inflation Expectations"]
)
for ticker in ["NVDA", "AMD", "INTC"]
}
)
# Show the results for Nvidia
regressions.loc["NVDA"]
```
For example, the coefficients for Nvidia are shown below.
| | Coefficient | Std. Error | t-Statistic | P-Value |
|:-----------------------|--------------:|-------------:|--------------:|----------:|
| Intercept | 0.049 | 0.0129 | 3.8028 | 0.0003 |
| Real Yield | -22.8132 | 5.6358 | -4.0479 | 0.0001 |
| Inflation Expectations | 18.1329 | 9.1029 | 1.992 | 0.0493 |
And below each coefficient is shown with its 95% confidence interval. A rise of 0.1 percentage point in the real yield went with a monthly return about 2.3% lower for Nvidia, 3.4% for AMD and 1.9% for Intel, as a higher real yield discounts their distant earnings more heavily. Inflation expectations matter far less: only for Nvidia does their coefficient come close to significance.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/econometrics-dark.png">
<img alt="Economic Relations" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/econometrics-light.png">
</picture>
The module also covers unit root and cointegration tests, Granger causality, panel data, causal inference, ARIMA, VAR and VECM forecasts, regime switching, a time-varying beta and pairs trading.
## Comparing the Sector's ETFs
Rather than picking three companies, a fund holds the whole industry. The [ETF](https://www.jeroenbouma.com/projects/financetoolkit/docs/etf) module analyzes the holdings, sector and country weightings, tracking, concentration, overlap, valuation and liquidity of any fund. Below it compares six semiconductor funds: three focused on the United States (SOXX, XSD and PSI), one global fund (SMH) and two that hold a single country, China (SMHC) and South Korea (KCHP):
```python
# Initialize the Toolkit for six semiconductor funds
funds = Toolkit(
["SOXX", "XSD", "PSI", "SMH", "SMHC", "KCHP"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2017-12-31",
end_date="2025-12-31",
)
# Where each fund invests, how concentrated it is and how much the funds hold of the same
country_weightings = funds.etf.get_country_weightings()
concentration = funds.etf.get_concentration()
overlap = funds.etf.get_overlap()
# Show the overlap between every pair of funds
overlap.round(2)
```
For example, the overlap between every pair of funds is shown below: the share of the two portfolios that is the same. Holdings are those of today, as funds publish their current holdings only.
| | SOXX | XSD | PSI | SMH | SMHC | KCHP |
|:-----|-------:|------:|------:|------:|-------:|-------:|
| SOXX | 1 | 0.38 | 0.46 | 0.7 | 0 | 0 |
| XSD | 0.38 | 1 | 0.34 | 0.28 | 0 | 0 |
| PSI | 0.46 | 0.34 | 1 | 0.38 | 0 | 0 |
| SMH | 0.7 | 0.28 | 0.38 | 1 | 0 | 0 |
| SMHC | 0 | 0 | 0 | 0 | 1.08 | 0 |
| KCHP | 0 | 0 | 0 | 0 | 0 | 1 |
The three US funds and SMH largely hold the same companies, with SOXX and SMH sharing 70% of their portfolios. SMH holds the most outside the United States, 9% in Taiwan and 6% in the Netherlands. The China and Korea funds share nothing with any other fund, which is what diversification within one sector looks like. Below, the country weights of each fund are plotted next to the overlap.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/etf-dark.png">
<img alt="Comparing the Sector's ETFs" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/etf-light.png">
</picture>
## Building a Diversified Portfolio
A fund spreads the risk over the sector, but the sector still moves as one. The [portfolio](https://www.jeroenbouma.com/projects/financetoolkit/docs/portfolio-optimization) module builds portfolios from the tickers of any Toolkit: minimum variance, maximum Sharpe ratio, mean-variance, risk parity, Hierarchical Risk Parity, minimum CVaR and Black-Litterman weights, the efficient frontier, risk contributions, stress tests and attribution. Below the semiconductor fund is combined with health care (XLV), energy (XLE), long-term Treasuries (TLT) and gold (GLD):
```python
# Initialize the Toolkit for funds across sectors and asset classes from 2021 to 2025
assets = Toolkit(
["SMH", "XLV", "XLE", "TLT", "GLD"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2021-01-01",
end_date="2025-12-31",
)
# The efficient frontier and the maximum Sharpe ratio portfolio, with at most 40% per asset
efficient_frontier = assets.portfolio.get_efficient_frontier(points=25, maximum_weight=0.4)
maximum_sharpe = assets.portfolio.get_maximum_sharpe_weights(maximum_weight=0.4)
# The portfolio in which every asset contributes the same share of the risk
risk_parity = assets.portfolio.get_risk_parity_weights()
# Show the risk parity portfolio
risk_parity
```
For example, the risk parity portfolio is shown below. Returns and volatilities are annualized and the risk contribution is each asset's share of the portfolio's volatility.
| | Weight | Expected Return | Volatility | Sharpe Ratio | Risk Contribution |
|:----------|---------:|------------------:|-------------:|---------------:|--------------------:|
| SMH | 0.1008 | 0.3067 | 0.3508 | 0.7782 | 0.2 |
| XLV | 0.2358 | 0.0901 | 0.1449 | 0.3889 | 0.2 |
| XLE | 0.1481 | 0.2463 | 0.2672 | 0.7954 | 0.2 |
| TLT | 0.275 | -0.0748 | 0.1606 | -0.6756 | 0.2 |
| GLD | 0.2403 | 0.1681 | 0.1562 | 0.8603 | 0.2 |
| Portfolio | 1 | 0.1084 | 0.1085 | 0.6888 | 1 |
And below the efficient frontier is plotted with both portfolios and each asset on its own, next to the weights of both portfolios.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/portfolio-optimization-dark.png">
<img alt="Building a Diversified Portfolio" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/portfolio-optimization-light.png">
</picture>
## Following the Portfolio
Optimal weights on paper still have to be held. The [Portfolio](https://www.jeroenbouma.com/projects/financetoolkit/docs/portfolio) class follows a portfolio over time, given as weights, as the shares held, as your own transactions or as one of thirteen classic portfolios such as the 60/40 and the All Weather portfolio. Below the risk parity weights are invested at the start of 2021, brought back to their weights every year and followed up to today:
```python
from financetoolkit import Portfolio
# Invest the risk parity weights and rebalance every year
portfolio = Portfolio(
weights=risk_parity,
start_date="2021-01-01",
rebalancing="yearly",
api_key="FINANCIAL_MODELING_PREP_KEY",
)
# Get an overview of the positions against the benchmark
overview = portfolio.get_portfolio_overview()
# Show the main figures
overview[["Weight", "Return", "Benchmark Return", "Volatility", "Alpha", "Beta"]]
```
For example, the main figures of each position are shown below.
| Identifier | Weight | Return | Benchmark Return | Volatility | Alpha | Beta |
|:-------------|---------:|---------:|-------------------:|-------------:|--------:|--------:|
| GLD | 0.1969 | 0.9399 | 0.849 | 0.2845 | 0.0909 | 0.8392 |
| SMH | 0.1307 | 2.0669 | 0.5236 | 0.4001 | 1.5433 | 2.4046 |
| TLT | 0.2273 | -0.2038 | 0.7457 | 0.096 | -0.9494 | 0.2198 |
| XLE | 0.2034 | 1.5458 | 0.2236 | 0.2212 | 1.3222 | -0.4119 |
| XLV | 0.2418 | 0.5502 | 0.7995 | 0.1632 | -0.2493 | 0.256 |
| Portfolio | 1 | 0.9703 | 1.1143 | 0.1047 | -0.144 | 0.5075 |
And below the return of each position is plotted against the return of the benchmark over the same period.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/portfolio-dark.png">
<img alt="Following the Portfolio" src="https://raw.githubusercontent.com/JerBouma/FinanceToolkit/main/assets/readme/portfolio-light.png">
</picture>
With `portfolio.toolkit` the portfolio, the time-weighted sum of all positions, is loaded into the Toolkit, so every metric above can be calculated for it as well.
# MCP Server
The Finance Toolkit MCP Server exposes 500+ financial methods directly to any AI assistant that supports the [Model Context Protocol](https://modelcontextprotocol.io) (MCP). Ask questions in plain English — the AI fetches live financial data on your behalf, backed by the transparent, open-source calculation methods of the Finance Toolkit.
See an example of the Finance Toolkit MCP server in action in Claude Desktop below:
https://github.com/user-attachments/assets/96ad5288-d83d-4497-a345-1841c48c29d5
### Remote server
Connect directly to the hosted server at `https://financetoolkit.jeroenbouma.com/mcp`. Nothing needs to be installed locally. On first connection your client opens an OAuth consent page asking for your FMP API key; enter it once and the server handles authentication from there.
| Client | Steps |
|:---|:---|
| **Claude Desktop** | Customize → Connectors → Add custom connector → paste the URL |
| **Claude.ai** | Customize → Connectors → Add custom connector → paste the URL |
| **Claude Code** | `claude mcp add --transport http finance-toolkit https://financetoolkit.jeroenbouma.com/mcp` |
| **VS Code** | Command Palette → MCP: Add Server → HTTP → paste the URL |
| **Cursor** | Settings → Features → MCP Servers → Add new → http → paste the URL |
| **Windsurf** | Settings → MCP Servers → Add Server → Remote/HTTP → paste the URL |
### Local installation
Run the setup wizard — it locates your client's config file and writes the MCP entry automatically, including the API key:
```bash
uvx --from "financetoolkit[mcp]" financetoolkit-mcp-setup
```
For manual config, add the following to your client's MCP config file (e.g. `claude_desktop_config.json`, `.cursor/mcp.json`, `.vscode/mcp.json`):
```json
{
"mcpServers": {
"finance-toolkit": {
"command": "uvx",
"args": ["--from", "financetoolkit[mcp]", "financetoolkit-mcp"],
"env": { "FINANCIAL_MODELING_PREP_API_KEY": "YOUR_API_KEY_HERE" }
}
}
}
```
Alternatively, download the [Finance Toolkit MCPB bundle](https://github.com/JerBouma/FinanceToolkit/releases/latest/download/financetoolkit.mcpb) and open it with Claude Desktop. An installation dialog will prompt for your FMP API key.
# Questions & Answers
This section includes frequently asked questions and is meant to clear up confusion about certain results and/or deviations from other sources. If you have any questions that are not answered here, feel free to reach out to me via the contact details below.
> **How do you deal with companies that have different fiscal years?**
For any financial statement, I make sure to line it up with the corresponding *calendar* period. For example, Apple's Q4 2023 relates to July to September of 2023. This corresponds to the calendar period Q3 which is why I normalize Apple's numbers to Q3 2023 instead. This is done to allow for comparison between companies that have different fiscal years.
> **Why do the numbers in the financial statements sometimes deviate from the data from FinancialModelingPrep?**
When looking at a company such as Hyundai Motor Company (ticker: 005380.KS), you will notice that the financial statements are reported in KRW (South Korean won). As this specific ticker is listed on the Korean Exchange, the historical market data will also be reported in KRW. However, if you use the ticker HYMTF, which is listed on the American OTC market, the historical market data will be reported in USD. To deal with this discrepancy, the end of year or end of quarter exchange rate is retrieved which is used to convert the financial statements to USD. This is done to prevent ratio calculations such as the Free Cash Flow Yield (which is based on the market capitalization) or Price Earnings Ratio (which is based on the stock price) from being incorrect. This can be disabled by setting `convert_currency=False` in the Toolkit initialization. It is recommended to always use the ticker that is listed on the exchange where the company is based.
> **How can I get TTM (Trailing Twelve Months) and Growth metrics?**
Most functions will have the option to define the `trailing` parameter. This lets you define the number of periods that you want to use to calculate the trailing metrics. For example, if you want to calculate the trailing 12-month (TTM) Price-to-Earnings Ratio, you can set `trailing=4` when you have set `quarterly=True` in the Toolkit initialization. The same goes for growth metrics which can be calculated by setting `growth=True`. This will calculate the growth for each period based on the previous period. This also includes a `lag` parameter in which you can define lagged growth. Furthermore, you can also combine the trailing and growth parameters to get trailing growth. For example, set `trailing=4` and `growth=True` for the Price-to-Earnings Ratio which will then calculate the TTM growth.
> **Does the Finance Toolkit retrieve the same data every time I run it?**
No. Any data that comes from an external source (financial statements, historical prices, economic indicators, yield curves, news and so on) is cached automatically in a local SQLite database and reused on the next run, in the Toolkit as well as in the Economics, Fixed Income, Discovery and Portfolio modules. Anything the Finance Toolkit calculates itself, such as ratios, models and risk metrics, is never cached: it is always derived from that data on demand, so it reflects the latest version of the Finance Toolkit.
Cached data does not go stale. Each dataset is retrieved again once it may have changed: prices and financial statements after a day (prices only for the last week, since older bars no longer change), quotes after a minute, company profiles after a month and economic releases according to how often they are published. An answer that a source has no data, such as the ETF holdings of a company, is cached as well, while a failed request, such as a rate limit, is not.
The cache keeps track of what it already holds per ticker and per date range, which means changing a parameter does not throw the rest away:
- Repeating the same request retrieves nothing at all.
- Widening the period only retrieves the years that were missing.
- Adding a ticker only retrieves that one ticker.
The database lives in your user configuration directory, which is the same one the MCP server uses, so both share a single cache. You can choose where it is stored, or switch caching off:
```python
from financetoolkit import Economics, Toolkit
# Store the cache in a specific folder
toolkit = Toolkit(["AAPL", "MSFT"], use_cached_data="datasets")
# Retrieve everything every time
toolkit = Toolkit(["AAPL", "MSFT"], use_cached_data=False)
economics = Economics(use_cached_data=False)
```
Setting the `FINANCE_TOOLKIT_CACHE_ENABLED` environment variable to `0` switches caching off by default everywhere, which suits environments where nothing should be written to disk, such as a continuous integration job. `FINANCE_TOOLKIT_CACHE_DB` moves the shared database to another file.
To see what is currently stored, use `toolkit.get_cache_contents()`. It reports the entries grouped by source and dataset:
| source | dataset | entities | entries | oldest_write | newest_write |
|:----------------------|:-----------|---------:|--------:|:--------------------|:--------------------|
| FinancialModelingPrep | historical | 2 | 2 | 2025-01-14 09:12:03 | 2025-01-14 09:12:05 |
| FinancialModelingPrep | statements | 2 | 2 | 2025-01-14 09:12:01 | 2025-01-14 09:12:02 |
The Finance Toolkit never clears the cache on its own, not even when its own internal structure changes. Removing data is always something you ask for explicitly with `toolkit.clear_cache()`, and it can be narrowed instead of wholesale:
```python
# Remove only the price history of a single ticker
toolkit.clear_cache(source="FinancialModelingPrep", ticker="AAPL")
# Remove everything retrieved from the OECD
toolkit.clear_cache(source="OECD")
# Remove the entire cache, which has to be confirmed
toolkit.clear_cache(confirm=True)
```
The `source` names match the ones used by the `enforce_source` parameter, so "FinancialModelingPrep" and "YahooFinance" mean the same thing in both places.
> **What is the "Benchmark" that is automatically obtained when acquiring historical data?**
This is related to the `benchmark_ticker` parameter which is set to "SPY" (S&P 500) by default. This is important when calculating performance metrics such as the Sharpe Ratio or Treynor Ratio that require a market return. This can be disabled by setting `benchmark_ticker=None` in the Toolkit initialization.
> **Data collection seems to be slow, what could be the issue?**
Generally, it should take less than 15 seconds to retrieve the historical data of 100 tickers. If it takes much longer, this could be due to reaching the API limit (the Starter plan has 250 requests per minute), due to a slow internet connection or due to unoptimized code. The Finance Toolkit collects data with a bounded pool of worker threads (10 by default, configurable through the `FINANCETOOLKIT_MAX_WORKERS` environment variable) over a shared connection, so it is recommended to initialize the Toolkit with all tickers you want to analyze at once rather than one at a time. If it is taking 10+ minutes consider having a look at [this issue](https://github.com/JerBouma/FinanceToolkit/issues/99#issuecomment-1889726000) that managed to resolve the problem.
> **I work behind a corporate proxy and get "certificate verify failed" errors, how do I solve this?**
Many corporate networks inspect encrypted traffic. The proxy opens every HTTPS connection on your behalf and presents a certificate signed by your company's own root certificate instead of the website's real one. Your browser trusts that root certificate because IT installed it on your computer, but Python does not: it checks certificates against its own list of public certificate authorities (the `certifi` package), which does not include your company's. The result is an error such as `SSLError: certificate verify failed: self-signed certificate in certificate chain`.
When a certificate cannot be verified, the Finance Toolkit first retries with your operating system's certificate file, where Python can find one (usually on Linux, not on Windows). If that fails as well, what happens next depends on whether the request carries an API key:
- Requests without an API key, such as those to the ECB, Eurostat or the BIS, are retried without verifying the certificate. A warning is logged when this happens.
- Requests with an API key, such as those to FinancialModelingPrep and FRED, are **not** retried without verification. The key is part of the web address, so anyone who can intercept an unverified connection could read it and use your subscription. The request fails with an error that explains the options below.
The recommended solution is to tell Python to trust your company's root certificate, so every connection stays verified:
1. Obtain the root certificate as a `.pem` (or `.crt`) file. Your IT department can usually provide it. You can also export it from your browser by opening the certificate details of any HTTPS website and exporting the top certificate in the chain ("Base-64 encoded" on Windows).
2. Combine it with Python's public certificates. The next step replaces Python's list rather than adding to it, so without the public certificates every connection that does not go through the proxy would fail:
```bash
# Prints the location of Python's public certificates
python -c "import certifi; print(certifi.where())"
# macOS and Linux: combine both into one file
cat /path/printed/above/cacert.pem /path/to/company-root.pem > ~/combined-certificates.pem
```
On Windows you can open both files in a text editor and paste the company certificate at the end of a copy of `cacert.pem`.
3. Point `REQUESTS_CA_BUNDLE` to the combined file before using the Finance Toolkit:
```bash
# macOS and Linux, e.g. in ~/.bashrc or ~/.zshrc
export REQUESTS_CA_BUNDLE=~/combined-certificates.pem
# Windows (PowerShell), for every window opened afterwards
setx REQUESTS_CA_BUNDLE "C:\Users\you\combined-certificates.pem"
```
`setx` does not change the window it runs in, so open a new terminal (or restart your editor) afterwards.
Or set it within Python, before the first request:
```python
import os
os.environ["REQUESTS_CA_BUNDLE"] = "/path/to/combined-certificates.pem"
from financetoolkit import Toolkit
```
When you use the MCP server, add the variable to the `env` section of the server in your AI assistant's configuration instead.
Alternatively, if your company's root certificate is already installed in your operating system (which is usually the case on managed Windows and macOS computers), the `truststore` package lets Python use the operating system's certificates directly. Install it with `pip install truststore` and run `import truststore; truststore.inject_into_ssl()` at the start of your script.
If none of this is possible, you can accept the risk and allow requests with an API key to be sent without verification by setting `FINANCETOOLKIT_ALLOW_UNVERIFIED_SSL=1` in the same way as above. Only do so on a network you trust: the connection is then encrypted to whoever answers it, which may not be the website you think you are talking to, and your API key is readable to them.
> **Are you part of FinancialModelingPrep?**
*No, I am not*. I've merely picked them as the primary data provider given that they have a generous free tier and fair pricing compared to other providers. Therefore, any questions related to the data should go through [their contact form](https://site.financialmodelingprep.com/contact). When it comes to any type of ratios, performance metrics, risk metrics, technical indicators or economic indicators, feel free to reach out to me as this is my own work.
# Contributing
First off all, thank you for taking the time to contribute (or at least read the Contributing Guidelines)! 🚀
___
<b><div align="center">Find the Contributing Guidelines <a href="/CONTRIBUTING.md">here</a>.</div></b>
___
The goal of the Finance Toolkit is to make any type of financial calculation as transparent and efficient as possible. I want to make these type of calculations as accessible to anyone as possible and seeing how many websites exists that do the same thing (but instead you have to pay) gave me plenty of reasons to work on this.
# Mentions
The Finance Toolkit has been mentioned in various blogposts, research papers, newsletters and social media. Below is a list of some of the mentions that I am aware of. **If you have any other mentions, feel free to reach out to me so I can add them to this list.**
**Blogposts**
- [A Deep Dive into EOY Financial Performance & Risk Measures of Big Five using the Finance Toolkit in Python](https://wire.insiderfinance.io/a-deep-dive-into-eoy-financial-performance-risk-measures-of-big-five-using-the-financetoolkit-in-ef93fddd11db)
- [Discovering the Best Integrated Platforms for Big Tech Quantitative Finance: 1. Finance Toolkit](https://wire.insiderfinance.io/discovering-the-best-integrated-platforms-for-big-tech-quantitative-finance-1-finance-toolkit-2e29b67eb4ea)
- [Investment Analysis with the Finance Database](https://alpha2phi.medium.com/investment-analysis-finance-database-61f47ecfe7ca)
- [Unlocking Financial Clarity: Introducing the Open-Source Finance Toolkit Powered by FMP](https://site.financialmodelingprep.com/education/ESG/unlocking-financial-clarity-introducing-the-open-source-finance-toolkit-powered-by-fmp)
**Research**
- [AI, Help Me Think, but for Myself: Assisting People in Complex Decision-Making by Providing Different Kinds of Cognitive Support](https://www.microsoft.com/en-us/research/wp-content/uploads/2025/03/AI-Help-Me-Think-CHI-2025.pdf)
- [Fundamental Analysis using Muli-Agent System and Agentic RAG](https://connect.cfauk.org/HigherLogic/System/DownloadDocumentFile.ashx?DocumentFileKey=3ae6f3fc-593a-04ec-c3b8-be5643cab479&forceDialog=0)
**Newsletters & Social Media**
- [LinkedIn #1](https://www.linkedin.com/posts/jerry-liu-64390071_this-is-an-extremely-comprehensive-100-activity-7340897396471623681-plI4?utm_source=share&utm_medium=member_desktop&rcm=ACoAABhYAQUBkaNnlBjz_IYBRfaurU68rfoZPE8) and [Linkedin #2](https://www.linkedin.com/posts/pyquant-news_getting-clean-fundamental-data-used-to-be-activity-7314273012927651841-KXP3?utm_source=share&utm_medium=member_desktop&rcm=ACoAABhYAQUBkaNnlBjz_IYBRfaurU68rfoZPE8)
- [Facebook](https://www.facebook.com/groups/techtitansgroup/posts/1515790739748239/)
- [Quant Seeker](https://www.quantseeker.com/p/weekly-research-recap)
- [Python Hub](https://pythonhub.dev/digest/2023-08-13/)
- [Python Weekly](https://www.pythonweekly.com/p/python-weekly-issue-611-august-3-2023)
- [Quant Science](https://www.threads.com/@quantscience_/post/DH1FDTGI7oi/the-project-is-finance-toolkit-its-available-on-github-here-httpsgithubcomjerbou?hl=zh-hk)
# Contact
If you have any questions about the Finance Toolkit or would like to share with me what you have been working on, feel free to reach out to me via:
- **Website**: https://jeroenbouma.com/
- **LinkedIn:** https://www.linkedin.com/in/boumajeroen/
- **Email:** jer.bouma@gmail.com
If you'd like to support my efforts, either help me out by contributing to the package or [Sponsor Me](https://github.com/sponsors/JerBouma).
<a href="https://www.star-history.com/?type=date&repos=JerBouma%2FFinanceToolkit">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=JerBouma/FinanceToolkit&type=date&theme=dark&legend=top-left&sealed_token=R4_fXwQ_uqTiS2P70MJ5ShMB5Pi7K8cY0AV697aqOyv6y_HKv63Z35Ax0B9uAlOgqvOOSm8c_N0NDF0bdVq-gJU0Fuzi1ZqQiMMg1YNbcC-PZ-EtWTE7WlYSgRLEk_8o6gUHxqKx32iYIZZ82pDDkDTImGG6ZTBmlt47QqF9aTp4Yd5FTtJ7tD9bbxxz" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=JerBouma/FinanceToolkit&type=date&legend=top-left&sealed_token=R4_fXwQ_uqTiS2P70MJ5ShMB5Pi7K8cY0AV697aqOyv6y_HKv63Z35Ax0B9uAlOgqvOOSm8c_N0NDF0bdVq-gJU0Fuzi1ZqQiMMg1YNbcC-PZ-EtWTE7WlYSgRLEk_8o6gUHxqKx32iYIZZ82pDDkDTImGG6ZTBmlt47QqF9aTp4Yd5FTtJ7tD9bbxxz" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=JerBouma/FinanceToolkit&type=date&legend=top-left&sealed_token=R4_fXwQ_uqTiS2P70MJ5ShMB5Pi7K8cY0AV697aqOyv6y_HKv63Z35Ax0B9uAlOgqvOOSm8c_N0NDF0bdVq-gJU0Fuzi1ZqQiMMg1YNbcC-PZ-EtWTE7WlYSgRLEk_8o6gUHxqKx32iYIZZ82pDDkDTImGG6ZTBmlt47QqF9aTp4Yd5FTtJ7tD9bbxxz" />
</picture>
</a>
TDQS
Scored across 27 tools
The 27 top-level tools are mostly partitioned by clear finance domains, so an agent can generally choose the right category. Minor confusion is possible among ratio categories (efficiency, liquidity, profitability, solvency, valuation) and technical-indicator categories (breadth, momentum, overlap, volatility), but the descriptions draw usable boundaries.
Most tools use consistent snake_case domain-category nouns, with search_by_category, search_metric_categories, and search_metrics forming a clear meta-search group. The convention is not verb_noun throughout, but it is predictable and readable rather than chaotic.
At 27 tools the surface is heavy for a single server, but the tools are broad category dispatchers rather than granular operations, which suits a comprehensive finance analytics toolkit. It is borderline rather than clearly excessive.
The surface covers raw market data, fundamentals, ratios, technicals, econometrics, portfolio construction, risk, options, fixed income, macro, government, environmental, labor, ETF, discovery, and meta-search workflows. No obvious material lifecycle gap appears for a finance analytics server.