Weighted Least Squares (WLS)
Fit a Weighted Least Squares (WLS) regression of dependent_ticker on independent_tickers.
When the error variance differs across observations (heteroskedasticity) with a known or estimable structure, Var(e_i) = sigma^2 / w_i, OLS remains unbiased but is no longer the most efficient estimator. WLS restores efficiency by minimising the weighted sum of squared residuals, so noisier observations (low weight) count less than precise ones (high weight).
The formula is as follows:
\[\text{betâ} = (\text{X'WX}) \text{⁻¹X'Wy},\;\; \text{with}\; W = \operatorname{diag}(\text{weights}),\;\; \text{the same as OLS of sqrt(w)ₜ*yₜ on sqrt(w)ₜ*xₜ}\] \[\operatorname{Cov}(\text{betâ}) = \text{sigmâ} ^{2} \cdot (\text{X'WX}) \text{⁻¹},\;\; \text{with}\; \text{sigmâ} ^{2} = \text{Σwₜ} \cdot \text{eₜ} ^{2} / (n - k) (\text{cov\_type} = \text{"nonrobust"})\]- y is the dependent ticker’s
column(Return by default) and X the independent tickers’columnplus a constant, on the dates where the returns andweightsall have data
With equal weights WLS reduces to OLS. A typical use is down-weighting periods of high volatility, so that a few turbulent periods do not dominate the estimated relationship. By default (weights=”feasible”) the weights are estimated from the regression itself with the feasible GLS procedure of Wooldridge (2016): the logarithm of the squared OLS residuals is regressed on the independent tickers, and each period’s weight is 1 / exp(fitted value), the inverse of its estimated error variance. Use get_breusch_pagan_test or get_white_test to establish whether heteroskedasticity is present before choosing WLS over OLS.
For more information about the feasible weights, see the following book:
- Wooldridge, J.M. (2016). “Introductory Econometrics: A Modern Approach”, 6th edition, Section 8.4. Cengage Learning.
Also known as: weighted regression, feasible WLS.
Weighted Least Squares (WLS) in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_wls 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; the weights are estimated
toolkit.econometrics.get_wls(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 weighted least squares regression?
Which returns:
| Coefficient | Std. Error | t-Statistic | P-Value | |
|---|---|---|---|---|
| Intercept | 0.0012 | 0.0019 | 0.6263 | 0.5317 |
| MSFT | 0.6356 | 0.0596 | 10.6643 | 0 |
Using Your Own Data
get_wls 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_wls()
Parameters
get_wls accepts the following parameters.
| Parameter | Type | Description | Example |
|---|---|---|---|
weights | pd.Series | str | The (positive) weight of each observation, aligned to the same period index as the return data (e.g. 1 / rolling_variance), or “feasible” to estimate them from the regression’s own residuals with the feasible GLS procedure of Wooldridge (2016). Defaults to “feasible”. | "feasible" |
dependent_ticker | str | None | The dependent (predicted) asset. Defaults to None, meaning the Toolkit instance’s first ticker. | "AAPL" |
independent_tickers | str | list[str] | None | The independent (predictor) asset(s). Defaults to None, meaning every other ticker in the Toolkit instance besides dependent_ticker. | ["MSFT", "Benchmark"] |
include_benchmark | bool | Whether to include “Benchmark” in the default independent ticker(s) (has no effect when independent_tickers is given explicitly). Defaults to False. | True |
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 |
cov_type | str | Which covariance estimator to use, applied to the weighted/ transformed problem – see get_ols’s cov_type for the full list of options. Defaults to “nonrobust”. | "HC3" |
clusters | pd.Series | None | The cluster label for each observation, required when cov_type="cluster". Defaults to None. | None |
maxlags | int | None | The maximum lag to include when estimating the HAC (Newey-West) covariance matrix, only used when cov_type="HAC". Defaults to None, meaning the Newey & West (1994) rule of thumb (see get_ols). | 5 |
rounding | int | None | The number of decimals to round the results to. Defaults to None. | 2 |