Algorithmic Trading Engine
Software Engineer
This is a long-only swing-trading system in Python. Each day it scans a universe of liquid ETFs and large-cap stocks, turns its signals into orders through the Alpaca brokerage API (paper trading by default), journals every decision, and reviews its own results each month. The most important part is not the strategy but the validation harness, which exists to keep the backtest numbers honest even when honest means less impressive.
How does the daily pipeline decide what to trade?
A scheduled run (APScheduler) pulls price history and classifies the market regime: trend (above or below the 200-day average) crossed with volatility (high or low realized volatility). Each strategy sleeve proposes positions only in the regimes it is allowed to trade. The sleeves cover index rotation, momentum across a screened stock list, and short-term pullbacks.
A shared risk layer then applies volatility targeting, per-position caps, a drawdown circuit breaker measured against a rolling one-year peak, a maximum daily loss, and a kill switch before any order reaches the broker. Configuration is validated with Pydantic models, and the research data is stored as Parquet.
What makes the backtests trustworthy?
Early versions produced exciting numbers that turned out to come from testing on a hand-assembled list of stocks that had already done well. The harness was rebuilt to remove each source of flattery:
- A point-in-time universe. Index membership is rebuilt from dated additions and removals, and companies that failed are booked as total losses, so the backtest cannot pick only from survivors.
- One screen for live and backtest. A single liquidity rule decides what is tradable on each date in both paths, so a backtest trades only what the live system could have traded.
- An engine that trades like the live system. Positions drift between trades and are adjusted only when the target moves past a rebalance band, instead of being reset to target every day at no cost.
- Real fill prices. Orders fill at the actual opening and closing auction prices, not the daily bar's open, a mistake that had produced a false result in an earlier study.
- Several start days. Every study runs from seven different start days, because a single backtest moved substantially depending on which day of the month it re-ranked.
- A holdout it cannot tune on. Recent years are cut out of everything that tunes, and every look at the holdout is logged.
Can the trading system change its own rules?
No, by design. A monthly review tests alternative settings on tuning data only, judging each test year with rules chosen from earlier years, and writes a proposal when one wins consistently. A change happens only by hand. A sleeve whose last 40 trades have negative expectancy is muted automatically and unmuted when it recovers, but the capital split stays fixed unless it is explicitly switched to adaptive.
An optional weekly analyst built on the Claude API reads the journal and writes a plain-language review, plus hypotheses for the monthly review to test. It never places a trade.
How is every trading decision recorded?
Each trade is journaled to CSV and SQLite with its entry and exit reasons, profit and loss, R-multiple, maximum adverse and favorable excursion, and the regime at entry. A local dashboard shows KPI tiles; equity against two benchmarks (the index, and an equal-weighted version of the stock list, so hand-picked winners cannot pass as skill); drawdown with a regime strip; a monthly heatmap; and per-trade replay charts drawn with Matplotlib.
A rulebook describes the active configuration in plain language, and a test fails if any setting is unexplained or the rulebook is out of date.
What did the research actually show?
Most ideas did not survive. Sixteen chart rules, a learned model on 30 price and volume features, earnings headlines, calendar patterns, and intraday rules were each tested against a plain alternative after costs, and none beat it. The one idea that passed a test written down in advance and scored once on unseen data is built in, switched off by default. The negative results are recorded alongside the positive one on purpose: the harness is there to stop me from fooling myself.