Hallo zusammen,
ich bin leider komplett am verzweifeln. Ich muss eine Fama French 5 Faktor Regression für den S&P500 durchführen.
Die Datengrundlage fängt im Jahr 2000 an und geht bis Ende 2024 mit monatlichen Daten.
Aber meine Ergebnisse wollen einfach nicht stimmen
Ich habe dies in R gemacht, da ich das Skript für weitere Analysen nutzen möchte. Leider ist das R-Forum aktuell nicht erreichbar. Hoffentlich findet sich auch hier ein Profi.
Der Code ist kommentiert, daher sollte man ihn einfach nachverfolgen können.
Der Code ließt die Dateien ein. Er rechnet die Renditen korrekt aus und verbindet das richtige Datum mit den richtigen Werten und Fama French 5 Faktoren, welche natürlich auch monatlich sind und im richtigen Format.
# Daten einlesen
etf_data <- SP500_und_MSCI_
# Basisnamen der ETFs extrahieren
etf_base_names <- unique(gsub(" - .*", "", names(etf_data)))
# Liste für DataFrames pro ETF
etf_dataframes <- list()
# Für jeden Basisnamen einen DataFrame erstellen
for (etf_base in etf_base_names) {
# Relevante Spalten für den aktuellen ETF filtern
columns_for_etf <- grep(etf_base, names(etf_data), value = TRUE)
# Subset der Daten für den ETF
etf_subset <- etf_data %>%
select(Date, all_of(columns_for_etf)) %>%
rename_with(~ gsub(".* - ", "", .))
# Berechnung der monatlichen Rendite, falls "TOT RETURN IND" existiert
if ("TOT RETURN IND" %in% names(etf_subset)) {
etf_subset <- etf_subset %>%
arrange(Date) %>%
mutate(Monthly_Return = (`TOT RETURN IND` / lag(`TOT RETURN IND`)-1)) %>%
drop_na()
}
# DataFrame speichern
etf_dataframes[[etf_base]] <- etf_subset
}
# Ergebnisse überprüfen
names(etf_dataframes)
##Fama French Faktoren
ff_data<- FF_5_Faktoren
# Fama-French-Faktoren den ETF-Daten hinzufügen
etf_dataframes <- lapply(etf_dataframes, function(df) {
df <- df %>%
left_join(ff_data, by = "Date") # Füge Fama-French-Daten basierend auf Datum hinzu
return(df)
})
# Ergebnisse überprüfen
names(etf_dataframes) # Namen der ETFs
head(etf_dataframes[[1]]) # Beispiel: Erster DataFrame mit hinzugefügten Faktoren
## Return Excess berechnen
etf_dataframes <- lapply(etf_dataframes, function(df) {
if ("Monthly_Return" %in% names(df) && "RF" %in% names(df)) {
df <- df %>%
mutate(Return_Excess = Monthly_Return - RF) # Berechnung der Überschussrendite
} else {
warning("Eine oder mehrere notwendige Spalten fehlen in diesem DataFrame.")
}
return(df)
})
# Namen des zu löschenden ETFs
etf_to_remove <- "Date" # Ersetze durch den Namen des ETFs
# Entferne den ETF aus der Liste
if (etf_to_remove %in% names(etf_dataframes)) {
etf_dataframes <- etf_dataframes[!names(etf_dataframes) %in% etf_to_remove]
print(paste("ETF", etf_to_remove, "wurde entfernt."))
} else {
print(paste("ETF", etf_to_remove, "ist nicht in der Liste enthalten."))
}
# Überprüfe die verbleibenden Namen in der Liste
names(etf_dataframes)
# Ergebnisse der Regressionen speichern
regression_results <- list()
# Für jeden ETF die Regression durchführen
for (etf_name in names(etf_dataframes)) {
df <- etf_dataframes[[etf_name]]
# Überprüfen, ob alle benötigten Spalten vorhanden sind
required_cols <- c("Return_Excess", "Mkt-RF", "SMB", "HML")
if (all(required_cols %in% names(df))) {
# Regression durchführen
model <- lm(Return_Excess ~ `Mkt-RF` + SMB + HML + RMW + CMA, data = df)
regression_results[[etf_name]] <- summary(model)
} else {
warning(paste("Spalten fehlen für ETF:", etf_name))
}
}
Aber leider sieht das Ergebnis wie folgt aus:
Call:
lm(formula = Return_Excess ~ `Mkt-RF` + SMB + HML + RMW + CMA,
data = df)
Residuals:
Min 1Q Median 3Q Max
-0.197098 -0.023568 0.004807 0.029034 0.152289
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.006344 0.002932 2.164 0.0313 *
`Mkt-RF` -0.006966 0.068712 -0.101 0.9193
SMB -0.012535 0.105820 -0.118 0.9058
HML 0.147553 0.112385 1.313 0.1902
RMW -0.167210 0.127119 -1.315 0.1894
CMA 0.016300 0.168997 0.096 0.9232
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.04795 on 292 degrees of freedom
(2 observations deleted due to missingness)
Multiple R-squared: 0.01385, Adjusted R-squared: -0.003037
F-statistic: 0.8201 on 5 and 292 DF, p-value: 0.5361
Weder der R2 noch p-Werte sind in der Nähe von sinnvollen Ergebnissen.
Sobald ich aber einen lag beim Return_Excess oder den Faktoren einbaue, erscheinen korrekte Werte.
Daher würde ja die Vermutung nahe liegen, dass die Werte falsch zugeordnet wurden. Dies habe ich in einer recht großen Stichprobe überprüft.
Die Rendite von zB Aug04 stimmen mit den Faktoren von Aug04 überein.
Habt ihr vielleicht eine Idee woran es liegen könnte?
Besten Dank!
Kevin