<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bot and Bull</title>
    <description>The latest articles on DEV Community by Bot and Bull (@botandbull).</description>
    <link>https://dev.to/botandbull</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4133644%2F62fe530e-18f8-4209-a2a0-d329ad7f24f3.png</url>
      <title>DEV Community: Bot and Bull</title>
      <link>https://dev.to/botandbull</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/botandbull"/>
    <language>en</language>
    <item>
      <title>The Bug That Passed Every Test and Still Lost Me Money</title>
      <dc:creator>Bot and Bull</dc:creator>
      <pubDate>Sun, 20 Sep 2026 04:46:31 +0000</pubDate>
      <link>https://dev.to/botandbull/the-bug-that-passed-every-test-and-still-lost-me-money-1gl5</link>
      <guid>https://dev.to/botandbull/the-bug-that-passed-every-test-and-still-lost-me-money-1gl5</guid>
      <description>&lt;p&gt;I am building an automated stock trading bot in public. I am not a developer by trade, so I lean hard on tests to feel safe shipping. Which is exactly why this one stung: a bug that passed every single test I had, and still lost me money the moment it touched the real market.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The suite was green, so I trusted it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every test passed. I deployed. That green checkmark felt like permission.&lt;/p&gt;

&lt;p&gt;The problem was hiding in plain sight: my tests fed the bot clean, well behaved data that I made up myself. The code did exactly what I told it to do. My tests just never told it to handle the real world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually happened&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bot runs a routine at the end of the trading day. My tests used fixed timestamps, so timing itself was never really under test.&lt;/p&gt;

&lt;p&gt;Live, the server ran on UTC while the market runs on Eastern time. The end of day routine fired before the session's data was actually final, so the bot made decisions on half baked numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# what I had (naive)
&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# server's timezone, not the market's
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="c1"&gt;# "after close"... in the wrong timezone
&lt;/span&gt;    &lt;span class="nf"&gt;run_end_of_day&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looked correct. It passed. It was wrong about the one thing that mattered: which clock the market actually runs on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the tests missed it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unit tests prove your code does what you told it to do. They do not prove your assumptions about the outside world are right.&lt;/p&gt;

&lt;p&gt;I had tested the logic and skipped the environment. Market hours, timezones, holidays, missing data, none of it was in my tests, because I was hand feeding the inputs. A green suite told me my code was consistent. It said nothing about whether it was correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I changed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tests now use messy, realistic data: wrong timezones, missing bars, holidays, odd prices.&lt;br&gt;
Anything time related is explicit and timezone aware. No more datetime.now() and a hopeful guess.&lt;br&gt;
New rule: nothing goes live until it has survived small, real stakes, not just the test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A green test suite means your code is consistent, not that it is correct. For anything that touches the real world, and money most of all, test the world, not just the function.&lt;/p&gt;

&lt;p&gt;I am documenting this whole build in public, including the &lt;a href="https://botandbull.com/tools-i-recommend/" rel="noopener noreferrer"&gt;tools I recommend&lt;/a&gt; to run it and the bruises like this one. If you want to follow along, everything lives at &lt;a href="https://botandbull.com" rel="noopener noreferrer"&gt;Bot and Bull&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is education, not financial advice.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>beginners</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
