Fama-Macbeth-Regression in Python

Mehvish Ashiq 15 Februar 2024
  1. Fama-Macbeth-Regression und ihre Bedeutung
  2. Schritte zum Implementieren der Fama-Macbeth-Regression in Python
  3. Verwenden Sie LinearModels, um die Fama-Macbeth-Regression in Python zu implementieren
  4. Alternativer Ansatz zur Implementierung der Fama-Macbeth-Regression in Python
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.

  1. 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 oder factor exposure bekannt ist.
  2. 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.

  1. Wir können die Funktion fama_macbeth in LinearModels verwenden, wenn wir Python Version 3 verwenden.
  2. 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 und numpy für Arrays.
    • Die pathlib erstellt einen Pfad zu der angegebenen Datei, indem sie dieses spezifische Skript in das Path-Objekt einfügt.
    • Wir importieren LinearFactorModel aus linearmodels.asset_pricing. Die linearen Faktormodelle setzen die Rendite des Vermögenswertes in Beziehung zu den Werten einer eingeschränkten/begrenzten Anzahl von Faktoren, mit einer Beziehung, die durch eine lineare Gleichung beschrieben wird.
    • Als nächstes importieren wir OLS, um das lineare Regressionsmodell auszuwerten, und add_constant, um dem Array eine Spalte mit Einsen hinzuzufügen. Mehr über statsmodels erfahren Sie hier.
    • Danach importieren wir pandas_datareader, um auf die neuesten Remote-Daten zuzugreifen, die mit pandas verwendet werden können. Es funktioniert für verschiedene pandas-Versionen.
    • Wir importieren matplotlib- und seaborn-Bibliotheken für Datenplot- und Visualisierungszwecke.
    • Wir importieren Warnings, um die Methode filterwarnings() zu verwenden, die Warnungen ignoriert.
    • Zuletzt verwenden wir die Methode set_style() aus dem Modul seaborn, die die Parameter festlegt, die den allgemeinen Stil der Plots steuern.
  • 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 Datenrahmen pandas zu extrahieren, der in unserem Code-Fence ff_factor_dataset ist. Der DataReader() unterstützt verschiedene Quellen, zum Beispiel Tiingo, 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() und df.describe(), wobei info() 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 den risikofreien Kurs (RF) von dem von DataReader() 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 einem data-Ordner, der sich im aktuellen Verzeichnis befindet. Als nächstes verwenden wir die Methode read_csv(), um die Dateien wiki_prices.csv und us_equities_data.csv im Ordner dataset aus demselben Verzeichnis zu lesen.

    Danach verwenden wir HDFStore() wie oben angegeben, um Daten im HDF5-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 Datei assets.h5 gespeichert haben, und speichern sie in den Variablen prices und equities.

    Dann wenden wir einige Filter auf Preise und Aktien an, führen eine erneute Stichprobe durch und entfernen fehlende Werte. Schließlich drucken wir die Informationen eines Datenrahmens returns_df mit der Methode info(); 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 in excess_returns_df.

    Als nächstes verwenden wir die Methode .clip(), die die Werte an den angegebenen Eingabeschwellenwerten trimmt. Verwenden Sie zuletzt info(), um die Informationen des Datenrahmens excess_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, dass axis=1 einen Drop von einer Spalte bedeutet und axis=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, und add_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:

    Fama-Macbeth-Regression in Python - Ergebnisse

  • 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önnen print(result.full_summary) anstelle von print(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, und statsmodels.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 und Renditen, um sie als unsere x-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 von groupby zurückgegeben wird) und eine pasty-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 auf numpy.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 mit fama_macbeth in pandas 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, dass x-var und y-var einen Multi-Index mit date als erste Variable und stock/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 einfach fm drucken, wie wir es im obigen Codezaun getan haben. Zusätzlich fügt fama_macbeth automatisch das intercept hinzu und x-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)
    
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

Verwandter Artikel - Python Regression