<?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 LAB</title>
    <description>The latest articles on DEV Community by Bot LAB (@botlab).</description>
    <link>https://dev.to/botlab</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%2F4176924%2Ff768f56f-00fb-4d05-983e-d608497a0de5.png</url>
      <title>DEV Community: Bot LAB</title>
      <link>https://dev.to/botlab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/botlab"/>
    <language>en</language>
    <item>
      <title>How to Detect Look-Ahead Bias in Your Own Backtest</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Wed, 14 Oct 2026 04:06:23 +0000</pubDate>
      <link>https://dev.to/botlab/how-to-detect-look-ahead-bias-in-your-own-backtest-4dd9</link>
      <guid>https://dev.to/botlab/how-to-detect-look-ahead-bias-in-your-own-backtest-4dd9</guid>
      <description>&lt;p&gt;Look-ahead bias is the failure where your backtest uses information that did not exist yet at the moment it made a decision. You detect it mechanically, not by reading your code: compute your indicator twice — once over the full price history the way a vectorised backtest does, and once bar by bar on history truncated at that bar the way a live bot sees it — then compare the two values at the same bar. If they differ anywhere, something in your pipeline peeked at the future. That is the whole method, and it takes about ten lines.&lt;/p&gt;

&lt;p&gt;This matters because look-ahead is the one backtest failure that never announces itself. Overfitting at least leaves a trail: good in-sample, bad out-of-sample. A leak looks like skill in every period, including your out-of-sample window, because the leak travels with the data. Reading the code does not reliably catch it either — the leak is usually not in a line that says &lt;code&gt;shift(-1)&lt;/code&gt;. It is in a &lt;code&gt;.mean()&lt;/code&gt; over a whole column, a resample that joins a daily close onto hourly bars, a &lt;code&gt;center=True&lt;/code&gt; you typed six months ago, or a gap-filling call that borrows the next bar's price.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test
&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;python full = signal(df)                  # vectorised, whole file for i in sampled_bars: inc = signal(df.iloc[:i+1])    # only data up to and including bar i assert full[i] == inc[-1]      # any difference = look-ahead&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Two details make it honest. First, truncate at the &lt;strong&gt;bar&lt;/strong&gt;, not at the row index of some already-merged frame — if your feature table was built by joining timeframes, rebuild the join inside the truncated call. Second, sample bars from across the whole history, not just the end; some leaks only fire where the data has gaps, or where a higher-timeframe boundary falls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like on real data
&lt;/h2&gt;

&lt;p&gt;We ran this on 3,000 closed BTCUSDT 1-hour candles from Bybit (2026-06-11 03:00 UTC to 2026-10-14 02:00 UTC), auditing 120 randomly sampled bars with &lt;code&gt;lookahead_analysis&lt;/code&gt; from our MIT-licensed library. Each row is a signal written the way people actually write signals.&lt;/p&gt;

&lt;p&gt;| Signal construction | Bars checked | Mismatches | Leaks? | |---|---|---|---| | EMA(20) over EMA(50) cross | 120 | 0 | no | | z-score vs trailing 200-bar mean/std | 120 | 0 | no | | &lt;code&gt;close.shift(-1) &amp;gt; close&lt;/code&gt; | 120 | 64 | yes | | Daily close joined onto 1h bars, not shifted | 120 | 57 | yes | | &lt;code&gt;rolling(21, center=True).mean()&lt;/code&gt; | 120 | 32 | yes | | Min-max normalised over the whole file | 120 | 31 | yes | | z-score vs full-sample mean/std | 120 | 4 | yes |&lt;/p&gt;

&lt;p&gt;Three things are worth reading off that table.&lt;/p&gt;

&lt;p&gt;The obvious bug (&lt;code&gt;shift(-1)&lt;/code&gt;) and the subtle one (a daily close joined onto hourly bars without shifting it forward) are equally fatal: 64 and 57 bad bars out of 120. The second is far more common in real code, because resampling and merging feels like data plumbing rather than a modelling decision.&lt;/p&gt;

&lt;p&gt;Normalisation is a leak. Min-max scaling over the whole file mismatched on 31 of 120 bars, because the minimum and maximum of a column are facts about the future. Anyone who has scaled features before splitting train and test has done this.&lt;/p&gt;

&lt;p&gt;A leak can be small and still be a leak. The full-sample z-score mismatched only 4 times in 120 bars — the mean and standard deviation of four months of hourly closes barely move when you add one more bar. It is still disqualifying: the value at bar &lt;em&gt;i&lt;/em&gt; depends on bars after &lt;em&gt;i&lt;/em&gt;, so the number your backtest traded on is a number your bot cannot compute.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boolean trap
&lt;/h2&gt;

&lt;p&gt;Here is the result that changed how we run this check. We took the same series with every seventh bar deleted, filled the holes with &lt;code&gt;bfill()&lt;/code&gt; — backward fill, which copies the &lt;em&gt;next&lt;/em&gt; available price into the gap — and computed an EMA(20) over it.&lt;/p&gt;

&lt;p&gt;| What we audited | Bars checked | Mismatches | |---|---|---| | The EMA value itself | 120 | 15 | | The boolean &lt;code&gt;close &amp;gt; EMA&lt;/code&gt; built from it | 120 | 0 |&lt;/p&gt;

&lt;p&gt;Same bug, same bars. Audit the final true/false signal and the test passes. Audit the number underneath and the leak is plainly there. A boolean is a lossy summary: a contaminated value has to cross a threshold before the comparison flips, so most of the corruption is invisible at the signal level — until a day when it is not. Audit every intermediate value you compute, not only the entry flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-timeframe and warm-up
&lt;/h2&gt;

&lt;p&gt;If your strategy reads a 4h or daily candle while deciding on a 1h bar, the rule is simple: every higher-timeframe row you touch must have &lt;strong&gt;closed&lt;/strong&gt; by the close of the bar you are evaluating. A partial candle is legal only if you build it yourself from lower-timeframe candles that have closed. Most exchange APIs return the currently-forming candle as the first element of the response, so this bug gets written by accident constantly. Our own fetch helper drops any candle whose close time is in the future, and the audit then checks the surviving rows against the decision timestamp.&lt;/p&gt;

&lt;p&gt;A related failure produces the same symptom — backtest results your bot cannot reproduce — without any future data at all. Long indicators depend on how much history you loaded. Computing EMA(200) on the real BTC series above with only 100 bars of warm-up, versus 1,000 bars, moved the value by a median of 0.48% and up to 2.18%. That sounds harmless until you look at the trend boolean it feeds: &lt;code&gt;close &amp;gt; EMA(200)&lt;/code&gt; flipped on 25% of the bars we evaluated (n = 20 evaluation bars, so treat the exact percentage as indicative, not precise). With 300 bars of warm-up the drift fell to 0.07% median and nothing flipped. Your backtest loads years of history; your live bot usually loads whatever its first API call returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a leak is worth
&lt;/h2&gt;

&lt;p&gt;To put a size on it, we ran one trading rule twice on the same 3,000 bars, with the same exits (stop at max(ATR14, 0.6%), target 1.5x the stop, 25-bar time stop) and the same cost assumption (0.055% taker fee per side, charged in R). The only difference is the entry condition: the second run compares the &lt;em&gt;next&lt;/em&gt; close to the current one.&lt;/p&gt;

&lt;p&gt;| Entry condition | Trades | Mean R | Win rate | Total R | |---|---|---|---|---| | EMA(20)/EMA(50) cross (clean) | 24 | +0.044R | 50.0% | +1.1R | | Next close &amp;gt; current close (leak) | 232 | +0.240R | 57.8% | +55.6R |&lt;/p&gt;

&lt;p&gt;One bar of hindsight turns a rule with no detectable edge into one that looks like a business. The trade counts differ — the leaky condition triggers far more often — so this is an illustration of magnitude, not a controlled comparison. The direction is the point: leaks do not nudge results, they manufacture them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this method does not prove
&lt;/h2&gt;

