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.

ParameterTypeDescriptionExample
dependent_tickerstrThe dependent (predicted) asset."AAPL"
endogenous_tickerstr | list[str]The endogenous regressor asset(s) – suspected correlated with the error term."MSFT"
instrument_tickersstr | 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_tickersstr | list[str] | NoneOther, non-instrumented control asset(s) included as-is in both stages. Defaults to None."GOOGL"
periodstrThe data frequency (daily, weekly, monthly, quarterly, or yearly). Defaults to “daily”."weekly"
columnstrThe historical data column to regress on. Defaults to “Return”."Return"
add_constantboolWhether to include an intercept. Defaults to True.False
roundingint | NoneThe number of decimals to round the results to. Defaults to None.2
Share