lstm-alpha-strategy/src/lstm_alpha_strategy/models/lstm_model.py

84 lines
2.9 KiB
Python
Raw Normal View History

2026-07-05 04:47:55 +01:00
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models, callbacks
def build_lstm_model(input_shape):
"""
Builds a robust LSTM classification network with regularizers
to handle noisy financial time-series data.
"""
model = models.Sequential([
# 1. First LSTM Layer: Returns sequences to feed into the next layer
layers.Input(shape=input_shape),
layers.LSTM(units=64, return_sequences=True,
kernel_regularizer=tf.keras.regularizers.l2(0.001)),
layers.Dropout(0.3), # High dropout to reduce overfitting
# 2. Second LSTM Layer: Returns only the last step's hidden state
layers.LSTM(units=32, return_sequences=False,
kernel_regularizer=tf.keras.regularizers.l2(0.001)),
layers.Dropout(0.3),
# 3. Dense Hidden Layer for abstract feature synthesis
layers.Dense(units=16, activation='relu'),
layers.BatchNormalization(), # Stabilizes training weights
# 4. Output Layer: Single neuron outputting a probability (0.0 to 1.0)
layers.Dense(units=1, activation='sigmoid')
])
# Compile with Binary Crossentropy for the binary UP/DOWN classification task
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.0005),
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.AUC(name='auc')]
)
return model
def train_trading_model(X, y):
"""Handles data splitting, model creation, and training with early stopping."""
# 1. Chronological Train/Test Split (Crucial for Time-Series! Do NOT random split)
# Using the last 20% of chronological data for evaluation to avoid data leakage
split_idx = int(len(X) * 0.8)
X_train, X_val = X[:split_idx], X[split_idx:]
y_train, y_val = y[:split_idx], y[split_idx:]
# 2. Extract dimensions for input shape: (Time Steps, Features)
input_shape = (X.shape[1], X.shape[2])
model = build_lstm_model(input_shape)
model.summary()
# 3. Set up Training Callbacks
# Early Stopping prevents the network from memorizing noise when val loss stalls
custom_callbacks = [
callbacks.EarlyStopping(
monitor='val_loss',
patience=5,
restore_best_weights=True
),
callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.5,
patience=3
)
]
# 4. Fit the Model
print("\nStarting model training...")
history = model.fit(
X_train, y_train,
validation_data=(X_val, y_val),
epochs=30,
batch_size=64,
callbacks=custom_callbacks,
verbose=1
)
return model, history
# --- PIPELINE INTEGRATION EXAMPLE ---
# trained_model, training_history = train_trading_model(X, y)
# trained_model.save("portfolio_lstm_bot.h5")