S&P 500 Regression

Alle Verfahren der Regressionanalyse.

S&P 500 Regression

Beitragvon kevnix » Mi 22. Jan 2025, 23:09

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 :oops:

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
kevnix
Grünschnabel
Grünschnabel
 
Beiträge: 2
Registriert: Mi 22. Jan 2025, 22:58
Danke gegeben: 1
Danke bekommen: 0 mal in 0 Post

Re: S&P 500 Regression

Beitragvon strukturmarionette » Do 23. Jan 2025, 01:30

Leider ist das R-Forum aktuell nicht erreichbar.
http://forum.r-statistik.de/
strukturmarionette
Schlaflos in Seattle
Schlaflos in Seattle
 
Beiträge: 4354
Registriert: Fr 17. Jun 2011, 22:15
Danke gegeben: 32
Danke bekommen: 587 mal in 584 Posts

folgende User möchten sich bei strukturmarionette bedanken:
kevnix

Re: S&P 500 Regression

Beitragvon bele » Do 23. Jan 2025, 14:46

Hallo kevnix,

ob nun hier oder in dem von strukturmarionette verlinkten Forum: Derzeit ist Dein Code schwer zu lesen, weil wir nicht wissen, was das für Datensätze sind, die da eingelesen werden, weil die Fragestellung nur für Menschen mit spezifsch finanzmathematischem Hintergrund verständlich ist und weil der Code dann eben doch sehr lang ist. Außerdem ist Dein Codingstyle ein merkwürdiger Mischmasch aus "altem R" und "dplyr"-Style. Da werden mal for-Schleifen, mal apply-Schleifen verwendet und dann taucht mitten im apply ein mutate und ein join auf, die in einen ganz anderen "Dialekt" der Sprache gehören. Das kann man machen, ist aber so einfach dann auch wieder nicht zu lesen, wenn man den einen oder den anderne Dialekt gewohnt ist.

> Der Code ließt die Dateien ein.

Ja, aber was sind das für Daten? "etf_base_names <- unique(gsub(" - .*", "", names(etf_data)))" Ich dachte, Fama und French haben mit Aktien gerechnet. Du rechnest anscheinend nicht mit Aktien sondern mit ETFs? Ich habe kein spezifisches Wirtschaftswissen und sage nur, dass es sich für uns nicht-Wiwis schwer nachvollziehen lässt, was hier passiert. Trotz Kommentaren.

> 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

Vielleicht solltest Du mal markieren, bis wohin der Code gesichert die richtigen Ergebnisse bringt, damit interessierte sich auf den Teil danach konzentrieren können.

> 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.

Das klingt nach einer überraschend genauen Problembeschreibung. Sollte sich mit diesem Wissen nicht etwas genauer eingrenzen lassen, wo im Code der Fehler zu erwarten ist?

> Die Rendite von zB Aug04 stimmen mit den Faktoren von Aug04 überein.

Zwischen dem 4. August und dem 4. August gibt es aber kein time lag, oder??

So oder so, ich wünsche Dir viel Erfolg!
Bernhard
----
`Oh, you can't help that,' said the Cat: `we're all mad here. I'm mad. You're mad.'
`How do you know I'm mad?' said Alice.
`You must be,' said the Cat, `or you wouldn't have come here.'
(Lewis Carol, Alice in Wonderland)
bele
Schlaflos in Seattle
Schlaflos in Seattle
 
Beiträge: 5924
Registriert: Do 2. Jun 2011, 23:16
Danke gegeben: 16
Danke bekommen: 1402 mal in 1388 Posts

Re: S&P 500 Regression

Beitragvon kevnix » Do 23. Jan 2025, 15:43

bele hat geschrieben:Hallo kevnix,

ob nun hier oder in dem von strukturmarionette verlinkten Forum: Derzeit ist Dein Code schwer zu lesen, weil wir nicht wissen, was das für Datensätze sind, die da eingelesen werden, weil die Fragestellung nur für Menschen mit spezifsch finanzmathematischem Hintergrund verständlich ist und weil der Code dann eben doch sehr lang ist. Außerdem ist Dein Codingstyle ein merkwürdiger Mischmasch aus "altem R" und "dplyr"-Style. Da werden mal for-Schleifen, mal apply-Schleifen verwendet und dann taucht mitten im apply ein mutate und ein join auf, die in einen ganz anderen "Dialekt" der Sprache gehören. Das kann man machen, ist aber so einfach dann auch wieder nicht zu lesen, wenn man den einen oder den anderne Dialekt gewohnt ist.

>> Aufgrund von verschiedenen Kursen und ein wenig Internettipps wurde dieser mehr oder weniger zusammengebastelt. Insgesamt sind meine R-Kenntnisse nicht so gut.

> Der Code ließt die Dateien ein.

Ja, aber was sind das für Daten? "etf_base_names <- unique(gsub(" - .*", "", names(etf_data)))" Ich dachte, Fama und French haben mit Aktien gerechnet. Du rechnest anscheinend nicht mit Aktien sondern mit ETFs? Ich habe kein spezifisches Wirtschaftswissen und sage nur, dass es sich für uns nicht-Wiwis schwer nachvollziehen lässt, was hier passiert. Trotz Kommentaren.

>> Das Ziel ist eine größere Menge an verschiedenen ETFs einzulesen. Diese sind mit der Systematik ETFName - Total Return gespeichert. Damit soll nur der ETFName als Name für den Datenframe angenommen werden

> 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

Vielleicht solltest Du mal markieren, bis wohin der Code gesichert die richtigen Ergebnisse bringt, damit interessierte sich auf den Teil danach konzentrieren können.

> 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.

Das klingt nach einer überraschend genauen Problembeschreibung. Sollte sich mit diesem Wissen nicht etwas genauer eingrenzen lassen, wo im Code der Fehler zu erwarten ist?

> Die Rendite von zB Aug04 stimmen mit den Faktoren von Aug04 überein.

Zwischen dem 4. August und dem 4. August gibt es aber kein time lag, oder??

>> Damit ist der August im Jahr 2004 gemeint. Wenn ich jedoch die Renditen von August 2004 mit den dazugehörigen Faktoren von September 2004 regressiere sind die Ergebnisse besser. Was ja dafür spricht, dass die Zuordnung nicht passt. Also entweder ist der Fehler recht marginal, was aber gegen grundlegend Falsche Ergebnisse sprechen würde. Oder der Code für die Regression stimmt nicht. Das schaue ich mir jetzt nochmal an.

So oder so, ich wünsche Dir viel Erfolg!
Bernhard


>> Danke dir für die Rückmeldung und deine Zeit!
kevnix
Grünschnabel
Grünschnabel
 
Beiträge: 2
Registriert: Mi 22. Jan 2025, 22:58
Danke gegeben: 1
Danke bekommen: 0 mal in 0 Post


Zurück zu Regressionanalyse

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast