Python Aktienkurse mit LSTM vorhersagen

Kingy1

Newbie
Registriert
Feb. 2023
Beiträge
1
Hallo Leute,

Ich habe ein Projekt entwickelt: Ich möchte die Schließungswerte für Aktien mithilfe eines LSTM-Modells vorhersagen. Konkreter Plan: Ich möchte, dass die KI die Schließungswerte für die nächsten 90 Tage vorhersagt, die auch in einem Graphen dargestellt werden. Ich möchte auch ein Bewertungssystem haben, das die KI aufgrund ihrer Genauigkeit bei der Vorhersage bewertet.

Für diese Aufgabe habe ich folgenden Code:
Python:
import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense

# Load the data of Adobe Systems Incorporated (ADBE) from Yahoo Finance
data = yf.download("ADBE", start="2000-01-01", end="2023-02-06")

# Preprocess the data
scaler = MinMaxScaler()
data_scaled = scaler.fit_transform(data[['Close']])

# Split the data into a training and testing set
training_data_len = int(len(data_scaled) * 0.8)
training_data = data_scaled[0:training_data_len, :]
testing_data = data_scaled[training_data_len:, :]

# Convert the data into a suitable format for the LSTM model
def create_dataset(dataset, look_back=1):
    data_x, data_y = [], []
    for i in range(len(dataset) - look_back - 1):
        a = dataset[i:(i + look_back), 0]
        data_x.append(a)
        data_y.append(dataset[i + look_back, 0])
    return np.array(data_x), np.array(data_y)

look_back = 1
training_x, training_y = create_dataset(training_data, look_back)
testing_x, testing_y = create_dataset(testing_data, look_back)

training_x = np.reshape(training_x, (training_x.shape[0], 1, training_x.shape[1]))
testing_x = np.reshape(testing_x, (testing_x.shape[0], 1, testing_x.shape[1]))

# Create the LSTM model
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(training_x.shape[1], look_back)))
model.add(LSTM(50, return_sequences=False))
model.add(Dense(25))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

# Train the LSTM model
model.fit(training_x, training_y, epochs=1, batch_size=1, verbose=2)

# Make predictions using the trained model
predictions = model.predict(testing_x)
predictions = scaler.inverse_transform(predictions)

# Evaluate the accuracy of the model
testing_y = scaler.inverse_transform(testing_y.reshape(-1, 1))
mae = np.mean(np.abs(predictions - testing_y))
mse = np.mean((predictions - testing_y) ** 2)
rmse = np.sqrt(mse)
print("Mean Absolute Error (MAE): ", mse)
print("Mean Squared Error (MSE): ", mse)
print("Root Mean Squared Error (RMSE): ", rmse)

# Plot the actual and predicted values
plt.figure(figsize=(12, 5))
plt.plot(testing_y, label='Actual Values')
plt.plot(predictions, label='Predicted Values')
plt.xlabel('Time')
plt.ylabel('Stock Closing Values')
plt.title('Adobe Systems Incorporated (ADBE) Stock Prediction')
plt.legend()
plt.show()

Der Compiler gibt einige Fehler aus. Kann sich jemand diesen Code ansehen und ihn ändern, sodass er funktioniert, oder Informationen geben, wie man den Code verbessern kann?

Ich danke euch im Voraus.
 
Kingy1 schrieb:
Der Compiler gibt einige Fehler aus.
Python ist idr nicht kompiliert... und es waere hilfreich zu sagen, was der fehler ist...
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: madmax2010
Dann schau dir die Fehler an, die der Kompiler ausspuckt und beheb sie.
Oder werde zumindest etwas konkreter, was denn nicht geht.

Und melde dich dann, wenn das Modell funktioniert und du reich bist ;)
 
  • Gefällt mir
Reaktionen: NJay, madmax2010, tRITON und eine weitere Person
Kingy1 schrieb:
Der Compiler gibt einige Fehler aus.
Und die sollen wir jetzt erraten? Wenn in irgendeiner Form Fehlermeldungen angezeigt werden, enthalten sie in der Regel auch Informationen zur Art und ggfs Ort des Fehlers.



Alternativ kannst du vermutlich auch einfach ChatGPT nach den Aktienkursen in 90 Tagen fragen. :D
 
  • Gefällt mir
