<?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: Aurora Systems</title>
    <description>The latest articles on DEV Community by Aurora Systems (@aurora_systems).</description>
    <link>https://dev.to/aurora_systems</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%2F4021491%2F707c6b9b-0bdc-4c13-844c-a446cd9ad424.png</url>
      <title>DEV Community: Aurora Systems</title>
      <link>https://dev.to/aurora_systems</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aurora_systems"/>
    <language>en</language>
    <item>
      <title>Your Trading Bot's Backtest Is Lying to You - Here Are the 4 Ways</title>
      <dc:creator>Aurora Systems</dc:creator>
      <pubDate>Sat, 11 Jul 2026 09:40:11 +0000</pubDate>
      <link>https://dev.to/aurora_systems/your-trading-bots-backtest-is-lying-to-you-here-are-the-4-ways-5044</link>
      <guid>https://dev.to/aurora_systems/your-trading-bots-backtest-is-lying-to-you-here-are-the-4-ways-5044</guid>
      <description>&lt;p&gt;A strategy I once tested quoted &lt;strong&gt;+740%&lt;/strong&gt; in the backtest. When it actually traded, it made about &lt;strong&gt;$2.81&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That gap - between what a backtest promises and what a live market pays - is where most trading bots quietly die. I've spent three years building bots in Python, and the most valuable thing I've learned isn't a strategy. It's that a backtest is the easiest thing in the world to rig in your own favor, usually by accident.&lt;/p&gt;

&lt;p&gt;Here are the four ways it lies, each with a real number from my own testing, and how to catch each one before it costs you money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The baseline: an honest test of the "hello world" strategy
&lt;/h2&gt;

&lt;p&gt;First, a calibration. The classic moving-average crossover - SMA(9/21), the strategy every tutorial starts with - backtested honestly on 1,000 hours of real BTC/USDT, with decisions using only past, closed bars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No fees: &lt;strong&gt;-6.3%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;With a realistic 0.1% fee per trade: &lt;strong&gt;-11.3%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Buy &amp;amp; hold over the same window: &lt;strong&gt;-21.4%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice two things. It loses &lt;em&gt;before&lt;/em&gt; a single fee. And it "beat buy &amp;amp; hold" while still losing money - those are not the same sentence, and any backtest report that only shows relative performance is already halfway to lying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #1: Lookahead - your strategy can see the future
&lt;/h2&gt;

&lt;p&gt;The most common bug, and it's usually one careless line:&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="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# WRONG - sees the whole series, including the future
&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;   &lt;span class="c1"&gt;# RIGHT - only the past, one bar at a time
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hand the strategy the entire price series instead of only the data up to the current bar, and every historical "decision" secretly knows how the story ends. The equity curve goes vertical. The returns are fiction. Subtler versions hide in feature scaling (normalizing by a series max that includes future data) and in fill assumptions (deciding at the close of a bar and getting filled at that same close).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to catch it:&lt;/strong&gt; run the backtest walk-forward - feed the strategy a growing window, never the whole series. And treat any curve that looks too smooth as a bug until proven otherwise. Real edges are messy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #2: Overfitting - you tuned until it looked perfect
&lt;/h2&gt;

&lt;p&gt;A real experiment from my logs. I grid-searched MA parameters on the first half of my data. The best combination returned &lt;strong&gt;+2.4%&lt;/strong&gt;. Then I ran those exact same parameters on the second half - data the search had never seen: &lt;strong&gt;-1.5%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The profit was a property of the search, not the market. Run enough parameter combinations against one slice of history and something will always look brilliant - you're not discovering an edge, you're memorizing noise. That green-in-sample, red-out-of-sample flip is the fingerprint of overfitting.&lt;/p&gt;

&lt;p&gt;I later re-ran this lesson at a bigger scale: parameters tuned on one half-year, validated on the next, then scored on a final unseen period across five coins. One of five survived. The other four evaporated exactly the way the +2.4% did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to catch it:&lt;/strong&gt; judge a strategy only on data it was never tuned on. Optimize on one slice, score on another. No exceptions, no peeking, no "just one more tweak" after seeing the holdout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #3: Ignored costs - you assume you trade for free at the price you see
&lt;/h2&gt;

&lt;p&gt;Fees alone nearly doubled the baseline loss above (-6.3% -&amp;gt; -11.3%). And fees are the &lt;em&gt;polite&lt;/em&gt; cost. Slippage is the rude one. Walking a market order through the real BTC order book:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$1,000: ~0.000% price impact&lt;/li&gt;
&lt;li&gt;$1,000,000: ~0.035%&lt;/li&gt;
&lt;li&gt;$10,000,000: ~0.132% - and it exhausts the entire visible book&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's on the deepest market in crypto. On a thin pair, the visible book collapses after the first few coins - which is exactly how a backtest can quote +740% on a freshly launched pool while the tradeable reality is about $2.81. The price you see is the price for the first few coins. Everything after that is slippage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to catch it:&lt;/strong&gt; model fees &lt;em&gt;and&lt;/em&gt; a slippage assumption from the very first backtest. The thinner the market and the bigger your size, the more the quote lies about the fill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #4: Survivorship - you only tested the winners
&lt;/h2&gt;

&lt;p&gt;Backtest "all coins" using today's coin list and you've silently deleted every project that went to zero and got delisted. Your universe is pre-filtered to survivors, so of course the results look great. The same trap hits stock strategies tested on the current index members - the companies that failed out of the index are exactly the ones your strategy would have bought on the way down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to catch it:&lt;/strong&gt; use data that includes the dead - delisted assets, failed projects, all of it. And be suspicious of any result that claims "tested on everything."&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest checklist
&lt;/h2&gt;

&lt;p&gt;Run this on every idea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Express it as "prices in -&amp;gt; signal out." If you can't, it isn't testable yet.&lt;/li&gt;
&lt;li&gt;Backtest with realistic fees and slippage from day one.&lt;/li&gt;
&lt;li&gt;Score it only on data it was never tuned on.&lt;/li&gt;
&lt;li&gt;Read absolute return &lt;em&gt;and&lt;/em&gt; max drawdown - "beat the market" while losing money is not a win.&lt;/li&gt;
&lt;li&gt;Distrust anything that looks great; hunt for the bug first.&lt;/li&gt;
&lt;li&gt;If it survives all that, paper-trade it on a testnet. For a long time.&lt;/li&gt;
&lt;li&gt;Size positions with a real risk layer and keep a kill-switch armed.&lt;/li&gt;
&lt;li&gt;Never run money you can't afford to lose to zero.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal was never to find a magic strategy. It's to build a backtester honest enough to kill your bad ideas cheaply - so the rare good one is the only thing left standing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write about the honest engineering behind trading bots - including the losing numbers. If this was useful:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;The full version is a book: &lt;a href="https://www.amazon.com/dp/B0H834V8L8" rel="noopener noreferrer"&gt;Backtests Lie&lt;/a&gt; - why most bots lose, and what building one really teaches you.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Free companion guide (PDF): &lt;a href="https://easytradingalgorithm.gumroad.com/l/onwouv" rel="noopener noreferrer"&gt;The 4 Ways Your Backtest Is Lying To You&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Day-to-day notes on X: &lt;a href="https://x.com/AuroraSystemsX" rel="noopener noreferrer"&gt;@AuroraSystemsX&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Educational only. Not financial advice. Trading carries real risk, including total loss.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algorithms</category>
      <category>tutorial</category>
      <category>finance</category>
    </item>
  </channel>
</rss>
