mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-12 12:22:35 +00:00
feature/econometrics: Added Variance Inflation Factor (#5866)
* Added Variance Inflation Factor * Return VIF values as a dataframe * General linting * Updated VIF test parameters * docstring grammar police * router example * pylint * pylint again --------- Co-authored-by: James Maslek <jmaslek11@gmail.com> Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>
This commit is contained in:
@@ -403,3 +403,22 @@ def test_econometrics_panel_fmac(params, obb):
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
({"data": "", "columns": ["income", "age"]}),
|
||||
({"data": "", "columns": ["education"]}),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_econometrics_variance_inflation_factor(params, obb):
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
params["data"] = mock_multi_index_data()
|
||||
|
||||
result = obb.econometrics.variance_inflation_factor(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Econometrics Router."""
|
||||
|
||||
from itertools import combinations
|
||||
from typing import Dict, List, Literal
|
||||
from typing import Dict, List, Literal, Optional
|
||||
|
||||
from openbb_core.app.model.example import APIEx, PythonEx
|
||||
from openbb_core.app.model.obbject import OBBject
|
||||
@@ -910,3 +910,76 @@ def panel_fmac(
|
||||
exogenous = sm.add_constant(X)
|
||||
results = FamaMacBeth(y, exogenous).fit()
|
||||
return OBBject(results={"results": results})
|
||||
|
||||
|
||||
@router.command(
|
||||
methods=["POST"],
|
||||
include_in_schema=False,
|
||||
examples=[
|
||||
PythonEx(
|
||||
description="Calculate the variance inflation factor.",
|
||||
code=[
|
||||
"stock_data = obb.equity.price.historical(symbol='TSLA', start_date='2023-01-01', provider='yfinance').to_df()", # noqa: E501 pylint: disable= C0301
|
||||
'obb.econometrics.variance_inflation_factor(data=stock_data, column="close")',
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def variance_inflation_factor(
|
||||
data: List[Data], columns: Optional[list] = None
|
||||
) -> OBBject[List[Data]]:
|
||||
"""Calculate VIF (variance inflation factor), which tests for collinearity.
|
||||
|
||||
It quantifies the severity of multicollinearity in an ordinary least squares regression analysis. The square
|
||||
root of the variance inflation factor indicates how much larger the standard error increases compared to if
|
||||
that variable had 0 correlation to other predictor variables in the model.
|
||||
|
||||
It is defined as:
|
||||
|
||||
$ VIF_i = 1 / (1 - R_i^2) $
|
||||
where $ R_i $ is the coefficient of determination of the regression equation with the column i being the result
|
||||
from the i:th series being the exogenous variable.
|
||||
|
||||
A VIF over 5 indicates a high collinearity and correlation. Values over 10 indicates causes problems, while a
|
||||
value of 1 indicates no correlation. Thus VIF values between 1 and 5 are most commonly considered acceptable.
|
||||
In order to improve the results one can often remove a column with high VIF.
|
||||
|
||||
For further information see: https://en.wikipedia.org/wiki/Variance_inflation_factor
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dataset: List[Data]
|
||||
Dataset to calculate VIF on
|
||||
columns: Optional[list]
|
||||
The columns to calculate to test for collinearity
|
||||
|
||||
Returns
|
||||
-------
|
||||
OBBject[List[Data]]
|
||||
The resulting VIF values for the selected columns
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.app.utils import (
|
||||
basemodel_to_df,
|
||||
df_to_basemodel,
|
||||
)
|
||||
from pandas import DataFrame
|
||||
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif
|
||||
from statsmodels.tools.tools import add_constant
|
||||
|
||||
# Convert to pandas dataframe
|
||||
dataset = basemodel_to_df(data)
|
||||
|
||||
# Add a constant
|
||||
df = add_constant(dataset if columns is None else dataset[columns])
|
||||
|
||||
# Remove date and string type because VIF doesn't work for these types
|
||||
df = df.select_dtypes(exclude=["object", "datetime", "timedelta"])
|
||||
|
||||
# Calculate the VIF values
|
||||
vif_values: dict = {}
|
||||
for i in range(len(df.columns))[1:]:
|
||||
vif_values[f"{df.columns[i]}"] = vif(df.values, i)
|
||||
|
||||
results = df_to_basemodel(DataFrame(vif_values, index=[0]))
|
||||
return OBBject(results=results)
|
||||
|
||||
Reference in New Issue
Block a user