Overview of Deep Learning in Financial Time-Series
The prediction of equity prices involves navigating complex, non-linear patterns inherent in financial markets. This research compares two prominent neural network architectures: the Backpropagation (BP) network and the Long Short-Term Memory (LSTM) unit. While BP networks serve as a foundational supervised learning tool, LSTMs demonstrate superior capability in modeling temporal dependencies due to their gating mechanisms. To further optimize predictive performance, we investigate two architectural enhancements: stacking multiple LSTM layers to increase depth and incorporating dynamic residual connections to facilitate gradient flow. Empirical validation indicates that these modifications significantly bolster the model's ability to generalize across volatile market conditions.
Data Acquisition and Preprocessing Strategy
Modern quantitative analysis relies heavily on high-frequency, multi-dimensional datasets. This study focuses on the Chinese equity market, leveraging historical daily records to evaluate systematic risk prediction capabilities.
Source and Selection Criteria
To ensure statistical robustness, we selected four equities with substantial trading history. Data was aggregated from multiple financial portals including Yahoo Finance and investing.com. The selection process prioritized stocks with long operational histories to maximize sample size for training.
We developed a modular ingestion pipeline capable of handling both API-driven downloads and HTML parsing. In cases where JavaScript rendered content dynamically, we utilized Dockerized Splash instances to execute client-side rendering before extraction.
import pandas as pd
import yfinance as yf
from requests import Session
from bs4 import BeautifulSoup
def fetch_equity_history(symbol, start_date="1991-01-01"):
"""
Retrieves historical OHLCV data using Yahoo Finance API wrapper.
"""
ticker_obj = yf.Ticker(symbol)
return ticker_obj.history(start=start_date)
def validate_dataset(raw_df, min_threshold=6800):
"""
Filters datasets based on minimum record length requirement.
"""
if len(raw_df) >= min_threshold:
return raw_df.reset_index()
return None
# Initialization
symbols = ['000001.SZ', '000002.SZ']
processed_frames = []
for sym in symbols:
df = fetch_equity_history(sym)
validated = validate_dataset(df)
if validated is not None:
processed_frames.append(validated)
final_dataset = pd.concat(processed_frames)
print(f"Total samples loaded: {len(final_dataset)}")
Architectural Mathematics and Theoretical Basis
Standard Feedforward Networks
The Backpropagation algorithm minimizes a loss function by computing gradients through the chain rule. Information propagates forward to generate predictions, errors are calculated at the output layer, and weights are adjusted backward.
Forward Pass:
aj(l) = g(zj(l)) ... (1)
Error Calculation:
E = ½ Σ(yk − ak(L))² ... (2)
Weight Update Rule:
ωij(l) = ωij(l) − α ∂E/∂ωij(l) ... (4)
To mitigate vanishing gradients common in standard RNNs, LSTM cells utilize a cell state controlled by gates. These gates regulate the retention and discarding of information over extended sequences.
The update equations involve the Forget Gate (ft), Input Gate (it), and Output Gate (ot):
ft = σ(Wf[ht-1, xt] + bf) ... (6)
it = σ(Wi[ht-1, xt] + bi) ... (7)
Ct = ft ⋅ Ct-1 + it ⋅ tanh(WC[ht-1, xt] + bC) ... (8)
Advanced Architectural Modifications
Deep Hierarchical Structures
Stacked LSTM configurations arrange multiple recurrent layers vertically. The hidden state of a lower layer serves as the input sequence for the upper layer, enabling the abstraction of hierarchical temporal features.
Ht(1) = LSTM1(xt) ... (10a)
Ht(2) = LSTM2(Ht(1)) ... (10b)
Dynamic Residual Integration
Inspired by ResNets, we introduce skip connections that bypass certain transformations. Unlike static shortcuts, our proposed mechanism allows the magnitude of the skip connection to adapt dynamically based on input complexity, easing gradient propagation through deeper stacks.
st = Adaptive_Skip(xt, ht-1) ... (11)
ht = LSTM(xt + st, ... ) ... (12)
We partitioned the dataset such that the final 100 observations served as the test set, while the remainder was used for training. Three variants were evaluated: Basic LSTM, Stacked LSTM, and Stacked LSTM with Dynamic Residuals.
Baseline Implementation
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
def build_baseline_lstm(units=[64, 16], dropout_prob=1e-4):
seq_model = Sequential()
# First Layer
seq_model.add(LSTM(units[0], input_shape=(lookback, feature_dim), return_sequences=True))
seq_model.add(Dropout(dropout_prob))
# Second Layer
seq_model.add(LSTM(units[1], return_sequences=False))
seq_model.add(Dropout(dropout_prob))
# Output Head
seq_model.add(Dense(4, activation='relu'))
seq_model.add(Dense(1, activation='linear'))
seq_model.compile(optimizer='adam', loss='mse', metrics=['mae'])
return seq_model
Residual Stacked Implementation
The following implementation utilizes the Keras Functional API to manage custom residual connections between layers explicitly.
from tensorflow.keras import Model, Input
from tensorflow.keras.layers import Add, Concatenate, GlobalAveragePooling1D
class ResidualSkipLayer(Layer):
"""Custom layer for adaptive skipping."""
def __init__(self):
super().__init__()
def call(self, inputs):
current_state, previous_skip = inputs
# Learnable scalar weight could be added here in advanced versions
return Concatenate(axis=-1)([current_state, previous_skip])
def construct_residual_network():
input_layer = Input(shape=(lookback, feature_dim))
# Layer 1
out_1 = LSTM(64, return_sequences=True)(input_layer)
skip_1 = out_1
# Layer 2 with Skip
out_2 = LSTM(32, return_sequences=True)(out_1)
res_2 = ResidualSkipLayer()([out_2, skip_1])
# Layer 3 with Skip
out_3 = LSTM(16, return_sequences=False)(res_2)
pooled = GlobalAveragePooling1D()(out_3)
x = Dense(4, activation='relu')(pooled)
output = Dense(1)(x)
model = Model(inputs=input_layer, outputs=output)
model.compile(loss='mse', optimizer='adam')
return model
Performance Evaluation
Metrics were recorded over 100 and 200 training epochs. The Stacked LSTM with Dynamic Residuals demonstrated the lowest Mean Squared Error (MSE) and Mean Absolute Percentage Error (MAPE).