Instrumental Variables (2SLS)
Fit an Instrumental Variables regression via Two-Stage Least Squares (2SLS) of dependent_ticker on endogenous_ticker, instrumented by instrument_tickers.
Also known as: IV, 2SLS, IV-2SLS.
For more information about the method, and why plain OLS on an asset suspected of reverse-causality/omitted-confounder bias against another asset is unreliable, see causal_inference_model.get_iv_2sls.
A natural use case in a multi-asset return panel: suppose endogenous_ticker’s return is suspected to be simultaneously determined together with dependent_ticker’s return (e.g. two closely related assets that react to each other intraday, or one asset’s return partly reflects news about the other) – plain OLS of one on the other is then biased. An instrument_tickers asset that moves endogenous_ticker for reasons unrelated to dependent_ticker’s own error term (e.g. a supplier/peer whose moves affect endogenous_ticker but only reach dependent_ticker, if at all, THROUGH endogenous_ticker) allows recovering a cleaner estimate of the causal pass-through.
The formula is as follows:
\[Z = \left[1,\; \text{exogenous tickers},\; \text{instruments}\right] \text{and}\; X = \left[1,\; \text{exogenous tickers},\; \text{endogenous tickers}\right],\;\; \text{all in column (Return by default)},\;\; \text{the constant only with add\_constant=True}\] \[\text{Stage 1:}\;\; \text{X̂} = Z(\text{Z'Z}) \text{⁻¹Z'X},\;\; \text{the fitted values of each endogenous ticker regressed on Z}\] \[\text{Stage 2:}\;\; \text{betâ} = (\text{X̂'X}) \text{⁻¹X̂'y}\] \[\operatorname{Cov}(\text{betâ}) = \text{sigmâ} ^{2} \cdot (\text{X̂'X̂}) \text{⁻¹},\;\; \text{with}\; \text{sigmâ} ^{2} = \operatorname{Σ}(\text{yₜ} - \text{xₜ'betâ}) ^{2} / (n - k) (\text{linearmodels}\; \text{IV2SLS} \;\text{with}\; \text{cov\_type} = \text{"unadjusted"} \;\text{and debiased} = \text{True})\]Instrumental Variables (2SLS) in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_iv_2sls as shown below.
from financetoolkit import Toolkit
toolkit = Toolkit(
["SMCI", "NVDA", "TSM"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2025-01-01",
end_date="2025-12-31",
)
toolkit.econometrics.get_iv_2sls(
dependent_ticker="SMCI", endogenous_ticker="NVDA", instrument_tickers="TSM"
)
Or, after setting up the Finance Toolkit MCP, ask:
How strongly did Nvidia's daily returns pass through to Super Micro Computer's in 2025, with TSMC's returns as the instrument for Nvidia's?
Which returns:
| Coefficient | Std. Error | t-Statistic | P-Value | |
|---|---|---|---|---|
| Intercept | -0.0008 | 0.0027 | -0.2931 | 0.7697 |
| NVDA | 1.2518 | 0.1094 | 11.441 | 0 |
Using Your Own Data
get_iv_2sls runs on any data, not only prices: ratios, economic indicators, yield curves or your own dataset. Pass a DataFrame, a Series or a dictionary of them to Econometrics as data, with the dates in the rows or the columns, and set changes to how its changes are calculated: "percentage", "log", "difference" for rates and ratios, or None when the data are changes already. For example, for the monthly unemployment rates of the United States and Germany, where each country is a column:
from financetoolkit import Economics, Econometrics
economics = Economics(start_date="2000-01-01")
unemployment = economics.get_unemployment_rate(
countries=["United States", "Germany"], period="monthly"
)
econometrics = Econometrics(data=unemployment, changes="difference")
Then call econometrics.get_iv_2sls with dependent_ticker, endogenous_ticker and instrument_tickers, using the column names of the data as tickers.
Parameters
get_iv_2sls accepts the following parameters.
| Parameter | Type | Description | Example |
|---|---|---|---|
dependent_ticker | str | The dependent (predicted) asset. | "AAPL" |
endogenous_ticker | str | list[str] | The endogenous regressor asset(s) – suspected correlated with the error term. | "MSFT" |
instrument_tickers | str | list[str] | The excluded instrument asset(s), correlated with endogenous_ticker but assumed uncorrelated with the error term. Must supply at least as many instruments as endogenous regressors. | "Benchmark" |
exogenous_tickers | str | list[str] | None | Other, non-instrumented control asset(s) included as-is in both stages. Defaults to None. | "GOOGL" |
period | str | The data frequency (daily, weekly, monthly, quarterly, or yearly). Defaults to “daily”. | "weekly" |
column | str | The historical data column to regress on. Defaults to “Return”. | "Return" |
add_constant | bool | Whether to include an intercept. Defaults to True. | False |
rounding | int | None | The number of decimals to round the results to. Defaults to None. | 2 |