Przejdź do treści

Jak zbudować model prognozujący kurs złotego używając LSTM

Dowiedz się, jak krok po kroku zbudować sieć LSTM do prognozowania kursu złotego w Pythonie. Praktyczny przewodnik po deep learningu w finansach, od danych po predykcję.

Zespół VITA6 min czytania

Prognozowanie kursu złotego z użyciem LSTM (Long Short-Term Memory) to jedno z najbardziej praktycznych zastosowań deep learningu w finansach. Model LSTM radzi sobie z długoterminowymi zależnościami w szeregach czasowych znacznie lepiej niż klasyczne metody statystyczne, takie jak ARIMA. W tym artykule budujesz pełny pipeline: od pobrania danych walutowych, przez przygotowanie sekwencji, po trening sieci i ocenę jej dokładności. Wszystko w Pythonie, z kodem gotowym do uruchomienia.

Dlaczego LSTM, a nie klasyczne metody prognozowania kursów walut?

Kursy walut to szeregi czasowe z silnymi zależnościami od przeszłości, ale też z nagłymi skokami wywołanymi przez decyzje banków centralnych, dane makroekonomiczne czy zdarzenia geopolityczne. Klasyczne modele, takie jak ARIMA czy SARIMA, zakładają stacjonarność i liniowość, co w przypadku forex jest założeniem zbyt restrykcyjnym.

LSTM to rekurencyjna sieć neuronowa zaprojektowana przez Seppa Hochreitera i Jürgena Schmidhubera w 1997 roku właśnie po to, by uczyć się długookresowych zależności bez problemu zanikającego gradientu. W praktyce oznacza to, że sieć może "pamiętać", że kurs EUR/PLN był pod presją trzy tygodnie temu, i uwzględniać to w dzisiejszej predykcji.

Badania porównawcze, np. opublikowane w Applied Soft Computing (Fischer i Krauss, 2018), pokazują, że sieci LSTM osiągają wyższą dokładność kierunkową niż modele liniowe na danych forex, szczególnie na horyzontach 1-5 sesji.

Kiedy LSTM zawodzi?

LSTM nie jest srebną kulą. Model słabo radzi sobie z prognozowaniem konkretnych wartości dalej niż kilka sesji do przodu, a jego wyniki są wrażliwe na jakość danych wejściowych i dobór hiperparametrów. Traktuj go jako narzędzie wspomagające decyzję, nie jako wyrocznię.

Dane wejściowe: co i skąd pobierać

Do projektu potrzebujesz historycznych notowań kursowych. Najprostsze źródła:

  • yfinance (biblioteka Pythona): darmowy dostęp do danych Yahoo Finance, kursy dzienne i tygodniowe
  • Stooq (stooq.pl): dane dla par z PLN, w tym EUR/PLN, USD/PLN, CHF/PLN
  • NBP API (api.nbp.pl): oficjalne kursy średnie Narodowego Banku Polskiego, format JSON

Dla pary EUR/PLN pobierasz dane tak:

Python
import yfinance as yf import pandas as pd df = yf.download("EURPLN=X", start="2018-01-01", end="2024-12-31") df = df[["Close"]].dropna() df.columns = ["EURPLN"] print(df.head())

Jakie cechy uwzględnić?

Sam kurs zamknięcia to punkt startowy, ale model uczy się lepiej, gdy dostarczysz mu dodatkowych sygnałów. Warto dodać:

  • Wolumen (jeśli dostępny dla danej pary)
  • Średnie kroczące (SMA 10, SMA 50): trend
  • RSI (Relative Strength Index): momentum
  • Zmienność historyczna (odchylenie standardowe z 20 sesji)
  • Spread EUR/USD, jeśli modelujesz EUR/PLN, bo dolar silnie wpływa na PLN
Python
df["SMA_10"] = df["EURPLN"].rolling(10).mean() df["SMA_50"] = df["EURPLN"].rolling(50).mean() df["Volatility"] = df["EURPLN"].rolling(20).std() df.dropna(inplace=True)

Przygotowanie danych dla sieci LSTM

