Refactoring econometrics for SDK usability (#3379)

* Econometrics enhancements

* Docsring

* norm show chart when true

* isort + lint

* Make coint sdk friendly

* mypy?

* Why you miss this locally pylint?

* Clean up granger command

* Tests

* #3323

* Fix up dwat function

* Fix rounding error in test--hopefully

* Update bgod and bpag

* testing mypy

* small commit to help rebase?

* Update Panel OLS stuff. Need some more examples and to fix mypy

* add docstring example

* update controller complete and duplicate printing

Co-authored-by: Jeroen Bouma <jer.bouma@gmail.com>
This commit is contained in:
James Maslek
2022-11-15 09:46:29 -05:00
committed by GitHub
parent 8bf8201690
commit 4495d4d2f5
58 changed files with 1079 additions and 1055 deletions

View File

@@ -42,12 +42,16 @@ repos:
"--quiet-level=2",
"--skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,build/pyinstaller/*,./website/config.toml",
]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v0.982"
- repo: local
hooks:
- id: mypy
args: ["--ignore-missing-imports", 'openbb_terminal']
additional_dependencies: [types-all]
- id: mypy
name: mypy
description: ''
entry: mypy
language: python
'types_or': [python, pyi]
args: ["--ignore-missing-imports", "--scripts-are-modules"]
require_serial: true
- repo: https://github.com/kynan/nbstripout
rev: 0.6.1
hooks:

View File

