All projects

Machine learning / 2025–2026

Evolutionary Stock Optimizer

A Python project for training trading agents on historical prices with reinforcement learning and genetic algorithms.

PythonReinforcement learningFastAPI

Training on historical prices

I swing trade ordinary shares, but I don’t have time to watch charts throughout the day. I built this project to experiment with trading agents trained on historical market data.

It combines reinforcement learning with evolutionary algorithms to train and compare agents. I use the Sharpe ratio to evaluate performance, with a web dashboard for following the training runs.

Simulated portfolio equity from 2016 through 2024
Equity curve from a historical simulation after 100 training cycles.

How it is put together

FastAPI and Uvicorn serve the dashboard and handle training requests. The data pipeline downloads historical prices through yfinance, calculates SMA, RSI, and MACD with NumPy and Pandas, and caches the results locally for repeated training runs.

The agents use PPO and A2C from Stable Baselines3 in custom Gymnasium environments. Training runs in parallel, while the HTML and JavaScript dashboard polls the backend for training metrics and Sharpe ratios.

The trading environment

My SimpleTradingEnv class simulates trading a single stock. The observation contains the closing price, SMA, RSI, MACD, current holdings, and available cash.

The agent chooses a target position between -1.0 and 1.0, ranging from fully short to fully long. The environment updates the position and accounts for simulated slippage and trading fees.

Reward calculation

The reward is the change in total equity at each step. This is separate from the Sharpe ratio used to evaluate the training results.

#Calculating the reward via equity delta
equity_before = self._mark_to_market(price)
target_position_value = float(np.clip(a, -self.max_w, self.max_w)) * equity_before
current_position_value = float(self.position * price)
delta_value = target_position_value - current_position_value

# trade execution and fee deduction ...

equity_after = self._mark_to_market(new_price)
reward = float(equity_after - equity_before)