What happens after you pick a stock
Picking a ticker/stock symbol starts the main data path. Stoxly requests the stock’s historical OHLCV records, cleans them, writes them to SQLite, calculates the indicators, and sends the processed data to the prediction model. Only then does the dashboard draw the chart and update the recommendation, so both views are based on the same set of prices.
The first request loads the stock’s full history, so if the user changes the chart from one month to three months, the app slices the copy already held in memory rather than calling Yahoo Finance again, while a new ticker clears that working set and starts the process over.
The first version felt slow
Most of the wait came from Yahoo Finance, not from drawing the chart or calculating an indicator. We measured the original requests at 1.11 seconds, then ran them concurrently and brought the same load down to 0.63 seconds. The difference was large enough to change how the app felt, especially when moving through several stocks in the watchlist.
Data fetching and model work run away from the Qt event loop, which leaves the window responsive while a stock is loading. Once the prices arrive, the SMA, EMA, RSI, MACD, and Bollinger calculations run in C++. We save the result locally in SQLite, using journal mode to avoid reading an incomplete write, and reuse it until fresh data is needed.
A label was not enough
The model uses normalized market features and returns a score for each outcome. At first it was tempting to surface only the winning label, but that hid too much. A result split 36/34/30 and one split 90/6/4 could both say “buy,” even though the model is far less certain about the first stock. We kept all three percentages on the dashboard so that difference remains visible.
The code that turns those scores into buy, hold, or sell is separate from the model itself. Thresholds can be adjusted without retraining or rewriting the prediction code, and the timestamp stays attached to the result so it is clear which market data the recommendation belongs to.
Keeping five people out of the same file
With five people working across the interface, model, database, and external APIs, the dashboard could not become the place where every feature was wired together. We split authentication, data loading, preprocessing, indicators, predictions, networking, and error handling into their own controls. The Qt widgets receive objects such as PriceBar, IndicatorSet, Prediction, and Recommendation and focus on displaying them.
That division also gave each external dependency somewhere sensible to live. Yahoo Finance has its caching and retry logic; SQLite handles market data; Firebase handles accounts and saved user information; and the Perplexity service owns its request limits and response parsing. A change to one provider does not need to spread through the interface.
Where Perplexity fits
Perplexity never touches the prediction. Its job is to help with the question that usually comes next: what was happening when the price moved? The service receives the selected company and date range, checks the API limit, builds the request, and sends the parsed answer back to Qt.
We did not use an empty chat box because it assumes the user already knows what to ask. Stoxly starts with three questions tied to the stock on screen; choosing one replaces the list with a short answer, still beside the chart. The model result stays exactly as it was.
Rebuilding the interface in Qt
Stoxly started with a React interface. Later in the project we moved it to C++ and Qt, which suited the desktop application better and brought the charts, background work, and service calls into the same native codebase. It was also a much bigger change than we planned for: every connection to the Python pipeline and the existing authentication flow had to be made again.
Firebase authentication was still tied to parts of the React version and was not fully reconnected in time for the final demo. That is the clearest mistake I would fix on a second build. I would settle the C++/Python interface during the first sprint, test it with one complete stock, and only then build the rest of the dashboard around it.
Watch the demo
The demo follows one stock through the app, from changing the chart range to opening one of the market assistant’s questions.