Fama-Macbeth-Regression in Python
- Fama-Macbeth-Regression und ihre Bedeutung
- Schritte zum Implementieren der Fama-Macbeth-Regression in Python
-
Verwenden Sie
LinearModels
, um die Fama-Macbeth-Regression in Python zu implementieren - Alternativer Ansatz zur Implementierung der Fama-Macbeth-Regression in Python
Der heutige Artikel informiert über die Fama-Macbeth-Regression, ihre Bedeutung und ihre Implementierung.
Fama-Macbeth-Regression und ihre Bedeutung
In Asset-Pricing-Theorien verwenden wir Risikofaktoren, um Asset-Renditen zu beschreiben. Diese Risikofaktoren können mikroökonomischer oder makroökonomischer Natur sein.
Zu den mikroökonomischen Risikofaktoren gehören die Unternehmensgröße und die unterschiedlichen Finanzkennzahlen des Unternehmens, während die makroökonomischen Risikofaktoren Verbraucherinflation und Arbeitslosigkeit sind.
Die Fama-Macbeth-Regression ist ein zweistufiges Regressionsmodell, das zum Testen der Asset-Pricing-Modelle verwendet wird. Es ist ein praktischer Ansatz, um zu messen, wie richtig diese Risikofaktoren Portfolio- oder Vermögensrenditen beschreiben.
Dieses Modell ist nützlich, um die Risikoprämie zu bestimmen, die mit der Exposition gegenüber diesen Faktoren verbunden ist.
Nun, der Punkt ist, warum nennen wir Fama-Macbeth ein zweistufiges Regressionsmodell? Lassen Sie uns diese Schritte unten herausfinden.
- In diesem Schritt geht es darum, die Rendite jedes Vermögenswerts anhand eines oder mehrerer Risikofaktoren unter Verwendung des Zeitreihenansatzes zu regressieren. Wir erhalten das Rendite-Exposure für jeden Faktor, der als
betas
,factor loadings
oderfactor exposure
bekannt ist. - In diesem Schritt geht es darum, die Renditen aller Vermögenswerte anhand eines Querschnittsansatzes gegen die im vorherigen Schritt (Schritt 1) erworbenen Vermögenswerte
betas
zu regressieren. Hier erhalten wir für jeden Faktor eine Risikoprämie.
Die prognostizierte Prämie im Laufe der Zeit für die Risikoeinheit gegenüber jedem Risikofaktor wird dann berechnet, indem gemäß Fama und Macbeth die Koeffizienten einmal für jedes Element gemittelt werden.
Schritte zum Implementieren der Fama-Macbeth-Regression in Python
Gemäss dem Update zur Darstellung der Bibliotheksumstände für Fama-Macbeth vom Herbst 2018 ist fama_macbeth
seit einiger Zeit aus dem Python-Modul pandas
gestrichen.
Wie können wir also Fama-Macbeth implementieren, wenn wir mit Python arbeiten? Wir haben die folgenden zwei Ansätze, die wir in diesem Tutorial nacheinander lernen werden.
- Wir können die Funktion
fama_macbeth
inLinearModels
verwenden, wenn wir Python Version 3 verwenden. - Wenn wir
LinearModels
nicht verwenden müssen, oder wir Python Version 2 verwenden, dann wäre es höchstwahrscheinlich der beste Fall, unsere Implementierung für Fama-Macbeth zu schreiben.
Verwenden Sie LinearModels
, um die Fama-Macbeth-Regression in Python zu implementieren
-
Importieren Sie die erforderlichen Module und Bibliotheken.
import pandas as pd import numpy as np from pathlib import Path from linearmodels.asset_pricing import LinearFactorModel from statsmodels.api import OLS, add_constant import matplotlib.pyplot as plt import pandas_datareader.data as web import seaborn as sns import warnings warnings.filterwarnings("ignore") sns.set_style("whitegrid")
Zuerst importieren wir alle Module und Bibliotheken, die wir benötigen, um Fama-Macbeth mit
LinearModels
zu implementieren. Nachfolgend finden Sie eine kurze Beschreibung aller von ihnen:- Wir importieren
pandas
für die Arbeit mit Datenrahmen undnumpy
für Arrays. - Die
pathlib
erstellt einen Pfad zu der angegebenen Datei, indem sie dieses spezifische Skript in dasPath
-Objekt einfügt. - Wir importieren
LinearFactorModel
auslinearmodels.asset_pricing
. Die linearen Faktormodelle setzen die Rendite des Vermögenswertes in Beziehung zu den Werten einer eingeschränkten/begrenzten Anzahl vonFaktoren
, mit einer Beziehung, die durch eine lineare Gleichung beschrieben wird. - Als nächstes importieren wir
OLS
, um das lineare Regressionsmodell auszuwerten, undadd_constant
, um dem Array eine Spalte mit Einsen hinzuzufügen. Mehr überstatsmodels
erfahren Sie hier. - Danach importieren wir
pandas_datareader
, um auf die neuesten Remote-Daten zuzugreifen, die mitpandas
verwendet werden können. Es funktioniert für verschiedenepandas
-Versionen. - Wir importieren
matplotlib
- undseaborn
-Bibliotheken für Datenplot- und Visualisierungszwecke. - Wir importieren
Warnings
, um die Methodefilterwarnings()
zu verwenden, die Warnungen ignoriert. - Zuletzt verwenden wir die Methode
set_style()
aus dem Modulseaborn
, die die Parameter festlegt, die den allgemeinen Stil der Plots steuern.
- Wir importieren
-
Greifen Sie auf Remote-Datensätze zu Risikofaktoren und Forschungsportfolios zu.
ff_research_data_five_factor = "F-F_Research_Data_5_Factors_2x3" ff_factor_dataset = web.DataReader( ff_research_data_five_factor, "famafrench", start="2010", end="2017-12" )[0]
Hier verwenden wir den aktualisierten Risikofaktor- und Research-Portfolio-Datensatz (die fünf Fama-French-Faktoren), der auf ihrer Website verfügbar ist, um zu einer monatlichen Häufigkeit zurückzukehren, die wir für
2010-2017
erhalten, wie oben angegeben.Wir verwenden
DataReader()
, um Daten aus der angegebenen Internetressource in den Datenrahmenpandas
zu extrahieren, der in unserem Code-Fenceff_factor_dataset
ist. DerDataReader()
unterstützt verschiedene Quellen, zum BeispielTiingo
,IEX
,Alpha Vantage
und mehr, die Sie auf dieser Seite lesen können.print("OUTPUT for info(): \n") print(ff_factor_dataset.info())
Als nächstes verwenden wir die Methoden
df.info()
unddf.describe()
, wobeiinfo()
die Informationen des Datenrahmens ausgibt, die die Anzahl der Spalten, Datentypen der Spalten, Spaltenbezeichnungen, Bereichsindex und Speicher enthalten Nutzung und die Anzahl der Zellen in jeder Spalte (Nicht-Null-Werte).Sie können die von
info()
erzeugte Ausgabe unten sehen.AUSGANG:
OUTPUT for info(): <class 'pandas.core.frame.DataFrame'> PeriodIndex: 96 entries, 2010-01 to 2017-12 Freq: M Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Mkt-RF 96 non-null float64 1 SMB 96 non-null float64 2 HML 96 non-null float64 3 RMW 96 non-null float64 4 CMA 96 non-null float64 5 RF 96 non-null float64 dtypes: float64(6) memory usage: 5.2 KB None
Als nächstes verwenden wir die Methode
describe()
wie folgt.print("OUTPUT for describe(): \n") print(ff_factor_dataset.describe())
Die Methode
describe()
zeigt die statistische Zusammenfassung des Datenrahmens; Wir können diese Methode auch für Python-Serien verwenden. Diese statistische Zusammenfassung enthält Mittelwert, Median, Anzahl, Standardabweichung, Perzentilwerte der Spalten und Min-Max.Unten finden Sie die Ausgabe der Methode
describe()
.AUSGANG:
OUTPUT for describe(): Mkt-RF SMB HML RMW CMA RF count 96.000000 96.000000 96.000000 96.000000 96.000000 96.000000 mean 1.158438 0.060000 -0.049271 0.129896 0.047708 0.012604 std 3.580012 2.300292 2.202912 1.581930 1.413033 0.022583 min -7.890000 -4.580000 -4.700000 -3.880000 -3.240000 0.000000 25% -0.917500 -1.670000 -1.665000 -1.075000 -0.952500 0.000000 50% 1.235000 0.200000 -0.275000 0.210000 0.010000 0.000000 75% 3.197500 1.582500 1.205000 1.235000 0.930000 0.010000 max 11.350000 7.040000 8.190000 3.480000 3.690000 0.090000
-
Greifen Sie auf 17 Branchenportfolios zu und subtrahieren Sie die Risikofaktorrate.
ff_industry_portfolio = "17_Industry_Portfolios" ff_industry_portfolio_dataset = web.DataReader( ff_industry_portfolio, "famafrench", start="2010", end="2017-12" )[0] ff_industry_portfolio_dataset = ff_industry_portfolio_dataset.sub( ff_factor_dataset.RF, axis=0 )
Hier greifen wir mit
DataReader()
monatlich auf 17 Branchenportfolios oder Assets zu und subtrahieren denrisikofreien
Kurs (RF
) von dem vonDataReader()
zurückgegebenen Datenrahmen. Warum? Denn das Faktormodell arbeitet mit den Überrenditen.Jetzt werden wir die Methode
info()
verwenden, um Informationen über den verketteten Datenrahmen zu erhalten.print(ff_industry_portfolio_dataset.info())
AUSGANG:
<class 'pandas.core.frame.DataFrame'> PeriodIndex: 96 entries, 2010-01 to 2017-12 Freq: M Data columns (total 17 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Food 96 non-null float64 1 Mines 96 non-null float64 2 Oil 96 non-null float64 3 Clths 96 non-null float64 4 Durbl 96 non-null float64 5 Chems 96 non-null float64 6 Cnsum 96 non-null float64 7 Cnstr 96 non-null float64 8 Steel 96 non-null float64 9 FabPr 96 non-null float64 10 Machn 96 non-null float64 11 Cars 96 non-null float64 12 Trans 96 non-null float64 13 Utils 96 non-null float64 14 Rtail 96 non-null float64 15 Finan 96 non-null float64 16 Other 96 non-null float64 dtypes: float64(17) memory usage: 13.5 KB None
In ähnlicher Weise beschreiben wir diesen Datenrahmen mit der Methode
describe()
.print(ff_industry_portfolio_dataset.describe())
AUSGANG:
Food Mines Oil Clths Durbl Chems \ count 96.000000 96.000000 96.000000 96.000000 96.000000 96.000000 mean 1.046771 0.202917 0.597187 1.395833 1.151458 1.305000 std 2.800555 7.904401 5.480938 5.024408 5.163951 5.594161 min -5.170000 -24.380000 -11.680000 -10.000000 -13.160000 -17.390000 25% -0.785000 -5.840000 -3.117500 -1.865000 -2.100000 -1.445000 50% 0.920000 -0.435000 0.985000 1.160000 1.225000 1.435000 75% 3.187500 5.727500 4.152500 3.857500 4.160000 4.442500 max 6.670000 21.940000 15.940000 17.190000 16.610000 18.370000 Cnsum Cnstr Steel FabPr Machn Cars \ count 96.000000 96.000000 96.000000 96.000000 96.000000 96.000000 mean 1.186979 1.735521 0.559167 1.350521 1.217708 1.279479 std 3.142989 5.243314 7.389679 4.694408 4.798098 5.719351 min -7.150000 -14.160000 -20.490000 -11.960000 -9.070000 -11.650000 25% -0.855000 -2.410000 -4.395000 -1.447500 -2.062500 -1.245000 50% 1.465000 2.175000 0.660000 1.485000 1.525000 0.635000 75% 3.302500 5.557500 4.212500 3.837500 4.580000 4.802500 max 8.260000 15.510000 21.350000 17.660000 14.750000 20.860000 Trans Utils Rtail Finan Other count 96.000000 96.000000 96.000000 96.000000 96.000000 mean 1.463750 0.896458 1.233958 1.248646 1.290938 std 4.143005 3.233107 3.512518 4.839150 3.697608 min -8.560000 -6.990000 -9.180000 -11.140000 -7.890000 25% -0.810000 -0.737500 -0.952500 -1.462500 -1.090000 50% 1.480000 1.240000 0.865000 1.910000 1.660000 75% 4.242500 2.965000 3.370000 4.100000 3.485000 max 12.980000 7.840000 12.440000 13.410000 10.770000
-
Berechnen Sie die Überschussrenditen.
Bevor wir uns der Berechnung der Überrenditen zuwenden, müssen wir noch einige Schritte ausführen.
data_store = Path("./data/assets.h5") wiki_prices_df = pd.read_csv( "./dataset/wiki_prices.csv", parse_dates=["date"], index_col=["date", "ticker"], infer_datetime_format=True, ).sort_index() us_equities_data_df = pd.read_csv("./dataset/us_equities_data.csv") with pd.HDFStore(data_store) as hdf_store: hdf_store.put("quandl/wiki/prices", wiki_prices_df) with pd.HDFStore(data_store) as hdf_store: hdf_store.put("us_equities/stocks", us_equities_data_df.set_index("ticker"))
Zuerst erstellen wir eine
assets.h5
-Datei in einemdata
-Ordner, der sich im aktuellen Verzeichnis befindet. Als nächstes verwenden wir die Methoderead_csv()
, um die Dateienwiki_prices.csv
undus_equities_data.csv
im Ordnerdataset
aus demselben Verzeichnis zu lesen.Danach verwenden wir
HDFStore()
wie oben angegeben, um Daten imHDF5
-Format zu speichern.with pd.HDFStore("./data/assets.h5") as hdf_store: prices = hdf_store["/quandl/wiki/prices"].adj_close.unstack().loc["2010":"2017"] equities = hdf_store["/us_equities/stocks"].drop_duplicates() sectors = equities.filter(prices.columns, axis=0).sector.to_dict() prices = prices.filter(sectors.keys()).dropna(how="all", axis=1) returns_df = prices.resample("M").last().pct_change().mul(100).to_period("M") returns_df = returns.dropna(how="all").dropna(axis=1) print(returns_df.info())
Im obigen Code-Fence lesen wir die
/quandl/wiki/prices
&/us_equities/stocks
, die wir gerade in der Dateiassets.h5
gespeichert haben, und speichern sie in den Variablenprices
undequities
.Dann wenden wir einige Filter auf
Preise
undAktien
an, führen eine erneute Stichprobe durch und entfernen fehlende Werte. Schließlich drucken wir die Informationen eines Datenrahmensreturns_df
mit der Methodeinfo()
; Sie können die Ausgabe unten sehen.AUSGANG:
<class 'pandas.core.frame.DataFrame'> PeriodIndex: 95 entries, 2010-02 to 2017-12 Freq: M Columns: 1986 entries, A to ZUMZ dtypes: float64(1986) memory usage: 1.4 MB None
Führen Sie nun den folgenden Code aus, um die Daten auszurichten.
ff_factor_dataset = ff_factor_dataset.loc[returns_df.index] ff_industry_portfolio_dataset = ff_industry_portfolio_dataset.loc[returns_df.index] print(ff_factor_dataset.describe())
AUSGANG:
Mkt-RF SMB HML RMW CMA RF count 95.000000 95.000000 95.000000 95.000000 95.000000 95.000000 mean 1.206000 0.057053 -0.054316 0.144632 0.043368 0.012737 std 3.568382 2.312313 2.214041 1.583685 1.419886 0.022665 min -7.890000 -4.580000 -4.700000 -3.880000 -3.240000 0.000000 25% -0.565000 -1.680000 -1.670000 -0.880000 -0.965000 0.000000 50% 1.290000 0.160000 -0.310000 0.270000 0.010000 0.000000 75% 3.265000 1.605000 1.220000 1.240000 0.940000 0.010000 max 11.350000 7.040000 8.190000 3.480000 3.690000 0.090000
Jetzt sind wir bereit, die Überrenditen zu berechnen.
excess_returns_df = returns_df.sub(ff_factor_dataset.RF, axis=0) excess_returns_df = excess_returns_df.clip( lower=np.percentile(excess_returns_df, 1), upper=np.percentile(excess_returns_df, 99), ) excess_returns_df.info()
Im obigen Codeblock subtrahieren wir den Risikofaktor vom
ff_factor_dataset
und speichern den zurückgegebenen Datenrahmen inexcess_returns_df
.Als nächstes verwenden wir die Methode
.clip()
, die die Werte an den angegebenen Eingabeschwellenwerten trimmt. Verwenden Sie zuletztinfo()
, um die Informationen des Datenrahmensexcess_returns_df
auszudrucken.AUSGANG:
<class 'pandas.core.frame.DataFrame'> PeriodIndex: 95 entries, 2010-02 to 2017-12 Freq: M Columns: 1986 entries, A to ZUMZ dtypes: float64(1986) memory usage: 1.4 MB
Bevor wir zur ersten Stufe der Fama-Macbeth-Regression übergehen, verwenden wir die Methode
.drop()
, die das angegebene Label aus Spalten oder Zeilen entfernt. Beachten Sie, dassaxis=1
einen Drop von einer Spalte bedeutet undaxis=0
einen Drop von Reihen bedeutet.ff_factor_dataset = ff_factor_dataset.drop("RF", axis=1) print(ff_factor_dataset.info())
AUSGANG:
<class 'pandas.core.frame.DataFrame'> PeriodIndex: 95 entries, 2010-02 to 2017-12 Freq: M Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Mkt-RF 95 non-null float64 1 SMB 95 non-null float64 2 HML 95 non-null float64 3 RMW 95 non-null float64 4 CMA 95 non-null float64 dtypes: float64(5) memory usage: 4.5 KB None
-
Implementieren Sie den Schritt 1 der Fama-Macbeth-Regression: Faktorbelastungen.
betas = [] for industry in ff_industry_portfolio_dataset: step_one = OLS( endog=ff_industry_portfolio_dataset.loc[ff_factor_dataset.index, industry], exog=add_constant(ff_factor_dataset), ).fit() betas.append(step_one.params.drop("const")) betas = pd.DataFrame( betas, columns=ff_factor_dataset.columns, index=ff_industry_portfolio_dataset.columns, ) print(betas.info())
Das obige Code-Snippet implementiert den ersten Schritt der Fama-Macbeth-Regression und greift auf die 17-Faktor-Ladeschätzungen zu. Hier verwenden wir
OLS()
, um das lineare Regressionsmodell auszuwerten, undadd_constant()
, um dem Array eine Spalte mit Einsen hinzuzufügen.AUSGANG:
<class 'pandas.core.frame.DataFrame'> Index: 17 entries, Food to Other Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Mkt-RF 17 non-null float64 1 SMB 17 non-null float64 2 HML 17 non-null float64 3 RMW 17 non-null float64 4 CMA 17 non-null float64 dtypes: float64(5) memory usage: 1.3+ KB None
-
Implementieren Sie den Schritt 2 der Fama-Macbeth-Regression: Risikoprämien.
lambdas = [] for period in ff_industry_portfolio_dataset.index: step_two = OLS( endog=ff_industry_portfolio_dataset.loc[period, betas.index], exog=betas ).fit() lambdas.append(step_two.params) lambdas = pd.DataFrame( lambdas, index=ff_industry_portfolio_dataset.index, columns=betas.columns.tolist() ) print(lambdas.info())
Im zweiten Schritt führen wir sechsundneunzig Regressionen von
Perioden
-Renditen für den Querschnitt des Portfolios zu Faktorladungen durch.AUSGANG:
<class 'pandas.core.frame.DataFrame'> PeriodIndex: 95 entries, 2010-02 to 2017-12 Freq: M Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Mkt-RF 95 non-null float64 1 SMB 95 non-null float64 2 HML 95 non-null float64 3 RMW 95 non-null float64 4 CMA 95 non-null float64 dtypes: float64(5) memory usage: 6.5 KB None
Wir können die Ergebnisse wie folgt visualisieren:
window = 24 # here 24 is the number of months axis1 = plt.subplot2grid((1, 3), (0, 0)) axis2 = plt.subplot2grid((1, 3), (0, 1), colspan=2) lambdas.mean().sort_values().plot.barh(ax=axis1) lambdas.rolling(window).mean().dropna().plot( lw=1, figsize=(14, 5), sharey=True, ax=axis2 ) sns.despine() plt.tight_layout()
AUSGANG:
-
Implementieren Sie die Fama-Macbeth-Regression mit dem Modul
LinearModels
.model = LinearFactorModel( portfolios=ff_industry_portfolio_dataset, factors=ff_factor_dataset ) result = model.fit() print(result)
Hier verwenden wir die
LinearModels
, um das zweistufige Fama-Macbeth-Verfahren zu implementieren, das die folgende Ausgabe erzeugt. Wir könnenprint(result.full_summary)
anstelle vonprint(result)
verwenden, um die vollständige Zusammenfassung zu erhalten.AUSGANG:
LinearFactorModel Estimation Summary ================================================================================ No. Test Portfolios: 17 R-squared: 0.6879 No. Factors: 5 J-statistic: 15.619 No. Observations: 95 P-value 0.2093 Date: Mon, Oct 24 2022 Distribution: chi2(12) Time: 20:53:52 Cov. Estimator: robust Risk Premia Estimates ============================================================================== Parameter Std. Err. T-stat P-value Lower CI Upper CI ------------------------------------------------------------------------------ Mkt-RF 1.2355 0.4098 3.0152 0.0026 0.4324 2.0386 SMB 0.0214 0.8687 0.0246 0.9804 -1.6813 1.7240 HML -1.1140 0.6213 -1.7931 0.0730 -2.3317 0.1037 RMW -0.2768 0.8133 -0.3403 0.7336 -1.8708 1.3172 CMA -0.5078 0.5666 -0.8962 0.3701 -1.6183 0.6027 ============================================================================== Covariance estimator: HeteroskedasticCovariance See full_summary for complete results
Alternativer Ansatz zur Implementierung der Fama-Macbeth-Regression in Python
Wir können diesen Ansatz verwenden, wenn wir nicht LinearModels
oder Python Version 2 verwenden möchten.
-
Importieren Sie die Module und Bibliotheken.
import pandas as pd import numpy as np import statsmodels.formula.api as sm
Wir importieren
pandas
, um mit Datenrahmen zu arbeiten,numpy
, um mit Arrays zu spielen, undstatsmodels.formula.api
, eine praktische Schnittstelle zum Spezifizieren von Modellen über Formelzeichenfolgen und Datenrahmen. -
Datensatz lesen und abfragen.
Angenommen, wir haben Vermögenswerte/Portfolios der Fama-Französischen Industrie im Panel, wie unten angegeben (wir haben auch einige Variablen berechnet, zum Beispiel früheres
beta
undRenditen
, um sie als unserex
-Variablen zu verwenden).data_df = pd.read_csv("industry_data.csv", parse_dates=["caldt"]) data_df.query("caldt == '1995-07-01'")
AUSGANG:
industry caldt ret beta r12to2 r36to13 18432 Aero 1995-07-01 6.26 0.9696 0.2755 0.3466 18433 Agric 1995-07-01 3.37 1.0412 0.1260 0.0581 18434 Autos 1995-07-01 2.42 1.0274 0.0293 0.2902 18435 Banks 1995-07-01 4.82 1.4985 0.1659 0.2951
-
Verwenden Sie
groupby()
, um das Querschnittsregressionsmodell Monat für Monat zu berechnen.def ols_coefficient(x, formula): return sm.ols(formula, data=x).fit().params gamma_df = data_df.groupby("caldt").apply( ols_coefficient, "ret ~ 1 + beta + r12to2 + r36to13" ) gamma_df.head()
Hier verwenden wir
groupby
, weil bei Fama-Macbeth Monat für Monat das exakte Querschnittsregressionsmodell berechnet wird. Wir können eine Funktion erstellen, die einen Datenrahmen (der vongroupby
zurückgegeben wird) und einepasty
-Formel akzeptiert; es passt dann das Modell an und gibt Parameterschätzungen zurück.AUSGANG:
Intercept beta r12to2 r36to13 caldt 1963-07-01 -1.497012 -0.765721 4.379128 -1.918083 1963-08-01 11.144169 -6.506291 5.961584 -2.598048 1963-09-01 -2.330966 -0.741550 10.508617 -4.377293 1963-10-01 0.441941 1.127567 5.478114 -2.057173 1963-11-01 3.380485 -4.792643 3.660940 -1.210426
-
Berechnen Sie den Mittelwert und den Standardfehler des Mittelwerts.
def fm_summary(p): s = p.describe().T s["std_error"] = s["std"] / np.sqrt(s["count"]) s["tstat"] = s["mean"] / s["std_error"] return s[["mean", "std_error", "tstat"]] fm_summary(gamma_df)
Als nächstes berechnen wir den Mittelwert, den t-Test (Sie können beliebige Statistiken verwenden) und den Standardfehler des Mittelwerts, der etwas wie oben ist.
AUSGANG:
mean std_error tstat Intercept 0.754904 0.177291 4.258000 beta -0.012176 0.202629 -0.060092 r12to2 1.794548 0.356069 5.039896 r36to13 0.237873 0.186680 1.274230
-
Verbessern Sie die Geschwindigkeit und verwenden Sie die Funktion
fama_macbeth
.def ols_np(dataset, y_var, x_var): gamma_df, _, _, _ = np.linalg.lstsq(dataset[x_var], dataset[y_var], rcond=None) return pd.Series(gamma_df)
Dieser Schritt ist wichtig, wenn es um Effizienz geht. Wenn ja, können wir von
statsmodels
aufnumpy.linalg.lstsq
wechseln.Um
ols
-Schätzungen durchzuführen, können wir eine ähnliche Funktion wie oben schreiben. Beachten Sie, dass wir nichts tun, um die Ränge dieser Matrizen zu überprüfen.Wenn Sie die ältere
pandas
-Version verwenden, sollte Folgendes funktionieren. Lassen Sie uns ein Beispiel mitfama_macbeth
inpandas
haben.print(data_df) fm = pd.fama_macbeth(y=data_df["y"], x=data_df[["x"]]) print(fm)
Beachten Sie dabei die folgende Struktur.
fama_macbeth
möchte, dassx-var
undy-var
einen Multi-Index mitdate
als erste Variable undstock/firm/entity
id als zweite Variable im Index haben.AUSGANG:
y x date id 2012-01-01 1 0.1 0.4 2 0.3 0.6 3 0.4 0.2 4 0.0 1.2 2012-02-01 1 0.2 0.7 2 0.4 0.5 3 0.2 0.1 4 0.1 0.0 2012-03-01 1 0.4 0.8 2 0.6 0.1 3 0.7 0.6 4 0.4 -0.1 ----------------------Summary of the Fama-Macbeth Analysis------------------------- Formula: Y ~ x + intercept # betas : 3 ----------------------Summary of the Estimated Coefficients------------------------ Variable Beta Std Err t-stat CI 2.5% CI 97.5% (x) -0.0227 0.1276 -0.18 -0.2728 0.2273 (intercept) 0.3531 0.0842 4.19 0.1881 0.5181 --------------------------------End of the Summary---------------------------------
Beachten Sie, dass wir
fm.summary
aufrufen, indem wir einfachfm
drucken, wie wir es im obigen Codezaun getan haben. Zusätzlich fügtfama_macbeth
automatisch dasintercept
hinzu undx-var
muss ein Datenframe sein.Wir können wie folgt vorgehen, wenn wir kein
intercept
haben wollen.fm = pd.fama_macbeth(y=data_df["y"], x=data_df[["x"]], intercept=False)