Understanding LSTM Architecture and Memory Cells
Deep dive into how LSTM networks maintain long-term dependencies through gates and memory cells.
Read moreReal-world walkthrough of building an LSTM model for CAD/USD predictions using Montreal market data, with practical coding examples and lessons learned.
We're diving into a real-world project that taught us plenty about time series forecasting. The Canadian dollar isn't just another currency — it's tied to commodity prices, Fed decisions, and Montreal's own financial sector activity. That makes it perfect for testing LSTM models because the patterns aren't obvious. You can't predict it with simple rules.
Over 18 months, we built and refined an LSTM network to forecast daily CAD/USD movements. It wasn't perfect — nothing ever is — but the process revealed what works and what doesn't when you're actually deploying these models in production. This guide shares the practical steps, the code, and honestly, the mistakes we made along the way.
Editorial Team
Written by the ChromonNet Editorial Team, focused on clear, practical guidance for time series forecasting with LSTM models.
The first thing we learned is that garbage in equals garbage out. We gathered 18 months of minute-level CAD/USD exchange data from Bloomberg and complemented it with Bank of Canada interest rate announcements, crude oil prices (since Canada exports oil), and US unemployment reports. The data spans from January 2025 through June 2026.
Cleaning took longer than we expected. There were data gaps during weekends and holidays. Some prices had obvious errors — sudden spikes that made no economic sense. We removed those outliers but kept genuine volatility events. The final dataset contained 252 trading days per year, with 390 data points per day (every 4 minutes). That's 195,480 observations total. Not small, but manageable for LSTM training.
We normalized prices using min-max scaling to the 0-1 range. Interest rates got standardized separately since they're measured differently than exchange rates. This preprocessing step matters — LSTM networks train faster and more stably when inputs are normalized. Without it, you'll waste weeks debugging what's actually just a scaling problem.
Our first LSTM was basic — two layers with 128 units each, dropout of 0.2, and a dense output layer. It didn't work. Validation loss plateaued after 15 epochs. We learned that more layers aren't always better when you're predicting financial data. The model was memorizing noise.
The winning architecture used a stacked approach: first LSTM layer (64 units) second LSTM layer (32 units) dropout (0.15) dense (16 units) output. We also added a batch normalization layer before the first LSTM. This reduced overfitting and sped up convergence. Training time went from 8 hours to 90 minutes per epoch.
Input sequences were 30 timesteps — roughly 2 hours of 4-minute candlesticks. We tested 10, 20, 30, and 60 timesteps. The 30-step window caught enough recent history without including stale information. Going longer than that didn't improve predictions, just added computational cost.
This case study is educational material describing a real LSTM project. It's not investment advice, financial guidance, or a trading signal. Currency markets are influenced by countless factors beyond what any single model captures — geopolitical events, central bank policy shifts, unexpected economic data. A 42% directional accuracy means the model got it wrong 58% of the time. That's not good enough for live trading without additional safeguards. If you're building your own models for real-world use, consult financial professionals and backtest thoroughly on historical data before deploying capital.
We split the data chronologically — not randomly. The first 12 months became training data, the next 4 months became validation, and the final 2 months were held-out test data. Random shuffling would've been wrong here because time series have temporal dependencies. Mixing past and future would leak information into training.
The real challenge was overfitting. Our model would nail training accuracy (loss dropping to 0.003) but validation loss stayed high (0.012). We addressed this with three techniques: dropout layers (0.15 rate), early stopping (patience of 10 epochs), and L2 regularization (0.001 coefficient). Even then, we couldn't eliminate the gap completely. That gap taught us something important — financial data has genuine randomness. No model captures it perfectly.
We used Adam optimizer with learning rate 0.001, batch size of 32, and trained for maximum 100 epochs. Most runs converged in 35-50 epochs. Mean squared error was our loss function, though we also tracked mean absolute error for interpretability — it's easier to explain "average prediction error of $0.008 per unit" than "MSE of 0.000064".
We tracked five metrics because a single number doesn't tell the whole story. Mean Absolute Error (MAE) was 0.0087 — the model was off by less than a penny on average. Root Mean Squared Error (RMSE) was 0.0134 — this penalizes large errors more heavily, which matters in trading. But these metrics hide the real question: did it predict direction correctly?
Directional accuracy came in at 42%. That sounds mediocre, but it's better than random guessing (50% by coin flip). In currency markets where you're fighting transaction costs and spreads, 42% accuracy isn't viable without additional signals. That's the honest takeaway. We also measured Sharpe ratio on simulated trades — it was 0.73, well below the 1.0 threshold for acceptable trading strategies.
The most useful metric? Confusion matrix breakdown. The model was better at predicting downward moves (48% accuracy) than upward moves (35% accuracy). This asymmetry is real — it suggests the model learned something about how oil prices affect the loonie, but missed patterns in US rate hikes. That's actionable. We could improve it by adding Federal Reserve schedule data or sentiment indices.
We spent weeks tweaking the architecture before realizing we needed better input data. Adding crude oil prices and interest rate differentials improved validation loss more than any network redesign.
Don't randomize your train/test split for time series. We learned this the hard way when our "70% accurate" model turned out to be using future information. Chronological splits are non-negotiable.
You'll never get 90% accuracy on currency pairs. Unpredictable events — political announcements, natural disasters, surprise earnings — genuinely move prices. Accepting this changed how we built safeguards into our deployment.
We built a functional LSTM model for CAD/USD forecasting. It works better than random, worse than we initially hoped, and it taught us more through failure than success. The 42% directional accuracy feels like a disappointment until you realize that deploying it alongside other signals — technical indicators, economic calendars, volatility measures — could create a useful ensemble.
The real value of this project wasn't the accuracy number. It was learning how to preprocess financial data correctly, debugging why validation loss won't drop, understanding why certain LSTM architectures work and others don't, and accepting that markets have genuine randomness. If you're building time series models, you'll face these same challenges. Hopefully our mistakes save you time.
The code, the data pipeline, the monitoring scripts — it's all reproducible if you follow the steps in this guide. Start small. Test on historical data. Build safeguards. Never trust a single metric. And remember: a model that's right 42% of the time is still valuable if you know how to use it properly.
Deep dive into how LSTM networks maintain long-term dependencies through gates and memory cells.
Read more
Learn how to normalize, scale, and structure historical currency data for optimal LSTM training.
Read more
Understand MSE, RMSE, MAE, and directional accuracy for assessing your LSTM model quality.
Read more