Quant

Context
I started this in my freshman year, and I started it by losing money. I was trading options on not much more than a feeling about which way something was going, which is a description of gambling rather than of trading, and the account agreed. What I had that most people losing money on options do not have is a degree that was teaching me to build software. If I could not do this by instinct, I could at least build something that did it by rule, on real data, the same way every time, and find out whether the rule was any good before it cost me anything.
Most trading ideas die in the plumbing rather than in the market. Testing one properly means fetching the data, cleaning it, computing the indicators, writing a backtest that fills honestly, and then wiring all of it to a broker — and that is the same work every time, for every idea, before you have learned a single thing about whether the idea was worth having. So the system is built the other way round. The plumbing exists once, and a strategy is a file that plugs into it: a class with an on_bar method, inheriting the data, the fills, the risk sizing, the charts and the live execution without having to ask for any of them.
It has been running on paper accounts for a few months now. Every trade it takes posts to a Discord channel — the entry, the exit, the price, the reason it closed, what the account is worth afterwards — so the thing tells me what it is doing whether or not I am sitting in front of it, and I find out about a bad exit on my phone rather than out of a log file a week later.
Details
- Role
- Developer and Researcher
- Team
- Solo, after a two-person start
- Timeline
- 2024 — present
- Deliverables
- Data pipeline, backtester, live runner, two dashboards
- Status
- Running on paper and evaluation accounts
Tech stack
- Infrastructure
- AWS Lightsail·Ubuntu·systemd·Tailscale
- Engine
- Python·FastAPI·WebSockets·SQLite
- Data
- Databento·Parquet·pandas·NumPy
- Research
- Walk-forward·Monte Carlo·Permutation tests·Regime gating
- Interface
- React·TypeScript·Vite·Tailwind·Lightweight Charts
- Alerts
- Discord webhooks
Final artifacts



Key design moments
The dorm laptop stopped being the server
For the first stretch of this the whole system ran on a spare laptop on a desk in my dorm room. It worked, in the sense that it was running, and it was never once out of my mind: a closed lid, a dropped connection, a roommate moving it, an update deciding two in the morning was a good time to restart. A trading loop that stops halfway through a position is worse than one that never started. So it moved onto an AWS box — the smallest Lightsail instance there is, in Ohio because that is the region nearest the exchange, with a static IP, the firewall cut back to SSH from my own address, and the runner registered as a systemd service so a reboot brings it back without me. The dashboard is reached over Tailscale rather than through an open port, which means I can look at it from my phone without the internet being able to. What stayed on my laptop is everything heavy: the years of one-minute bars, the backtests, the optimisation runs. Those want a real machine for an hour at a time and they want it for free, and the box only has to hold one live loop and one broker connection, which is why it costs what it costs. I set out to buy peace of mind and came away having learned AWS properly, which was the better half of the trade.

Starting again in Python
The first version of all of this was TypeScript from end to end, written with another developer I was working with at the time. Then I stepped away from it for a while, and when I came back I was on my own and had to read it as a stranger would. Rewriting the backend in Python was the decision I put off longest and should have made first. It is not that the language is better. It is that every library this problem needs already exists there — pandas and NumPy and Parquet, the broker and data vendor SDKs, the statistics — and, more than that, so does everything anyone has written about the problem. Every paper, every notebook, every answer to the exact question I was stuck on, all in Python. The interface stayed TypeScript, where it is the right tool and where React and a charting library do in an afternoon what would otherwise take a week. What the split bought was speed: an idea now goes from a sentence to a tested result in a fraction of what it used to take, and the honest part of that figure is not the language, it is that rewriting the thing alone was how I finally understood every piece of it.

It had to be able to tell me what it was doing
The system runs on a machine I never look at, which is the whole point of the machine and also the problem with it. A log file you have to go and open is a log file you do not open. So every entry and every exit posts to a Discord channel the moment it happens: the instrument, the side, the size, the price it went in at, and the stop and the target it is going to be judged against — then, at the other end, where it actually closed, in dollars and in points, with the account value and the strategy's running total underneath. The line I read first is the mode, because it says which account this was, a test run or a paper account or a prop firm evaluation, and a message that does not say that is a message you can misread badly. Two rules hold the whole thing up, and both of them are about the trading loop rather than about the messages: the notifier can never raise, because a listener that throws gets dropped and the alerts would go quiet without telling me, and the post is fire and forget, because a webhook having a slow afternoon must not be able to stall a bar. What it changed most is how I find bugs. Exits recorded at the entry price, a position the venue had already closed that the runner still thought was open — those are a fortnight of not noticing in a log, and about four seconds of noticing on a phone.

Impact
All three of those are mine rather than anybody's measurement, and the third is the softest: nothing is monitoring the box but me, so read the uptime as an impression rather than a reading. The zero is real and slightly misleading — the backtests run on a laptop I already owned, and the instance that runs live is the smallest one AWS sells, which is enough for one strategy loop and one broker connection and not much else. The 62% is measured against my own habit, an idea to a tested result, before and after the framework existed. What I have deliberately not put here is a return. Every account value on this page is simulated — practice accounts and prop firm evaluations, not a dollar of it real — the system has been running on them for months rather than years, and quoting a P&L off that would be the same mistake I started out making: taking a number that came out well as evidence that the method was sound.
Reflections
The thing I actually learned is that a backtest will tell you whatever you want to hear. My first genuinely exciting results were the ones I had fitted, and I could not see it, because a curve that goes up is very persuasive when you are the one who drew it. Most of the work since has gone into making the system harder to fool than I am: walk-forward rather than one optimisation over the whole history, Monte Carlo and permutation tests to ask whether the result survives its own trades being shuffled, a regime gate so a strategy only trades in the conditions it was actually good in. Nearly everything that passes those is boring, and nearly everything that looked brilliant does not pass them. That is the useful finding.
What is next is the part I have been putting off, which is real money at a size where being wrong is unpleasant. Paper accounts fill in ways real ones do not, and I know that a fill I never had to pay for is worth less as evidence than I want it to be. The thing I would do differently is the language, and not for the reason it sounds like: the mistake was not picking TypeScript, it was picking what I was already comfortable with instead of spending an afternoon finding out what everyone solving this problem was using and why. That afternoon would have saved a year.