<?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: Alex Rincon</title>
    <description>The latest articles on DEV Community by Alex Rincon (@alexrincontrading).</description>
    <link>https://dev.to/alexrincontrading</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%2F4227143%2Fefd26148-6636-447f-8e3c-b86d7bce95ea.jpg</url>
      <title>DEV Community: Alex Rincon</title>
      <link>https://dev.to/alexrincontrading</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexrincontrading"/>
    <language>en</language>
    <item>
      <title>I tested 12 trading signals for grid bots on 6 years of data. Most of them were noise.</title>
      <dc:creator>Alex Rincon</dc:creator>
      <pubDate>Thu, 05 Nov 2026 14:00:03 +0000</pubDate>
      <link>https://dev.to/alexrincontrading/i-tested-12-trading-signals-for-grid-bots-on-6-years-of-data-most-of-them-were-noise-35im</link>
      <guid>https://dev.to/alexrincontrading/i-tested-12-trading-signals-for-grid-bots-on-6-years-of-data-most-of-them-were-noise-35im</guid>
      <description>&lt;p&gt;A grid bot buys and sells inside a price range. On futures you also choose a direction: long, short or neutral. Everyone who runs one asks the same thing every morning: &lt;em&gt;which grid should I launch today?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I spent the last months trying to answer that with data instead of chart patterns. This is what I did, what failed, and what survived.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8 pairs&lt;/strong&gt; (BTC, ETH, SOL, XRP, DOGE, BNB, ADA, LINK), Binance USDT perpetual futures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4,846 simulated 30-day grid bots&lt;/strong&gt;, one every 3 days per pair, from 2020 to September 2026. Each start is simulated three times: long, short and neutral.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1-minute candles&lt;/strong&gt;. Before trusting the simulator I replayed 33 real bots and compared them order by order: 96.6% of the fills matched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The question becomes measurable: for each start date, &lt;em&gt;how much would choosing the right direction have paid&lt;/em&gt; (&lt;code&gt;long − short&lt;/code&gt;), and can any signal known on that date predict it?&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule I fixed before looking
&lt;/h2&gt;

&lt;p&gt;This is the part that matters most. With enough candidate signals, something always "works" on past data. So the criterion was written down before running anything:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spearman correlation with &lt;code&gt;long − short&lt;/code&gt;, computed &lt;strong&gt;inside each pair&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Split history into three periods (2021–2023, 2024-05 → 2025-07, 2025-08 → now).&lt;/li&gt;
&lt;li&gt;A signal passes only if it has &lt;strong&gt;the same sign and |ρ| ≥ 0.08 in all three&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Survivors are then tested &lt;strong&gt;walk-forward&lt;/strong&gt;: every month, percentiles are recalibrated using only the past, exactly as it would run live.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;months&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;past&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;past&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# past only
&lt;/span&gt;    &lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchsorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;long&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;short&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;neutral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What failed
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;2021–23&lt;/th&gt;
&lt;th&gt;2024–25&lt;/th&gt;
&lt;th&gt;2025–26&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7-day momentum&lt;/td&gt;
&lt;td&gt;+0.04&lt;/td&gt;
&lt;td&gt;+0.01&lt;/td&gt;
&lt;td&gt;−0.07&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30-day momentum&lt;/td&gt;
&lt;td&gt;−0.01&lt;/td&gt;
&lt;td&gt;−0.10&lt;/td&gt;
&lt;td&gt;+0.05&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fear &amp;amp; Greed index&lt;/td&gt;
&lt;td&gt;+0.12&lt;/td&gt;
&lt;td&gt;−0.10&lt;/td&gt;
&lt;td&gt;−0.13&lt;/td&gt;
&lt;td&gt;❌ flips sign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change in top-trader positioning (1d / 7d)&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RSI(6), daily&lt;/td&gt;
&lt;td&gt;+0.01&lt;/td&gt;
&lt;td&gt;+0.01&lt;/td&gt;
&lt;td&gt;−0.04&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14-day breakout exhaustion ("reversal" labels)&lt;/td&gt;
&lt;td&gt;+0.11&lt;/td&gt;
&lt;td&gt;+0.11&lt;/td&gt;
&lt;td&gt;−0.03&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last two come from a popular "grid bot" indicator on TradingView. On the chart it looks great: it deletes its previous label every time it draws a new one, so you only ever see the latest call. Walk-forward, using it to pick the direction did &lt;strong&gt;−0.7 points per month worse&lt;/strong&gt; than always launching neutral. I tried it on 1D, 4h and 1h candles: same result.&lt;/p&gt;

&lt;p&gt;Fear &amp;amp; Greed is the interesting failure: it looked like a strong signal for two years and then reversed. That's exactly what the three-period rule is there to catch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What survived
&lt;/h2&gt;

&lt;p&gt;Only positioning data from Binance itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Top traders' long/short ratio — as a contrarian signal.&lt;/strong&gt; When the biggest accounts are heavily long, the price tends to fall over the next weeks (ρ ≈ −0.10 to −0.25).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggressive buying (taker buy/sell volume)&lt;/strong&gt; points the other way (ρ ≈ +0.12 to +0.20).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined (four measures of that positioning, each as a percentile of the pair's own history), walk-forward since 2022:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+1.8 points per 30-day bot&lt;/strong&gt; versus always going neutral (95% CI +0.4 to +3.3).&lt;/li&gt;
&lt;li&gt;Better in &lt;strong&gt;32 of 52 months&lt;/strong&gt;. Not 52. There are whole stretches where it does worse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The range matters more than the direction
&lt;/h2&gt;

&lt;p&gt;The surprise was the range. A fixed ±10% grid is what most people launch. Sizing it from the expected 30-day volatility instead:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Fixed ±10%&lt;/th&gt;
&lt;th&gt;Volatility-based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bots that ended in profit&lt;/td&gt;
&lt;td&gt;55%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worst 10% of bots&lt;/td&gt;
&lt;td&gt;−24.1%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−11.5%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A wider grid earns less per day, but it loses far less when the market runs away — and the runaway months are what wipe out a grid's year.&lt;/p&gt;

&lt;p&gt;One more rule fell out of the data: when a pair is in the calmest 20% of its past year, neutral grids lost money on average. Low volatility looks safe and isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built with it
&lt;/h2&gt;

&lt;p&gt;I turned the surviving rules into a small free page that recalculates every time you load it from live Binance data: direction, range and number of grids for BTC and ETH. The full validation — including the failures above — is published next to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oracle: &lt;a href="https://gridreplay.com/en/oracle/" rel="noopener noreferrer"&gt;https://gridreplay.com/en/oracle/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Validation: &lt;a href="https://gridreplay.com/en/validation/" rel="noopener noreferrer"&gt;https://gridreplay.com/en/validation/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disclosure: I made it. The page has a Pionex affiliate link, and there's a paid tier planned for the other pairs. None of this is financial advice; it's an average edge over many months, not a prediction.&lt;/p&gt;

&lt;p&gt;If you have a signal you think works for grids, tell me in the comments and I'll run it through the same test.&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>showdev</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
