Fit a Generalized Least Squares (GLS) regression of dependent_ticker on independent_tickers, given a known error covariance structure omega.

GLS generalises WLS to an arbitrary error covariance matrix Var(e) = sigma^2 * Omega. Where WLS only corrects for heteroskedasticity (a diagonal Omega), GLS also corrects for correlation between the errors of different observations, such as the autocorrelation that is common in financial time series (a non-diagonal Omega).

The formula is as follows:

\[\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} = \text{e'Ω⁻¹e} / (n - k)\]
  • y is the dependent ticker’s column (Return by default) and X the independent tickers’ column plus a constant (add_constant=True)

Under a correctly specified Omega this is the most efficient linear unbiased estimator. By default (omega=”ar1”) Omega is estimated from the regression itself as an AR(1) error structure, eₜ = ρ·eₜ₋₁ + uₜ: ρ is the slope of the OLS residuals on their own lag and Ωᵢⱼ = ρ^|i - j|, which makes this the Prais-Winsten estimator. Any other structure can be supplied as omega. get_durbin_watson_test helps establish whether the residuals are autocorrelated in the first place.

For more information about the method, see the following paper:

  • Aitken, A.C. (1935). “On Least Squares and Linear Combinations of Observations.” Proceedings of the Royal Society of Edinburgh, 55, 42-48.
  • Prais, S.J. and Winsten, C.B. (1954). “Trend Estimators and Serial Correlation.” Cowles Commission Discussion Paper No. 383.

Also known as: GLS, Prais-Winsten.

Generalised Least Squares (GLS) in Python or via the MCP

Install the Finance Toolkit with:

pip install financetoolkit -U

Then call get_gls as shown below.

from financetoolkit import Toolkit

toolkit = Toolkit(
    ["AAPL", "MSFT"],
    api_key="FINANCIAL_MODELING_PREP_KEY",
    start_date="2021-01-01",
    end_date="2025-12-31",
)

# AAPL (the first ticker) is dependent, MSFT is independent; Omega is estimated (AR(1))
toolkit.econometrics.get_gls(period="weekly")

Or, after setting up the Finance Toolkit MCP, ask:

How sensitive were Apple's weekly returns to Microsoft's from 2021 to 2025, according to a generalized least squares regression?

Which returns:

  Coefficient Std. Error t-Statistic P-Value
Intercept 0.0012 0.0017 0.7282 0.4671
MSFT 0.6312 0.0576 10.9557 0

Using Your Own Data

get_gls 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:

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")

econometrics.get_gls()

Parameters

get_gls accepts the following parameters.

ParameterTypeDescriptionExample
omegapd.DataFrame | strThe (symmetric, positive-definite) error covariance structure, up to a scalar, shape (n, n), or “ar1” to estimate an AR(1) structure from the regression’s own residuals (Prais-Winsten). Defaults to “ar1”."ar1"
dependent_tickerstr | NoneThe dependent (predicted) asset. Defaults to None, meaning the Toolkit instance’s first ticker."AAPL"
independent_tickersstr | list[str] | NoneThe independent (predictor) asset(s). Defaults to None, meaning every other ticker in the Toolkit instance besides dependent_ticker.["MSFT", "Benchmark"]
include_benchmarkboolWhether to include “Benchmark” in the default independent ticker(s) (has no effect when independent_tickers is given explicitly). Defaults to False.True
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