@@ -5,40 +5,42 @@ __docformat__ = "numpy"
import argparse
import logging
from itertools import chain
import os
from itertools import chain
from pathlib import Path
from typing import List, Dict, Any
from typing import Any, Dict, List
import numpy as np
import pandas as pd
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
import openbb_terminal.econometrics.regression_model
import openbb_terminal.econometrics.regression_view
from openbb_terminal.core.config.paths import USER_CUSTOM_IMPORTS_DIRECTORY
from openbb_terminal import feature_flags as obbff
from openbb_terminal.core.config.paths import USER_EXPORTS_DIRECTORY
from openbb_terminal.common import common_model
from openbb_terminal.core.config.paths import (
USER_CUSTOM_IMPORTS_DIRECTORY,
USER_EXPORTS_DIRECTORY,
)
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
check_positive,
check_positive_float,
NO_EXPORT,
EXPORT_ONLY_FIGURES_ALLOWED,
EXPORT_ONLY_RAW_DATA_ALLOWED,
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
export_data,
from openbb_terminal.econometrics import (
econometrics_model,
econometrics_view,
regression_model,
regression_view,
)
from openbb_terminal.helper_funcs import (
print_rich_table,
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
EXPORT_ONLY_FIGURES_ALLOWED,
EXPORT_ONLY_RAW_DATA_ALLOWED,
NO_EXPORT,
check_list_values,
check_positive,
check_positive_float,
export_data,
print_rich_table,
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.econometrics import econometrics_model, econometrics_view
from openbb_terminal.common import common_model
from openbb_terminal.rich_config import MenuText, console
logger = logging.getLogger(__name__)
@@ -88,6 +90,19 @@ class EconometricsController(BaseController):
"pie",
"hexbin",
]
PANEL_CHOICES = [
"pols",
"re",
"bols",
"fe",
"fdols",
"POLS",
"RE",
"BOLS",
"FE",
"FDOLS",
]
PATH = "/econometrics/"
loaded_dataset_cols = "\n"
@@ -170,7 +185,7 @@ class EconometricsController(BaseController):
choices["support"] = self.SUPPORT_CHOICES
choices["about"] = self.ABOUT_CHOICES
choices["panel"]["-r"] = {c: {} for c in self.PANEL_CHOICES}
self.completer = NestedCompleter.from_nested_dict(choices)
def update_runtime_choices(self):
@@ -262,13 +277,11 @@ class EconometricsController(BaseController):
mt.add_cmd("bpag", self.files and self.regression["OLS"]["model"])
console.print(text=mt.menu_text, menu="Econometrics")
console.print()
def custom_reset(self):
"""Class specific component of reset command"""
if self.files:
load_files = [f"load -f {file}" for file in self.files]
return ["econometrics"] + load_files
return []
return ["econometrics"]
def update_loaded(self):
self.list_dataset_cols = []
@@ -355,7 +368,7 @@ class EconometricsController(BaseController):
if not file:
console.print(
"[red]The file/dataset selected does not exist.[/red]\n"
"[red]The file/dataset selected does not exist.[/red]"
)
return
else:
@@ -372,7 +385,7 @@ class EconometricsController(BaseController):
# check if this dataset has been added already
if alias in self.files:
console.print(
"[red]The file/dataset selected has already been loaded.[/red]\n"
"[red]The file/dataset selected has already been loaded.[/red]"
)
return
@@ -388,8 +401,6 @@ class EconometricsController(BaseController):
self.update_loaded()
console.print()
@log_start_end(log=logger)
def call_export(self, other_args: List[str]):
"""Process export command"""
@@ -1189,6 +1200,13 @@ class EconometricsController(BaseController):
),
required="-h" not in other_args,
)
parser.add_argument(
"--no-output",
action="store_true",
default=False,
help="Hide the output of the regression",
dest="no_output",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-d")
@@ -1204,15 +1222,25 @@ class EconometricsController(BaseController):
)
elif ns_parser.dependent in self.choices["regressions"]:
(
self.regression["OLS"]["data"],
self.regression["OLS"]["dependent"],
self.regression["OLS"]["independent"],
self.regression["OLS"]["model"],
) = openbb_terminal.econometrics.regression_model.get_ols(
regression_df,
dependent_variable,
independent_variables,
) = regression_model.get_regression_data(
[ns_parser.dependent] + ns_parser.independent,
self.datasets,
export=ns_parser.export,
"OLS",
)
self.regression["OLS"]["data"] = regression_df
self.regression["OLS"]["dependent"] = dependent_variable
self.regression["OLS"]["independent"] = independent_variables
model = regression_model.get_ols(
regression_df[dependent_variable],
regression_df[independent_variables],
)
self.regression["OLS"]["model"] = model
if not ns_parser.no_output:
console.print(model.summary())
else:
console.print(
f"{ns_parser.dependent} not in {','.join(self.choices['regressions'])}\n"
@@ -1273,7 +1301,7 @@ class EconometricsController(BaseController):
else:
return console.print(f"Can not find {dataset}. Did you load the data?")
return econometrics_view.display_norm(
econometrics_view.display_norm(
data, dataset, column, ns_parser.plot, ns_parser.export
)
@@ -1386,18 +1414,7 @@ class EconometricsController(BaseController):
"-r",
"--regression",
type=str,
choices=[
"pols",
"re",
"bols",
"fe",
"fdols",
"POLS",
"RE",
"BOLS",
"FE",
"FDOLS",
],
choices=self.PANEL_CHOICES,
dest="type",
help="The type of regression you wish to perform. This can be either pols (Pooled OLS), "
"re (Random Effects), bols (Between OLS), fe (Fixed Effects) or fdols (First Difference OLS)",
@@ -1459,7 +1476,7 @@ class EconometricsController(BaseController):
)
# Ensure that OLS is always ran to be able to perform tests
regression_types = ["OLS", ns_parser.type.upper()]
regression_types = [ns_parser.type.upper(), "OLS"]
for regression in regression_types:
regression_name = regression
@@ -1470,18 +1487,29 @@ class EconometricsController(BaseController):
regression_name = regression_name + "_IE"
(
self.regression[regression_name]["data"],
self.regression[regression_name]["dependent"],
self.regression[regression_name]["independent"],
self.regression[regression_name]["model"],
) = openbb_terminal.econometrics.regression_view.display_panel(
regression_df,
dependent_variable,
independent_variables,
) = regression_model.get_regression_data(
[ns_parser.dependent] + ns_parser.independent,
self.datasets,
regression_vars,
regression,
)
self.regression[regression]["data"] = regression_df
self.regression[regression]["dependent"] = dependent_variable
self.regression[regression][
"independent"
] = independent_variables
self.regression[regression_name][
"model"
] = regression_view.display_panel(
regression_df[dependent_variable],
regression_df[independent_variables],
regression,
ns_parser.entity_effects,
ns_parser.time_effects,
ns_parser.export,
)
console.print()
else:
console.print(
f"{ns_parser.dependent} not in {','.join(self.choices['regressions'])}\n"
@@ -1501,9 +1529,7 @@ class EconometricsController(BaseController):
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
openbb_terminal.econometrics.regression_model.get_comparison(
self.regression, ns_parser.export
)
regression_model.get_comparison(self.regression, ns_parser.export)
console.print()
@log_start_end(log=logger)
@@ -1538,9 +1564,9 @@ class EconometricsController(BaseController):
dependent_variable = self.regression["OLS"]["data"][
self.regression["OLS"]["dependent"]
]
openbb_terminal.econometrics.regression_view.display_dwat(
regression_view.display_dwat(
self.regression["OLS"]["model"],
dependent_variable,
self.regression["OLS"]["model"].resid,
ns_parser.plot,
ns_parser.export,
)
@@ -1578,7 +1604,7 @@ class EconometricsController(BaseController):
"Perform an OLS regression before estimating the Breusch-Godfrey statistic.\n"
)
else:
openbb_terminal.econometrics.regression_view.display_bgod(
regression_view.display_bgod(
self.regression["OLS"]["model"], ns_parser.lags, ns_parser.export
)
@@ -1590,7 +1616,7 @@ class EconometricsController(BaseController):
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="bpag",
description=(
"Show Breusch-Pagan heteroscedasticity test results."
"Show Breusch-Pagan heteroscedasticity test results. "
"Needs OLS to be run in advance with independent and dependent variables"
),
)
@@ -1605,7 +1631,7 @@ class EconometricsController(BaseController):
"Perform an OLS regression before estimating the Breusch-Pagan statistic.\n"
)
else:
openbb_terminal.econometrics.regression_view.display_bpag(
regression_view.display_bpag(
self.regression["OLS"]["model"], ns_parser.export
)
@@ -1626,6 +1652,7 @@ class EconometricsController(BaseController):
"by the second time series.",
type=str,
dest="ts",
metavar="Available time series",
)
parser.add_argument(
"-l",
@@ -1708,24 +1735,24 @@ class EconometricsController(BaseController):
if ns_parser:
if ns_parser.ts:
# We are going to pass through a variable number of series, so datasets will be a list of series
if len(ns_parser.ts) > 1:
datasets = {}
for stock in ns_parser.ts:
if "." not in stock:
datasets = []
for series in ns_parser.ts:
if "." not in series:
console.print(
"[red]Invalid time series format. Should be dataset.column, "
"e.g. historical.open[/red]\n"
)
else:
dataset, column = stock.split(".")
datasets[stock] = self.datasets[dataset][column]
dataset, column = series.split(".")
datasets.append(self.datasets[dataset][column])
econometrics_view.display_cointegration_test(
datasets,
ns_parser.significant,
ns_parser.plot,
ns_parser.export,
*datasets,
significant=ns_parser.significant,
plot=ns_parser.plot,
export=ns_parser.export,
)
else:

View File

@@ -1,4 +1,5 @@
from typing import Dict
import pandas as pd

View File

@@ -5,14 +5,16 @@ __docformat__ = "numpy"
import logging
import warnings
from typing import Dict, Union, Any, Optional
from itertools import combinations
from typing import Any, Dict, Optional, Union
import pandas as pd
from scipy import stats
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller, kpss, grangercausalitytests
from scipy import stats
from statsmodels.tsa.stattools import adfuller, grangercausalitytests, kpss
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -205,7 +207,7 @@ def get_root(
@log_start_end(log=logger)
def get_granger_causality(dependent_series, independent_series, lags):
def get_granger_causality(dependent_series, independent_series, lags=3):
"""Calculate granger tests
Parameters
@@ -221,7 +223,82 @@ def get_granger_causality(dependent_series, independent_series, lags):
granger = grangercausalitytests(granger_set, [lags], verbose=False)
return granger
for test in granger[lags][0]:
# As ssr_chi2test and lrtest have one less value in the tuple, we fill
# this value with a '-' to allow the conversion to a DataFrame
if len(granger[lags][0][test]) != 4:
pars = granger[lags][0][test]
granger[lags][0][test] = (pars[0], pars[1], "-", pars[2])
granger_df = pd.DataFrame(
granger[lags][0], index=["F-test", "P-value", "Count", "Lags"]
).T
return granger_df
# TODO: Maybe make a new function to return z instead of having this flag.
# TODO: Allow for numpy arrays as well
def get_coint_df(
*datasets: pd.Series, return_z: bool = False
) -> Union[pd.DataFrame, Dict]:
"""Calculate cointegration tests between variable number of input series
Parameters
----------
datasets : pd.Series
Input series to test cointegration for
return_z : bool
Flag to return the z data to plot
Returns
-------
Union[pd.DataFrame,Dict]
Dataframe with results of cointegration tests or a Dict of the z results
"""
result: Dict[str, list] = {}
z_values: Dict[str, pd.Series] = {}
# The *datasets lets us pass in a variable number of arguments
# Here we are getting all possible combinations of unique inputs
pairs = list(combinations(datasets, 2))
for x, y in pairs:
if sum(y.isnull()) > 0:
console.print(
f"The Series {y} has nan-values. Please consider dropping or filling these "
f"values with 'clean'."
)
elif sum(x.isnull()) > 0:
console.print(
f"The Series {x.name} has nan-values. Please consider dropping or filling these "
f"values with 'clean'."
)
elif not y.index.equals(x.index):
console.print(
f"The Series {y.name} and {x.name} do not have the same index."
)
(
c,
gamma,
alpha,
z,
adfstat,
pvalue,
) = get_engle_granger_two_step_cointegration_test(x, y)
result[f"{x.name}/{y.name}"] = [c, gamma, alpha, adfstat, pvalue]
z_values[f"{x.name}/{y.name}"] = z
if result and z_values:
if return_z:
return z_values
df = pd.DataFrame.from_dict(
result,
orient="index",
columns=["Constant", "Gamma", "Alpha", "Dickey-Fuller", "P Value"],
)
return df
return pd.DataFrame()
def get_engle_granger_two_step_cointegration_test(dependent_series, independent_series):

View File

@@ -3,27 +3,20 @@ __docformat__ = "numpy"
import logging
import os
from itertools import combinations
from typing import Dict, Optional, List, Union
from typing import Dict, List, Optional, Union
from matplotlib.units import ConversionError
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.units import ConversionError
from pandas.plotting import register_matplotlib_converters
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
)
from openbb_terminal.helper_funcs import (
print_rich_table,
)
from openbb_terminal.rich_config import console
from openbb_terminal.econometrics import econometrics_model
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.econometrics import econometrics_model
from openbb_terminal.econometrics.econometrics_helpers import get_ending
from openbb_terminal.helper_funcs import export_data, plot_autoscale, print_rich_table
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -137,7 +130,7 @@ def display_norm(
data: pd.Series,
dataset: str = "",
column: str = "",
plot: bool = False,
plot: bool = True,
export: str = "",
external_axes: Optional[List[plt.axes]] = None,
):
@@ -284,21 +277,10 @@ def display_granger(
f"{independent_series.dtype}. Consider using the command 'type' to change this."
)
else:
granger = econometrics_model.get_granger_causality(
granger_df = econometrics_model.get_granger_causality(
dependent_series, independent_series, lags
)
for test in granger[lags][0]:
# As ssr_chi2test and lrtest have one less value in the tuple, we fill
# this value with a '-' to allow the conversion to a DataFrame
if len(granger[lags][0][test]) != 4:
pars = granger[lags][0][test]
granger[lags][0][test] = (pars[0], pars[1], "-", pars[2])
granger_df = pd.DataFrame(
granger[lags][0], index=["F-test", "P-value", "Count", "Lags"]
).T
print_rich_table(
granger_df,
headers=list(granger_df.columns),
@@ -306,7 +288,7 @@ def display_granger(
title=f"Granger Causality Test [Y: {dependent_series.name} | X: {independent_series.name} | Lags: {lags}]",
)
result_ftest = round(granger[lags][0]["params_ftest"][1], 3)
result_ftest = round(granger_df.loc["params_ftest"]["P-value"], 3)
if result_ftest > confidence_level:
console.print(
@@ -330,9 +312,9 @@ def display_granger(
@log_start_end(log=logger)
def display_cointegration_test(
datasets: Union[pd.DataFrame, Dict[str, pd.Series]],
*datasets: pd.Series,
significant: bool = False,
plot: bool = False,
plot: bool = True,
export: str = "",
external_axes: Optional[List[plt.axes]] = None,
):
@@ -355,8 +337,8 @@ def display_cointegration_test(
Parameters
----------
datasets: Union[pd.DataFrame, Dict[str, pd.Series]]
All time series to perform co-integration tests on.
datasets: pd.Series
Variable number of series to test for cointegration
significant: float
Show only companies that have p-values lower than this percentage
plot: bool
@@ -366,81 +348,45 @@ def display_cointegration_test(
external_axes:Optional[List[plt.axes]]
External axes to plot on
"""
if len(datasets) < 2:
console.print("[red]Co-integration requires at least two time series.[/red]")
return
pairs = list(combinations(datasets.keys(), 2))
result: Dict[str, list] = {}
z_values: Dict[str, pd.Series] = {}
df: pd.DataFrame = econometrics_model.get_coint_df(*datasets)
for x, y in pairs:
if sum(datasets[y].isnull()) > 0:
console.print(
f"The Series {y} has nan-values. Please consider dropping or filling these "
f"values with 'clean'."
)
elif sum(datasets[x].isnull()) > 0:
console.print(
f"The Series {x} has nan-values. Please consider dropping or filling these "
f"values with 'clean'."
)
elif not datasets[y].index.equals(datasets[x].index):
console.print(f"The Series {y} and {x} do not have the same index.")
if significant:
console.print(
f"Only showing pairs that are statistically significant ({significant} > p-value)."
)
df = df[significant > df["P Value"]]
console.print()
print_rich_table(
df,
headers=list(df.columns),
show_index=True,
index_name="Pairs",
title="Cointegration Tests",
)
if plot:
if external_axes is None:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
else:
try:
(
c,
gamma,
alpha,
z,
adfstat,
pvalue,
) = econometrics_model.get_engle_granger_two_step_cointegration_test(
datasets[x], datasets[y]
)
result[f"{x}/{y}"] = [c, gamma, alpha, adfstat, pvalue]
z_values[f"{x}/{y}"] = z
except ValueError:
console.print(
"[red]Error: please only send string and integer columns[/red]\n"
)
ax = external_axes[0]
if result and z_values:
df = pd.DataFrame.from_dict(
result,
orient="index",
columns=["Constant", "Gamma", "Alpha", "Dickey-Fuller", "P Value"],
)
z_values = econometrics_model.get_coint_df(*datasets, return_z=True)
if significant:
console.print(
f"Only showing pairs that are statistically significant ({significant} > p-value)."
)
df = df[significant > df["P Value"]]
console.print()
for pair, values in z_values.items():
ax.plot(values, label=pair)
print_rich_table(
df,
headers=list(df.columns),
show_index=True,
index_name="Pairs",
title="Cointegration Tests",
)
ax.legend()
ax.set_title("Error correction terms")
if plot:
if external_axes is None:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
else:
ax = external_axes[0]
theme.style_primary_axis(ax)
for pair, values in z_values.items():
ax.plot(values, label=pair)
ax.legend()
ax.set_title("Error correction terms")
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
if external_axes is None:
theme.visualize_output()
export_data(
export,

View File

@@ -1,70 +1,107 @@
"""Regression Model"""
__docformat__ = "numpy"
import logging
import os
import warnings
import logging
from typing import List, Tuple, Dict, Any
from typing import Any, Dict, List, Tuple
import pandas as pd
import statsmodels
import statsmodels.api as sm
from linearmodels import PooledOLS
from linearmodels.panel import (
RandomEffects,
BetweenOLS,
PanelOLS,
FirstDifferenceOLS,
PanelOLS,
RandomEffects,
compare,
)
from pandas import DataFrame
from statsmodels.api import add_constant
import statsmodels.api as sm
from statsmodels.stats.api import het_breuschpagan
from statsmodels.stats.diagnostic import acorr_breusch_godfrey
from statsmodels.stats.stattools import durbin_watson
from openbb_terminal.decorators import log_start_end
from openbb_terminal.econometrics.econometrics_helpers import get_datasets
from openbb_terminal.helper_funcs import export_data
from openbb_terminal.rich_config import console
from openbb_terminal.econometrics.econometrics_helpers import get_datasets
logger = logging.getLogger(__name__)
def get_regressions_results(
regression_type: str,
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
Y: pd.DataFrame,
X: pd.DataFrame,
regression_type: str = "OLS",
entity_effects: bool = False,
time_effects: bool = False,
) -> Tuple[DataFrame, Any, List[Any], Any]:
) -> Any:
"""Based on the regression type, this function decides what regression to run.
Parameters
----------
regression_type: str
The type of regression you wish to execute.
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
entity_effects: bool
Whether to apply Fixed Effects on entities.
time_effects: bool
Whether to apply Fixed Effects on time.
Parameters
----------
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
regression_type: str
The type of regression you wish to execute.
entity_effects: bool
Whether to apply Fixed Effects on entities.
time_effects: bool
Whether to apply Fixed Effects on time.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the regression model.
Returns
-------
A regression model
Examples
--------
>>> from openbb_terminal.sdk import openbb
>>> df = openbb.econometrics.load("wage_panel")
>>> df = df.set_index(["nr","year"])
>>> X = df[["exper","educ","union"]]
>>> Y = df["lwage"]
>>> pooled_ols_model = openbb.econometrics.panel(Y,X,"POLS")
>>> print(pooled_ols_model.summary)
PooledOLS Estimation Summary
================================================================================
Dep. Variable: lwage R-squared: 0.1634
Estimator: PooledOLS R-squared (Between): 0.1686
No. Observations: 4360 R-squared (Within): 0.1575
Date: Sun, Nov 13 2022 R-squared (Overall): 0.1634
Time: 13:04:02 Log-likelihood -3050.4
Cov. Estimator: Unadjusted
F-statistic: 283.68
Entities: 545 P-value 0.0000
Avg Obs: 8.0000 Distribution: F(3,4356)
Min Obs: 8.0000
Max Obs: 8.0000 F-statistic (robust): 283.68
P-value 0.0000
Time periods: 8 Distribution: F(3,4356)
Avg Obs: 545.00
Min Obs: 545.00
Max Obs: 545.00
Parameter Estimates
==============================================================================
Parameter Std. Err. T-stat P-value Lower CI Upper CI
------------------------------------------------------------------------------
const -0.0308 0.0620 -0.4965 0.6196 -0.1523 0.0908
exper 0.0561 0.0028 20.220 0.0000 0.0507 0.0616
educ 0.1080 0.0045 24.034 0.0000 0.0992 0.1168
union 0.1777 0.0172 10.344 0.0000 0.1441 0.2114
==============================================================================
"""
regressions = {
"OLS": lambda: get_ols(regression_variables, data, False),
"POLS": lambda: get_pols(regression_variables, data),
"RE": lambda: get_re(regression_variables, data),
"BOLS": lambda: get_bols(regression_variables, data),
"FE": lambda: get_fe(regression_variables, data, entity_effects, time_effects),
"FDOLS": lambda: get_fdols(regression_variables, data),
"OLS": lambda: get_ols(Y, X),
"POLS": lambda: get_pols(Y, X),
"RE": lambda: get_re(Y, X),
"BOLS": lambda: get_bols(Y, X),
"FE": lambda: get_fe(Y, X, entity_effects, time_effects),
"FDOLS": lambda: get_fdols(Y, X),
}
if regression_type in regressions:
return regressions[regression_type]()
@@ -134,212 +171,185 @@ def get_regression_data(
@log_start_end(log=logger)
def get_ols(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
show_regression: bool = True,
export: str = "",
) -> Tuple[DataFrame, Any, List[Any], Any]:
Y: pd.DataFrame,
X: pd.DataFrame,
) -> Any:
"""Performs an OLS regression on timeseries data. [Source: Statsmodels]
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
show_regression: bool
Whether to show the regression results table.
export: str
Format to export data
Parameters
----------
Y: pd.DataFrame
Dependent variable series.
X: pd.DataFrame
Dataframe of independent variables series.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the OLS model.
Returns
-------
statsmodels.regression.linear_model.RegressionResultsWrapper
Regression model wrapper from statsmodels.
Examples
-------
>>> import openbb_terminal.sdk as openbb
>>> df = openbb.econometrics.load("wage_panel")
>>> OLS_model = openbb.econometrics.OLS(df["lwage"], df[["educ", "exper", "expersq"]])
>>> print(OLS_model.summary())
OLS Regression Results
=======================================================================================
Dep. Variable: lwage R-squared (uncentered): 0.920
Model: OLS Adj. R-squared (uncentered): 0.919
Method: Least Squares F-statistic: 1.659e+04
Date: Thu, 10 Nov 2022 Prob (F-statistic): 0.00
Time: 15:28:11 Log-Likelihood: -3091.3
No. Observations: 4360 AIC: 6189.
Df Residuals: 4357 BIC: 6208.
Df Model: 3
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
educ 0.0986 0.002 39.879 0.000 0.094 0.103
exper 0.1018 0.009 10.737 0.000 0.083 0.120
expersq -0.0034 0.001 -4.894 0.000 -0.005 -0.002
==============================================================================
Omnibus: 1249.642 Durbin-Watson: 0.954
Prob(Omnibus): 0.000 Jarque-Bera (JB): 9627.436
Skew: -1.152 Prob(JB): 0.00
Kurtosis: 9.905 Cond. No. 86.4
==============================================================================
Notes:
[1] R² is computed without centering (uncentered) since the model does not contain a constant.
[2] Standard Errors assume that the covariance matrix of the errors is correctly specified.
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "OLS"
)
if regression_df.empty:
if X.empty or Y.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
model = sm.OLS(
regression_df[dependent_variable], regression_df[independent_variables]
).fit()
if show_regression:
console.print(model.summary())
console.print("")
model = sm.OLS(Y, X).fit()
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
if export:
results_as_html = model.summary().tables[1].as_html()
df = pd.read_html(results_as_html, header=0, index_col=0)[0]
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"{dependent_variable}_ols_regression",
df,
)
else:
console.print("")
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_pols(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
) -> Tuple[DataFrame, Any, List[Any], Any]:
def get_pols(Y: pd.DataFrame, X: pd.DataFrame) -> Any:
"""PooledOLS is just plain OLS that understands that various panel data structures.
It is useful as a base model. [Source: LinearModels]
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the Pooled OLS model.
PooledOLS model
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "POLS"
)
if regression_df.empty:
if Y.empty or X.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
exogenous = add_constant(regression_df[independent_variables])
model = PooledOLS(regression_df[dependent_variable], exogenous).fit()
console.print(model)
exogenous = add_constant(X)
model = PooledOLS(Y, exogenous).fit()
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_re(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
) -> Tuple[DataFrame, Any, List[Any], Any]:
def get_re(Y: pd.DataFrame, X: pd.DataFrame) -> Any:
"""The random effects model is virtually identical to the pooled OLS model except that is accounts for the
structure of the model and so is more efficient. Random effects uses a quasi-demeaning strategy which
subtracts the time average of the within entity values to account for the common shock. [Source: LinearModels]
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the RandomEffects model.
RandomEffects model
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "RE"
)
if regression_df.empty:
if X.empty or Y.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
exogenous = add_constant(regression_df[independent_variables])
model = RandomEffects(regression_df[dependent_variable], exogenous).fit()
console.print(model)
exogenous = add_constant(X)
model = RandomEffects(Y, exogenous).fit()
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_bols(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
) -> Tuple[DataFrame, Any, List[Any], Any]:
def get_bols(Y: pd.DataFrame, X: pd.DataFrame) -> Any:
"""The between estimator is an alternative, usually less efficient estimator, can can be used to
estimate model parameters. It is particular simple since it first computes the time averages of
y and x and then runs a simple regression using these averages. [Source: LinearModels]
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the Between OLS model.
BetweenOLS model
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "BOLS"
)
if regression_df.empty:
if Y.empty or X.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
exogenous = add_constant(regression_df[independent_variables])
model = BetweenOLS(regression_df[dependent_variable], exogenous).fit()
console.print(model)
exogenous = add_constant(X)
model = BetweenOLS(Y, exogenous).fit()
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_fe(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
Y: pd.DataFrame,
X: pd.DataFrame,
entity_effects: bool = False,
time_effects: bool = False,
) -> Tuple[DataFrame, Any, List[Any], Any]:
) -> Any:
"""When effects are correlated with the regressors the RE and BE estimators are not consistent.
The usual solution is to use Fixed Effects which are called entity_effects when applied to
entities and time_effects when applied to the time dimension. [Source: LinearModels]
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
entity_effects : bool
Whether to include entity effects
time_effects : bool
@@ -347,40 +357,30 @@ def get_fe(
Returns
-------
The dataset used, the dependent variable, the independent variable and
the OLS model.
PanelOLS model with Fixed Effects
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "FE"
)
if regression_df.empty:
if X.empty or Y.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
exogenous = add_constant(regression_df[independent_variables])
exogenous = add_constant(X)
model = PanelOLS(
regression_df[dependent_variable],
Y,
exogenous,
entity_effects=entity_effects,
time_effects=time_effects,
).fit()
console.print(model)
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_fdols(
regression_variables: List[Tuple],
data: Dict[str, pd.DataFrame],
) -> Tuple[DataFrame, Any, List[Any], Any]:
def get_fdols(Y: pd.DataFrame, X: pd.DataFrame) -> Any:
"""First differencing is an alternative to using fixed effects when there might be correlation.
When using first differences, time-invariant variables must be excluded. Additionally,
only one linear time-trending variable can be included since this will look like a constant.
@@ -389,41 +389,31 @@ def get_fdols(
Parameters
----------
regression_variables : list
The regressions variables entered where the first variable is
the dependent variable.
data : dict
A dictionary containing the datasets.
Y: pd.DataFrame
Dataframe containing the dependent variable.
X: pd.DataFrame
Dataframe containing the independent variables.
Returns
-------
The dataset used, the dependent variable, the independent variable and
the OLS model.
First Difference OLS model
"""
regression_df, dependent_variable, independent_variables = get_regression_data(
regression_variables, data, "FDOLS"
)
if regression_df.empty:
if X.empty or Y.empty:
model = None
else:
with warnings.catch_warnings(record=True) as warning_messages:
model = FirstDifferenceOLS(
regression_df[dependent_variable], regression_df[independent_variables]
).fit()
console.print(model)
model = FirstDifferenceOLS(Y, X).fit()
if len(warning_messages) > 0:
console.print("Warnings:")
for warning in warning_messages:
console.print(f"[red]{warning.message}[/red]".replace("\n", ""))
return regression_df, dependent_variable, independent_variables, model
return model
@log_start_end(log=logger)
def get_comparison(regressions, export: str = ""):
def get_comparison(regressions: Dict, export: str = ""):
"""Compare regression results between Panel Data regressions.
Parameters
@@ -471,51 +461,76 @@ def get_comparison(regressions, export: str = ""):
@log_start_end(log=logger)
def get_dwat(residual: pd.DataFrame) -> pd.DataFrame:
"""Calculate test statistics for Durbing Watson autocorrelation
def get_dwat(
model: statsmodels.regression.linear_model.RegressionResultsWrapper,
) -> float:
"""Calculate test statistics for Durbin Watson autocorrelation
Parameters
----------
residual : OLS Model
Model containing residual values.
model : statsmodels.regression.linear_model.RegressionResultsWrapper
Previously fit statsmodels OLS.
Returns
-------
Test statistic of the Durbin Watson test.
float
Test statistic of the Durbin Watson test.
Notes
------
When using chart = True, the dependent variable in the regression must be passed to view the residuals
Example
-------
>>> from openbb_terminal.sdk import openbb
>>> df = openbb.econometrics.load("wage_panel")
>>> Y, X = df["lwage"], df[["exper","educ"]]
>>> model = openbb.econometrics.ols(Y,X)
>>> durbin_watson_value = openbb.econometrics.dwat(model)
>>> durbin_watson_value
0.96
"""
# Durbin Watson test: The test statistic is approximately equal to 2*(1-r) where r is the
# sample autocorrelation of the residuals. Thus, for r == 0, indicating no serial correlation,
# the test statistic equals 2. This statistic will always be between 0 and 4. The closer
# to 0 the statistic, the more evidence for positive serial correlation. The closer to 4,
# the more evidence for negative serial correlation.
result = durbin_watson(residual)
result = durbin_watson(model.resid)
return round(result, 2)
@log_start_end(log=logger)
def get_bgod(model: pd.DataFrame, lags: int = 3) -> tuple:
def get_bgod(
model: statsmodels.regression.linear_model.RegressionResultsWrapper, lags: int = 3
) -> pd.DataFrame:
"""Calculate test statistics for autocorrelation
Parameters
----------
model : OLS Model
Model containing residual values.
OLS model that has been fit.
lags : int
The amount of lags.
Returns
-------
Test results from the Breusch-Godfrey Test
pd.DataFrame
Test results from the Breusch-Godfrey Test
"""
lm_stat, p_value, f_stat, fp_value = acorr_breusch_godfrey(model, nlags=lags)
return lm_stat, p_value, f_stat, fp_value
return pd.DataFrame(
[lm_stat, p_value, f_stat, fp_value],
index=["lm-stat", "p-value", "f-stat", "fp-value"],
)
@log_start_end(log=logger)
def get_bpag(model: pd.DataFrame) -> tuple:
def get_bpag(
model: statsmodels.regression.linear_model.RegressionResultsWrapper,
) -> pd.DataFrame:
"""Calculate test statistics for heteroscedasticity
Parameters
@@ -525,9 +540,12 @@ def get_bpag(model: pd.DataFrame) -> tuple:
Returns
-------
Test results from the Breusch-Pagan Test
pd.DataFrame
Test results from the Breusch-Pagan Test
"""
lm_stat, p_value, f_stat, fp_value = het_breuschpagan(model.resid, model.model.exog)
return lm_stat, p_value, f_stat, fp_value
return pd.DataFrame(
[lm_stat, p_value, f_stat, fp_value],
index=["lm-stat", "p-value", "f-stat", "fp-value"],
)

View File

@@ -1,29 +1,28 @@
"""Regression View"""
__docformat__ = "numpy"
from typing import Optional, List, Tuple, Dict
import os
import logging
import os
from typing import List, Optional
import pandas as pd
from matplotlib import pyplot as plt
import statsmodels
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import plot_autoscale, export_data
from openbb_terminal.rich_config import console
from openbb_terminal.econometrics import regression_model
from openbb_terminal.helper_funcs import (
print_rich_table,
)
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.econometrics import regression_model
from openbb_terminal.helper_funcs import export_data, plot_autoscale, print_rich_table
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def display_panel(
data: Dict[str, pd.DataFrame],
regression_variables: List[Tuple],
Y: pd.DataFrame,
X: pd.DataFrame,
regression_type: str = "OLS",
entity_effects: bool = False,
time_effects: bool = False,
@@ -54,23 +53,20 @@ def display_panel(
The dataset used, the dependent variable, the independent variable and
the regression model.
"""
(
regression_df,
dependent,
independent,
model,
) = regression_model.get_regressions_results(
model = regression_model.get_regressions_results(
Y,
X,
regression_type,
regression_variables,
data,
entity_effects,
time_effects,
)
if regression_type != "OLS":
console.print(model)
if export:
results_as_html = model.summary.tables[1].as_html()
df = pd.read_html(results_as_html, header=0, index_col=0)[0]
dependent = Y.columns[0]
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
@@ -78,14 +74,14 @@ def display_panel(
df,
)
return regression_df, dependent, independent, model
return model
@log_start_end(log=logger)
def display_dwat(
model: statsmodels.regression.linear_model.RegressionResultsWrapper,
dependent_variable: pd.Series,
residual: pd.DataFrame,
plot: bool = False,
plot: bool = True,
export: str = "",
external_axes: Optional[List[plt.axes]] = None,
):
@@ -93,10 +89,10 @@ def display_dwat(
Parameters
----------
model : OLS Model
A fit statsmodels OLS model.
dependent_variable : pd.Series
The dependent variable.
residual : OLS Model
The residual of an OLS model.
The dependent variable for plotting
plot : bool
Whether to plot the residuals
export : str
@@ -104,7 +100,7 @@ def display_dwat(
external_axes: Optional[List[plt.axes]]
External axes to plot on
"""
autocorr = regression_model.get_dwat(residual)
autocorr = regression_model.get_dwat(model)
if 1.5 < autocorr < 2.5:
console.print(
@@ -123,7 +119,7 @@ def display_dwat(
else:
ax = external_axes[0]
ax.scatter(dependent_variable, residual)
ax.scatter(dependent_variable, model.resid)
ax.axhline(y=0, color="r", linestyle="-")
ax.set_ylabel("Residual")
ax.set_xlabel(dependent_variable.name.capitalize())
@@ -140,33 +136,25 @@ def display_dwat(
autocorr,
)
console.print()
@log_start_end(log=logger)
def display_bgod(model: pd.DataFrame, lags: int = 3, export: str = ""):
def display_bgod(
model: statsmodels.regression.linear_model.RegressionResultsWrapper,
lags: int = 3,
export: str = "",
):
"""Show Breusch-Godfrey autocorrelation test
Parameters
----------
model : OLS Model
Model containing residual values.
OLS model that has been fit.
lags : int
The amount of lags included.
export : str
Format to export data
"""
(
lm_stat,
p_value,
f_stat,
fp_value,
) = regression_model.get_bgod(model, lags)
df = pd.DataFrame(
[lm_stat, p_value, f_stat, fp_value],
index=["LM-stat", "p-value", "f-stat", "fp-value"],
)
df = regression_model.get_bgod(model, lags)
print_rich_table(
df,
@@ -174,7 +162,7 @@ def display_bgod(model: pd.DataFrame, lags: int = 3, export: str = ""):
show_index=True,
title=f"Breusch-Godfrey autocorrelation test [Lags: {lags}]",
)
p_value = df.loc["p-value"][0]
if p_value > 0.05:
console.print(
f"{round(p_value, 2)} indicates the autocorrelation. Consider re-estimating with "
@@ -191,27 +179,20 @@ def display_bgod(model: pd.DataFrame, lags: int = 3, export: str = ""):
@log_start_end(log=logger)
def display_bpag(model: pd.DataFrame, export: str = ""):
def display_bpag(
model: statsmodels.regression.linear_model.RegressionResultsWrapper,
export: str = "",
):
"""Show Breusch-Pagan heteroscedasticity test
Parameters
----------
model : OLS Model
Model containing residual values.
OLS model that has been fit.
export : str
Format to export data
"""
(
lm_stat,
p_value,
f_stat,
fp_value,
) = regression_model.get_bpag(model)
df = pd.DataFrame(
[lm_stat, p_value, f_stat, fp_value],
index=["lm-stat", "p-value", "f-stat", "fp-value"],
)
df = regression_model.get_bpag(model)
print_rich_table(
df,
@@ -219,7 +200,7 @@ def display_bpag(model: pd.DataFrame, export: str = ""):
show_index=True,
title="Breusch-Pagan heteroscedasticity test",
)
p_value = df.loc["p-value"][0]
if p_value > 0.05:
console.print(
f"{round(p_value, 2)} indicates heteroscedasticity. Consider taking the log "

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
,F-test,P-value,Count,Lags
ssr_ftest,2.66991,0.04882,193.0,3.0
ssr_chi2test,8.30024,0.0402,-,3.0
lrtest,8.13263,0.04335,-,3.0
params_ftest,2.66991,0.04882,193.0,3.0
1 F-test P-value Count Lags
2 ssr_ftest 2.66991 0.04882 193.0 3.0
3 ssr_chi2test 8.30024 0.0402 - 3.0
4 lrtest 8.13263 0.04335 - 3.0
5 params_ftest 2.66991 0.04882 193.0 3.0

View File

@@ -0,0 +1,5 @@
,F-test,P-value,Count,Lags
ssr_ftest,3.26559,0.04026,196.0,2.0
ssr_chi2test,6.69779,0.03512,-,2.0
lrtest,6.58862,0.03709,-,2.0
params_ftest,3.26559,0.04026,196.0,2.0
1 F-test P-value Count Lags
2 ssr_ftest 3.26559 0.04026 196.0 2.0
3 ssr_chi2test 6.69779 0.03512 - 2.0
4 lrtest 6.58862 0.03709 - 2.0
5 params_ftest 3.26559 0.04026 196.0 2.0

View File

@@ -0,0 +1,5 @@
,F-test,P-value,Count,Lags
ssr_ftest,1.01264,0.31549,199.0,1.0
ssr_chi2test,1.0279,0.31065,-,1.0
lrtest,1.0253,0.31127,-,1.0
params_ftest,1.01264,0.31549,199.0,1.0
1 F-test P-value Count Lags
2 ssr_ftest 1.01264 0.31549 199.0 1.0
3 ssr_chi2test 1.0279 0.31065 - 1.0
4 lrtest 1.0253 0.31127 - 1.0
5 params_ftest 1.01264 0.31549 199.0 1.0

View File

@@ -218,11 +218,9 @@ def test_get_root(recorder, df, fuller_reg, kpss_reg):
def test_get_granger_causality(recorder, time_series_y, time_series_x, lags):
result = econometrics_model.get_granger_causality(
dependent_series=time_series_y, independent_series=time_series_x, lags=lags
)
).applymap(lambda x: round(float(x), 5) if x != "-" else x)
# The first item is taken since the second item contains Statsmodels
# objects (which change their identifier on every iteration)
recorder.capture_list(result[lags][0])
recorder.capture(result)
@pytest.mark.vcr()

View File

@@ -148,34 +148,34 @@ def test_display_granger(time_series_y, time_series_x, lags, confidence_level):
"datasets, significant, plot",
[
(
{
"y": common_model.load(
[
common_model.load(
"interest_inflation",
{},
{"interest_inflation": "interest_inflation"},
)["Dp"],
"x": common_model.load(
common_model.load(
"interest_inflation",
{},
{"interest_inflation": "interest_inflation"},
)["R"],
},
],
True,
False,
),
(
{
"y": common_model.load(
[
common_model.load(
"interest_inflation",
{},
{"interest_inflation": "interest_inflation"},
)["Dp"],
"x": common_model.load(
common_model.load(
"interest_inflation",
{},
{"interest_inflation": "interest_inflation"},
)["R"],
},
],
False,
False,
),
@@ -183,5 +183,5 @@ def test_display_granger(time_series_y, time_series_x, lags, confidence_level):
)
def test_get_engle_granger_two_step_cointegration_test(datasets, significant, plot):
econometrics_view.display_cointegration_test(
datasets=datasets, significant=significant, plot=plot
*datasets, significant=significant, plot=plot
)

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['-n', 'dataset']
Perform an OLS regression before estimating the Breusch-Godfrey statistic.

View File

@@ -1,3 +1,2 @@
Perform an OLS regression before estimating the Breusch-Godfrey statistic.

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['data']
Perform an OLS regression before estimating the Breusch-Pagan statistic.

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['-n', 'dataset']
Perform an OLS regression before estimating the Breusch-Pagan statistic.

View File

@@ -1,3 +1,2 @@
Perform an OLS regression before estimating the Breusch-Pagan statistic.

View File

@@ -1,3 +1,2 @@
[red]'data' is not valid.[/red]

View File

@@ -1,3 +1,2 @@
No Panel regression estimates available. Please use the command 'panel' before using this command.

View File

@@ -1,4 +1,3 @@
cancer population
count 301.000000 301.000000
mean 39.857143 11288.056478

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['data']
Please perform an OLS regression before estimating the Durbin-Watson statistic.

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['-n', 'dataset']
Please perform an OLS regression before estimating the Durbin-Watson statistic.

View File

@@ -1,3 +1,2 @@
Please perform an OLS regression before estimating the Durbin-Watson statistic.

View File

@@ -1,3 +1,2 @@
The following args couldn't be interpreted: ['-n', 'dataset']

View File

@@ -1,4 +1,3 @@
The following args couldn't be interpreted: ['cancer']
cancer population

View File

@@ -1,4 +1,3 @@
[red]No data available for dataset.[/red]

View File

@@ -1,4 +1,3 @@
[red]badcol not a valid column. Showing without sorting.
[/red]
cancer population

View File

@@ -1,4 +1,3 @@
cancer population
300 360.0 88456.0
293 302.0 60161.0

View File

@@ -1,4 +1,3 @@
cancer population
0 1.0 445.0
1 0.0 559.0

View File

@@ -1,4 +1,3 @@
0
cancer float64
population float64

View File

@@ -1,4 +1,3 @@
0
cancer float64
population float64

View File

@@ -1,4 +1,4 @@
Only showing pairs that are statistically significant (True > p-value).
Constant Gamma Alpha Dickey-Fuller P Value
y/x -0.003126 0.154512 -1.2884 -13.123662 1.544757e-24
Constant Gamma Alpha Dickey-Fuller P Value
Dp/R -0.003126 0.154512 -1.2884 -13.123662 1.544757e-24

View File

@@ -1,2 +1,2 @@
Constant Gamma Alpha Dickey-Fuller P Value
y/x -0.003126 0.154512 -1.2884 -13.123662 1.544757e-24
Constant Gamma Alpha Dickey-Fuller P Value
Dp/R -0.003126 0.154512 -1.2884 -13.123662 1.544757e-24