LSTM przyjmuje dane w formacie (próbki, kroki czasowe, cechy). Musisz przekształcić szereg czasowy w sekwencje okien.

Normalizacja

Sieci neuronowe są wrażliwe na skalę danych. Użyj MinMaxScaler z biblioteki scikit-learn:

Python
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() scaled = scaler.fit_transform(df)

Ważne: scaler dopasowujesz tylko na zbiorze treningowym, a zbior testowy transformujesz tym samym scalerem. Inaczej "przeciekają" informacje z przyszłości do modelu, co zawyża metryki.

Tworzenie sekwencji

Python
import numpy as np def create_sequences(data, seq_len=30): X, y = [], [] for i in range(len(data) - seq_len): X.append(data[i:i+seq_len]) y.append(data[i+seq_len, 0]) # kurs zamknięcia return np.array(X), np.array(y) SEQ_LEN = 30 # okno 30 sesji X, y = create_sequences(scaled, SEQ_LEN) split = int(len(X) * 0.8) X_train, X_test = X[:split], X[split:] y_train, y_test = y[:split], y[split:]

Okno 30 sesji (ok. 6 tygodni handlowych) to rozsądny punkt startowy dla EUR/PLN. Możesz eksperymentować z wartościami od 10 do 60.

Architektura modelu LSTM w Keras

Czas zbudować sieć. Użyjesz TensorFlow/Keras, które są standardem w deep learningu dla finansów.

Python
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout, BatchNormalization n_features = X_train.shape[2] model = Sequential([ LSTM(128, return_sequences=True, input_shape=(SEQ_LEN, n_features)), Dropout(0.2), BatchNormalization(), LSTM(64, return_sequences=False), Dropout(0.2), Dense(32, activation="relu"), Dense(1) ]) model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss="mean_squared_error", metrics=["mae"] ) model.summary()

Kluczowe decyzje architektoniczne

Dwie warstwy LSTM dają sieci możliwość uczenia się hierarchicznych wzorców. Pierwsza warstwa wychwytuje lokalne zależności, druga integruje szerszy kontekst.

Dropout 0.2 zapobiega przeuczeniu, które jest bardzo realne przy kilkuset sesjach danych.

BatchNormalization przyspiesza trening i stabilizuje gradienty, szczególnie gdy cechy mają różne skale (nawet po normalizacji).

Adam z lr=0.001 to bezpieczny punkt startowy. Jeśli strata oscyluje, zmniejsz do 0.0005.

Trening i ewaluacja modelu

Python
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau callbacks = [ EarlyStopping(patience=15, restore_best_weights=True), ReduceLROnPlateau(factor=0.5, patience=7, min_lr=1e-6) ] history = model.fit( X_train, y_train, epochs=100, batch_size=32, validation_split=0.1, callbacks=callbacks, verbose=1 )

EarlyStopping zatrzymuje trening, gdy model przestaje się poprawiać, i przywraca najlepsze wagi. Dzięki temu nie musisz ręcznie dobierać liczby epok.

Metryki oceny

Po treningu ewaluujesz model na zbiorze testowym:

Python
from sklearn.metrics import mean_absolute_error, mean_squared_error y_pred = model.predict(X_test) # Odwrócenie normalizacji dla kursu zamknięcia y_pred_inv = scaler.inverse_transform( np.concatenate([y_pred, np.zeros((len(y_pred), n_features-1))], axis=1) )[:, 0] y_test_inv = scaler.inverse_transform( np.concatenate([y_test.reshape(-1,1), np.zeros((len(y_test), n_features-1))], axis=1) )[:, 0] mae = mean_absolute_error(y_test_inv, y_pred_inv) rmse = np.sqrt(mean_squared_error(y_test_inv, y_pred_inv)) print(f"MAE: {mae:.4f} PLN") print(f"RMSE: {rmse:.4f} PLN")

Dla EUR/PLN, gdzie kurs oscyluje między 4,20 a 4,80, MAE poniżej 0,03 PLN na horyzoncie jednodniowym to dobry wynik. Ważniejsza od absolutnych błędów jest jednak dokładność kierunkowa (czy model poprawnie przewiduje, czy kurs wzrośnie czy spadnie):

