Trading System Automation
An end-to-end system that predicts next-day BUY, SELL, or HOLD signals for 31 large-cap US stocks. It pulls live financial data, engineers 22 features, trains the models, and serves everything through a Streamlit app with backtesting.
One pipeline, one definition.
The whole system, from raw financials to a live signal, runs across 31 tickers with a single shared feature definition so training and serving can never drift apart.
Two models, one problem.
Most stocks share one model, a logistic regression on 26 tickers and 16 features that tests at 50.1%. Banks and payment providers report their financials differently, so they get their own: a gradient boosting model on 5 tickers and 11 features, testing at 54.7% and the stronger of the two on the financial-sector stocks, where the standard fundamental ratios do not translate. Neither is far from a coin toss, which is why accuracy is not the number this project is judged on.
Recall over accuracy.
Before balancing, the model scored 52% by calling "up" almost every day, catching only 35% of down moves. After balancing the classes, it catches 61% of them. That is a genuinely more useful model, even if headline accuracy barely moves.
From a number to a decision.
The classifier outputs 0 or 1 with a confidence. One shared strategy module turns that into a signal, and both training and the live app import it, so the signal the model learned is exactly the signal the app shows.
Confidence 0.50 is under 0.51, so the model stays out of the trade.
22 features, 4 groups.
The ETL pipeline cleans five years of SimFin data, handles stock-split artefacts and missing fields, and engineers 22 columns in four groups. Sixteen of them are model inputs; the other six are computed only to draw the app's charts. The financial fallback drops the five fundamental ratios and trains on eleven.
One prediction, end to end.
One prediction, left to right. The app asks SimFin for live prices through a wrapper that renames every field to match the training schema, the same engineer_features() the training script ran turns them into 22 columns, strategy.py routes the ticker to its feature list, the matching model returns a probability, and one shared rule turns that into the signal the app shows. Because training and serving import the same two modules, the signal the model learned is exactly the signal you see. The wrapper and the app are the two pieces I built.
Where I came in.
On a team of six, I built the SimFin API wrapper and co-built the Streamlit app. The wrapper is what lets the same feature code run on both historical and live data, and the app is where all of it turns into something a person can actually use. We also kept an AI usage log in the repo so the way AI helped build the project is documented alongside the code.