Reaktionen: sh.
Nicht sachdienlich bzgl. der Fehlerausgaben, aber es ist, glaube ich, nicht möglich, über YFinance einen data pull für so viele Tagesschlusskurse, geschweigedenn open, close, low, high, close, adj. close, volume etc. zu bekommen. Selbst wenn, was passiert bei Splits z. B.? Falls das nicht gelingt, wirf einen Blick auf alpha vantage und iexcloud. - Davon ab wäre es natürlich interessant, bspw. mehrere Monate im letzten Jahr, und die Vorhersage der damals nächsten Tage mit den tatsächlichen Kursen abzugleichen.

P.S.: Ohne diese High-Fly-KI-SciKit-Modelle kommst du vielleicht auch mit dem sog. ARIMA für Zeitreihen weiter, so wie hier beschrieben: https://towardsdatascience.com/creating-an-arima-model-for-time-series-forecasting-ff3b619b848d - Vielleicht ist das kompakter und mit weniger Fehlern verbunden.
 
Zuletzt bearbeitet:
Raijin schrieb:
Alternativ kannst du vermutlich auch einfach ChatGPT nach den Aktienkursen in 90 Tagen fragen.
oder nach dem fehler. (=
aber ohne garantie, chatgpt halt


code.png
 
  • Gefällt mir
Reaktionen: BeBur, Nilson, Jurial und 2 andere
Ich verstehe noch nicht ganz wie der Code auf Basis von einer einzigen Aktie dann ein Modell trainieren soll, das ueberhaupt irgendeine Aussagekraft hat? Was ist die Idee dahinter? Ueber 23 Jahre hinweg bekommst du eine Zeitreihe, aber ist der Aktienmarkt nicht ungleich komplexer? Fuer die Temperaturen an einem Ort kann ich das ja noch nachvollziehen, wenn man sowas mal aus Spass probiert.
Ich gebe aber zu, ich hab keinerlei Kenntnisse in der Domaene, aber ich haette ja jetzt vermutet dass es doch schon Korrelationen zu anderen Aktien resp. Indexen gibt? Zudem muesste man wohl auch (Tages-aktuelle) Ereignisse mit einbeziehen um wirklich was zu erreichen, oder nicht?

Aber hey, warum nicht. Sowas soll ja auch Spass machen, evtl. kannst du ja dann mal die Ergebnisse von deinem Modell dann psten, also sobald dein Code funktioniert.
Kingy1 schrieb:
Ich möchte auch ein Bewertungssystem haben, das die KI aufgrund ihrer Genauigkeit bei der Vorhersage bewertet.
Was genau soll das sein? Willst du jetzt eine Feedback Loop integrieren?
Kingy1 schrieb:
Der Compiler gibt einige Fehler aus.
Warum postest du die nicht einfach hier?
 
  • Gefällt mir
Reaktionen: madmax2010
Hallo,

nun ja dein selbstentwickeltes Programm sieht sehr nach dem hier aus https://programmer.ink/think/a-small-example-of-time-series-prediction-using-lstm.html. Vorallem die create_dataset() Funktion fällt mir da besonders ins Auge...

Aber sei es wie es sei. Was mir so spontan in deinem Code auffällt, ist die Tatsache, dass du den MinMaxScaler über deinen gesamten Datensatz skalieren lässt und danach erst einen Split in Trainings und Testdaten machst. Da Aktienkurse nicht stationär sind, fließen also bereits "zukünftige" Informationen (das Min und Max) in die Betrachtung während des Trainings hinein. Angenommen dein LSTM-Modell würde tatsächlich beim Backtesting funktionieren, dann wirst du beim Versuch unter realen Bedingungen, wo du wirklich nur Zugriff auf die Vergangenheit hast, dann bitter böse enttäuscht werden, da du nicht weißt, was in Zukunft für ein Maximum oder Minimum für den Vorhersagezeitraum real kommen wird.

In deinen Code verwendest du ausschließlich den "rohen" Schlußkurs, wie bereits von XCatenaccioX nachgefragt, wird hierbei nicht der Split einer Aktie berücksichtigt, wenn sich plötzlich an einem Tag der Preis für eine Aktie je nach Ratio dann halbiert, viertelt ... Ebenso gibt es noch die Dividenden, die ebenfalls einen ähnlichen Einfluß auf den Preis haben. Diese Ereignisse werden dein Modell sehr stark beeinflußen bzw. unbrauchbar machen. Ein möglicher Ansatz wäre es den Adjusted Close zu verwenden oder falls dieser nicht von deinem Datenprovider geliefert wird, dann selbst zu berechnen, z.B. https://leiq.bus.umich.edu/docs/crsp_calculations_splits.pdf

Als Alternative könntest du auch den Anbieter Tiingo verwenden um historische Daten zu bekommen. Zum einen bietet Tiingo eine kostenlose Subscription an, zum anderen hast du hier bereits auch den Zugriff auf die adjusted Prices für Open, High, Low und Close. In der Doku gibt es Beispiele in Python und Javascript, wie man deren RestAPI nutzt. Was dann auch interessant sein könnte, ist der Zugriff auf deren Websocket Schnittstelle, wo du Live-Daten von der IEX zu mehreren tausend Tickern bekommst.

Was mir noch so in deinem Code auffällt, dass du quasi Rohdaten reinfütterst und hoffst, dass dann auf magische Art der reale Kurs herauspurzelt. Was ich an deiner Stelle machen würde, wäre mich erstmal mit der Aufbereitung von Rohdaten, Bereinigung und Featureengineering zu befassen. Ein recht guter Anlaufpunkt wäre für mich dann Kaggle, wo es auch recht interessante und kostenlose Kurse gibt um hier die Basics zu erlernen. Interessant ist auch die Möglichkeit dort an den Competitions teilzunehmen, wo du einerseits dein erlerntes Wissen anwenden kannst und im Ranking siehst, wo du stehst.

Das Thema Validierung solltest du dir ebenfalls mal genauer anschauen, was mir in deinem Code definitiv zu kurz kommt.

Also im Endeffekt wirst du mit den genannten Punkten seeeehrrr viel Zeit verbringen und nicht durch das einfache Copy&Paste eines Scripts aus dem Internet die ultimative Gelddruckmaschine in weniger als 10min entwickeln können.

 
  • Gefällt mir
Reaktionen: XCatenaccioX
Ich habe mich mal einem ähnlichen Problem angenommen für die Apple Aktie. Folgendermaßen war mein Plan: Ich habe historische Kursdaten als den Schlusskurs (adj. Close) im täglichen Abstand abgerufen. Zusätzlich dazu habe ich Firmenstammdaten wie das Kurs-Gewinn-Verhältnis, den Gewinn, den operativen Cashflow usw. erhalten. Diese Daten wurden dann zeitlich dem Kurs zugeordnet. Die Lücken zwischen den Daten (da Finanzberichte in der Regel quartalsweise veröffentlicht werden) habe ich bei allen Daten, die keinen Status markieren (0 oder 1), linear interpoliert und "Ausreißer" entsprechend angepasst.

Den Datensatz habe ich anschließend mit Hilfe einer eigenen Funktion normalisiert. Zur Funktion: Diese hat einen im Voraus definierten Bereich mittels Min- und Max-Wert. In diesem Bereich werden die Daten prozentual zugeordnet, wobei der Maximalwert 100% bzw. 1 und der Minimalwert 0% bzw. 0 entsprechen.

Mein Gedanke war es, die Normalisierung unabhängig von der Struktur der Daten durchzuführen. Danach habe ich ein einfaches zweischichtiges LSTM erstellt und einen Rückblick (lockback) von 2 Quartalen implementiert. Anschließend habe ich den Datensatz entsprechend nach dem Training bzw. der Validierung aufgeteilt. Für die Auswertung habe ich TensorBoard und das Early Stopping über Callbacks hinzugefügt.

Während des Trainings ist mir aufgefallen, dass es bereits nach der 3. Epoche einen viel zu geringen Validation Loss gibt, etwa im Bereich von 7 * 10^(-7). Kann das sein, besonders wenn er sich weiter konstant verringert, bis er sich bei etwa 1,2 * 10^(-12) stabilisiert, was eigentlich ein gutes Zeichen ist? Zudem ist die Validierungskurve fast identisch zur Trainingskurve. Hat jemand generelle Ideen dazu? Oder sind genauere Informationen erwünscht?
 
Leon_1091 schrieb:
Die Lücken zwischen den Daten (da Finanzberichte in der Regel quartalsweise veröffentlicht werden) habe ich bei allen Daten, die keinen Status markieren (0 oder 1), linear interpoliert und "Ausreißer" entsprechend angepasst.
So komplett kann ich da nicht folgen, aber warum sollte es für die Vorhersage eine gute Idee sein, wenn zeitlich mit Daten aus der Zukunft interpoliert wird? Woher soll man die im Prognosefall dann nehmen?
 
Also Trainingsset besteht aus einem pandas Array der folgende Features hat: Close, Volume, cashflow, profitloss, operating income, investments, currentDebt, dabei alle Daten bis Januar 2018 und bei täglichem Abstand resultiert das in 8831 Rows. Bei einem Lockbach von rund 6 Monaten sollten das abzüglich dem 20 % Train/ Validationsplit natürlich zu zu wenig Daten führen, was auch das teilweise extreme overfitting erklären würde. Zur Frage von Simpsonsfan. Vielen Dank manchmal einfach nen Denkfehler. Mir bleibt in diesem Fall ja nur übrig die Lücken zwischen den Daten "Aufzufüllen" mit den zu Zeitpunkt x vorhandenen Finanzdaten oder übersehe ich hier was? Das zusammen würde natürlich auch die zu "gute" Performance um Wahr zu sein erklären. Viele Dank für die Hilfen.
 
Hallo Leon_1091 und Mitlesende,

man kann nur hoffen, dass hier keiner jemals bei einem Pensionsfonds oder in der Finanzindustrie arbeiten wird... :D Von ML & Co. habe ich keine Ahnung, beste Voraussetzung, um hier was anzumerken, aber erstmal zusammenfassend deine beiden Postings, dann ein paar Anregungen dazu:

Daten/Material:
  • nur Apple
  • historische Kursdaten (adj. Close)
  • täglicher Abstand (ca. 8800 rows)
  • Firmenstammdaten
  • Kurs-Gewinn-Verhältnis
  • Gewinn
  • operativer Cashflow
Methoden:
  • Lücken linear interpoliert
  • Ausreißer angepasst
  • normalisiert
  • zweischichtiges LSTM
  • Lookback 2 Quartale
  • Aufteilung Training vs. Validierung
  • Early Stopping über Callbacks
Ergebnis:
  • nach 3. Epoche viel zu geringer Validation Loss
  • Validierungskurve fast identisch zur Trainingskurve

Anregungen:

1. Apple oder alle
Inwiefern unterscheidet sich die gewählte Methode (vermutlich Standard-Masterplan bei ML) bei der Apple-Aktie von einer beliebigen anderen Aktie? Kurzum, einfach anderen Datensatz ziehen, z. B. von einer volatileren Aktie, z. B. Tesla. Gleiches Verhalten?

2. Anzahl der rows
Verständnisfrage: Wie kommt es zu rd. 8.800 rows bei Pi mal Daumen 6 Jahren à 250 Handelstagen, sollte es sich um einen DataFrame mit täglichen adj. close und den Stammdaten in den "Spalte" handeln? Bei rd. 1.500 wäre eigentlich Schluss.

3. Datengüte bzw. KGV
Warum das Kurs-Gewinn-Verhältnis von einem Datendienstleister herunterladen, wenn dieses doch nur ein arithmetischer Wert ist, den du bei Tagesschlusskursen selbst berechnen könntest (z. B. adj. close / (earnings / per share)). Wahrscheinlich wäre dein Datensatz tagesaktuell, jener des Dienstleisters schleppt veraltete KGVs durch dein DataFrame und stört das LSTM. Mit so einem durchgängig selbsterrechneten KGV könnte man ja schon interessante Dinge anstellen, statt ML z. B. einfach gleitende Durchschnitte dafür, diese visualisieren mit Über-/unterbewertungen etc.

4. Datenvarianz bzw. Q-Zahlen
Die genannten Firmenstammdaten bleiben über ein Quartal identisch, deswegen schmieren Aktien bei earning calls ja auch gern mal ab oder gehen durch die Decke, denn das sind für Nicht-Insider oder für Nicht-Finanzjournalisten, die vermutlich nach Absprach mal wieder einen "earnings beat" um 3 Cent attestieren, also für Ottonormals alles unbekannte Werte. Du könntest die "expected" Quartalszahlen beitreiben (Datendienstleister), aber der Blick ist ja sowieso historisch. Im Grunde müsstest du das "unbekannte" (laufende) Quartal aus dem Modell herausschneiden. Die Tage +/- earnings call date sind sowieso krasse Ausreißer. Hinzu kommt: Bei einem Lookback von zwei Quartalen hast du über die dort knapp 125 Datensätze eh nur zwei unterschiedliche Inhalte in allen Spalten außer dem Tagesschlusskurs. Und noch: Dadurch, dass sich der Datensatz eigentlich nur in der Spalte ad. close unterscheidet, woher soll eine Modellierung von XYZ kommen bzw. müsste ein overfitting nicht zwingend sein, wenn ich einen Datensatz betrachte, dessen Datenpunkte sich nur im Schnitt nur im niedrig-einstelligen Prozentbereich unterscheiden? Die paar identischen Q-Zahlen sorgen ja nicht für Varianz.

5. Datentrennung bzw. was ist ein gutes Segment in der Zeitreihe?
Bei der Aufteilung von Training und Validierung trennst du in diesem Fall nicht bspw. einen Textkorpus von 100.000 Amazon-Rezensionen oder Blütenblätter, sondern Kurse auf einer Zeitreihe, wobei jüngere/zukünftige Kurse stets von älteren abhängen (und nicht isoliert betrachtet werden können). Man könnte hier z. B saisonale Blöcke bilden oder besser Quartalsblöcke, also nur alle Q1 statt die letzten zwei Quartale z. B., da sicherlich auch Apple krasse saisonale Schwankungen beim Absatz haben wird (Black Friday, Weihnachtsgeschäft etc.)

Wegen dieser Dinge kann ich mir vorstellen, kommt es zu solch glatten Ergebnissen im Modell.

Natürlich reizt das ja als Übungsaufgabe. Man muss sich natürlich klar sein, dass solchen Aktienvorhersagen nicht einmal so gut auflösen würden wie eine simple Wettervorhersage von Tagestemperaturen auf der Basis nur von Tabellen (bzw. ohne zusätzliche metereologische Beobachtungen), zumal das Wetter sowas wie revidierte Gewinnerwartungen, Handelsrestriktionen, positive schwarze Schwäne oder Geopolitik nicht kennt. Denn nicht nur "etwas" vorhersagen, sondern "richtig" vorhersagen, darum ginge es ja. Täglich rauf oder runter? Wenn ein solches Modell auch nur einen Prozent genauer wäre als ein unendlicher Münzwurf, hätte man die Goldgrube. Methodisch beneidenswert jedenfalls dieses ML-Zeug. Kann man damit nicht noch andere Muster erkennen? Handelsvolumen? Zeitreihen bei Präsidentschaftswahlen? Abhängigkeiten von anderen Derivaten etc.? Machen die Großen ja auch, "modern portfolio theory", natürlich verkacken die dann auch in loser Frequenz im ganz großen Stile, aber halt nicht im Daytrading.
 
  • Gefällt mir
Reaktionen: kuddlmuddl
Vielen Dank für deine Anregungen,

gedacht war es nur als reine Spielerei. Ich kann mir gut vorstellen das sich da schon große Firmen mit beschäftigen, also war die Gewinnerwartung relativ gering. Bevor ich hier weiter mach werd ich mir die Kennzahlen und die mathematischen Hintergründe erstmal genauer anschauen. Grundsätzliche bin ich der Meinung das es Strukturen in solchen Daten gibt, die ein Mensch so einfach nicht wahrnimmt, darunter vllt auch die Marktmechanismen. Zumindest lassen Forschungen in diesem Bereich darauf schließen. Ich werde vllt das Modell auf weitere Aktien erweitern. Apple war einfach nur das gängige Beispiel. Interessanter wäre es vllt Aktien einer Branche zu betrachten, zudem dann auch mehr Daten vorliegen. Eher habe ich Problem zuverlässige historische Daten zu den Finanzberichten zu finden. Zur anderen Frage. Ja. Grundsätzlich lassen sich alle in Zeitreihen aufgeteilte Daten untersuchen und vorhersagen, die Frage ist nur ob genug Daten vorliegen und sich tatsächlich ein Muster erkennen lässt, oder ob dieses so tief liegt, dass es jetzt noch nicht errechnet werden kann. Weiterer Interessanter Punkt wäre im Kontext noch eine Nachrichtenanalyse zu erstellen und diese mit zu integrieren.
 
  • Gefällt mir
Reaktionen: XCatenaccioX
Zurück
Oben