Python
direction_actual = np.sign(np.diff(y_test_inv)) direction_pred = np.sign(np.diff(y_pred_inv)) directional_accuracy = np.mean(direction_actual == direction_pred) print(f"Dokładność kierunkowa: {directional_accuracy:.2%}")

W praktycznych projektach wynik powyżej 55% uznaje się za istotny sygnał, choć i tak nie zastępuje analizy fundamentalnej.

Najczęstsze błędy i jak ich unikać

Prognozowanie kursu złotego przez LSTM brzmi prosto, ale w praktyce czai się kilka pułapek:

1. Data leakage (przeciek danych) Najpoważniejszy błąd. Polega na tym, że informacje z przyszłości trafiają do zbioru treningowego. Scaler, jak wspomniano, dopasowuj wyłącznie na train. Wskaźniki techniczne (SMA, RSI) obliczaj przed podziałem, ale na pełnym szeregu, czyli też tylko na tym, co "historycznie widziałby" model.

2. Zbyt krótkie okno treningowe Neural networks forex potrzebują wystarczającej liczby próbek. Przy oknie 30 sesji i 1500 dniach danych masz ok. 1200 próbek treningowych, to minimum. Poniżej 500 próbek model będzie się przeuczać.

3. Brak walidacji walk-forward Klasyczny podział train/test nie oddaje realiów rynkowych. Użyj TimeSeriesSplit z scikit-learn lub własnej walidacji kroczącej, by sprawdzić, jak model radziłby sobie w różnych reżimach rynkowych.

4. Ignorowanie reżimów rynkowych Model trenowany w 2018-2022 może słabo działać w 2023, gdy NBP agresywnie zmieniał stopy. Rozważ retrenowanie modelu co kilka miesięcy lub użycie mechanizmu attention, który lepiej radzi sobie ze zmianami strukturalnymi.

5. Metryki bez kontekstu Niskie RMSE nie oznacza, że model zarabia. Zawsze sprawdzaj dokładność kierunkową i symuluj prostą strategię (kup jeśli model przewiduje wzrost), by ocenić praktyczną użyteczność.

Rozszerzenia: co warto dodać do modelu

Gdy masz działający baseline, możesz go rozbudować:

  • Bidirectional LSTM: czyta sekwencję w obu kierunkach, pomocne przy danych z wyraźnymi cyklami
  • Attention mechanism: pozwala sieci "skupić się" na najważniejszych momentach w oknie czasowym
  • Dane makroekonomiczne: stopy NBP, inflacja CPI, saldo handlowe Polski i strefy euro jako dodatkowe cechy
  • Sentyment z mediów: analiza NLP nagłówków finansowych (np. przez Hugging Face FinBERT) jako sygnał pomocniczy
  • Ensemble z XGBoost: połączenie predykcji LSTM i gradientowego boostingu często obniża błąd o 5-10% względem samego LSTM

Jeśli chcesz przejść od teorii do praktyki z pełnym wsparciem kodu, gotowymi notebookami i zadaniami z oceną ryzyka portfela, sprawdź kurs AI w finansach: analiza danych, prognozowanie i ocena ryzyka w Pythonie na vita.edu.pl/courses/ai-finanse. Kurs obejmuje m.in. budowę modeli predykcyjnych, analizę szeregów czasowych i ocenę ryzyka w Pythonie, a wszystko to w ramach jednego abonamentu VITA.

Możesz zacząć już dziś: 3 dni pełnego dostępu za 0 zł do wszystkich kursów na platformie. Karta płatnicza jest wymagana, a po okresie próbnym abonament to 79 zł miesięcznie albo 590 zł rocznie. Anulujesz jednym kliknięciem przed upływem 3 dni, jeśli uznasz, że to nie dla Ciebie. Kurs posiada egzamin końcowy, a certyfikat ukończenia otrzymujesz po pierwszej płatności (możesz ją zrealizować od razu w panelu, nawet w trakcie okresu próbnego). Zacznij okres próbny na vita.edu.pl/abonament.

Podsumowanie: co zabrać z tego artykułu

