Last Updated 09/20/26
Table of Contents
There is a version of this story where I tell you I built a trading bot, made none of the classic trading bot mistakes, and now I’m printing money. That would be a much shorter post, and it would be a lie. This is the other version. The one where things broke in ways I didn’t expect, at times I definitely didn’t want, and where I learned more from the failures than from anything that went right.
This is Part 1 of what I already suspect will be a long series, because the failures have not stopped coming. They have just gotten more interesting.
Before I get into the specific mistakes, one thing worth saying up front. None of these were dramatic. Nothing caught fire. There was no single catastrophic loss that wiped me out. That is exactly why they are worth writing about. The trading bot mistakes that hurt you are almost never the loud, obvious ones you brace for. They are the quiet structural gaps that sit in your system looking perfectly fine until the one moment they decide not to be fine anymore. Every story below is a version of that same shape: something I thought was handled, that turned out not to be, discovered only because I was watching closely enough to notice.
Let me walk you through the first four.
The Bot Was Live. The Protection Wasn’t.
When you run an automated trading system, you think about entries. You think about scoring, signals, when to buy. You spend almost all of your design energy on the moment of getting in, because that is the part that feels like the strategy. What I didn’t think hard enough about, at least not at first, was what happens to open positions after the market closes and everyone goes home.
My stop updater ran during regular market hours. Every few minutes it would check each position, compare the current price to its stop level, and adjust if the math called for it. Clean, automated, exactly what I designed it to do. During the trading day, my positions were watched, managed, and protected. I felt good about it.
What I hadn’t fully built out was what happens between 4 PM and 9:30 AM the next morning. The answer, for an uncomfortable while, was nothing. Positions sat overnight with stops that couldn’t be actively monitored. If something moved against me in extended hours, an earnings surprise, a news event, a sudden gap on some headline, there was no system watching it. The stops existed, resting as open orders, but nobody was home to react if the situation changed faster than a resting order could handle. The protection was technically present and functionally asleep.
Here is the part that makes it a real lesson and not just a to-do item I forgot. The system did not feel broken. Every day it ran, managed positions beautifully during market hours, and clocked out. From the outside it looked complete. The gap only existed in the hours when I wasn’t looking at it, which is precisely why it took me a while to see it at all. You do not go hunting for a hole in the part of the system that appears to be working.
The fix was building an entirely separate component, a night guard, that picks up exactly where the stop updater leaves off. Regular hours end, the night guard activates. Extended hours end, it goes quiet. The handoff is clean now, one component awake at all times, no window where the account is unwatched. But getting there required first realizing the gap existed, which only happened because I was paying close attention to what the system was and wasn’t doing at every hour of the day. That is trading bot mistake number one, at least for this article.
Lesson: Automation doesn’t protect you from the gaps in your automation. It only protects you inside the exact boundaries you drew, and it will never tell you where you forgot to draw them.
The Day the Scores Tied
Here’s a thing that can happen when you’re scoring stocks with a multi-factor model. Every single candidate can end up with the exact same score.
That’s what I woke up to one morning. The system ran, produced its ranked list, and the top twenty names were all tied. Not similar scores, not clustered closely, identical. And because there was nothing to sort by, the list had quietly fallen back to alphabetical order. The model had stopped discriminating between good setups and bad ones, and in the absence of any real signal it was handing me the alphabet.
I won’t go into the mechanics of why it happened or how I fixed it, because that is the part of the machine that stays proprietary. But I’ll tell you exactly what it felt like, because the feeling is the useful part. It was unsettling in a very specific way, the kind that only comes from realizing your system has been confidently wrong in complete silence. It wasn’t crashing. It wasn’t throwing errors. It wasn’t giving me any signal at all that something was off. It was running perfectly and producing meaningless output, and it would have kept doing that indefinitely if I hadn’t happened to look at the actual list and notice the names were in alphabetical order.
Sit with that for a second, because it is the whole point. A crash is a gift. A crash tells you exactly where and when something went wrong and refuses to let you ignore it. This was the opposite. This was a system that had failed at its single most important job, ranking, while continuing to behave like everything was normal. The output was garbage dressed up as a decision.
I paused the live trading cron that day, rebuilt the relevant piece of the scoring logic, ran a dry test to confirm there was real spread in the results again, and then made the call to go live the same day, with one clean run of validation behind me and real money on the line. Not comfortable. Necessary. There is a version of me that would have sat out a week to feel safe, but sitting out has its own cost, and I judged one validated run to be enough. That is trading bot mistake number two.
Lesson: A system that doesn’t fail loudly is harder to fix than one that crashes. Silence is not the same as correct, and a confident wrong answer is more dangerous than an obvious error.
The Data That Was Never There
For the first several weeks of live trading, I thought I was saving my data. I had a file that logged every buy. Symbol, price, shares, the factors that drove the score. It felt like a record. It looked like a record. I would open it, see rows of trades, and feel like a responsible operator keeping good books.
What I eventually realized was that the file was being overwritten every single time the scanner ran. Not appended to. Overwritten. The previous run’s data simply ceased to exist the moment a new run completed. What I had was not a growing history. It was a single snapshot of the most recent run, wearing the costume of a logbook.
I discovered this at the worst possible time, which is of course the only time you ever discover things like this. It was the night I needed to go back and look at the exact factor breakdown for a specific buy, to understand why the system had bought what it bought. I went looking for the history, and the history was gone. Not corrupted, not misplaced, just gone, quietly replaced by that afternoon’s output days earlier. Every trade I might have wanted to study had been painted over the moment the next run finished.
That was the night I built a proper database. Every run now gets its own permanent row. Every scored candidate, every buy, every gate pass and gate failure, all of it written once and never touched again. Going back weeks to understand a trade, to see exactly what the system saw at the moment it made a decision, is now something I can actually do. Before that night, it was impossible, and I didn’t even know it was impossible, which is the worse of the two problems. That is trading bot mistake number three.
Lesson: “Saving data” and “having a durable record” are not the same thing. A file you can open is not automatically a history you can trust. Know the difference before the night you need it, not during.
The Bug That Was One Word
The bot is designed to work through a ranked list of candidates and buy the best ones until it runs out of buying power. Start at the top, buy what it can afford, move down, keep going until the money is gone. Straightforward enough.
What it was actually doing, for longer than I’d like to admit, was stopping entirely the moment it hit a candidate it couldn’t afford. Not skipping that name and moving to the next one. Stopping. Full stop, done for the run. Which meant that if the single most expensive stock happened to land at the top of the ranked list, the bot would look at it, decide it couldn’t afford it, and then buy nothing at all that day, regardless of how many perfectly affordable candidates were sitting right below it.
The fix was a single word in the code. One word, in the right place, and the behavior changed completely, from “stop at the first thing you can’t afford” to “skip it and keep going.” That is the entire difference between a bot that deploys your capital and a bot that occasionally just sits there holding it.
But finding that one word was not quick. Nothing about the system announced the problem. There was no error, no crash, no red flag. There was just a day where I looked at what had been bought, felt that something was subtly off about it, and started pulling the thread. It took looking at a real trade, noticing the shape of the decision was wrong, and tracing the logic backward until the word finally revealed itself. That is trading bot mistake number four. Ughhh.
Lesson: The smallest bugs sometimes have the biggest behavioral consequences. Read the code like it means exactly what it says, because it does, and it will happily do exactly the wrong thing forever without ever raising its voice.
What These Four Mistakes Have in Common
Look back at the four stories and you’ll notice they are not really four different problems. They are the same problem wearing four different costumes.
The overnight gap looked fine because it only failed when I wasn’t watching. The tied scores looked fine because the system kept running while producing nonsense. The overwritten data looked fine because there was a file sitting right there. The one-word bug looked fine because nothing ever errored out. In every case the system presented a confident, healthy-looking face while something underneath it was quietly not working. Not one of these announced itself. Every single one had to be noticed.
That is the real lesson hiding behind all four, and it is the thing I wish someone had told me before I started. When you build software that runs on its own, your biggest enemy is not the error that stops everything. You will find that one. It stops everything. Your biggest enemy is the failure that lets the system keep running while doing the wrong thing, because that one can operate for days or weeks inside the appearance of normal, and the only thing standing between you and it is how closely you are actually looking.
Automated does not mean unattended. I learned that the boring way, four times in a row.
There is a second thread running through all of them too, and it is about attention. Every one of these got caught for the same reason: I was looking. Not at a dashboard that summarized things for me, but at the raw output, the actual trades, the real rows in the real file. The overnight gap turned up because I asked myself what the system was doing at 2 AM. The tied scores turned up because I read the actual ranked list instead of trusting that a list existed. The overwritten data turned up because I went looking for history and found none. The one-word bug turned up because a single real trade looked wrong to me. None of these came from an alert. They came from paying attention to the ground truth, on purpose, when nothing was demanding it. That habit is not glamorous and it does not scale beautifully, but in the early life of a system it is the only thing standing between you and a quiet failure that has been running for a month.
What I’d Tell You If You’re Building Your First Bot
If you are standing at the start of this, excited about the strategy and ready to let a machine run it for you, here is what I wish someone had grabbed me by the collar and said. It is the same thing I get into more deeply in what I’d do differently if I started over, but the short version fits here.
Watch the boring parts. The strategy is the fun part, the part you’ll want to obsess over, and it matters far less to your survival than the plumbing does. The overnight handoff, the logging, the way the code behaves when it hits an edge it wasn’t expecting. That is the stuff that actually keeps you in the game long enough for the strategy to matter.
Assume your system is lying to you until you’ve checked. Not maliciously, just by omission. A running process is not proof of a working process. A file is not proof of a record. A ranked list is not proof of real ranking. Build the habit of looking at the actual output, the real trades, the actual rows, rather than trusting that because nothing errored, everything is fine.
And keep a record you can go back to. Almost every one of these mistakes got easier to fix the moment I could look at exactly what the system did and when. The database was not a glamorous project. It is the single thing that has saved me the most pain since. The tools I lean on for the boring reliability side are the ones I keep on my tools I recommend page, and they earn their place there precisely because they make this part less painful.
This Is What Trading Bot Mistakes Actually Look Like
None of these stories are the ones I planned to write when I started this project. I planned to write about strategy and signals and the theory behind the approach, and I will. That content is coming. But the trading bot mistakes are real, and I think they are far more useful to anyone building something similar than a polished, everything-went-great version of events would ever be. Every one of these failures made the system more reliable. Every one of them was invisible until it wasn’t.
If you’ve been following along from the beginning, you already know what I’d do differently if I started over. This post is the companion to that one, the specific moments where the gap between what I planned and what actually happened showed up and forced a fix.
Part 2 is live now, and it is the one I was most nervous to publish. It involves a rate limit, a shared authentication token, and ten open positions that briefly had no protection at all. If these four mistakes were papercuts, that one was a longer, worse day, and you can read the whole thing in Trading Bot Errors Nobody Warns You About (Part 2).
If you’re building something like this and you haven’t hit your first major unexpected failure yet, you will. The goal was never to avoid them. It’s to catch them fast, fix them cleanly, and walk away knowing what to watch for next time. That is the whole job, and honestly, it’s most of the fun.
Steve is the founder of Bot and Bull. He reviews and evaluates the tools featured on this site and only recommends what he genuinely believes in. No press releases, no paid placements.
Found Bot and Bull useful? A quick review helps others decide whether this site is worth their time, and it takes about a minute. Review us on SmartCustomer →
Disclaimer: Everything in this post is shared for educational and informational purposes only and is not financial, investment, or trading advice. I am not a licensed financial advisor, broker, or tax professional. Automated trading carries real risk, including the possible loss of your capital, and the tools or platforms mentioned may not be suitable for your situation. Do your own research, and consider speaking with a licensed professional, before making any financial decision.