&lt;p&gt;A clean look-ahead audit is a licence to keep testing, nothing more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not prove your edge is real.&lt;/strong&gt; It proves only that your numbers were computable at the time. Overfitting, too few trades, concentration in two coins and ignored costs are separate failures with separate tests. For scale: across the 128 strategy books we track, as of 2026-10-14, &lt;strong&gt;zero&lt;/strong&gt; pass our six readiness gates — and almost all of them are look-ahead clean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It only covers the code you hand it.&lt;/strong&gt; If the leak lives in how your trade ledger was assembled, or in a cached feature file built earlier over the whole history, auditing the signal function will not see it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is a sampled test.&lt;/strong&gt; We checked 120 bars, not 3,000. Zero mismatches means "no leak at those bars", which is strong evidence, not proof. Increase the sample when a result looks surprisingly good.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your data vendor can leak.&lt;/strong&gt; Prices revised after the fact, timestamps labelled with a candle's close instead of its open, or funding rates stamped at the start of a settlement period rather than the end, will all pass a self-consistency check and still be wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing here says anything about fills.&lt;/strong&gt; A signal that was computable at 14:00 can still be impossible to fill at the price your backtest assumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this means for your own bot
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write a &lt;code&gt;signal(df) -&amp;gt; one value per bar&lt;/code&gt; function&lt;/strong&gt; with no hidden state and no reads outside &lt;code&gt;df&lt;/code&gt;. If you cannot, that is your first finding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the full-versus-truncated comparison on at least 100 bars&lt;/strong&gt; spread over your whole history. Any mismatch stops everything else until it is fixed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit values, not booleans.&lt;/strong&gt; Every indicator, every normalised feature, every merged higher-timeframe column — and the entry flag last.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grep for the usual suspects&lt;/strong&gt; as a second pass, never as the first: &lt;code&gt;shift(-&lt;/code&gt;, &lt;code&gt;center=True&lt;/code&gt;, &lt;code&gt;bfill&lt;/code&gt;, &lt;code&gt;backfill&lt;/code&gt;, &lt;code&gt;.interpolate()&lt;/code&gt;, &lt;code&gt;resample(...).last()&lt;/code&gt;, and any &lt;code&gt;.mean()&lt;/code&gt;, &lt;code&gt;.std()&lt;/code&gt;, &lt;code&gt;.min()&lt;/code&gt; or &lt;code&gt;.max()&lt;/code&gt; taken over a full column.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop unclosed candles at the source.&lt;/strong&gt; Timestamp every input with the moment it became available, and compare that timestamp to the decision time rather than trusting row order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix warm-up before comparing backtest to live.&lt;/strong&gt; Load the same amount of history live as your backtest effectively used, and measure the sensitivity rather than assuming it is small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-run the audit after every change to the feature pipeline.&lt;/strong&gt; Leaks arrive with refactors, not with new ideas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Python implementation of all of the above — the full-versus-truncated audit, the warm-up sensitivity test, the multi-timeframe closed-candle check, plus the cost model and the statistical gates we use on our own books — is MIT-licensed at &lt;a href="https://github.com/botlabtrade/botlab-oss" rel="noopener noreferrer"&gt;github.com/botlabtrade/botlab-oss&lt;/a&gt;. Install numpy and pandas, point it at your own data, and you get the same report we run on ours. If you would rather not install anything, there is a browser version of the checks at &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;botlab.org.uk/#tool&lt;/a&gt;, which runs locally on a CSV of your trades.&lt;/p&gt;

&lt;p&gt;This is educational material about testing methodology. Nothing here is financial advice, and no result above is a live trading record.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/how-to-detect-look-ahead-bias-in-your-own-backtest" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>NEAR Protocol Trading Bot: What to Test First</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Wed, 14 Oct 2026 04:06:22 +0000</pubDate>
      <link>https://dev.to/botlab/near-protocol-trading-bot-what-to-test-first-fdh</link>
      <guid>https://dev.to/botlab/near-protocol-trading-bot-what-to-test-first-fdh</guid>
      <description>&lt;p&gt;Before you point a trading bot at NEAR Protocol or any other coin that is trending right now, test four things first: real trading costs at today's spreads, a large enough sample of trades, how the strategy did on data it never saw, and how it behaves when the hype fades. A backtest that only looks good during a hot streak usually reflects the streak, not an edge.&lt;/p&gt;

&lt;p&gt;This guide shows how to run those checks step by step. It does not say anything about where NEAR's price is going, and it won't. The goal is to judge the bot, not the coin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why trending coins are a trap for backtests
&lt;/h2&gt;

&lt;p&gt;When a coin like NEAR Protocol, Injective or Optimism shows up on trending lists, three things usually change at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Volatility jumps.&lt;/strong&gt; Bigger candles mean bigger wins &lt;em&gt;and&lt;/em&gt; bigger losses per trade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume and attention change quickly.&lt;/strong&gt; Order books can look deep at one moment and thin the next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The recent past is unusual.&lt;/strong&gt; A bot tuned on the last few weeks is tuned to an unusual regime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A strategy that "would have made money" on a trending coin may only be showing that the coin moved a lot in one direction. That is market beta, not skill. A simple buy-and-hold over the same window would often show the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Count the trades before you look at returns
&lt;/h2&gt;

&lt;p&gt;The first number to check is not profit. It is the trade count.&lt;/p&gt;

&lt;p&gt;A trending window is often short, so a bot may only have taken 15–30 trades on it. With that few trades, one or two lucky outliers can create the whole result. We cover this in depth in &lt;a href="https://botlab.org.uk/learn/how-many-trades-does-a-backtest-need" rel="noopener noreferrer"&gt;How Many Trades Does a Backtest Need?&lt;/a&gt;. In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under ~30 trades: treat any result as anecdotal.&lt;/li&gt;
&lt;li&gt;30–100 trades: early signal at best, wide uncertainty.&lt;/li&gt;
&lt;li&gt;Several hundred trades across different market conditions: now you can start comparing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the coin doesn't have enough history for a meaningful sample, test the same rules across several similar coins and pool the results. If the rules only work on one hot coin, that is a warning sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Put realistic costs in first
&lt;/h2&gt;

&lt;p&gt;Costs decide whether a strategy survives, especially on fast timeframes. During a trend spike, two costs rise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spread and slippage.&lt;/strong&gt; Your fill price can be noticeably worse than the candle close your backtest assumed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Funding (for perpetual futures).&lt;/strong&gt; When a coin is crowded on one side, funding payments can become a real drag on positions held for hours or days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fees in USDT add up quickly on small accounts too. Always use your exchange's actual fee tier, and assume taker fees unless your bot genuinely posts limit orders that get filled. Our Lab News post &lt;a href="https://botlab.org.uk/news/13" rel="noopener noreferrer"&gt;Costs come first&lt;/a&gt; explains why we subtract costs before looking at anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Split the data and test out-of-sample
&lt;/h2&gt;

&lt;p&gt;Never judge a bot on the same data used to choose its settings. A basic honest setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In-sample (e.g. first 60–70% of the data):&lt;/strong&gt; pick parameters here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-sample (the remaining 30–40%):&lt;/strong&gt; run once, no tweaking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Walk-forward (better):&lt;/strong&gt; repeat the split on rolling windows, so every period gets tested on data the parameters never saw.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If performance collapses out-of-sample, the strategy was probably fitted to noise. The more parameter combinations you tried, the more likely the best one looks good by chance. That is what the &lt;a href="https://botlab.org.uk/learn/deflated-sharpe-ratio-explained" rel="noopener noreferrer"&gt;Deflated Sharpe Ratio&lt;/a&gt; is designed to correct for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Check the regime, not just the total
&lt;/h2&gt;

&lt;p&gt;Split results by market condition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trending up&lt;/li&gt;
&lt;li&gt;Trending down&lt;/li&gt;
&lt;li&gt;Sideways / choppy&lt;/li&gt;
&lt;li&gt;High-volatility spikes (the "trending coin" moments)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A trend-following bot will often look great in a strong move and bleed slowly in sideways markets. A mean-reversion bot often does the opposite. Neither is wrong, but you need to know which one you have, and what happens to it when the trending phase ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Look past win rate
&lt;/h2&gt;

&lt;p&gt;A high win rate can hide a bad bot if the few losses are large. A low win rate can be fine if winners are much bigger than losers. Look at these together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Profit factor&lt;/strong&gt; (gross wins ÷ gross losses, after costs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average win vs average loss&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max drawdown&lt;/strong&gt; and how long it took to recover&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Longest losing streak&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We compare the first two in &lt;a href="https://botlab.org.uk/learn/profit-factor-vs-win-rate-trading-bots" rel="noopener noreferrer"&gt;Profit Factor vs Win Rate for Trading Bots&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example (illustration only)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The numbers below are made up to show the method. They are not BOTLAB results and do not describe any real bot or coin.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine a 1-hour breakout bot backtested on a trending altcoin over six weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trades:&lt;/strong&gt; 60&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average gross result per trade:&lt;/strong&gt; +0.60%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now subtract realistic costs, assuming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fees: 0.06% per side → 0.12% round trip&lt;/li&gt;
&lt;li&gt;Slippage during volatile hours: 0.15% per side → 0.30% round trip&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total cost per trade:&lt;/strong&gt; 0.42%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Net per trade:&lt;/strong&gt; 0.60% − 0.42% = &lt;strong&gt;+0.18%&lt;/strong&gt;. Two-thirds of the apparent edge disappeared.&lt;/p&gt;

&lt;p&gt;Next, split the trades by time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First 40 trades (in-sample, during the strongest trend): +0.45% net per trade&lt;/li&gt;
&lt;li&gt;Last 20 trades (out-of-sample, after the trend cooled): −0.36% net per trade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "profitable" backtest was really one strong move. On data it hadn't seen, the bot lost money after costs. With only 20 out-of-sample trades, you can't even say confidently how bad it is. The honest conclusion: &lt;strong&gt;not proven, keep paper trading or drop it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Paper trade on live candles before any real money
&lt;/h2&gt;

&lt;p&gt;A backtest replays the past. Paper trading (simulated money, real market prices) runs the bot forward on candles it has never seen, with no chance of hindsight leaking in. It also exposes practical problems a backtest misses: delayed signals, missed fills, API errors and funding at the moment it actually applies.&lt;/p&gt;

&lt;p&gt;Our view is simple: &lt;a href="https://botlab.org.uk/news/14" rel="noopener noreferrer"&gt;every bot flies the simulator first&lt;/a&gt;. For a trending coin, paper trade long enough to see the trend end, not just while it's hot.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we judge bots at BOTLAB
&lt;/h2&gt;

&lt;p&gt;We run every bot through 6 statistical gates (G1–G6), defined on the site. A bot is only marked "ready for micro live" after passing all six.&lt;/p&gt;

&lt;p&gt;Passing the gates isn't the same as being proven. Of the 159 BOTLAB bots tracked when the site was last built (2026-10-14), 1 is marked ready for micro live, 1 is on watch and 157 are not ready. The one that passed, mr4h/long, has 80 paper trades from 2026-08-16 to 2026-10-13 (58 days) with a 73.8% win rate, and our own verdict is still "sample too small to conclude." Another bot, Atlas/ichimoku-4h, passed 4 of 6 gates over 229 paper trades (2026-08-08 to 2026-10-13) and is flagged as a suspected overfit. Those are paper trading results, and they don't predict future results.&lt;/p&gt;

&lt;p&gt;If you have your own bot's trade history, you can run it through the same kind of checks with the free tool: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick checklist before running a bot on a hot coin
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] At least several dozen trades, ideally hundreds across different conditions&lt;/li&gt;
&lt;li&gt;[ ] Fees, slippage and funding included at realistic levels&lt;/li&gt;
&lt;li&gt;[ ] Out-of-sample or walk-forward results reviewed, not just in-sample&lt;/li&gt;
&lt;li&gt;[ ] Results split by regime (trend, chop, spike)&lt;/li&gt;
&lt;li&gt;[ ] Profit factor, drawdown and losing streaks checked, not only win rate&lt;/li&gt;
&lt;li&gt;[ ] Paper traded on live candles, including after the trend cooled&lt;/li&gt;
&lt;li&gt;[ ] Exchange API key set to trade-only, withdrawals off, IP-restricted&lt;/li&gt;
&lt;li&gt;[ ] You've decided in advance the maximum loss you can accept, including losing all of it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is it a good idea to run a trading bot on a trending coin like NEAR Protocol?
&lt;/h3&gt;

&lt;p&gt;That depends on the bot, not the trend. A trending coin gives you a short, unusual sample with higher costs and sharper reversals. Test the rules out-of-sample and across several coins before trusting any result. This guide makes no prediction about NEAR or any other coin.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long should I backtest a bot on a new trending coin?
&lt;/h3&gt;

&lt;p&gt;Long enough to include more than one market regime and enough trades to be meaningful. If the coin's history is too short, test the same rules on similar coins with longer histories and pool the trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does my bot look profitable in the backtest but lose in paper trading?
&lt;/h3&gt;

&lt;p&gt;The most common reasons are underestimated costs (especially slippage in volatile hours), parameters fitted to the in-sample period, and a regime change after the backtest window. Paper trading on live candles is designed to catch exactly this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a high win rate mean the bot is safe?
&lt;/h3&gt;

&lt;p&gt;No. A high win rate with occasional large losses can still lose money overall and produce deep drawdowns. Check profit factor, average loss size and max drawdown alongside win rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Judge the bot, not the coin. Trending markets inflate backtests.&lt;/li&gt;
&lt;li&gt;Count trades first; small samples prove very little.&lt;/li&gt;
&lt;li&gt;Subtract fees, slippage and funding before reading any result.&lt;/li&gt;
&lt;li&gt;Only out-of-sample and forward (paper) results count as evidence.&lt;/li&gt;
&lt;li&gt;Even a bot that passes every gate can still have too small a sample to conclude anything.&lt;/li&gt;
&lt;li&gt;Use trade-only API keys with withdrawals off, and never risk money you can't afford to lose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/near-protocol-trading-bot-what-to-test" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Deflated Sharpe Ratio Explained: Why Your Backtest Looks Better Than It Is</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Mon, 12 Oct 2026 16:06:37 +0000</pubDate>
      <link>https://dev.to/botlab/deflated-sharpe-ratio-explained-why-your-backtest-looks-better-than-it-is-480c</link>
      <guid>https://dev.to/botlab/deflated-sharpe-ratio-explained-why-your-backtest-looks-better-than-it-is-480c</guid>
      <description>&lt;p&gt;A Sharpe ratio tells you how much return a strategy produced per unit of wobble. The Deflated Sharpe Ratio asks a harder question: given how many versions of this strategy you tried before picking this one, how impressive is that number really?&lt;/p&gt;

&lt;p&gt;The gap between the two is where most backtests quietly die. This guide explains what the deflation does, how to compute it, and what number you should expect your own bot to produce.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem in one example
&lt;/h2&gt;

&lt;p&gt;Take a strategy with no edge at all. Now test 50 variants of it: different moving-average lengths, different stop distances, different hours of the day. Keep the best one.&lt;/p&gt;

&lt;p&gt;That winner will have a good-looking equity curve and a respectable Sharpe ratio. Not because it works, but because you ran 50 lotteries and kept the winning ticket. The ordinary Sharpe ratio has no way of knowing this happened. It sees one strategy and one track record, and it answers the question you asked rather than the question you should have asked.&lt;/p&gt;

&lt;p&gt;The Probabilistic Sharpe Ratio (PSR) and the Deflated Sharpe Ratio (DSR), both from work by Marcos López de Prado and David Bailey, close that hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  PSR: is this Sharpe ratio distinguishable from zero?
&lt;/h2&gt;

&lt;p&gt;PSR(0) is the probability that a strategy's true Sharpe ratio is above zero, given the Sharpe you observed, the number of observations, and the shape of the return distribution.&lt;/p&gt;

&lt;p&gt;It rises with sample size, and it falls when returns are negatively skewed or have fat tails — which is exactly the profile of a strategy that wins small and often and then loses big. Two bots can show the same Sharpe ratio and have very different PSR values if one of them earned it over 1,000 trades and the other over 60, or if one of them has a hidden tail.&lt;/p&gt;

&lt;p&gt;A common working threshold is &lt;strong&gt;PSR(0) ≥ 0.95&lt;/strong&gt;: at least a 95% probability the true Sharpe is positive.&lt;/p&gt;

&lt;h2&gt;
  
  
  DSR: the same question, after counting your attempts
&lt;/h2&gt;

&lt;p&gt;DSR takes PSR and deflates the benchmark it is measured against. Instead of asking whether the Sharpe beats zero, it asks whether the Sharpe beats &lt;strong&gt;the Sharpe you would expect the best of N trials to produce by pure chance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That expected maximum grows with the number of trials, and it grows faster than people's intuition. The intuition to carry around is the one from order statistics: the expected largest value from N independent standard-normal draws rises roughly with the square root of twice the natural log of N. Sixty trials put the bar near 2.9 standard deviations; a thousand trials push it past 3.7. The number of attempts is not a footnote to the result. It is part of the result.&lt;/p&gt;

&lt;p&gt;Two things follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DSR is always lower than PSR&lt;/strong&gt;, and the gap widens with every variant you try.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A strategy can have PSR(0) = 0.99 and DSR = 0.30 at the same time.&lt;/strong&gt; That combination is the signature of overfitting, and it is the single most informative pair of numbers you can compute about a backtest.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What counts as a trial
&lt;/h2&gt;

&lt;p&gt;This is where almost everyone under-counts. A trial is &lt;strong&gt;any variant you looked at and could have chosen&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every parameter combination in a grid search, not just the ones you wrote down;&lt;/li&gt;
&lt;li&gt;every entry filter you added and then removed because it did not help;&lt;/li&gt;
&lt;li&gt;every coin universe you tried;&lt;/li&gt;
&lt;li&gt;every version of the strategy from earlier sessions, if the current version descends from it;&lt;/li&gt;
&lt;li&gt;every timeframe you tested before settling on the one you kept.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you ran a 10 by 10 grid, that is 100 trials, not 1. If you then added a filter and ran it again, that is 200. The honest number is almost always larger than the number you remember, and the correct response to uncertainty is to use the larger estimate. Deflating by too many trials makes you slow. Deflating by too few makes you confident about noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  A worked comparison
&lt;/h2&gt;

&lt;p&gt;Two of our own demonstration strategies, both audited the same way:&lt;/p&gt;

&lt;p&gt;| | Honest trend-follower | Curve-fitted variant | |---|---|---| | What it is | EMA crossover with a band, past bars only | the best of 50 variants: a crossover that only trades on two weekdays, at one hour, held for exactly 36 bars | | Variants tried | 3 | 50 | | PSR(0) | 0.95 | 0.98 | | DSR | 0.74 | 0.39 | | Verdict | not yet enough evidence | not ready, and the gap says why |&lt;/p&gt;

&lt;p&gt;The curve-fitted one has the &lt;strong&gt;better&lt;/strong&gt; ordinary statistics. It is the one you would pick if you only looked at PSR, or at the equity curve, or at the win rate. Its DSR is what gives it away: once the 50 attempts behind it are priced in, most of its apparent edge is explained by having tried 50 times.&lt;/p&gt;

&lt;p&gt;Note also that the honest strategy does not pass either. That is normal and it is the point. A real edge usually needs more trades before it can be told apart from luck, and "not yet" is a legitimate verdict.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use these numbers in practice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write down your trial count before you compute anything.&lt;/strong&gt; Deciding it afterwards, when you can see which number you need, is how the count ends up at 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report PSR and DSR together.&lt;/strong&gt; PSR alone flatters. DSR alone hides whether the problem is sample size or selection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set the bar in advance.&lt;/strong&gt; Ours: PSR(0) ≥ 0.95 and DSR ≥ 0.5, alongside a minimum trade count, a recency check, concentration limits and a drawdown limit. Six fixed gates, decided before the result is known.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expect to fail.&lt;/strong&gt; Across the hundred strategy books we track, mostly paper, none currently passes all six gates at our 300-trade floor. That is the honest base rate, and a tool that frequently tells you yes is not measuring anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What these statistics cannot do
&lt;/h2&gt;

&lt;p&gt;DSR works on your list of trades. It cannot see your code. So it will not catch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;look-ahead bias&lt;/strong&gt;, where the backtest used information that did not exist yet — that needs a separate audit that recomputes the signal on truncated history and checks it does not change;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;wrong cost assumptions&lt;/strong&gt; — if your R values were computed with optimistic fees, every statistic downstream inherits the optimism;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;a backtest that never could have been filled&lt;/strong&gt; at the prices it assumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get the trades right first. Then deflate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compute it on your own trades
&lt;/h2&gt;

&lt;p&gt;The implementation we use — PSR, DSR, minimum track record length, the six gates, the cost model and the look-ahead audit — is MIT-licensed Python at &lt;a href="https://github.com/botlabtrade/botlab-oss" rel="noopener noreferrer"&gt;github.com/botlabtrade/botlab-oss&lt;/a&gt;. There is also a &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;checker that runs in your browser&lt;/a&gt;: paste a CSV of closed trades, enter how many variants you tried, and read the six gates with your own numbers. Nothing is uploaded.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/deflated-sharpe-ratio-explained" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>statistics</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Do Funding Rate and Open Interest Filters Improve a Crypto Bot?</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Mon, 12 Oct 2026 16:06:35 +0000</pubDate>
      <link>https://dev.to/botlab/do-funding-rate-and-open-interest-filters-improve-a-crypto-bot-1h1c</link>
      <guid>https://dev.to/botlab/do-funding-rate-and-open-interest-filters-improve-a-crypto-bot-1h1c</guid>
      <description>&lt;p&gt;Exchange data is sold as the missing ingredient for crypto bots. Funding rate, open interest, the long/short account ratio, the perp premium: add one as an entry filter, the pitch goes, and your signal starts skipping the bad trades.&lt;/p&gt;

&lt;p&gt;We tested that claim properly and the answer was mostly no. Out of 60 filter-and-dataset combinations, one cleared the bar that separates a real effect from the best of sixty coin flips. This guide shows the test, the numbers, and the reason the result is so one-sided.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we tested
&lt;/h2&gt;

&lt;p&gt;Five trade lists, all on 15 USDT perpetual contracts on Bybit:&lt;/p&gt;

&lt;p&gt;| Dataset | What it is | Trades | Baseline mean R per trade | |---|---|---|---| | 15m | a 20-indicator voting scalp signal | 113,013 | -0.188R | | 30m | the same signal on 30-minute bars | 62,585 | -0.151R | | 4h (all) | a 4-hour mean-reversion bot's full ledger | 6,159 | -0.111R | | 4h (subset) | the part that bot actually trades | 424 | +0.101R | | 1D | a Donchian-20 daily breakout, 2 ATR stop | 886 | +0.205R |&lt;/p&gt;

&lt;p&gt;R is the result of a trade measured in units of its own risk: risk 1% of the account, make 2%, that is +2R. Every R above is &lt;strong&gt;after costs&lt;/strong&gt; — taker fee 0.055% per side, slippage measured by walking a real order book for the trade size, and average funding multiplied by holding time.&lt;/p&gt;

&lt;p&gt;Twelve filters, each with fixed rules taken from tools that already existed, nothing tuned for this test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price and trend:&lt;/strong&gt; BTC daily regime against its 200-day EMA, multi-timeframe EMA agreement on 4h, the Ichimoku cloud, Supertrend, ADX between 20 and 35, position in the 20-day Donchian range, Choppiness below 55.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exchange data:&lt;/strong&gt; funding not crowded on our side of the trade, open interest rising with price over 24 hours, no open-interest spike above 8% in 4 hours, the long/short account ratio contrarian against its 30-day median, the perp premium contrarian against its 7-day mean.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How we avoided fooling ourselves
&lt;/h2&gt;

&lt;p&gt;Three decisions did most of the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every data point carries the moment it became knowable.&lt;/strong&gt; Funding is stamped at its settlement time, open interest and the long/short ratio at the end of their hour, candle-derived values at candle close. A trade may only read rows that were available strictly before its entry. We re-checked a random sample of 48 trades against the live exchange API and they matched. Without this rule, a filter that quietly reads the current hour's open interest will look brilliant and be worthless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The split is by time, not at random.&lt;/strong&gt; The oldest 60% of entries are the training period, the newest 40% the test period. A filter counts as helping only if the trades it agrees with beat the baseline in &lt;strong&gt;both&lt;/strong&gt; periods, with at least 30 agreeing trades in each. Random splits leak: a trade from June sitting in training while its neighbour from the same June afternoon sits in test is not an out-of-sample test of anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We counted our own attempts.&lt;/strong&gt; Twelve filters across five datasets is 60 trials. If all 60 were pure noise, the largest t-statistic you would expect to see by chance is roughly the square root of twice the natural log of 60, about &lt;strong&gt;2.86&lt;/strong&gt;. That is the bar. A filter scoring t = 2.0 in a 60-trial study has not found anything; it is simply the luckiest of sixty.&lt;/p&gt;

&lt;p&gt;Because trades opened on the same day share the same market, we also computed a daily-clustered statistic: the average of each day's agree-minus-disagree difference, rather than treating every trade as independent. This matters more than most people expect. A filter that tags 400 trades across 30 days has roughly 30 independent observations, not 400.&lt;/p&gt;

&lt;h2&gt;
  
  
  What came back
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One combination cleared 2.86.&lt;/strong&gt; Multi-timeframe EMA agreement on the 4-hour bot: both the fast pair and the slow pair pointing the same way as the trade. It helped in training, it helped in test, and it cleared the noise bar. Everything else either failed one period, or beat the baseline by less than the study's own luck threshold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The funding and open-interest guardrails almost never disagree.&lt;/strong&gt; Across all ten cells where they applied, they agreed with 84% to 100% of trades, and in six of those ten they were effectively constant — they say "fine, go ahead" nearly every time. That is a useful property for a risk check, which should only ever stop you in a genuinely extreme state. It is a useless property for a signal, because a filter that never says no cannot improve anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The long/short ratio changed its mind by dataset.&lt;/strong&gt; It helped on 15m, on 30m and on the 4-hour ledger, overfit on the 4-hour subset, and did nothing on the daily. A filter whose direction depends on which dataset you show it is describing the dataset, not the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reason, which is simpler than the statistics
&lt;/h2&gt;

&lt;p&gt;Look at the fee arithmetic on the 15-minute signal. Fees alone are 0.055% twice, so 0.11% per round trip, before slippage and before funding. The minimum stop is 0.6%. So 0.11 divided by 0.6 is about &lt;strong&gt;0.18R of pure cost per trade&lt;/strong&gt; — almost exactly the size of that signal's loss per trade of -0.188R.&lt;/p&gt;

&lt;p&gt;The 15-minute signal does not have a filtering problem. It has a cost problem. No entry filter can rescue an edge smaller than the cost of taking it; the best a filter can do is make you lose more slowly by trading less.&lt;/p&gt;

&lt;p&gt;On the daily breakout, with a stop measured in multiples of ATR, the same 0.11% is a rounding error. This is why the same filter can look useless on one timeframe and plausible on another: the thing that changed was the denominator.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for your own bot
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check costs before you check filters.&lt;/strong&gt; Divide your round-trip cost by your typical stop distance. If the answer is a meaningful fraction of your expected edge per trade, no filter will save the strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count every variant you tried&lt;/strong&gt;, including the ones you abandoned, and raise your evidence bar accordingly. The honest number is almost always larger than the one you remember.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat exchange data as a guardrail, not as alpha.&lt;/strong&gt; Funding and open-interest extremes are good reasons to stand aside. They are poor reasons to enter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check how often your filter disagrees.&lt;/strong&gt; If it agrees with 95% of your trades, it cannot be doing much, however good its numbers look.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What we are not claiming
&lt;/h2&gt;

&lt;p&gt;The 60-trial count covers this study alone. These five datasets came from strategies that were themselves selected after earlier experiments, so the true number of attempts behind them is larger and every figure here is, if anything, flattering. The 15m and 30m lists are backtests of our own scalp signal rather than live bots. The order-book slippage uses a recent snapshot, which understates the cost of trading in thinner past markets. And the split is a single cut in time, not a walk-forward.&lt;/p&gt;

&lt;p&gt;The one surviving result is a reason to keep testing multi-timeframe trend agreement on new trades. It is not a reason to trade it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the numbers yourself
&lt;/h2&gt;

&lt;p&gt;The statistics behind all of this — the probabilistic and deflated Sharpe ratios, the minimum track record length, the six readiness gates, the cost model and the look-ahead audit — are MIT-licensed Python at &lt;a href="https://github.com/botlabtrade/botlab-oss" rel="noopener noreferrer"&gt;github.com/botlabtrade/botlab-oss&lt;/a&gt;. Point it at your own trade list and you can reproduce the method on your own data. There is also a &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;browser version&lt;/a&gt; that needs no install.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/do-funding-rate-and-open-interest-filters-improve-a-crypto-bot" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Is a Trading Bot Profitable? How to Test One Honestly</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Mon, 12 Oct 2026 04:06:30 +0000</pubDate>
      <link>https://dev.to/botlab/is-a-trading-bot-profitable-how-to-test-one-honestly-69g</link>
      <guid>https://dev.to/botlab/is-a-trading-bot-profitable-how-to-test-one-honestly-69g</guid>
      <description>&lt;p&gt;Is a trading bot profitable? Some can be for a while, but most crypto trading bots are not profitable once fees, slippage and changing market conditions are counted, and no bot can promise future profit. The only honest way to find out is to test a specific bot with enough trades, real costs and a forward test on prices it has never seen.&lt;/p&gt;

&lt;p&gt;This guide shows you how to run that test yourself, step by step, without relying on screenshots or marketing claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is a trading bot profitable? The short, honest answer
&lt;/h2&gt;

&lt;p&gt;A trading bot is a set of rules that buys and sells automatically. It is not a source of profit by itself. A bot only makes money if its rules have a real &lt;strong&gt;edge&lt;/strong&gt;, meaning a repeatable advantage that survives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trading costs&lt;/strong&gt;: exchange fees, funding rates on perpetual futures, and slippage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different market regimes&lt;/strong&gt;: trending, sideways and high-volatility periods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time&lt;/strong&gt;: results that keep holding on new data, not just on the past.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most bots fail at least one of these. Sometimes a bot looks profitable because the market went up and it was simply holding long positions. That is market exposure (often called "beta"), not skill. When the market turns, the "profit" turns too.&lt;/p&gt;

&lt;p&gt;So a better question than "is a trading bot profitable?" is: &lt;strong&gt;"Does this bot have evidence of an edge, and how strong is that evidence?"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why most bots that look profitable are not
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The sample is too small
&lt;/h3&gt;

&lt;p&gt;Twenty winning trades in a row feel convincing, but they can easily be luck. You usually need many trades across different market conditions before a result means much. We cover this in detail in &lt;a href="https://botlab.org.uk/learn/how-many-trades-does-a-backtest-need" rel="noopener noreferrer"&gt;How Many Trades Does a Backtest Need?&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The backtest is overfit
&lt;/h3&gt;

&lt;p&gt;Overfitting happens when a strategy is tuned so tightly to past data that it "memorises" history. Warning signs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many parameters (for example, five indicators, each with custom settings).&lt;/li&gt;
&lt;li&gt;Very smooth backtest equity curves.&lt;/li&gt;
&lt;li&gt;Results that collapse when you change a setting slightly.&lt;/li&gt;
&lt;li&gt;Great results on one coin or one time window only.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Costs are ignored or underestimated
&lt;/h3&gt;

&lt;p&gt;A strategy that makes many small trades can look excellent before costs and lose money after them. Fees and slippage hit high-frequency and scalping bots hardest.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Win rate is mistaken for profitability
&lt;/h3&gt;

&lt;p&gt;A high win rate says nothing on its own. A bot can win 75% of trades and still lose money if its losses are much bigger than its wins. See &lt;a href="https://botlab.org.uk/learn/profit-factor-vs-win-rate-trading-bots" rel="noopener noreferrer"&gt;Profit Factor vs Win Rate for Trading Bots&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to test whether a trading bot is profitable
&lt;/h2&gt;

&lt;p&gt;Use this checklist on any bot: one you built, one you found online, or one someone is trying to sell you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Get the full trade list, not a summary
&lt;/h3&gt;

&lt;p&gt;Ask for (or export) every trade: entry time, exit time, side, size, price and fees. A summary like "+40% last month" is not evidence. If a seller cannot or will not share a trade list, treat that as a red flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Add realistic costs
&lt;/h3&gt;

&lt;p&gt;Re-calculate every trade with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your exchange's actual taker/maker fees.&lt;/li&gt;
&lt;li&gt;A slippage estimate (more for small-cap coins and fast markets).&lt;/li&gt;
&lt;li&gt;Funding payments if the bot holds perpetual futures positions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Check the sample size and period
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How many trades are there in total?&lt;/li&gt;
&lt;li&gt;Over how many days or months?&lt;/li&gt;
&lt;li&gt;Does the period include a downtrend, an uptrend and a sideways stretch?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few dozen trades over a few weeks is an early signal at best.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Look at risk, not just return
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Max drawdown&lt;/strong&gt;: the largest peak-to-trough fall. Could you sit through it without switching the bot off?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average loss vs average win&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Longest losing streak&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage used&lt;/strong&gt;: high leverage turns ordinary drawdowns into liquidations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Compare against simply holding
&lt;/h3&gt;

&lt;p&gt;If the bot only makes money when the market rises, compare it with just holding the same coin. If buying and holding did about as well, the bot may not be adding anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Forward test with paper trading
&lt;/h3&gt;

&lt;p&gt;Run the bot on live prices with simulated money (paper trading) for a period it has never seen. This is the closest you can get to real conditions without risking capital. Backtests describe the past; forward tests show whether the rules still behave the same way on new data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Set pass/fail rules before you look
&lt;/h3&gt;

&lt;p&gt;Decide in advance what counts as "good enough": a minimum number of trades, a maximum drawdown, a minimum result after costs. Writing the rules first stops you from moving the goalposts when a result looks exciting.&lt;/p&gt;

&lt;p&gt;At BOTLAB we apply this idea through 6 statistical gates (G1–G6), defined on the site. A bot is only labelled "ready for micro live" after passing all six.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: a bot that wins most trades but still loses
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Illustration only.&lt;/strong&gt; These are made-up numbers to show the maths. They are not BOTLAB results and do not describe any real bot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine a bot that made &lt;strong&gt;100 trades&lt;/strong&gt; in a backtest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wins: 60 trades, averaging &lt;strong&gt;+1.0%&lt;/strong&gt; each&lt;/li&gt;
&lt;li&gt;Losses: 40 trades, averaging &lt;strong&gt;−1.4%&lt;/strong&gt; each&lt;/li&gt;
&lt;li&gt;Round-trip fees and slippage: &lt;strong&gt;0.12%&lt;/strong&gt; per trade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Before costs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wins: 60 × 1.0% = +60%&lt;/li&gt;
&lt;li&gt;Losses: 40 × 1.4% = −56%&lt;/li&gt;
&lt;li&gt;Gross result: &lt;strong&gt;+4%&lt;/strong&gt; (simple sum, ignoring compounding)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After costs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Costs: 100 × 0.12% = −12%&lt;/li&gt;
&lt;li&gt;Net result: 4% − 12% = &lt;strong&gt;−8%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A 60% win rate and a positive gross backtest, yet the bot loses money once costs are included. Now imagine the same bot run with x20 leverage: every number above is multiplied, and a bad streak could wipe out the account. This is why testing must always include costs and leverage.&lt;/p&gt;

&lt;h2&gt;
  
  
  What real paper-trading data looks like
&lt;/h2&gt;

&lt;p&gt;Honest testing usually produces more "no" answers than "yes" answers. At BOTLAB, as of 12 October 2026, we track 142 bots in paper trading (simulated money, real market prices): &lt;strong&gt;0&lt;/strong&gt; are rated ready for micro live, &lt;strong&gt;2&lt;/strong&gt; are on watch and &lt;strong&gt;140&lt;/strong&gt; are not ready.&lt;/p&gt;

&lt;p&gt;Two examples from that paper-trading data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mr4h/long&lt;/strong&gt;: 77 paper trades over 57 days (16 Aug – 12 Oct 2026), win rate 72.7%, passes 5 of 6 gates. Status: WATCH. Verdict: sample too small to conclude.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atlas/live&lt;/strong&gt;: 392 paper trades over 65 days (8 Aug – 12 Oct 2026), win rate 40.6%, passes 1 of 6 gates. Status: NOT_READY.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the best-looking bot here is not considered proven, because 77 trades is not enough to rule out luck. Publishing failures is part of the method; see &lt;a href="https://botlab.org.uk/news/9" rel="noopener noreferrer"&gt;Failure is the method&lt;/a&gt; and the &lt;a href="https://botlab.org.uk/news/7" rel="noopener noreferrer"&gt;mr4h/long paper update&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want a structured second opinion on your own bot's numbers, you can run them through our free tool: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Red flags when someone claims their bot is profitable
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fixed monthly return promises (for example "10% every month").&lt;/li&gt;
&lt;li&gt;Only screenshots, no exportable trade history.&lt;/li&gt;
&lt;li&gt;No mention of drawdown, fees or number of trades.&lt;/li&gt;
&lt;li&gt;Countdown timers or "limited spots" pressure.&lt;/li&gt;
&lt;li&gt;Requests for your exchange password, 2FA codes, seed phrase, or an API key with withdrawal permission.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you ever connect a bot to an exchange, the API key should be &lt;strong&gt;trade-only, withdrawals off, and IP-restricted&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Are trading bots legit?
&lt;/h3&gt;

&lt;p&gt;The software itself is a legitimate tool; many traders automate rules they already use. What is often not legitimate is the marketing around bots, especially promises of fixed returns. Judge a bot by its full trade history, costs and drawdown, not by claims.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a realistic trading bot success rate?
&lt;/h3&gt;

&lt;p&gt;"Success rate" usually means win rate, and it can be misleading. A bot with a 40% win rate can do well if its wins are much larger than its losses, and a bot with a 75% win rate can lose money. Look at win rate together with average win, average loss, costs and number of trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a trading bot worth it for beginners?
&lt;/h3&gt;

&lt;p&gt;A bot does not remove the need to understand risk. For beginners, the most useful first step is paper trading: run a bot with simulated money on live prices, learn how drawdowns feel, and only then decide whether automation fits you. Never use money you cannot afford to lose.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long should I paper trade a bot before trusting it?
&lt;/h3&gt;

&lt;p&gt;There is no magic number, but aim for enough trades to cover different market conditions, usually more than a few weeks of data. Decide your pass/fail rules in advance and stick to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A trading bot is only as good as its edge after fees, slippage and funding.&lt;/li&gt;
&lt;li&gt;High win rates and short winning streaks are not proof of profitability.&lt;/li&gt;
&lt;li&gt;Test with full trade lists, realistic costs, enough trades and a forward paper test.&lt;/li&gt;
&lt;li&gt;Watch drawdown and leverage as closely as returns.&lt;/li&gt;
&lt;li&gt;Most bots fail honest testing, and that is useful information, not a setback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not available in restricted jurisdictions (see the Service Agreement). You trade with your own exchange account; BOTLAB never holds funds.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/is-trading-bot-profitable-how-to-test" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Profit Factor vs Win Rate for Trading Bots</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Sun, 11 Oct 2026 12:07:12 +0000</pubDate>
      <link>https://dev.to/botlab/profit-factor-vs-win-rate-for-trading-bots-dce</link>
      <guid>https://dev.to/botlab/profit-factor-vs-win-rate-for-trading-bots-dce</guid>
      <description>&lt;p&gt;Profit factor is usually the more useful of the two, because it measures whether a bot's wins are bigger than its losses. Win rate only tells you how often it wins. Neither number is enough alone, though. A bot can win 80% of its trades and still lose money, and a bot that wins 35% of the time can come out ahead. This guide explains both metrics, how they relate, and how to use them together without fooling yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What win rate actually measures
&lt;/h2&gt;

&lt;p&gt;Win rate is the share of closed trades that ended in profit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Win rate = winning trades ÷ total trades&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is easy to understand and easy to market, which is why bot sellers love to quote it. But it ignores two things that decide whether a strategy makes or loses money:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How big the wins are&lt;/strong&gt; compared with the losses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How much each trade costs&lt;/strong&gt; in fees, funding and slippage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A high win rate often comes from taking profit quickly and letting losers run. That produces lots of small wins and a few large losses. The equity curve looks smooth for weeks, then one bad trade wipes out a month of gains.&lt;/p&gt;

&lt;h2&gt;
  
  
  What profit factor actually measures
&lt;/h2&gt;

&lt;p&gt;Profit factor compares the money made on winning trades with the money lost on losing trades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Profit factor = gross profit ÷ gross loss&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to read it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Below 1.0&lt;/strong&gt;: the bot lost money over the sample&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exactly 1.0&lt;/strong&gt;: break-even before anything else goes wrong&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Above 1.0&lt;/strong&gt;: winners outweighed losers over the sample&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profit factor captures both how often a bot wins and by how much. That makes it a better first summary than win rate. It still has weaknesses, which we cover below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The link between them: expectancy
&lt;/h2&gt;

&lt;p&gt;The cleanest way to connect the two metrics is &lt;strong&gt;expectancy&lt;/strong&gt;, the average result per trade:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Expectancy = (win rate × average win) − (loss rate × average loss)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From it you can work out the &lt;strong&gt;break-even win rate&lt;/strong&gt; for any payoff profile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Break-even win rate = average loss ÷ (average win + average loss)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This one formula answers most "is this win rate good?" questions. A 70% win rate is excellent if the average loss equals the average win. It is a losing system if the average loss is five times the average win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: two bots, opposite profiles
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Illustration only.&lt;/strong&gt; The numbers below are made up to show the maths. They are not BOTLAB results and do not describe any real bot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine two bots, each tested on 100 trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bot A: high win rate, small wins, big losses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Win rate: 80% (80 wins, 20 losses)&lt;/li&gt;
&lt;li&gt;Average win: $10&lt;/li&gt;
&lt;li&gt;Average loss: $50&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calculations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gross profit = 80 × $10 = $800&lt;/li&gt;
&lt;li&gt;Gross loss = 20 × $50 = $1,000&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profit factor = 800 ÷ 1,000 = 0.80&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expectancy = (0.80 × 10) − (0.20 × 50) = 8 − 10 = −$2 per trade&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Break-even win rate = 50 ÷ (10 + 50) = &lt;strong&gt;83.3%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bot A wins four trades out of five and still loses money. It needs to win more than 83% of the time just to break even.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bot B: low win rate, big wins, small losses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Win rate: 35% (35 wins, 65 losses)&lt;/li&gt;
&lt;li&gt;Average win: $30&lt;/li&gt;
&lt;li&gt;Average loss: $10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calculations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gross profit = 35 × $30 = $1,050&lt;/li&gt;
&lt;li&gt;Gross loss = 65 × $10 = $650&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profit factor = 1,050 ÷ 650 ≈ 1.62&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expectancy = (0.35 × 30) − (0.65 × 10) = 10.5 − 6.5 = +$4 per trade&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Break-even win rate = 10 ÷ (30 + 10) = &lt;strong&gt;25%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bot B loses almost two trades out of three. Over this sample its winners more than covered the losers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now add costs
&lt;/h3&gt;

&lt;p&gt;Suppose fees and slippage cost $1 per round trip (again, an illustration):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bot A expectancy falls from −$2 to &lt;strong&gt;−$3&lt;/strong&gt; per trade&lt;/li&gt;
&lt;li&gt;Bot B expectancy falls from +$4 to &lt;strong&gt;+$3&lt;/strong&gt; per trade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Costs hurt every strategy, but they hurt high-frequency, small-target strategies the most. If a bot's average win is only a little larger than its round-trip cost, a modest rise in fees or slippage can flip it negative. Always check whether a reported profit factor is &lt;strong&gt;net of fees&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why each metric can mislead you
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Win rate traps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hidden tail risk.&lt;/strong&gt; Strategies with no stop-loss, or with averaging-down, can show very high win rates until one large loss arrives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Survivorship in short samples.&lt;/strong&gt; A few weeks without a big adverse move can make a fragile bot look brilliant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Psychological comfort.&lt;/strong&gt; Frequent small wins feel good, which makes people overlook the size of the losses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Profit factor traps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small samples.&lt;/strong&gt; With 20 trades, one lucky outlier can push profit factor from 1.1 to 2.5. The number is only as reliable as the number of trades behind it. See &lt;a href="https://botlab.org.uk/learn/how-many-trades-does-a-backtest-need" rel="noopener noreferrer"&gt;How Many Trades Does a Backtest Need?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outlier dependence.&lt;/strong&gt; If removing the single best trade drops profit factor below 1.0, the "edge" may be one lucky event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gross vs net.&lt;/strong&gt; A profit factor calculated before fees can be very different from what you'd actually see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overfitting.&lt;/strong&gt; Tune enough parameters on one dataset and you can make almost any profit factor look good. It usually falls apart on new data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market beta.&lt;/strong&gt; A long-only bot in a rising market can show a strong profit factor simply because prices went up. That is exposure to the market, not a proven edge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to judge a bot using both numbers
&lt;/h2&gt;

&lt;p&gt;Use this checklist when you look at any bot's results, including your own:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get the trade count and the period first.&lt;/strong&gt; No trade count, no conclusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read win rate together with average win and average loss.&lt;/strong&gt; Calculate the break-even win rate and compare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check profit factor is net of costs.&lt;/strong&gt; Ask what fee level and slippage were assumed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove the best one or two trades.&lt;/strong&gt; Recalculate profit factor. If it collapses, be cautious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Look at the worst losing streak and max drawdown.&lt;/strong&gt; A good profit factor with a drawdown you couldn't sit through is not usable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare to simply holding the asset.&lt;/strong&gt; If the bot did roughly what the market did, it may have no edge of its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer out-of-sample or forward results.&lt;/strong&gt; A backtest is a hypothesis. Paper trading on live prices is a better test, and it is still not proof. Our &lt;a href="https://botlab.org.uk/news/2" rel="noopener noreferrer"&gt;Paper trading, explained&lt;/a&gt; post covers the difference.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How we apply this at BOTLAB
&lt;/h2&gt;

&lt;p&gt;We don't treat a high win rate as evidence by itself. Every bot we track has to pass 6 statistical gates (G1–G6), defined on the site, before it is labelled "ready for micro live". As of our latest build, 101 of the 102 bots we track are marked not ready.&lt;/p&gt;

&lt;p&gt;A real example of why win rate alone isn't enough: in paper trading (simulated money, real market prices) from 2026-08-16 to 2026-10-03, our mr4h/long bot recorded 53 trades with an 81.1% win rate and passed 6 of 6 gates. Our own verdict is still "sample too small to conclude". Another bot, botGPT/dir2s, had a 39.0% win rate over 41 paper trades (2026-09-17 to 2026-10-06), and our verdict there is "market beta, no proven edge". A high or low win rate doesn't settle the question either way. You can follow the &lt;a href="https://botlab.org.uk/news/7" rel="noopener noreferrer"&gt;mr4h/long paper update&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to run your own bot's trade list through these kinds of checks, try the free tool: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a good profit factor for a crypto trading bot?
&lt;/h3&gt;

&lt;p&gt;There is no universal "good" number. A net profit factor above 1.0 means winners outweighed losers in that sample. How much that matters depends on the trade count, whether fees are included, how much the result depends on a few outliers, and whether it holds up on data the bot was not tuned on. A high profit factor on a small sample deserves extra suspicion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a bot with a 90% win rate lose money?
&lt;/h3&gt;

&lt;p&gt;Yes. If the average loss is more than nine times the average win, a 90% win rate loses money. Use the break-even formula, average loss ÷ (average win + average loss), to check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a low win rate a red flag?
&lt;/h3&gt;

&lt;p&gt;Not by itself. Trend-following strategies often win less than half their trades and rely on occasional large winners. The real questions are whether the average win is large enough to cover the losses and costs, and whether you could tolerate the losing streaks that come with a low win rate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use profit factor or expectancy?
&lt;/h3&gt;

&lt;p&gt;Use both. Profit factor is a ratio and is easy to compare across bots. Expectancy tells you the average result per trade in money or R terms, which makes the impact of fees easier to see. Both need a sufficient trade count to mean anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Win rate tells you how often a bot wins. Profit factor tells you whether the wins outweigh the losses.&lt;/li&gt;
&lt;li&gt;Always calculate the break-even win rate from average win and average loss.&lt;/li&gt;
&lt;li&gt;Use profit factor net of fees and slippage, and check that it survives removing the best trades.&lt;/li&gt;
&lt;li&gt;Small samples make both metrics unreliable. Look at trade count and period first.&lt;/li&gt;
&lt;li&gt;A strong-looking metric can just be market beta or overfitting. Forward and paper results are better evidence, but they are still not proof.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not available in restricted jurisdictions (see the Service Agreement). You trade with your own exchange account; BOTLAB never holds funds.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/profit-factor-vs-win-rate-trading-bots" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Many Trades Does a Backtest Need? A Practical Guide</title>
      <dc:creator>Bot LAB</dc:creator>
      <pubDate>Sun, 11 Oct 2026 12:07:07 +0000</pubDate>
      <link>https://dev.to/botlab/how-many-trades-does-a-backtest-need-a-practical-guide-1a3i</link>
      <guid>https://dev.to/botlab/how-many-trades-does-a-backtest-need-a-practical-guide-1a3i</guid>
      <description>&lt;p&gt;There is no single magic number. As a rough guide, under 30 trades tells you almost nothing, around 100 starts to be informative, and several hundred trades across different market conditions is where a backtest becomes hard to dismiss. The number you actually need depends on how big the bot's average edge is compared with how noisy its individual trades are. This guide shows you how to work that out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why trade count matters so much
&lt;/h2&gt;

&lt;p&gt;Every backtest is a small sample of a strategy's possible outcomes. If you flip a fair coin 10 times, getting 7 heads is not unusual. Trading results work the same way. A bot with zero real edge can produce a beautiful equity curve over 20 or 40 trades purely by luck.&lt;/p&gt;

&lt;p&gt;The question a backtest should answer is not "did it make money?" but "&lt;strong&gt;how likely is it that this result came from luck?&lt;/strong&gt;" Trade count is the main thing that shrinks luck's influence.&lt;/p&gt;

&lt;h3&gt;
  
  
  The core idea: noise shrinks slowly
&lt;/h3&gt;

&lt;p&gt;The uncertainty around a bot's average result per trade shrinks with the &lt;strong&gt;square root&lt;/strong&gt; of the number of trades. That has an uncomfortable consequence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To halve your uncertainty, you need &lt;strong&gt;4x&lt;/strong&gt; the trades.&lt;/li&gt;
&lt;li&gt;To cut it to a third, you need &lt;strong&gt;9x&lt;/strong&gt; the trades.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why 50 trades feels like a lot but usually isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rough tiers for trade count
&lt;/h2&gt;

&lt;p&gt;These are rules of thumb, not laws. Treat them as a starting point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Under 30 trades:&lt;/strong&gt; Anecdote. Useful for spotting obvious bugs, not for judging an edge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;30–100 trades:&lt;/strong&gt; Early signal. You can rule out strategies that are clearly broken, but a profitable-looking result can still easily be noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100–300 trades:&lt;/strong&gt; Informative, if trades are reasonably independent and the edge per trade is not tiny.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;300+ trades across several market regimes:&lt;/strong&gt; Strong enough to take seriously, provided you didn't test hundreds of variants to find it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What changes the number you need
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Size of the edge versus the noise
&lt;/h3&gt;

&lt;p&gt;Measure each trade in &lt;strong&gt;R&lt;/strong&gt; (profit or loss divided by the amount risked). A bot averaging +0.5R per trade with consistent outcomes needs far fewer trades to prove itself than one averaging +0.05R with wild swings. Small edges need big samples.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Skewed payoffs
&lt;/h3&gt;

&lt;p&gt;Strategies with a high win rate and occasional large losses are the hardest to judge. A short sample may simply not include the rare big loss yet. The reverse is also true: trend-following bots with many small losses and rare big wins can look terrible over a short window.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Market regimes
&lt;/h3&gt;

&lt;p&gt;200 trades all taken during one strong uptrend is really one experiment repeated. You want trades spread across trending, sideways and volatile periods. Count regimes, not just trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. How many variants you tested
&lt;/h3&gt;

&lt;p&gt;If you tried 100 parameter combinations and kept the best, that winner's backtest is inflated. The more variants you test, the higher the bar should be. This is the heart of overfitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Trade independence
&lt;/h3&gt;

&lt;p&gt;Ten positions opened on the same day on correlated coins behave more like one or two trades than ten. Clustered trades reduce your effective sample size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: how many trades would this bot need?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Illustration only. These are made-up numbers to show the method, not results from any real bot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine a backtest with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trades:&lt;/strong&gt; 40&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average result per trade:&lt;/strong&gt; +0.15R&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard deviation of trade results:&lt;/strong&gt; 1.2R&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Standard error of the average.&lt;/strong&gt; 1.2 ÷ √40 ≈ 1.2 ÷ 6.32 ≈ &lt;strong&gt;0.19R&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Compare the edge to the noise.&lt;/strong&gt; 0.15 ÷ 0.19 ≈ &lt;strong&gt;0.79&lt;/strong&gt;. A common rough bar is about 2. At 0.79, the result is well within what luck alone could produce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: A rough plausible range.&lt;/strong&gt; Average ± 2 standard errors: 0.15 ± 0.38, so roughly &lt;strong&gt;−0.23R to +0.53R&lt;/strong&gt;. The true edge could easily be negative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: How many trades to reach the bar of 2?&lt;/strong&gt; n ≈ (2 × 1.2 ÷ 0.15)² = 16² = &lt;strong&gt;256 trades&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Now add realistic costs.&lt;/strong&gt; Suppose fees and slippage cut the average to +0.10R. Then: n ≈ (2 × 1.2 ÷ 0.10)² = 24² = &lt;strong&gt;576 trades&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A third less edge more than doubled the trades needed. This is why fee assumptions matter so much, especially for high-frequency bots.&lt;/p&gt;

&lt;h2&gt;
  
  
  The high win rate trap
&lt;/h2&gt;

&lt;p&gt;A high win rate feels reassuring, but it says little on its own.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Illustration only:&lt;/em&gt; a bot wins 9 out of 10 trades at +0.3R each, then loses 1 trade at −3R. Win rate: 90%. Net result over those 10 trades: 9 × 0.3 − 3 = &lt;strong&gt;−0.3R&lt;/strong&gt;. Over a short sample that happened to avoid the loss, it would have looked flawless.&lt;/p&gt;

&lt;p&gt;Always look at the &lt;strong&gt;average win, average loss, and the worst loss&lt;/strong&gt;, not just the win rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example of "good numbers, not enough trades"
&lt;/h2&gt;

&lt;p&gt;Here is one from our own lab. At BOTLAB, the bot mr4h/long recorded, in &lt;strong&gt;paper trading&lt;/strong&gt; (simulated money, real market prices), &lt;strong&gt;53 trades over 48 days&lt;/strong&gt; (2026-08-16 to 2026-10-03) with an &lt;strong&gt;81.1% win rate&lt;/strong&gt;. It passed all 6 statistical gates (G1–G6), defined on the site, and is marked ready for a micro live test. Even so, its verdict is still &lt;strong&gt;"sample too small to conclude"&lt;/strong&gt;. You can see the &lt;a href="https://botlab.org.uk/news/7" rel="noopener noreferrer"&gt;paper update for mr4h/long&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That combination is the point of this article: passing filters and having a high win rate does not replace a larger sample. It only means the bot has earned the right to keep being tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  A checklist before trusting any backtest
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Trade count:&lt;/strong&gt; At least 100, ideally several hundred.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Regimes:&lt;/strong&gt; Trades spread across trending, sideways and volatile periods.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Costs:&lt;/strong&gt; Realistic fees, funding and slippage included.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Edge vs noise:&lt;/strong&gt; Average R divided by its standard error is comfortably above about 2.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Payoff shape:&lt;/strong&gt; Average win, average loss and worst loss reviewed, not only win rate.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Variants tested:&lt;/strong&gt; You know how many combinations were tried before this one.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Out-of-sample:&lt;/strong&gt; Some data was held back and never used for tuning.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Independence:&lt;/strong&gt; Clustered or correlated trades are not counted as fully separate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  From backtest to forward testing
&lt;/h2&gt;

&lt;p&gt;Even a large, clean backtest is still a test on data you've already seen. The next step is &lt;strong&gt;forward testing&lt;/strong&gt; on live prices without real money, usually called paper trading. It is the honest check against overfitting because the bot meets data that didn't exist when it was built. If you're new to the idea, see &lt;a href="https://botlab.org.uk/news/2" rel="noopener noreferrer"&gt;Paper trading, explained&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The same sample-size rules apply to forward tests. A few weeks of good paper results is still a small sample; let the trade count build up before drawing conclusions.&lt;/p&gt;

&lt;p&gt;If you want a quick sanity check of your own bot's numbers, the free BOTLAB tool can help: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is 30 trades enough for a backtest?
&lt;/h3&gt;

&lt;p&gt;Usually not. 30 trades can reveal bugs or a clearly broken strategy, but the uncertainty around the average result is too wide to confirm an edge unless that edge is very large and consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does more historical data always help?
&lt;/h3&gt;

&lt;p&gt;More trades help, but only if the data is relevant. Very old data from a different market structure can mislead. Prefer more trades across varied, reasonably recent regimes, and keep some data aside for out-of-sample testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a higher win rate mean I need fewer trades?
&lt;/h3&gt;

&lt;p&gt;Not necessarily. High win rate strategies often hide rare large losses, which a short sample may miss entirely. What matters is the average result per trade relative to its variability, plus the size of the worst loss.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long should I paper trade a bot after backtesting?
&lt;/h3&gt;

&lt;p&gt;Think in trades, not days. Run it until it has built up a meaningful number of trades across different market conditions, and compare those forward results with the backtest. Large gaps between the two are a warning sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;There is no magic number, but under 30 trades is anecdote and 100+ is a sensible minimum.&lt;/li&gt;
&lt;li&gt;Uncertainty shrinks with the square root of trades: halving it needs 4x the data.&lt;/li&gt;
&lt;li&gt;Smaller edges, higher costs and skewed payoffs all raise the trades you need.&lt;/li&gt;
&lt;li&gt;Count regimes and tested variants, not just trades.&lt;/li&gt;
&lt;li&gt;A high win rate or passing filters does not replace a larger sample.&lt;/li&gt;
&lt;li&gt;Confirm backtests with forward paper trading before drawing conclusions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Paper trading results are simulated. Past results don't predict future results. Crypto trading can lose money, including all capital. Not financial advice. Not available in restricted jurisdictions (see the Service Agreement). You trade with your own exchange account; BOTLAB never holds funds.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://botlab.org.uk/learn/how-many-trades-does-a-backtest-need" rel="noopener noreferrer"&gt;BOTLAB&lt;/a&gt;. Score your own bot's trade log free: &lt;a href="https://botlab.org.uk/#tool" rel="noopener noreferrer"&gt;Check your bot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>statistics</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