Budowa modelu LSTM do prognozowania kursu złotego to projekt, który realnie można zrealizować w Pythonie w kilka godzin, o ile masz ustrukturyzowane podejście. Kluczowe punkty:

  • Dane pobierasz z yfinance, Stooq lub API NBP; wzbogacasz je o wskaźniki techniczne
  • Normalizujesz i przekształcasz w sekwencje okien (standardowo 20-60 sesji)
  • Architektura: dwie warstwy LSTM z Dropout i BatchNormalization, optymalizator Adam
  • Ewaluujesz przez MAE, RMSE i dokładność kierunkową na zbiorze testowym
  • Unikasz data leakage i stosować walidację krocząca zamiast prostego podziału train/test
  • Rozbudowujesz model o dane makroekonomiczne, sentyment i mechanizmy attention

Przewidywanie kursów walut przez AI nie zastępuje analizy fundamentalnej ani zarządzania ryzykiem, ale jako jeden z elementów procesu decyzyjnego, oparty na danych i testowalny empirycznie, jest narzędziem wartym opanowania.

Najczęściej zadawane pytania

Czy LSTM naprawdę działa do prognozowania kursu EUR/PLN?

LSTM osiąga dokładność kierunkową rzędu 55-60% na horyzoncie 1-5 sesji, co jest lepsze niż modele liniowe, ale dalekie od pewności. Model sprawdza się jako narzędzie wspomagające analizę, nie jako samodzielny system transakcyjny. Wyniki zależą silnie od jakości danych wejściowych i stabilności reżimu rynkowego.

Ile danych historycznych potrzebuję do treningu modelu LSTM dla walut?

Minimum to ok. 1000-1500 sesji dziennych, czyli mniej więcej 4-6 lat notowań. Przy krótszych szeregach model jest podatny na przeuczenie. Dla EUR/PLN dane sięgające 2018 roku dają wystarczający kontekst, uwzględniając różne reżimy zmienności i zmiany polityki monetarnej NBP.

Jakie biblioteki Pythona są potrzebne do zbudowania modelu LSTM dla forex?

Podstawowy zestaw to: TensorFlow lub PyTorch (sieć neuronowa), scikit-learn (normalizacja, metryki, walidacja krzyżowa), pandas i numpy (przetwarzanie danych) oraz yfinance lub requests (pobieranie danych). Opcjonalnie TA-Lib lub pandas-ta do wskaźników technicznych.

Czym różni się LSTM od zwykłej sieci RNN w kontekście prognozowania walut?

Klasyczna sieć RNN cierpi na problem zanikającego gradientu: informacje sprzed wielu kroków czasowych są tracone podczas uczenia. LSTM rozwiązuje to przez mechanizm bramek (input, forget, output gate), które regulują, co sieć pamięta, a co zapomina. W praktyce LSTM może uwzględniać wzorce sprzed kilku tygodni, co w przypadku kursów walut ma istotne znaczenie.

Jak uniknąć data leakage przy budowie modelu prognozującego kursy walut?

Kluczowe zasady to: scaler (MinMaxScaler) dopasowujesz wyłącznie na zbiorze treningowym i tym samym obiektem transformujesz zbiór testowy; podział na train/test robisz chronologicznie, nie losowo; wskaźniki techniczne liczysz z przesunięciem, by nie używać przyszłych wartości do obliczenia sygnałów dla przeszłości. Naruszenie tych zasad zawyża metryki i daje fałszywy obraz jakości modelu.

Jak ocenić, czy model LSTM do prognozowania kursów walut jest użyteczny?

Poza standardowymi metrykami regresji (MAE, RMSE) najważniejsza jest dokładność kierunkowa, czyli odsetek sesji, w których model poprawnie przewidział kierunek zmiany kursu. Wynik powyżej 55% na nieznanym zbiorze testowym wskazuje na użyteczny sygnał. Warto też przeprowadzić prostą symulację strategii opartej na predykcjach, by sprawdzić, czy model generuje wartość ekonomiczną po uwzględnieniu spreadu.

Udostępnij artykuł

Polecane kursy

Powiązane artykuły