<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Mechanical Premia]]></title><description><![CDATA[Welcome to my publication, where we quantify structural market edges. Expect unfiltered backtests, robust portfolio mechanics, and ready-to-run MetaTrader code. No discretionary guesswork—just pure mechanical systems.]]></description><link>https://mechanicalpremia.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!gX2g!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e41d6f2-4dc3-434a-8016-cb5d3708f374_1280x1280.png</url><title>Mechanical Premia</title><link>https://mechanicalpremia.substack.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 05 Nov 2026 11:34:19 GMT</lastBuildDate><atom:link href="https://mechanicalpremia.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Mechanical Premia]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[mechanicalpremia@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[mechanicalpremia@substack.com]]></itunes:email><itunes:name><![CDATA[Mechanical Risk Premia]]></itunes:name></itunes:owner><itunes:author><![CDATA[Mechanical Risk Premia]]></itunes:author><googleplay:owner><![CDATA[mechanicalpremia@substack.com]]></googleplay:owner><googleplay:email><![CDATA[mechanicalpremia@substack.com]]></googleplay:email><googleplay:author><![CDATA[Mechanical Risk Premia]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Finding Systematic Strategies from Scratch (Part 2): What Does the Market Actually Want to Do?]]></title><description><![CDATA[Market tendency analysis, asset personalities, and the roadmap before feature engineering.]]></description><link>https://mechanicalpremia.substack.com/p/finding-systematic-strategies-from</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/finding-systematic-strategies-from</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Sun, 25 Oct 2026 09:12:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b9bbb476-912f-4003-a1a8-3a6cc854658a_2752x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Finding What the Market Actually Wants to Do</h3><p>The last post I wrote turned out to be my most viewed and liked one yet. It&#8217;s been up for about two weeks now, and I picked up 50+ subscribers from it.</p><p>I honestly didn&#8217;t expect that. We all know human psychology: if I post a pretty equity curve and say I have a bulletproof set of rules, that&#8217;s what usually hooks people. Not boring data analysis, charts, and curves. But I was genuinely surprised by the reception, and I really appreciate everyone who read it and subscribed. So this time, I want to go a bit deeper into the actual process.</p><p>When you&#8217;re doing systematic strategy research, there&#8217;s a whole workflow to follow. In the last post, I talked about universe selection being the most important part. About 50% of the work is just picking where to trade. Once you actually have that data downloaded on your machine, what&#8217;s next? How do you decide what to build?</p><p>A lot of people naively start slapping random indicators together. Others try reading academic papers to find an edge. I love quantitative research as much as the next guy, but because of the massive pressure to publish in universities, the amount of overfit, useless garbage papers online is incredible. The rise of AI has only magnified that problem. Rant over.</p><p>Then there are people who take an AI like Claude and just let it loose on raw price data until it spits out some strategy. But you end up with something you can&#8217;t really trust. You don&#8217;t understand why it works, how it works, or what market regime it&#8217;s going to blow up in. I might look like a bit of a luddite, but I still prefer actually understanding what I&#8217;m putting my money on. I want to know why it works, and just as importantly, when it won&#8217;t work.</p><p>Back when I started doing strategy research and didn&#8217;t know any better, I used to use genetic programming to craft strategies. It can work, sure. But it gave me some really weird, convoluted rules that I could never fully trust. Back then, the only fix was running intense validation loops on a big basket of 10, 20, or 30+ strategies combined, just so you could gather real data on your equity curve over a month or two. That turned into a pure computational headache. If you want to build that way, you do you, but it wasn&#8217;t for me.</p><p>The methods and strategies I share here aren&#8217;t some secret I need to hide. I trade risk premiums. First of all, you can&#8217;t arbitrage basic risk away. And second, most people won&#8217;t be able to bear the drawdowns required to harvest them anyway. So before letting any code or AI loose on the data, the very next step is what I call <em><strong>Market Tendency Analysis</strong></em>.</p><p>Before you write a single rule, you need to know what you&#8217;re looking for. Does this market naturally favor breakouts, or does it favor mean reversion? On what timeframe? Where should you be looking for longs, and where should you be looking for shorts? That is what we are going to look at next.</p><h3>Sorting the Noise: The Decile Analysis</h3><p>To figure out these tendencies, you don&#8217;t need fancy deep learning models. This is basic data science 101.</p><p>I wrote a simple Python script (which I&#8217;ve included at the very bottom of this post) using Streamlit and Plotly to do one thing: sort past price moves into deciles and show me the average forward return across different horizons and regimes.</p><p>Here is the logic in plain English:</p><ol><li><p><strong>Calculate the past move:</strong> Over a lookback window N (like 5, 20, or 50 bars), measure how much the price gained or lost.</p></li><li><p><strong>Sort into 10 buckets (Deciles):</strong> Bucket D1 holds the steepest, most violent drops in the dataset. Bucket D10 holds the biggest explosive rallies. Buckets D4 to D7 represent the quiet middle where nothing much happened.</p></li><li><p><strong>Measure forward return:</strong> For every single bar in a bucket, look forward H bars (say, 10 or 20 bars ahead) and calculate the percentage return from that point.</p></li><li><p><strong>Take the average:</strong> Average out those forward returns for each bucket and plot them on a line.</p></li><li><p><strong>Apply basic regime masks:</strong> Filter the sample to see how the curve changes when the market is above or below its 100-day EMA (trend filter), or whether rolling 14-period ATR is above or below its median (volatility filter).</p></li></ol><p>When you look at the chart, the shape of the lines gives you an immediate fingerprint of the asset. Here is how to read them:</p><ul><li><p><strong>Sloping down from left to right (D1 is high, D10 is low):</strong> That&#8217;s <strong>mean reversion</strong>. Big drops snap right back up, and big rallies fizzle out. You want to fade extremes and buy the dips.</p></li><li><p><strong>Sloping up from left to right (D1 is low, D10 is high):</strong> That&#8217;s <strong>momentum</strong>. Severe drops keep falling, and big rallies keep running. You want to buy breakouts and sell breakdowns.</p></li><li><p><strong>A &#8220;U-Shape&#8221; curve:</strong> Both extremes yield positive forward returns. Panic selloffs get bought up aggressively, but massive breakout rallies also carry enough follow-through to make money.</p></li><li><p><strong>An Inverted &#8220;U-Shape&#8221; curve:</strong> The extremes are absolute trap zones. If price dumps hard or runs up violently, it tends to bleed out or get slapped down afterward. Forward returns only look decent when the market is idling in the middle deciles.</p></li><li><p><strong>Long Bias vs. Short Bias:</strong> Look at the dashed 0% line. If the entire curve sits above zero across almost all deciles, the asset has an underlying <strong>long bias</strong>&#8212;the market naturally drifts upward over time, and you&#8217;re swimming with the current. If the curve sits mostly below the 0% line, the asset has a structural <strong>short bias</strong>, meaning the market&#8217;s default drift is downward.</p></li></ul><p>Once you know how to read these shapes, you can instantly see an asset&#8217;s real personality before you waste time coding a strategy. Let&#8217;s look at what real market data actually looks like.</p><h3>Reading Real Market Tendencies</h3><p>When you run this script across different assets, you quickly realize there is no such thing as a single universal rule. Every market has its own structural personality, and those personalities shift depending on the timeframe and the volatility regime.</p><p>Let&#8217;s look at a few real examples.</p><h3>1. US500 (H1, No Filter)</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!P3c5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!P3c5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 424w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 848w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 1272w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!P3c5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png" width="1362" height="593" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:593,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:113249,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!P3c5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 424w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 848w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 1272w, https://substackcdn.com/image/fetch/$s_!P3c5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4aa8b8d7-f852-4e52-a68f-078325973d97_1362x593.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>When we run raw US500 data on the 1-hour timeframe with no filters applied, a single glance gives us a ton of information:</p><ul><li><p><strong>Structural Long Bias:</strong> Almost every single line across every decile sits comfortably above the 0% dashed line. The equity risk premium is always present in the background.</p></li><li><p><strong>Massive Mean Reversion on Dips:</strong> Look at D1 (the deepest drops) on the far left. The forward returns spike right up to 0.08%&#8211;0.12%+. When the US500 gets slammed on shorter lookbacks, buying that panic is historically the highest-yielding bet on the chart.</p></li><li><p><strong>Room for Breakouts:</strong> Look at D10 on the right. The curve doesn&#8217;t crash back down; it hooks upward toward 0.07%&#8211;0.09% for lookbacks like N=20 and N=50.</p></li></ul><p>You get that classic &#8220;U-shape&#8221; smile: panic selloffs snap back violently, but genuine breakout momentum also carries forward. The quiet middle (D4&#8211;D7) is just low-yield chop.</p><h3>2. Natural Gas (H4, No Filter)</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ph4l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ph4l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 424w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 848w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 1272w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ph4l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png" width="1344" height="601" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94d96f47-0511-4739-950d-5123801cf762_1344x601.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:601,&quot;width&quot;:1344,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:107172,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ph4l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 424w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 848w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 1272w, https://substackcdn.com/image/fetch/$s_!ph4l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d96f47-0511-4739-950d-5123801cf762_1344x601.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Natural Gas is a completely different beast.</p><p>The lines slope straight down from left to right. D1 sits high up between +0.3% and +1.0%, while D10 plummets deep into negative territory around -0.5% to -1.0%.</p><p>There is no structural long bias here. It&#8217;s a clean, stable range that snaps back in both directions. Rallies get faded hard, drops get bought. If you try to run an unfiltered momentum breakout strategy on H4 NatGas, the market will grind your account to dust.</p><h3>3. Gold (H1, Low Vol Filter)</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5B02!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5B02!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 424w, https://substackcdn.com/image/fetch/$s_!5B02!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 848w, https://substackcdn.com/image/fetch/$s_!5B02!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 1272w, https://substackcdn.com/image/fetch/$s_!5B02!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!5B02!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png" width="1364" height="598" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:598,&quot;width&quot;:1364,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:106325,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5B02!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 424w, https://substackcdn.com/image/fetch/$s_!5B02!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 848w, https://substackcdn.com/image/fetch/$s_!5B02!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 1272w, https://substackcdn.com/image/fetch/$s_!5B02!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb37c038b-0af7-4744-b4d3-fe3e3402a9fa_1364x598.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Gold shares the US500&#8217;s structural long drift (most of the curve sits well above zero), but its internal mechanics are the exact opposite.</p><p>Instead of a dip-buying machine, Gold heavily favors <strong>momentum</strong> in calm regimes. Look at D10 on the right: across almost all lookbacks, forward returns ramp up aggressively to +0.10%&#8211;0.18%. Meanwhile, D1 is muted or flat. In low volatility, buying strength on Gold pays far better than trying to catch falling knives.</p><h3>4. Crude Oil: The Timeframe Flip</h3><p>Crude Oil is one of the clearest examples of why testing multiple timeframes matters.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qNw4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qNw4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 424w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 848w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 1272w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!qNw4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png" width="1359" height="596" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:596,&quot;width&quot;:1359,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:99311,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qNw4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 424w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 848w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 1272w, https://substackcdn.com/image/fetch/$s_!qNw4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b197a1e-59ab-4ca4-99d5-b89672c0ee48_1359x596.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>On the <strong>H1 timeframe</strong>, the curve slopes upward. D1 is negative (-0.1% to -0.3%), while D10 pushes up into solid positive territory (+0.1% to +0.35%). On the 1-hour chart, it&#8217;s a simple trend asset: rallies tend to continue, and dips tend to fail.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mqHP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mqHP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 424w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 848w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 1272w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mqHP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png" width="1358" height="603" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:603,&quot;width&quot;:1358,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103830,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mqHP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 424w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 848w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 1272w, https://substackcdn.com/image/fetch/$s_!mqHP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5339528-fa00-4a58-ad20-9b4cec048657_1358x603.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Step back to the <strong>H4 timeframe</strong>, and the personality completely flips. Now we see an aggressive mean-reversion U-shape skewed to the long side. D1 spikes massive returns (+1.0% to +2.3%), the middle deciles hover around zero, and D10 still carries some breakout kick.</p><p>The exact same commodity acts like a breakout momentum vehicle on H1 and a dip-buying mean-reversion vehicle on H4.</p><h3>5. EURGBP: The Volatility Regime Trap</h3><p>Finally, look at EURGBP across volatility regimes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e-mx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e-mx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 424w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 848w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 1272w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!e-mx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png" width="1362" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:110779,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e-mx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 424w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 848w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 1272w, https://substackcdn.com/image/fetch/$s_!e-mx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3333e3-ae6e-402e-b938-6ea1e54029ab_1362x592.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In <strong>Low Vol</strong>, you get a textbook, clean mean-reversion diagonal. D1 is up at +0.15% to +0.25%, and D10 drops to -0.1% to -0.25%. When the market is quiet, fading moves on EURGBP is about as reliable as it gets.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AMGK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AMGK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 424w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 848w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 1272w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!AMGK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png" width="1351" height="609" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:609,&quot;width&quot;:1351,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:113175,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/222010593?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AMGK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 424w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 848w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 1272w, https://substackcdn.com/image/fetch/$s_!AMGK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff5d820b-05be-44c3-b4ec-bd67fb102ebf_1351x609.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Flip the filter to <strong>High Vol</strong> , and that clean diagonal completely dissolves. The lines chop randomly around the 0% line. In high-vol regimes, the edge practically evaporates into noisy random drift. If you don&#8217;t gate that strategy with a basic volatility filter, your backtest might look acceptable on paper, but your live performance will get wrecked during volatile sessions.</p><p><em>(Note: When I tested 10-year US Treasuries without a filter, it looked like random drift. But slapping on an uptrend filter revealed a clear buy-the-dip bias. im not adding it here because by now you get the point)</em></p><h3>The Roadmap to Feature Engineering</h3><p>Once the tendency script gives us our roadmap, we aren&#8217;t guessing anymore. If the data shows Gold on H1 during low volatility wants momentum, we point our pipeline directly at momentum.</p><p>Because we&#8217;re swimming with the market&#8217;s natural grain, we can generate thousands of features in that direction at once, knowing a large chunk will naturally work. We aren&#8217;t overfitting by hunting for a lucky spike in a random basket; we&#8217;re picking the best out of an already favorable one.</p><p>For those who want to start building, here is the high-level architecture of the feature engineering engine coming in the next post. The script takes three inputs: <strong>timeframe</strong>, <strong>direction</strong> (long/short), and <strong>type</strong> (mean reversion or momentum). No complex filters at this stage.</p><p>A few strict rules keep it clean:</p><ul><li><p><strong>No candle shapes, wicks, or streaks:</strong> They carry zero statistical weight. and I personally don&#8217;t like them, they remind me of the bullshit I did as a new trader</p></li><li><p><strong>No bounded oscillators:</strong> Indicators like RSI or ADX flatline at long lookbacks like N=200. We only use unbounded primitives that scale smoothly across lookbacks.</p></li><li><p><strong>Lookback Grid (N):</strong> 2, 3, 5, 8, 13, 21, 34, 55, 89, 144.</p></li><li><p><strong>Expanding Percentile Rank:</strong> Every raw feature is converted to a 0&#8211;1 percentile rank so entry thresholds (e.g., top 10%) apply uniformly across all primitives. <em>(Handling your initial warm-up sample here is an exercise left for the reader).</em></p></li></ul><p>The engine uses two core primitive sets:</p><ul><li><p><strong>Mean Reversion Primitives (10):</strong> Z-score of close, % distance from EMA, distance from N-bar extreme in ATR, N-bar return / ATR, Bollinger %B, deviation from rolling median (MAD), regression channel Z-score, distance from range midpoint, distance from session open, and distance from prior day close.</p></li><li><p><strong>Momentum Primitives (10):</strong> Log return, skip-recent return ($t-N$ to $t-k$), regression slope of log price, EMA spread, Donchian distance in ATR, acceleration (R_a - R_b), EMA slope, run-up from low, drawdown from high, and lagged cycle return.</p></li></ul><p>These 20 are just a baseline&#8212;you can easily plug in order flow, volume, and session times. Downstream, a search script crosses each ranked feature with holding periods and ATR stops, scores them on <strong>mean bps per day held</strong> (so long holds don&#8217;t win on duration alone), and clusters the survivors by entry overlap to eliminate duplicates.</p><p>Keep in mind this tool is strictly for <strong>time-series</strong> strategies; cross-sectional and rotational models have their own tendency tests for later articles. In the next piece, we&#8217;ll dive into the script that scores these features, prunes the noise, and bundles the survivors into a portfolio. Then Yay we get that pretty historical equity curve&#128514;, run it out of sample for a few months, and see how it actually handles live capital. subscribe so you dont miss it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h3>The Decile Analysis Script</h3><p>Here is the complete Streamlit script used to generate all the charts above. Save it as a Python file (e.g., <code>tendency_tool.py</code>), update the <code>DATA_PATH</code> to point to your local CSV containing OHLC data, and launch it from your terminal with:</p><p><code>streamlit run tendency_tool.py</code></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;5d3a7c81-71af-413a-8660-d508a954b846&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">

import streamlit as st

import pandas as pd

import numpy as np

import plotly.graph_objects as go

# =====================================================================

# USER INPUT CONFIGURATION

# =====================================================================

# File path to your dataset

DATA_PATH = r&#8221;C:\path\to\your\data\BTCUSD_Spot_Data.csv&#8221;

# Timeframe options for the selector and starting default

AVAILABLE_TIMEFRAMES = [&#8221;H1&#8221;, &#8220;H4&#8221;, &#8220;H8&#8221;, &#8220;D1&#8221;]

DEFAULT_TIMEFRAME = &#8220;H1&#8221;

# Forward horizons (H) for the selector and starting default

AVAILABLE_HORIZONS = [1, 5, 10, 20]

DEFAULT_HORIZON = 10

# Lookbacks (N) available in the multiselect and starting active lines

AVAILABLE_LOOKBACKS = [1, 2, 3, 5, 10, 20, 50, 100, 200, 500]

DEFAULT_LOOKBACKS = [1, 5, 20, 50, 100]

# --- Filter Settings (Configured at Code Level) ---

DAILY_EMA_PERIOD = 100           # Period for the daily trend EMA

ATR_PERIOD = 14                 # ATR length computed on the active timeframe

ATR_LOOKBACK_MEDIAN = 100       # Rolling median window to partition High vs Low Vol

# =====================================================================

# ---------------------------------------------------------------------

# Page Setup &amp; Modern Dark Canvas Styling

# ---------------------------------------------------------------------

st.set_page_config(

    page_title=&#8221;Directional Tendency Test&#8221;,

    layout=&#8221;wide&#8221;,

    initial_sidebar_state=&#8221;expanded&#8221;

)

st.markdown(

    &#8220;&#8221;&#8220;

    &lt;style&gt;

        .block-container {

            padding-top: 1.8rem;

            padding-bottom: 2rem;

        }

        [data-testid=&#8221;stSidebar&#8221;] {

            background-color: #0d1117;

            border-right: 1px solid #21262d;

        }

    &lt;/style&gt;

    &#8220;&#8221;&#8220;,

    unsafe_allow_html=True

)

# ---------------------------------------------------------------------

# Data Loading, Resampling &amp; Indicator Engineering

# ---------------------------------------------------------------------

@st.cache_data

def load_base_data(file_path: str) -&gt; pd.DataFrame:

    df = pd.read_csv(file_path)

    # Detect datetime column

    date_col = None

    for col in [&#8221;datetime&#8221;, &#8220;date&#8221;, &#8220;timestamp&#8221;, &#8220;time&#8221;, &#8220;Date&#8221;, &#8220;Datetime&#8221;]:

        if col in df.columns:

            date_col = col

            break

    if date_col is not None:

        df[date_col] = pd.to_datetime(df[date_col])

        df = df.sort_values(date_col).set_index(date_col)

    else:

        df.iloc[:, 0] = pd.to_datetime(df.iloc[:, 0])

        df = df.sort_values(df.columns[0]).set_index(df.columns[0])

    # Standardize column names (lowercase)

    col_map = {}

    for col in df.columns:

        c_lower = str(col).lower()

        if c_lower in [&#8221;open&#8221;, &#8220;o&#8221;]:

            col_map[col] = &#8220;open&#8221;

        elif c_lower in [&#8221;high&#8221;, &#8220;h&#8221;]:

            col_map[col] = &#8220;high&#8221;

        elif c_lower in [&#8221;low&#8221;, &#8220;l&#8221;]:

            col_map[col] = &#8220;low&#8221;

        elif c_lower in [&#8221;close&#8221;, &#8220;c&#8221;]:

            col_map[col] = &#8220;close&#8221;

    df = df.rename(columns=col_map)

    if &#8220;close&#8221; not in df.columns:

        df[&#8221;close&#8221;] = df.iloc[:, 0]

    # Ensure OHLC presence or fallback to close

    for col in [&#8221;open&#8221;, &#8220;high&#8221;, &#8220;low&#8221;]:

        if col not in df.columns:

            df[col] = df[&#8221;close&#8221;]

    return df[[&#8221;open&#8221;, &#8220;high&#8221;, &#8220;low&#8221;, &#8220;close&#8221;]].dropna().astype(float)

def resample_and_compute_indicators(

    raw_df: pd.DataFrame, 

    tf_label: str, 

    daily_ema_len: int, 

    atr_len: int, 

    atr_median_window: int

) -&gt; pd.DataFrame:

    # 1. Compute Daily EMA without lookahead bias

    daily_df = raw_df.resample(&#8221;1D&#8221;).agg({

        &#8220;open&#8221;: &#8220;first&#8221;,

        &#8220;high&#8221;: &#8220;max&#8221;,

        &#8220;low&#8221;: &#8220;min&#8221;,

        &#8220;close&#8221;: &#8220;last&#8221;

    }).dropna()

    daily_ema = daily_df[&#8221;close&#8221;].ewm(span=daily_ema_len, adjust=False).mean()

    # Shift by 1 day so intraday bars only reference the prior completed day&#8217;s EMA

    daily_ema_lagged = daily_ema.shift(1)

    # 2. Resample to selected intraday timeframe

    freq_map = {&#8221;H1&#8221;: &#8220;1h&#8221;, &#8220;H4&#8221;: &#8220;4h&#8221;, &#8220;H8&#8221;: &#8220;8h&#8221;, &#8220;D1&#8221;: &#8220;1D&#8221;}

    freq = freq_map.get(tf_label, &#8220;1h&#8221;)

    if tf_label == &#8220;D1&#8221;:

        tf_df = daily_df.copy()

        tf_df[&#8221;daily_ema&#8221;] = daily_ema_lagged

    else:

        tf_df = raw_df.resample(freq).agg({

            &#8220;open&#8221;: &#8220;first&#8221;,

            &#8220;high&#8221;: &#8220;max&#8221;,

            &#8220;low&#8221;: &#8220;min&#8221;,

            &#8220;close&#8221;: &#8220;last&#8221;

        }).dropna()

        # Merge lagged Daily EMA onto intraday bars

        tf_df[&#8221;daily_ema&#8221;] = daily_ema_lagged.reindex(tf_df.index, method=&#8221;ffill&#8221;)

    # 3. Compute ATR on the active timeframe

    high = tf_df[&#8221;high&#8221;]

    low = tf_df[&#8221;low&#8221;]

    prev_close = tf_df[&#8221;close&#8221;].shift(1)

    tr1 = high - low

    tr2 = (high - prev_close).abs()

    tr3 = (low - prev_close).abs()

    true_range = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)

    tf_df[&#8221;atr&#8221;] = true_range.rolling(window=atr_len).mean()

    tf_df[&#8221;atr_median&#8221;] = tf_df[&#8221;atr&#8221;].rolling(window=atr_median_window).median()

    return tf_df.dropna()

# ---------------------------------------------------------------------

# Core Quantile &amp; Mask Computation Engine

# ---------------------------------------------------------------------

def compute_conditioned_slope(

    df: pd.DataFrame, 

    n_list: list, 

    h_val: int, 

    filter_mode: str

) -&gt; dict:

    results = {}

    close_series = df[&#8221;close&#8221;]

    fwd_ret = (close_series.shift(-h_val) / close_series) - 1.0

    decile_labels = [f&#8221;D{i}&#8221; for i in range(1, 11)]

    # Define filter conditions

    if filter_mode == &#8220;Uptrend&#8221;:

        mask = df[&#8221;close&#8221;] &gt; df[&#8221;daily_ema&#8221;]

    elif filter_mode == &#8220;Downtrend&#8221;:

        mask = df[&#8221;close&#8221;] &lt; df[&#8221;daily_ema&#8221;]

    elif filter_mode == &#8220;High Vol&#8221;:

        mask = df[&#8221;atr&#8221;] &gt; df[&#8221;atr_median&#8221;]

    elif filter_mode == &#8220;Low Vol&#8221;:

        mask = df[&#8221;atr&#8221;] &lt;= df[&#8221;atr_median&#8221;]

    else:

        mask = pd.Series(True, index=df.index)

    for n in sorted(n_list):

        sig_ret = (close_series / close_series.shift(n)) - 1.0

        combined = pd.DataFrame({

            &#8220;signal&#8221;: sig_ret,

            &#8220;fwd&#8221;: fwd_ret,

            &#8220;mask&#8221;: mask

        }).dropna()

        if len(combined) &lt; 10:

            continue

        try:

            # 1. Lock decile boundaries on the FULL unfiltered sample

            combined[&#8221;bucket&#8221;] = pd.qcut(

                combined[&#8221;signal&#8221;],

                q=10,

                labels=decile_labels,

                duplicates=&#8221;drop&#8221;

            )

            # 2. Filter rows according to selected regime

            filtered_combined = combined[combined[&#8221;mask&#8221;]]

            if len(filtered_combined) == 0:

                continue

            # 3. Calculate mean forward return for surviving bars

            mean_returns = filtered_combined.groupby(&#8221;bucket&#8221;, observed=False)[&#8221;fwd&#8221;].mean() * 100.0

            results[n] = mean_returns.reindex(decile_labels)

        except Exception:

            continue

    return results

# ---------------------------------------------------------------------

# Sidebar Controls

# ---------------------------------------------------------------------

st.sidebar.markdown(&#8221;### Controls&#8221;)

selected_tf = st.sidebar.selectbox(

    &#8220;Timeframe&#8221;,

    options=AVAILABLE_TIMEFRAMES,

    index=AVAILABLE_TIMEFRAMES.index(DEFAULT_TIMEFRAME) if DEFAULT_TIMEFRAME in AVAILABLE_TIMEFRAMES else 0

)

selected_h = st.sidebar.selectbox(

    &#8220;Forward Horizon (H)&#8221;,

    options=AVAILABLE_HORIZONS,

    index=AVAILABLE_HORIZONS.index(DEFAULT_HORIZON) if DEFAULT_HORIZON in AVAILABLE_HORIZONS else 0

)

selected_filter = st.sidebar.selectbox(

    &#8220;Filter&#8221;,

    options=[&#8221;None&#8221;, &#8220;Uptrend&#8221;, &#8220;Downtrend&#8221;, &#8220;High Vol&#8221;, &#8220;Low Vol&#8221;],

    index=0

)

selected_n = st.sidebar.multiselect(

    &#8220;Lookback (N)&#8221;,

    options=AVAILABLE_LOOKBACKS,

    default=[x for x in DEFAULT_LOOKBACKS if x in AVAILABLE_LOOKBACKS]

)

# ---------------------------------------------------------------------

# Execution &amp; Chart Construction

# ---------------------------------------------------------------------

try:

    raw_data = load_base_data(DATA_PATH)

    processed_df = resample_and_compute_indicators(

        raw_data, 

        selected_tf, 

        DAILY_EMA_PERIOD, 

        ATR_PERIOD, 

        ATR_LOOKBACK_MEDIAN

    )

except Exception as e:

    st.error(f&#8221;Error loading or preparing data from `{DATA_PATH}`: {e}&#8221;)

    st.stop()

if not selected_n:

    st.warning(&#8221;Please select at least one Lookback (N) from the sidebar.&#8221;)

    st.stop()

slope_data = compute_conditioned_slope(processed_df, selected_n, selected_h, selected_filter)

palette = [

    &#8220;#38bdf8&#8221;, &#8220;#818cf8&#8221;, &#8220;#c084fc&#8221;, &#8220;#f472b6&#8221;, 

    &#8220;#fb923c&#8221;, &#8220;#facc15&#8221;, &#8220;#4ade80&#8221;, &#8220;#2dd4bf&#8221;

]

fig = go.Figure()

fig.add_hline(

    y=0,

    line_dash=&#8221;dash&#8221;,

    line_color=&#8221;#4b5563&#8221;,

    line_width=1.5,

    opacity=0.7

)

for idx, (n_val, series_returns) in enumerate(slope_data.items()):

    color = palette[idx % len(palette)]

    fig.add_trace(

        go.Scatter(

            x=series_returns.index.tolist(),

            y=series_returns.values,

            mode=&#8221;lines+markers&#8221;,

            name=f&#8221;N = {n_val}&#8221;,

            line=dict(width=2.5, color=color),

            marker=dict(size=6, color=color),

            hovertemplate=(

                f&#8221;&lt;b&gt;Lookback N = {n_val}&lt;/b&gt;&lt;br&gt;&#8221;

                &#8220;Decile: %{x}&lt;br&gt;&#8221;

                &#8220;Mean Forward Return: %{y:.3f}%&#8221;

                &#8220;&lt;extra&gt;&lt;/extra&gt;&#8221;

            )

        )

    )

chart_subtitle = f&#8221;Filter: {selected_filter} | Horizon: H={selected_h} | Timeframe: {selected_tf}&#8221;

fig.update_layout(

    template=&#8221;plotly_dark&#8221;,

    paper_bgcolor=&#8221;rgba(0,0,0,0)&#8221;,

    plot_bgcolor=&#8221;rgba(0,0,0,0)&#8221;,

    height=720,

    margin=dict(l=20, r=20, t=30, b=20),

    legend=dict(

        orientation=&#8221;h&#8221;,

        yanchor=&#8221;bottom&#8221;,

        y=1.02,

        xanchor=&#8221;right&#8221;,

        x=1,

        title=dict(text=&#8221;&#8220;)

    ),

    xaxis=dict(

        title=dict(

            text=f&#8221;Decile Bucket (D1: Deepest Drops -&gt; D10: Largest Rallies) &#8212; [{chart_subtitle}]&#8221;,

            font=dict(size=12, color=&#8221;#94a3b8&#8221;)

        ),

        showgrid=True,

        gridcolor=&#8221;#1f2937&#8221;,

        tickfont=dict(color=&#8221;#cbd5e1&#8221;, size=12)

    ),

    yaxis=dict(

        title=dict(text=f&#8221;Mean Forward Return [%]&#8221;, font=dict(size=13, color=&#8221;#94a3b8&#8221;)),

        showgrid=True,

        gridcolor=&#8221;#1f2937&#8221;,

        zeroline=False,

        ticksuffix=&#8221;%&#8221;,

        tickfont=dict(color=&#8221;#cbd5e1&#8221;, size=12)

    )

)

st.plotly_chart(fig, use_container_width=True)



</code></pre></div>]]></content:encoded></item><item><title><![CDATA[How to Discover Systematic Trading Strategies From Scratch]]></title><description><![CDATA[How we turn raw data into tradeable signals, and the exact framework behind our upcoming system.]]></description><link>https://mechanicalpremia.substack.com/p/how-to-discover-systematic-trading</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/how-to-discover-systematic-trading</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Sun, 11 Oct 2026 15:04:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4a362b63-6d90-403c-874d-f4d43eb6f5cf_2400x1792.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the last few weeks, I&#8217;ve spent time talking with subscribers, and one question keeps coming up: <em>how do you actually discover new strategies from scratch?</em></p><p>Most of the content in this space falls into two categories: people selling finished strategies (something I&#8217;ve done myself), or people talking about managing and risk-sizing an existing system. Almost nobody writes about the discovery phase itself. Which is unfortunate, because sitting down with raw data, testing an idea, and seeing if there is an actual pulse there is easily the most rewarding part of systematic trading.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Mechanical Premia! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>It is definitely a grind. It is not something you knock out in an afternoon. Most of the work is unglamorous&#8212;cleaning bad broker data, aligning timestamps across different sessions, tracking down selection bias, and making sure you didn&#8217;t accidentally code lookahead bias into your rolling calculations. But once your data pipeline is clean, testing and building the actual features is where the craft really is.</p><h3>Standing on the Shoulders of Giants</h3><p>You don&#8217;t need to reinvent the wheel when you start. Newton had the quote about standing on the shoulders of giants, and it applies directly here in two practical ways.</p><p>First is your asset universe. The universe you pick dictates your odds before you even write a single line of logic. Trying to find a breakout edge on short-term bonds or dead FX crosses is just asking for frustration&#8212;the structural volatility isn&#8217;t there to pay for the false breakouts. If you want to research momentum, look at equity indices or commodities. If you want carry, look at high-yielding currency pairs. Pick an asset class where the behavior you are trying to capture actually happens.</p><p>Second is the core anomaly. Decades of research have already mapped out anomalies with structural staying power: momentum, overnight equity drift, post-liquidity mean reversion, carry premiums. You don&#8217;t need a brand-new concept. You just need to take an established idea and translate it into clear, systematic features you can test.</p><h3>The Practical Sandbox: Building the Universe</h3><p>To make this practical, we need an actual sandbox. I picked a small, diversified macro basket that you can trade on almost any standard prop firm: <strong>SPY, DAX, Gold, Crude Oil, Natural Gas, and the Japanese Yen</strong>. I deliberately left crypto out. Adding Bitcoin or Ethereum to an exploratory momentum universe tends to artificially flatter your results&#8212;crypto&#8217;s multi-year structural bull runs will make almost any trend signal look better than it is, masking flaws you would otherwise catch immediately.</p><p>The core idea here is borrowed directly from classic CTA futures trend-following. The caveat is that we aren&#8217;t running an institutional book across 60 exchange-traded futures contracts; we are applying the logic to a tight basket of CFDs on a retail prop broker. Decades of research have established that momentum has persistent staying power across these exact sectors&#8212;equities, energies, metals, and foreign exchange.</p><p>For the data, we pulled daily OHLC bars from Dukascopy dating from 2014 to the current day, cleaned the timestamps, and aligned them to a common trading calendar.</p><h3>Feature Engineering: Turning Data Into Signals</h3><p>A lot of people approach strategy design differently, and everyone has their own biases. But since you&#8217;re reading this to see my actual process, here is how I approach it. At its core, momentum is straightforward: it is simply a bet that the change between price X bars ago and price Now will continue into the future. Feature engineering is just taking your raw data&#8212;whether that&#8217;s OHLC, volume, order flow, or alternative datasets&#8212;and transforming it into a mathematical number that represents that change.</p><p>Once you have that number, you have an execution choice: <strong>discrete</strong> or <strong>continuous</strong>.</p><ul><li><p><strong>Discrete:</strong> A binary trigger. Price crosses a threshold, and your system flips a switch: buy 1 lot, sell 1 lot, or sit flat. It is either on or off.</p></li><li><p><strong>Continuous:</strong> A dial. The feature outputs a scaled intensity value (for example, from 0.0 to 1.0), and your position size scales smoothly with the strength of the move.</p></li></ul><p>Neither approach is objectively better than the other. It is purely a matter of execution philosophy. For this framework, I prefer continuous signals because they double as an automatic position-sizing and exit engine.</p><h3>The 7 Breakout Transforms</h3><p>To measure that price change from different mathematical angles, I built 7 basic transforms across five rolling lookback windows (5, 20, 50, 100, and 200 bars).</p><p>These are by no means an exhaustive or complete list. You can probably think of half a dozen other ways to formulate price displacement, volatility expansion, or momentum. These are simply practical examples of how to quantify the concept:</p><ol><li><p><strong>Normalized Momentum (</strong><code>norm_mom</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> (Close - Close[t-w]) / ATR(w)</p></li><li><p><strong>The logic:</strong> Measures the point change over window w, divided by the Average True Range. Scaling by ATR keeps the value comparable across calm and volatile market regimes.</p></li></ul></li><li><p><strong>Moving Average Distance (</strong><code>dist</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> (Close - SMA(w)) / StdDev(w)</p></li><li><p><strong>The logic:</strong> A classic rolling Z-score. It measures how many standard deviations current price is sitting above or below its rolling average.</p></li></ul></li><li><p><strong>Channel Position (</strong><code>channel_pos</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> (Close - Min(w)) / (Max(w) - Min(w)) - 0.5</p></li><li><p><strong>The logic:</strong> A bounded oscillator centered at zero. It maps where price sits within its rolling high-low channel on a scale from -0.5 (at the low) to +0.5 (at the high).</p></li></ul></li><li><p><strong>Trend Slope (</strong><code>trend_slope</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> (EMA(w) - EMA(w)[t-step]) / (step * ATR(w))</p></li><li><p><strong>The logic:</strong> Instead of measuring price relative to the moving average, this measures the velocity and angle of the moving average itself, normalized by ATR.</p></li></ul></li><li><p><strong>Efficiency Ratio (</strong><code>efficiency</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> Sign(Net Move) * (|Net Move| / Gross Path)</p></li><li><p><strong>The logic:</strong> A noise filter based on Kaufman&#8217;s efficiency ratio. It measures the net displacement divided by the total path traveled, separating straight-line moves from noisy chop.</p></li></ul></li><li><p><strong>Momentum Acceleration (</strong><code>accel</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> norm_mom(w) - norm_mom(w)[t-5]</p></li><li><p><strong>The logic:</strong> The rate of change of normalized momentum, showing whether the thrust is speeding up or slowing down.</p></li></ul></li><li><p><strong>Trend Persistence (</strong><code>persistence</code><strong>)</strong></p><ul><li><p><strong>Formula:</strong> Consecutive closes above the EMA divided by w (or negative if below).</p></li><li><p><strong>The logic:</strong> Measures how many bars price has consistently stayed on one side of the trend line, regardless of the distance moved.</p></li></ul></li></ol><h3>Regime Filters, Cost Auditing, and Turnover</h3><p>Once you generate raw features, the immediate urge is to start taking trades on every single fluctuation. In practice, that is usually how an account bleeds out. This is where regime filters come into play. In my testing, I use four basic states: <code>HIGH_VOL</code>, <code>LOW_VOL</code>, <code>HIGH_CHOP</code>, and <code>LOW_CHOP</code>. I do not add filters to create an edge. If the underlying price transform has zero statistical pulse on its own, stacking two or three indicators on top of it will not save it. I add filters when the trade count is simply way too high.</p><p>Their primary job is pruning: cutting out low-quality trades and reducing turnover while preserving the core edge. If a filter cuts your total trade count in half while preserving 80% to 90% of the gross profit, your net performance improves substantially because you stopped paying transaction costs on marginal setups.</p><h3>The Overfitting Reality</h3><p>This is also the stage where most research goes off the rails.</p><p>Historical market data will give you any return you want if you mess with it long enough. If you keep stacking conditions say, an ADX threshold, a specific moving average slope, and a session time filter you can easily produce an immaculate 45-degree equity curve on past data. But all you have done is curve-fit past noise, and the system will fall apart the moment live capital is deployed.</p><p>To avoid tricking myself, I stick to two ground rules:</p><ol><li><p><strong>Keep parameters minimal:</strong> Filters should represent broad conditions, like a rolling volatility rank or Kaufman efficiency ratio, rather than a hyper-tuned set of nested logic.</p></li><li><p><strong>Audit with pessimistic costs:</strong> There is no point in deceiving yourself during the discovery phase. On spot FX pairs, my actual execution costs usually sit around 3 bps. When running research backtests, I routinely test against 10 bps. If a system cannot survive aggressive, pessimistic cost drag in backtesting, it will never survive real-world slippage, spread widening during news events, and weekend swap fees on a live broker.</p></li></ol><h3>Managing Turnover: The Rebalance Buffer</h3><p>Because I prefer continuous signals over discrete binary entries, the system outputs a target weight vector for each asset across the basket every day rather than an on/off switch. That introduces a mechanical issue: continuous signals adjust slightly on almost every bar. If your target weight on Gold shifts from 12.0% on Monday to 12.3% on Tuesday, naively rebalancing to match that 0.3% drift will churn your account to pieces in spread and commissions.</p><p>To handle this, I use a simple rebalancing buffer:</p><ul><li><p><strong>Target weight shift greater than 10 - 20%:</strong> Rebalance to the new target.</p></li><li><p><strong>Target weight shift 10-20% or less:</strong> Hold the current position.</p></li></ul><p>Unless the target position moves by more than the 10-20% buffer, the model does nothing. That keeps turnover under control, lets the system ride persistent trends, and avoids bleeding capital on micro-adjustments.</p><h3>Validation and Conceptual Neighborhoods</h3><p>Once you run this pipeline across your universe, you end up with a table of metrics&#8212;Sharpe, CAGR, maximum drawdown, and win rates across different combinations.</p><p>How you validate those results comes down to personal preference. You will find endless academic literature on rigorous statistical tests: combinatorial purged cross-validation, Deflated Sharpe Ratios, Monte Carlo permutations, and White&#8217;s Reality Check. I do not disagree with any of those methods. If you use them and they fit your workflow, keep using them.</p><p>For me, what works consistently is keeping the parameter count low and testing <strong>conceptual neighborhoods</strong>.</p><p>Most retail traders focus only on parameter neighborhoods. If an EMA lookback of 20 produces a profitable backtest, they check 18, 19, 21, and 22 to see if the performance cliff-dives. That is a useful baseline check against local overfitting, but it misses the larger question: <em>is the underlying idea itself valid?</em></p><p>If an economic anomaly is genuine, neighboring expressions of that exact same concept should also show a pulse across the same asset universe:</p><ul><li><p>If a 50-day Donchian breakout (<code>channel_pos</code>) shows a durable edge, then trend slope (<code>trend_slope</code>), moving average distance (<code>dist</code>), and volatility-normalized momentum (<code>norm_mom</code>) across similar horizons should also register positive performance.</p></li><li><p>If only one specific channel formula works, while every other mathematical way of measuring &#8220;price went up&#8221; falls completely flat, you have not discovered a market edge. You have simply isolated a historical fluke that fit past price action by luck.</p></li></ul><p>When an idea is robust, the entire conceptual cluster tends to stay above water. It might not all have the highest Sharpe, but the underlying direction holds up across multiple mathematical formulations.</p><h3>What Comes Next</h3><p>That is the discovery process in practice: selecting a sensible playground where anomalies naturally occur, writing basic transforms that convert raw data into scaled mathematical signals, gating turnover with simple regime filters, accounting for pessimistic costs, and making sure the broad concept holds up across neighboring math.</p><p>In the next piece, we will take the logic built here, wire it into a fully formed strategy, and walk through the portfolio allocation rules, position sizing, and live trade mechanics needed to run it in a real terminal and we will build this system </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TOMc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TOMc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 424w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 848w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 1272w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!TOMc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png" width="1364" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1364,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89455,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/219858586?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TOMc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 424w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 848w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 1272w, https://substackcdn.com/image/fetch/$s_!TOMc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe90dc8e2-9c79-43ee-9904-8413c0919bfc_1364x728.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Sb_U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 424w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 848w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 1272w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Sb_U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png" width="722" height="188" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8aeced35-be20-44a6-95e3-04578731b089_722x188.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:188,&quot;width&quot;:722,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:10182,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/219858586?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Sb_U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 424w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 848w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 1272w, https://substackcdn.com/image/fetch/$s_!Sb_U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aeced35-be20-44a6-95e3-04578731b089_722x188.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div></figure></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Mechanical Premia! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[What Casinos, Prop Firms, and Averaging Down Have in Common (And Why That’s Actually a Good Thing)]]></title><description><![CDATA[Averaging down on live market positions will blow your account. Averaging down on evaluation fees, however, is the exact mechanic that breaks the prop firm's bank (Disclaimer: must have edge &#128514;)]]></description><link>https://mechanicalpremia.substack.com/p/what-casinos-prop-firms-and-averaging</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/what-casinos-prop-firms-and-averaging</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Sat, 26 Sep 2026 08:45:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/71c79ee3-b04d-4af8-918c-2a6c805a0f5f_2814x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have never set foot in a real casino. Well, unless you count blowing up my very first trading account years ago, which was practically the exact same thing with worse lighting and no complimentary drinks. I don&#8217;t know how blackjack tables operate behind the scenes, and I couldn&#8217;t tell you the first thing about roulette odds. But I do understand how prop firms run their business, and the overlap is undeniable.</p><p>Prop firms are not angel investors combing the retail market to discover undiscovered trading prodigies. They operate high-turnover casinos. The business model is simple: sell cheap challenge tickets, say, $70 for a $10,000 account, knowing full well that about 95% of retail traders are going to blow up. People overleverage, hit arbitrary daily loss limits, revenge-trade after one red morning, blow the evaluation, and immediately buy another ticket. The challenge fees fund the entire machine.</p><p>In a normal casino, the house edge is mathematically baked into the game; play long enough, and the math guarantees you lose. But prop firms have a unique flaw in their setup: they are offering leverage for a fixed fee to anyone who walks through the door, assuming the player has no real edge.</p><p>If you are a systematic trader running an automated model that actually has an edge (and you haven&#8217;t overfitted your backtests), you aren&#8217;t the gambler anymore. You are someone walking in with positive expectancy against a house that expects you to fail They&#8217;ll kick you out if you win too much, so take it easy. The trick is that you cannot play the game the way they expect you to play it. Most people treat challenge accounts like their ticket out of the trenches. They take it slow, risk tiny amounts, and try to crawl their way through evaluation targets.</p><p>That approach plays directly into the house&#8217;s hands. The longer you hang around an evaluation, the more time you give the market and the firm to hand you random friction, widened spreads, and other miscellaneous bullshit. If we want positive expected value, we have to look at the rules, accept that accounts will be blown, and turn the math entirely on its head.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h3>Meet the Contender Or The Test Subject: The Index Mean Reversion Portfolio</h3><p>Before we dive into the simulation numbers, we need a test subject. You cannot run this math on vibes. You need an actual systematic edge, which brings us right back to the disclaimer in the title: you must have an edge. If you don&#8217;t have a tested system of your own, grab one of the open-source strategies I have already released to make sure you are operating with positive EV. A broken system with a 0.2 Sharpe will get you wiped out regardless of how clever your account math is.</p><p>Here is the candidate we are using today. It isn&#8217;t just one single indicator firing blind trades; it is a multi-strategy mean-reversion portfolio built for US indices (US100 and US500).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MzbA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MzbA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 424w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 848w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 1272w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MzbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png" width="727" height="454.04928315412184" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:697,&quot;width&quot;:1116,&quot;resizeWidth&quot;:727,&quot;bytes&quot;:55988,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/217499893?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MzbA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 424w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 848w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 1272w, https://substackcdn.com/image/fetch/$s_!MzbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f5f3a74-3156-4b1f-b5a7-0ebb6da6fd56_1116x697.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WNeW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WNeW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 424w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 848w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 1272w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!WNeW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png" width="1456" height="659" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:659,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38162,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/217499893?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WNeW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 424w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 848w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 1272w, https://substackcdn.com/image/fetch/$s_!WNeW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F294b1e93-26fb-48fd-9b0f-10e9427fdb7e_1582x716.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>As you can see from the inputs, everything in this book is designed around buying dips:</p><ul><li><p><strong>Strategy 1: Daily RSI(2) Pullback:</strong> Classic short-term exhaustion buyer above the 100 EMA.</p></li><li><p><strong>Strategy 2: Daily Internal Bar Strength (IBS) Pullback:</strong> Entering on deep intraday flushes where IBS closes near the low of the day.</p></li><li><p><strong>Strategy 3: H1 Momentum Seasonality:</strong> Forgive the silly name on this one, it literally buys when momentum is down.</p></li><li><p><strong>Strategy 4: D1 KER-Modulated CMMA:</strong> Using efficiency ratios to capture mean-reverting moves when price stretches too far from its moving average.</p></li></ul><p>More importantly, look at the very top setting: <code>Daily_Loss_Limit_Perc = 3.8</code>.</p><p>Not just any strategy can be plugged into a prop firm. Your EA must be built to be prop-firm safe. It needs hard internal circuit breakers specifically coded to handle news restrictions, weekend holding limits, and hard daily drawdowns. If your daily limit at the firm is 4.0%, you hard-code your bot to pull the plug at 3.8% so server slippage doesn&#8217;t breach you.</p><h3>The Playing Field: Why 2-Step Accounts</h3><p>The final prerequisite is picking the right battlefield. We strictly target 2-step evaluation models over 1-step accounts.</p><p>1-step accounts lure people in because there is only one profit target to hit, but they almost always saddle you with a trailing drawdown. I don&#8217;t think I need to explain to anyone why trailing drawdowns are simply worse edge. A drawdown floor that moves up every time you make money, locking your risk cushion into a tighter box, is obviously far worse than a static floor that stays anchored to your starting balance.</p><p>With 2-step accounts, you have to hit two targets (+8% and +5%), but you get a static drawdown limit. That fixed floor gives a mean-reversion system room to take its normal sequence of paper cuts without the rules shifting underneath it.</p><h3>Averaging Down on Fees: The Meta-Account Engine</h3><p>You know how grid systems and averaging down strategies lure retail traders in. They produce unnaturally smooth, beautiful 45-degree equity curves and absurdly high win rates right up until the tail event hits and nukes the balance. We are borrowing that exact behavioral mechanic, but with one critical distinction: we never average down on live market positions where our downside is open-ended. Instead, we apply it strictly to our challenge fees.</p><p>We treat our 3-account queue as one single meta-account with $210 of total capital expenditure. If Account #1 takes a statistically normal, healthy drawdown right after we buy it and hits the static floor, we do not get emotional. We simply average down into bullet #2, and then bullet #3 if needed. We stop the moment a single account gets funded.</p><p>Why not just play it safe, trade tiny, and try to pass a single evaluation over six months? Because the calendar friction will bleed you dry. Look at the single-account timeline from our simulations: even with our aggressive sizing, the P95 slow case takes 188.4 trading days just to turn a cash payout. Note that this is active trading days, not calendar days. That is roughly nine months of market exposure. If you trade with standard baseline sizing, you are signing up to sit in evaluation purgatory for well over a year. The longer you hang around, the more chances the firm has to knock you out with spread spikes or server issues.</p><p>Of course, this entire averaging down mechanic only works if you actually have positive expected value. If your underlying trading system has no edge, averaging down on fees is just burning cash in three-ticket batches. You need to know that your edge is real and track whether it is still functioning as expected. I wrote an article a while back titled <em>&#8220;Strategy Invalidation &amp; When to Pull the Plug&#8221;</em>&#8212;read that if you want the framework for knowing when a system is actually broken.</p><h3>The Two Gears: The 1.5x Sprint vs. The 0.5x Grind</h3><p>To make the math work, we run the system in two completely different gears.</p><p>When we run our backtest in MT5, our baseline trades are sized around typical conservative numbers (like 0.2% or 0.3% per position). Python takes those daily returns and applies our multiplier:</p><ol><li><p><strong>The Evaluation Phase (</strong><code>CHALLENGE_RISK_MULT = 1.50</code><strong>):</strong></p><p>During Phase 1 (+8%) and Phase 2 (+5%), we deliberately step on the gas. We size at 1.5x baseline risk because we want variance on our side to clear the hurdles quickly.</p><p>Some people ask why we don&#8217;t just crank the multiplier to 5x or 10x to pass in two days. The answer is the daily loss ceiling. Prop firms enforce a hard daily loss limit, typically 4%. If you crank your risk too high, a single correlated red day will punch straight through that ceiling and blow the account before your edge has a chance to play out. The 1.5x setting is the sweet spot that sprints through the phases without constantly face-planting into the 4% daily limit.</p></li><li><p><strong>The Funded Phase (</strong><code>FUNDED_RISK_MULT = 0.50</code><strong>):</strong></p><p>The second Phase 2 is cleared, our ego goes out the window. We drop the multiplier down to 0.5x. Now that real payouts are on the line, we cut our baseline trade risk in half. This gives our daily return fluctuations massive breathing room away from both the 4% daily loss limit and the 8% static drawdown floor.</p></li></ol><p>We also do not fall into the retail trap of trying to turn a $10,000 funded account into $100,000.</p><blockquote><p><strong>Important note on withdrawals:</strong> Prop firms are not your personal bank accounts, and they are not interested in keeping you funded. If you try to run a $10,000 account up to a $3,000 or $4,000 payout balance, you are painting a massive target on your back. The larger the withdrawal request, the more manual compliance scrutiny, &#8220;toxic flow&#8221; reviews, and arbitrary roadblocks you run into. The tinier the payout, the less likely they are to deny it. Get in, take small slices, get out, and use the cash to build your own personal live brokerage account that you actually control.</p></blockquote><p>Our extraction rule is purely mechanical: every time the account hits +3% ($300), we pull the cash immediately. At an 80% split, that puts $240 in our pocket, plus the $70 fee refund on the very first payout. We reset the balance back to the $10,000 baseline, let the EA run, and keep taking $240 bites until the account eventually meets its end.</p><p></p><h3>The Cold Hard Data and The Reality Filter</h3><p>To test whether this averaging-down mechanic actually works over thousands of market days, I wrote a Monte Carlo simulator in Python. It feeds on the daily trade tape from our Index Mean Reversion portfolio, shuffling sequences across 1,000 full campaigns (each with our 3-bullet reserve queue) so the results don&#8217;t rely on one lucky historical period.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bYKA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bYKA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 424w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 848w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 1272w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!bYKA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png" width="946" height="746" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:746,&quot;width&quot;:946,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60466,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/217499893?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bYKA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 424w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 848w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 1272w, https://substackcdn.com/image/fetch/$s_!bYKA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c652d3-f237-4d12-885f-9e2e1a22cbbd_946x746.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Look at the single most telling conversion stat: out of 863 accounts that passed Phase 2, 858 reached a cash payout. That is a 99.4% conversion rate once funded. Retail traders usually blow funded accounts because they get greedy and crank up their sizing. Slashing risk to 0.5x ensures that once you get a funded seat, you almost always survive long enough to pull real cash out.</p><p>Now for the reality check: kill the fantasy of the P5 fast case. Everyone expects to be funded in 19 trading days and cashing checks on day 45. You must plan for the P95 case. In slow market regimes, a campaign can take 122.9 trading days just to get funded, and 222.6 trading days (nearly a full year of active trading) to turn a single payout. If you do not mentally prepare for a 200+ day grind, boredom will set in, you will fiddle with your code, crank risk, and manually blow your own account.</p><h3>The Bullshit Parameter and the True +$674 EV</h3><p>The raw simulation prints an average net profit of $9,317.40 over the multi-year tape. Let&#8217;s be completely honest: no retail prop firm is letting you run an automated trading bot for two continuous years without finding an excuse to shut you down. In the real world, you have to factor in a linear increasing parameter of bullshit happening &#128514;. Rule tweaks, latency slippage, IP flags, or consistency clauses will eventually hit you.</p><p>So let&#8217;s kill the fantasy and run an aggressive, pessimistic calculation:</p><ul><li><p><strong>Worst-Case Cost:</strong> Assume we fail two attempts and burn all 3 accounts in the queue every single time (3 * $70 = $210 total CapEx).</p></li><li><p><strong>Short Lifespan:</strong> Assume the firm stays functional for just 4 small 3% payouts before the bullshit parameter clips the account.</p></li><li><p><strong>Cash Collected:</strong></p><ul><li><p>Payout 1: $240 split + $70 fee refund = $310</p></li><li><p>Payouts 2, 3, 4: $240 each = $720</p></li><li><p>Total Cash Extracted = $1,030</p></li></ul></li><li><p><strong>Net Win on a Successful Campaign:</strong> $1,030 - $210 = <strong>$820</strong></p></li></ul><p>Using our simulation&#8217;s 85.8% campaign profitability rate (and a 14.2% total wipeout rate):</p><p>EV = (P_win * Net Win) - (P_loss * Total CapEx)</p><p>EV = (0.858 * $820) - (0.142 * $210)</p><p>EV = $703.56 - $29.82 = <strong>+$673.74 per campaign</strong></p><p>Even assuming you burn every single reserve fee upfront, and even assuming the firm shuts you down after four tiny withdrawals, you are still walking away with nearly +$674 of positive expected value per 3-account campaign.</p><h3>The Assembly Line: Interleaving Campaigns</h3><p>Because the P95 case can take over 200 trading days, you cannot simply launch one campaign and sit on your hands waiting around. You solve this by interleaving your campaigns. You launch a new 3-account queue every month or so. Ideally, you run an uncorrelated system on each new campaign (for example, pairing this Index Mean Reversion engine with an FX trend-following model). This turns your prop firm trading into an assembly line: while one campaign is grinding through a slow evaluation stage, another is sitting in the funded phase collecting a +3% payout. You smooth out the calendar dry spells, keep the cash flow consistent, and let the law of large numbers do what it does best.</p><h3>The Simulation Engine: Test Your Own Data</h3><p>For those who want to verify the numbers or plug in their own system&#8217;s daily trade tape, here is the Python script. Drop in your daily returns CSV, play around with the variables, and adjust the risk multipliers, target percentages, or reserve queue size to match your own setup.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;4474d894-d17b-4c63-a10f-7442cb210315&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">import os
import numpy as np
import pandas as pd

# ==============================================================================
# INPUT VARIABLES
# ==============================================================================
FILE_PATH                   = r"C:\Users\HP ELITEBOOK\PropFirm Sims\MT5_BackTest_Results\Index_Mean_Rev_Only_Portfolio.xlsx"
INITIAL_BALANCE             = 10000.0
CHALLENGE_FEE               = 70.0
MAX_ATTEMPTS_PER_CAMPAIGN   = 3         # Stop immediately when 1 account gets funded
NUM_SIMULATIONS             = 1000

# Risk Multipliers
CHALLENGE_RISK_MULT         = 1.50      # Aggressive risk for P1 &amp; P2 clearance speed
FUNDED_RISK_MULT            = 0.50      # De-risked once funded to protect daily limits

# Prop Firm Rules &amp; Targets
PHASE1_TARGET_PCT           = 0.08      # 8% target ($10,800)
PHASE2_TARGET_PCT           = 0.05      # 5% target ($10,500)
PAYOUT_TARGET_PCT           = 0.03      # 3% target per payout withdrawal ($10,300)
MAX_STATIC_DD_PCT           = 0.08      # 8% static floor ($9,200)
MAX_DAILY_LOSS_PCT          = 0.04      # 4% max daily loss limit
MAX_DAYS_PER_PHASE          = 500       # Safety cutoff per evaluation stage

# Profit Sharing &amp; Refund
PAYOUT_SHARE_PCT            = 0.80      # 80% trader split
REFUND_FEE_ON_FIRST_PAYOUT  = True      # Refund the $70 fee on 1st payout

# ==============================================================================
# STEP 1: PARSE MT5 DATA (TRUE OPENING BALANCE PERCENTAGE)
# ==============================================================================
def parse_and_aggregate_daily_trades(file_path):
    print("[1/3] Reading and parsing deals table from MT5 backtest report...")
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"File not found: {file_path}")

    raw_df = pd.read_excel(file_path, header=None)
    deals_idx = raw_df[raw_df.iloc[:, 0].astype(str).str.strip() == "Deals"].index
    if len(deals_idx) == 0:
        raise ValueError("Could not locate 'Deals' section in the file.")
    
    header_row_idx = deals_idx[0] + 1
    headers = raw_df.iloc[header_row_idx].tolist()
    deals_data = raw_df.iloc[header_row_idx + 1:].copy()
    deals_data.columns = [str(col).strip() for col in headers]
    
    closed_deals = deals_data[deals_data["Direction"].astype(str).str.strip().str.lower() == "out"].copy()
    
    numeric_cols = ["Profit", "Commission", "Swap", "Balance"]
    for col in numeric_cols:
        if col in closed_deals.columns:
            closed_deals[col] = pd.to_numeric(closed_deals[col].astype(str).str.replace(" ", ""), errors="coerce").fillna(0.0)
        else:
            closed_deals[col] = 0.0

    closed_deals["Net_PnL"] = closed_deals["Profit"] + closed_deals["Commission"] + closed_deals["Swap"]
    closed_deals["Prior_Balance"] = closed_deals["Balance"] - closed_deals["Net_PnL"]
    closed_deals["Time"] = pd.to_datetime(closed_deals["Time"])
    closed_deals = closed_deals.sort_values("Time").reset_index(drop=True)
    closed_deals["Date"] = closed_deals["Time"].dt.date
    
    daily_summary = closed_deals.groupby("Date").agg(
        day_open_balance=("Prior_Balance", "first"),
        day_total_pnl=("Net_PnL", "sum")
    )
    daily_returns = (daily_summary["day_total_pnl"] / daily_summary["day_open_balance"]).values.astype(float)
    print(f"      Extracted {len(closed_deals):,} closed trades aggregated into {len(daily_returns):,} active trading days.")
    return daily_returns

# ==============================================================================
# STEP 2: STAGE AND LIFECYCLE SIMULATOR
# ==============================================================================
def simulate_single_stage(daily_returns, initial_balance, target_pct, risk_mult, max_static_dd_pct, max_daily_loss_pct, max_days):
    num_days = len(daily_returns)
    current_balance = initial_balance
    target_balance = initial_balance * (1.0 + target_pct)
    static_limit = initial_balance * (1.0 - max_static_dd_pct)
    days_spent = 0
    
    while True:
        days_spent += 1
        day_return = daily_returns[np.random.randint(0, num_days)] * risk_mult
        
        # Daily Loss Check
        if day_return &lt;= -max_daily_loss_pct:
            return "BLOWN_DAILY", days_spent
        
        current_balance += current_balance * day_return
        
        # Static Floor Check
        if current_balance &lt;= static_limit:
            return "BLOWN_STATIC", days_spent
            
        # Target Check
        if current_balance &gt;= target_balance:
            return "PASSED", days_spent
            
        if days_spent &gt;= max_days:
            return "TIMEOUT", days_spent

def simulate_single_account(daily_returns, initial_balance, chal_fee, chal_risk, fund_risk,
                            p1_pct, p2_pct, payout_pct, max_static_dd_pct, max_daily_loss_pct,
                            payout_share, refund_fee, max_days_per_phase):
    num_days = len(daily_returns)
    account_stats = {
        "passed_p1": False,
        "passed_p2": False,
        "funded": False,
        "got_payout": False,
        "p1_days": 0,
        "p2_days": 0,
        "days_to_first_payout": None,
        "total_days_spent": 0,
        "payout_count": 0,
        "total_cash_withdrawn": 0.0
    }
    
    # --- PHASE 1 ---
    res_p1, days_p1 = simulate_single_stage(daily_returns, initial_balance, p1_pct, chal_risk, max_static_dd_pct, max_daily_loss_pct, max_days_per_phase)
    account_stats["p1_days"] = days_p1
    account_stats["total_days_spent"] += days_p1
    if res_p1 != "PASSED":
        return account_stats
    account_stats["passed_p1"] = True

    # --- PHASE 2 ---
    res_p2, days_p2 = simulate_single_stage(daily_returns, initial_balance, p2_pct, chal_risk, max_static_dd_pct, max_daily_loss_pct, max_days_per_phase)
    account_stats["p2_days"] = days_p2
    account_stats["total_days_spent"] += days_p2
    if res_p2 != "PASSED":
        return account_stats
    account_stats["passed_p2"] = True
    account_stats["funded"] = True

    # --- FUNDED STAGE (Until Blown or Backtest Tape Exhaustion) ---
    current_balance = initial_balance
    target_balance = initial_balance * (1.0 + payout_pct)
    static_limit = initial_balance * (1.0 - max_static_dd_pct)
    funded_days = 0
    
    while True:
        funded_days += 1
        day_return = daily_returns[np.random.randint(0, num_days)] * fund_risk
        
        if day_return &lt;= -max_daily_loss_pct or (current_balance + current_balance * day_return) &lt;= static_limit:
            break
            
        current_balance += current_balance * day_return
        
        if current_balance &gt;= target_balance:
            profit_slice = current_balance - initial_balance
            trader_share = profit_slice * payout_share
            if account_stats["payout_count"] == 0:
                account_stats["got_payout"] = True
                account_stats["days_to_first_payout"] = account_stats["p1_days"] + account_stats["p2_days"] + funded_days
                if refund_fee:
                    trader_share += chal_fee
            
            account_stats["payout_count"] += 1
            account_stats["total_cash_withdrawn"] += trader_share
            current_balance = initial_balance
            
        if funded_days &gt;= 2520:  # 10-year market horizon safety cutoff
            break

    account_stats["total_days_spent"] += funded_days
    return account_stats

# ==============================================================================
# STEP 3: RUN MONTE CARLO (FIRST-FUNDED-WINS QUEUE)
# ==============================================================================
def run_campaign_monte_carlo(daily_returns, initial_balance, chal_fee, max_attempts,
                             chal_risk, fund_risk, p1_pct, p2_pct, payout_pct,
                             max_static_dd_pct, max_daily_loss_pct, payout_share,
                             refund_fee, max_days_per_phase, num_simulations):
    print(f"[2/3] Simulating {num_simulations:,} business campaigns (Max {max_attempts} attempts, stop upon 1 funded)...")
    
    campaign_results = []
    unit_account_records = []
    
    for i in range(1, num_simulations + 1):
        campaign_days = 0
        challenges_bought = 0
        campaign_funded = False
        campaign_payouts = 0.0
        
        camp_p1_day = None
        camp_p2_day = None
        camp_first_payout_day = None
        
        for attempt in range(1, max_attempts + 1):
            challenges_bought += 1
            acct = simulate_single_account(
                daily_returns, initial_balance, chal_fee, chal_risk, fund_risk,
                p1_pct, p2_pct, payout_pct, max_static_dd_pct, max_daily_loss_pct,
                payout_share, refund_fee, max_days_per_phase
            )
            unit_account_records.append(acct)
            
            if acct["passed_p1"] and camp_p1_day is None:
                camp_p1_day = campaign_days + acct["p1_days"]
                
            if acct["funded"]:
                campaign_funded = True
                camp_p2_day = campaign_days + acct["p1_days"] + acct["p2_days"]
                if acct["got_payout"]:
                    camp_first_payout_day = campaign_days + acct["days_to_first_payout"]
                campaign_payouts = acct["total_cash_withdrawn"]
                campaign_days += acct["total_days_spent"]
                # STOP IMMEDIATELY &#8212; Discard the rest of the queue
                break
            else:
                campaign_days += acct["total_days_spent"]
                
        total_spent = challenges_bought * chal_fee
        net_profit = campaign_payouts - total_spent
        
        campaign_results.append({
            "challenges_bought": challenges_bought,
            "funded": campaign_funded,
            "total_spent": total_spent,
            "total_payouts": campaign_payouts,
            "net_profit": net_profit,
            "p1_finish_day": camp_p1_day,
            "funded_day": camp_p2_day,
            "payout_day": camp_first_payout_day,
            "campaign_days": campaign_days
        })
        
        if i % (num_simulations // 5) == 0 or i == num_simulations:
            print(f"      Progress: {i:,}/{num_simulations:,} campaigns processed...")
            
    print("[3/3] Simulations completed successfully.")
    return campaign_results, unit_account_records

# ==============================================================================
# STEP 4: DISPLAY CLEAN REPORT
# ==============================================================================
def display_report(campaign_results, unit_accounts, max_attempts, chal_fee):
    total_campaigns = len(campaign_results)
    total_units = len(unit_accounts)
    
    def calc_percentiles(data_list):
        if len(data_list) == 0:
            return "Not Available", "Not Available", "Not Available"
        p5 = f"{np.percentile(data_list, 5):.1f} trading days"
        p50 = f"{np.percentile(data_list, 50):.1f} trading days"
        p95 = f"{np.percentile(data_list, 95):.1f} trading days"
        return p5, p50, p95

    print("\n" + "=" * 96)
    print(f"{'PROP FIRM BUSINESS ARCHITECTURE SIMULATION REPORT':^96}")
    print(f"{f'({total_campaigns:,} Full Campaigns | Maximum Reserve: {max_attempts} Accounts @ ${chal_fee:.0f} Each)':^96}")
    print("=" * 96)

    # --------------------------------------------------------------------------
    # SECTION 1: ACCOUNT-LEVEL METRICS (UNIT ECONOMICS)
    # --------------------------------------------------------------------------
    p1_pass_count = sum(1 for a in unit_accounts if a["passed_p1"])
    p2_pass_count = sum(1 for a in unit_accounts if a["passed_p2"])
    payout_count  = sum(1 for a in unit_accounts if a["got_payout"])
    
    p1_days_list = [a["p1_days"] for a in unit_accounts if a["passed_p1"]]
    p2_days_list = [a["p2_days"] for a in unit_accounts if a["passed_p2"]]
    pay_days_list = [a["days_to_first_payout"] for a in unit_accounts if a["got_payout"]]
    
    p1_p5, p1_p50, p1_p95 = calc_percentiles(p1_days_list)
    p2_p5, p2_p50, p2_p95 = calc_percentiles(p2_days_list)
    pay_p5, pay_p50, pay_p95 = calc_percentiles(pay_days_list)

    print("\n" + "-" * 96)
    print("1. INDIVIDUAL ACCOUNT UNIT CONVERSION AND VELOCITY")
    print("-" * 96)
    print(f"&#8226; Phase 1 Pass Rate:                      {(p1_pass_count / total_units * 100):&gt;6.2f}% ({p1_pass_count:,}/{total_units:,} challenges)")
    print(f"&#8226; Phase 2 Pass Rate (from Phase 1):       {(p2_pass_count / p1_pass_count * 100 if p1_pass_count &gt; 0 else 0):&gt;6.2f}% ({p2_pass_count:,}/{p1_pass_count:,})")
    print(f"&#8226; Full Pass-to-Funded Rate:               {(p2_pass_count / total_units * 100):&gt;6.2f}% ({p2_pass_count:,}/{total_units:,})")
    print(f"&#8226; Probability of Reaching Payout:         {(payout_count / total_units * 100):&gt;6.2f}% ({payout_count:,}/{total_units:,} challenges paid cash)")
    print()
    print(f"{'Milestone (Single Account)':&lt;32} | {'P5 (Fast Case)':&lt;18} | {'P50 (Median)':&lt;18} | {'P95 (Slow Case)':&lt;18}")
    print("-" * 96)
    print(f"{'Phase 1 Completion (+8%)':&lt;32} | {p1_p5:&lt;18} | {p1_p50:&lt;18} | {p1_p95:&lt;18}")
    print(f"{'Phase 2 Completion (+5%)':&lt;32} | {p2_p5:&lt;18} | {p2_p50:&lt;18} | {p2_p95:&lt;18}")
    print(f"{'Days to First Cash Payout':&lt;32} | {pay_p5:&lt;18} | {pay_p50:&lt;18} | {pay_p95:&lt;18}")

    # --------------------------------------------------------------------------
    # SECTION 2: CAMPAIGN-LEVEL BUSINESS DASHBOARD
    # --------------------------------------------------------------------------
    funded_campaigns = sum(1 for c in campaign_results if c["funded"])
    profitable_campaigns = sum(1 for c in campaign_results if c["net_profit"] &gt; 0)
    wiped_campaigns = sum(1 for c in campaign_results if not c["funded"])
    
    avg_attempts_used = np.mean([c["challenges_bought"] for c in campaign_results])
    avg_spent = np.mean([c["total_spent"] for c in campaign_results])
    avg_net = np.mean([c["net_profit"] for c in campaign_results])
    
    c_p1_list = [c["p1_finish_day"] for c in campaign_results if c["p1_finish_day"] is not None]
    c_p2_list = [c["funded_day"] for c in campaign_results if c["funded_day"] is not None]
    c_pay_list = [c["payout_day"] for c in campaign_results if c["payout_day"] is not None]
    
    cp1_p5, cp1_p50, cp1_p95 = calc_percentiles(c_p1_list)
    cp2_p5, cp2_p50, cp2_p95 = calc_percentiles(c_p2_list)
    cpay_p5, cpay_p50, cpay_p95 = calc_percentiles(c_pay_list)

    print("\n" + "-" * 96)
    print(f"2. CAMPAIGN BUSINESS PERFORMANCE (MAXIMUM {max_attempts} ATTEMPTS QUEUE)")
    print("-" * 96)
    print(f"&#8226; Campaign Success Rate:                  {(funded_campaigns / total_campaigns * 100):&gt;6.2f}% (Successfully minted a funded seat)")
    print(f"&#8226; Total Wipeout Rate:                     {(wiped_campaigns / total_campaigns * 100):&gt;6.2f}% (Lost all {max_attempts} attempts)")
    print(f"&#8226; Net Profitable Campaign Rate:           {(profitable_campaigns / total_campaigns * 100):&gt;6.2f}% (Finished campaign with net cash gain)")
    print(f"&#8226; Average Challenges Purchased:           {avg_attempts_used:&gt;6.2f} accounts (out of {max_attempts} maximum reserve)")
    print(f"&#8226; Average Challenge Fee Outlay:           ${avg_spent:&gt;8,.2f}")
    print(f"&#8226; Average Net Cash Profit:                ${avg_net:&gt;8,.2f} per campaign")
    print()
    print("CAMPAIGN TIMELINE (TOTAL ACTIVE TRADING DAYS FROM DAY ZERO):")
    print(f"{'Campaign Milestone':&lt;32} | {'P5 (Fast Case)':&lt;18} | {'P50 (Median)':&lt;18} | {'P95 (Slow Case)':&lt;18}")
    print("-" * 96)
    print(f"{'Time to Clear Phase 1':&lt;32} | {cp1_p5:&lt;18} | {cp1_p50:&lt;18} | {cp1_p95:&lt;18}")
    print(f"{'Time to Become Funded (Phase 2 End)':&lt;32} | {cp2_p5:&lt;18} | {cp2_p50:&lt;18} | {cp2_p95:&lt;18}")
    print(f"{'Time to First Cash Payout':&lt;32} | {cpay_p5:&lt;18} | {cpay_p50:&lt;18} | {cpay_p95:&lt;18}")
    print("=" * 96 + "\n")

# ==============================================================================
# MAIN EXECUTION
# ==============================================================================
if __name__ == "__main__":
    daily_returns = parse_and_aggregate_daily_trades(FILE_PATH)
    campaign_results, unit_accounts = run_campaign_monte_carlo(
        daily_returns, INITIAL_BALANCE, CHALLENGE_FEE, MAX_ATTEMPTS_PER_CAMPAIGN,
        CHALLENGE_RISK_MULT, FUNDED_RISK_MULT,
        PHASE1_TARGET_PCT, PHASE2_TARGET_PCT, PAYOUT_TARGET_PCT,
        MAX_STATIC_DD_PCT, MAX_DAILY_LOSS_PCT,
        PAYOUT_SHARE_PCT, REFUND_FEE_ON_FIRST_PAYOUT,
        MAX_DAYS_PER_PHASE, NUM_SIMULATIONS
    )
    display_report(campaign_results, unit_accounts, MAX_ATTEMPTS_PER_CAMPAIGN, CHALLENGE_FEE)</code></pre></div>]]></content:encoded></item><item><title><![CDATA[Trading the Squeeze: A Multi-Currency Yen Breakout System (1,400+ Trades)]]></title><description><![CDATA[Why the Yen actually trends, how low-volatility filters keep you out of bad chop, and the clean MQL5 script I use to trade USDJPY, GBPJPY, and CADJPY.]]></description><link>https://mechanicalpremia.substack.com/p/trading-the-squeeze-a-multi-currency</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/trading-the-squeeze-a-multi-currency</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Wed, 16 Sep 2026 11:27:20 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/edaf54ef-3721-4f07-8d6f-77137c242831_2816x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It&#8217;s been a minute since I posted a raw strategy breakdown.</p><p>I&#8217;ll be completely honest with you: FX is a market that&#8217;s very close to my heart, mainly because it is where I blew up my very first trading account years ago. &#128514;</p><p>You know the usual story: candlestick setups, fading the Asian range, and all that. I&#8217;m not saying it&#8217;s complete nonsense; all I&#8217;m saying is it didn&#8217;t work for me, and I honestly didn&#8217;t test anything. My friend was making $50 a day from FX, and I wanted to get in. Needless to say, it didn&#8217;t end well.</p><p>Fast forward to current times. I&#8217;m not yet a quant genius making millions from the market, but I&#8217;ve run my live models, I&#8217;ve learned a lot about what works and what doesn&#8217;t work, and FX is not as complicated as it was before. It&#8217;s just a price chart driven by macro flows that simple systems can take advantage of.</p><p>When you look across currencies, the Japanese Yen pairs stand out because of persistent interest rate differentials. Carry trade dynamics mean money actually flows into or out of these pairs with real momentum over multi-day stretches. Unlike something like EURUSD that can spend months trapped in a choppy, sideways blender, the Yen actually trends when it gets moving.</p><p>You don&#8217;t need some complicated macroeconomic data or thesis to take advantage of this. Our hypothesis is simply that yen pairs trend. You can look at any chart&#8212;it&#8217;s right there. What&#8217;s the simplest model we can create to take advantage of that? That&#8217;s what we are building today. Please Like, Sub and Restack lets get started.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h3>The Logic (Nothing Fancy, Just the Squeeze)</h3><p>We aren&#8217;t trying to outsmart the market here; it&#8217;s just a basic breakout model. It sets stop orders when volatility is low, anticipating the breakout, and rides the move with a dynamic trailing stop.</p><p>Some models chase big momentum candles no matter the regime, and if that&#8217;s your methodology, you do you. From my testing, this specific system simply prefers low-vol regimes before looking for expansion, so that&#8217;s what we are going with.</p><p>Here is the exact setup:</p><ul><li><p><strong>The Volatility Filter:</strong> Every hour on the close, the system checks the 14-period ATR against its 100-period median. If the previous hour&#8217;s ATR is strictly below that median, the volatility condition is met. If volatility is high, it simply skips that bar.</p></li><li><p><strong>The Execution (Stop Orders):</strong> Instead of waiting around for a bar to close beyond a level, the EA looks at the highest high and lowest low of the last 500 hours. It places a <code>BuyStop</code> right at the 500-hour high and a <code>SellStop</code> at the 500-hour low. These orders have a 1-hour expiration. If price pops through within that hour, you&#8217;re filled. If it doesn&#8217;t, the pending order expires and the bot recalculates on the next hour.</p></li><li><p><strong>The Trailing Exit:</strong> There is no fixed profit target. The initial stop loss is set at 2x ATR away from entry. As the trade develops, an internal timer evaluates the position once a minute and trails the stop at exactly 2x ATR behind the current price. It only ratchets in your favor; it never widens.</p></li><li><p><strong>Position Sizing:</strong> The lot size is dynamically calculated based on your set risk percentage (e.g., 1.0%), using the distance to that initial 2x ATR stop and the tick value of whichever Yen pair is triggering.</p></li></ul><h3>Baseline Performance &amp; Data</h3><p>Here are the raw results running this system across USDJPY, GBPJPY, and CADJPY on the 1-hour timeframe using 1.0% risk per trade.</p><p>I did in-sample and out-of-sample testing on this, but honestly, I don&#8217;t feel the need to post 3D optimization plots or split tables here. The bot has so few moving parts that there was no material difference between the periods. You can&#8217;t really overfit if there is barely anything to fit in the first place.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xDEh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xDEh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 424w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 848w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 1272w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!xDEh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png" width="1456" height="718" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:718,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54479,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/215969925?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xDEh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 424w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 848w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 1272w, https://substackcdn.com/image/fetch/$s_!xDEh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3077c45-94f9-4248-af94-42cdd4ee0b6d_1590x784.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Not the prettiest but it works</figcaption></figure></div><p><strong>The Numbers:</strong></p><ul><li><p><strong>Total Trades:</strong> 1,423 (984 Long, 439 Short)</p></li><li><p><strong>Profit Factor:</strong> 1.35</p></li><li><p><strong>Win Rate:</strong> 39.21% (Typical trend-following win rate; the average winner is more than double the average loser at $109.55 vs -$52.39)</p></li><li><p><strong>Max Equity Drawdown:</strong> 14.26% ($4,014 on a $10k deposit)</p></li><li><p><strong>Total Net Profit:</strong> $15,810.60 (Gross profit of $61k against $45k in gross losses)</p></li><li><p><strong>Recovery Factor:</strong> 3.94</p></li></ul><p>The distribution between longs and shorts also tells the story: 984 longs versus 439 shorts. The long side picks up the multi-day carry drift, but having the short side active still bagged 439 trades with a slightly higher win rate (40.32%) to catch sharp downside flushes when the Yen rallied.</p><h3>The Weak Spot</h3><p>You already know the weak spot of trend following by now: chop and sideways markets. I can&#8217;t predict when those periods are coming, and I doubt anyone else can either. I don&#8217;t really have much more to add to that.</p><p>One thing worth noting from testing, though, is parameter dynamics: the smaller the stop loss, the better the overall return metrics, and the longer the lookback period, the better the performance. In essence, the system thrives on massive breakouts caught with tight stops.</p><p>The obvious catch is that a smaller stop means more whipsaws and paper cuts during dead periods. If you can&#8217;t stomach extended flat stretches or strings of small losses while waiting for the next trend to take off, trading this system by itself is probably not for you.</p><h3>The Source Code</h3><p>Here is the complete multi-currency expert advisor. You can drop this directly onto any chart in MetaTrader 5 (it manages USDJPY, GBPJPY, and CADJPY simultaneously from a single chart using an internal timer loop, so you don&#8217;t need to open three different charts).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;83dfa891-1d3e-4bc5-86ad-f518f35b37e1&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">//+------------------------------------------------------------------+
//|                                           FX_Trend_Following.mq5 |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include &lt;Trade/Trade.mqh&gt;
CTrade Trading_Function;

input group "------ FX Trend Following ------"
input string Asset_Universe = "USDJPY,GBPJPY,CADJPY";
input int lookback_bars = 20;
input double atr_multiplier = 2.0;
input double risk_percent = 1.0;
input int base_magic = 500000;

struct Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    H1_ATR_Handle;
};
Asset_State Portfolio[];

bool Position_State_Checker(string symbol_name, int magic_number)
{
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      if(PositionGetTicket(i) &lt;= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == symbol_name &amp;&amp; PositionGetInteger(POSITION_MAGIC) == magic_number) return true;
   }
   for(int i = OrdersTotal() - 1; i &gt;= 0; i--)
   {
      if(OrderGetTicket(i) &lt;= 0) continue;
      if(OrderGetString(ORDER_SYMBOL) == symbol_name &amp;&amp; OrderGetInteger(ORDER_MAGIC) == magic_number) return true;
   }
   return false;
}

double Calculate_Robust_Volume(string symbol, double entry_price, double stop_loss, double risk_perc)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   if (balance &lt;= 0.0) return 0.0;
   
   double tick_size   = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tick_value  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   double min_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double max_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   if (tick_size == 0.0 || tick_value == 0.0 || volume_step == 0.0) return 0.0;
   if (entry_price == stop_loss) return 0.0;

   double sl_distance_ticks = MathAbs(entry_price - stop_loss) / tick_size;
   if (sl_distance_ticks == 0.0) return 0.0;
   
   double risk_per_lot = sl_distance_ticks * tick_value;
   if (risk_per_lot == 0.0) return 0.0;

   double final_lot = MathFloor((balance * (risk_perc / 100.0) / risk_per_lot) / volume_step) * volume_step;
   if (final_lot &lt; min_volume) final_lot = min_volume;
   if (final_lot &gt; max_volume) final_lot = max_volume;

   int vol_digits = (volume_step == 0.1) ? 1 : (volume_step == 0.01) ? 2 : (volume_step == 0.001) ? 3 : (volume_step == 0.0001) ? 4 : 0;
   return NormalizeDouble(final_lot, vol_digits);
}

void Run_Trend_Executor()
{
   static datetime Last_H1_Time = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == Last_H1_Time) return;
   if(Current_H1 == 0) return;
   
   Last_H1_Time = Current_H1;
   
   int total_assets = ArraySize(Portfolio);
   datetime expiry = TimeCurrent() + PeriodSeconds(PERIOD_H1);
   
   for(int i = 0; i &lt; total_assets; i++)
   {
      string sym = Portfolio[i].Symbol;
      int magic = Portfolio[i].Magic_Number;
      
      int atr_handle = Portfolio[i].H1_ATR_Handle;
      
      if(atr_handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(sym, magic)) continue;
      if(!SeriesInfoInteger(sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      double atr_100[];
      ArraySetAsSeries(atr_100, true);
      if(CopyBuffer(atr_handle, 0, 1, 100, atr_100) &lt; 100) continue;
      
      double previous_atr = atr_100[0];
      
      double atr_sorted[];
      ArrayResize(atr_sorted, 100);
      for(int k = 0; k &lt; 100; k++)
      {
         atr_sorted[k] = atr_100[k];
      }
      ArraySort(atr_sorted);
      double median_atr = atr_sorted[50];
      
      if(previous_atr &gt;= median_atr) continue;
      
      int digits = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS);
      
      double highs[];
      ArraySetAsSeries(highs, true);
      if(CopyHigh(sym, PERIOD_H1, 1, lookback_bars, highs) &gt;= lookback_bars)
      {
         int highest_idx = ArrayMaximum(highs, 0, lookback_bars);
         if(highest_idx &gt;= 0)
         {
            double highest_high = highs[highest_idx];
            double ask = SymbolInfoDouble(sym, SYMBOL_ASK);
            
            double entry_price = NormalizeDouble(highest_high, digits);
            if(entry_price &gt; ask)
            {
               double sl = NormalizeDouble(entry_price - (previous_atr * atr_multiplier), digits);
               if(entry_price &gt; sl)
               {
                  double vol = Calculate_Robust_Volume(sym, entry_price, sl, risk_percent);
                  if(vol &gt; 0.0)
                  {
                     double margin = 0.0;
                     if(OrderCalcMargin(ORDER_TYPE_BUY, sym, vol, entry_price, margin) &amp;&amp; margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
                     {
                        Trading_Function.SetExpertMagicNumber(magic);
                        Trading_Function.BuyStop(vol, entry_price, sym, sl, 0.0, ORDER_TIME_SPECIFIED, expiry, "Trend_Long_Stop");
                     }
                  }
               }
            }
         }
      }
      
      double lows[];
      ArraySetAsSeries(lows, true);
      if(CopyLow(sym, PERIOD_H1, 1, lookback_bars, lows) &gt;= lookback_bars)
      {
         int lowest_idx = ArrayMinimum(lows, 0, lookback_bars);
         if(lowest_idx &gt;= 0)
         {
            double lowest_low = lows[lowest_idx];
            double bid = SymbolInfoDouble(sym, SYMBOL_BID);
            
            double entry_price = NormalizeDouble(lowest_low, digits);
            if(entry_price &lt; bid)
            {
               double sl = NormalizeDouble(entry_price + (previous_atr * atr_multiplier), digits);
               if(entry_price &lt; sl)
               {
                  double vol = Calculate_Robust_Volume(sym, entry_price, sl, risk_percent);
                  if(vol &gt; 0.0)
                  {
                     double margin = 0.0;
                     if(OrderCalcMargin(ORDER_TYPE_SELL, sym, vol, entry_price, margin) &amp;&amp; margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
                     {
                        Trading_Function.SetExpertMagicNumber(magic);
                        Trading_Function.SellStop(vol, entry_price, sym, sl, 0.0, ORDER_TIME_SPECIFIED, expiry, "Trend_Short_Stop");
                     }
                  }
               }
            }
         }
      }
   }
}

void Run_Trend_Manager()
{
   static datetime last_time = 0;
   datetime current_time = TimeCurrent();
   if(current_time &lt; last_time + 60) return;
   last_time = current_time;

   int total_assets = ArraySize(Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(ticket)) continue;
      
      long pos_magic = PositionGetInteger(POSITION_MAGIC);
      string pos_sym = PositionGetString(POSITION_SYMBOL);
      long pos_type  = PositionGetInteger(POSITION_TYPE);
      
      int asset_idx = -1;
      for(int j = 0; j &lt; total_assets; j++)
      {
         if(Portfolio[j].Magic_Number == pos_magic &amp;&amp; Portfolio[j].Symbol == pos_sym)
         {
            asset_idx = j;
            break;
         }
      }
      
      if(asset_idx == -1) continue;
      
      int atr_handle = Portfolio[asset_idx].H1_ATR_Handle;
      if(atr_handle == INVALID_HANDLE) continue;
      
      double atr_h1[];
      ArraySetAsSeries(atr_h1, true);
      if(CopyBuffer(atr_handle, 0, 1, 1, atr_h1) &lt;= 0) continue;
      
      int digits = (int)SymbolInfoInteger(pos_sym, SYMBOL_DIGITS);
      double point_size = SymbolInfoDouble(pos_sym, SYMBOL_POINT);
      double min_stop_distance = 2 * point_size;
      
      double current_sl = PositionGetDouble(POSITION_SL);
      double current_tp = PositionGetDouble(POSITION_TP);
      
      if(pos_type == POSITION_TYPE_BUY)
      {
         double bid = SymbolInfoDouble(pos_sym, SYMBOL_BID);
         double target_sl = NormalizeDouble(bid - (atr_h1[0] * atr_multiplier), digits);
         
         if(target_sl &gt; current_sl + min_stop_distance || current_sl == 0.0)
         {
            Trading_Function.SetExpertMagicNumber((int)pos_magic);
            Trading_Function.PositionModify(ticket, target_sl, current_tp);
         }
      }
      else if(pos_type == POSITION_TYPE_SELL)
      {
         double ask = SymbolInfoDouble(pos_sym, SYMBOL_ASK);
         double target_sl = NormalizeDouble(ask + (atr_h1[0] * atr_multiplier), digits);
         
         if(target_sl &lt; current_sl - min_stop_distance || current_sl == 0.0)
         {
            Trading_Function.SetExpertMagicNumber((int)pos_magic);
            Trading_Function.PositionModify(ticket, target_sl, current_tp);
         }
      }
   }
}

int OnInit()
{
   ushort sep = StringGetCharacter(",", 0);
   string symbols[];
   
   int num_symbols = StringSplit(Asset_Universe, sep, symbols);
   if(num_symbols &gt; 0)
   {
      ArrayResize(Portfolio, num_symbols);
      
      for(int i = 0; i &lt; num_symbols; i++)
      {
         StringTrimLeft(symbols[i]);
         StringTrimRight(symbols[i]);
         
         SymbolSelect(symbols[i], true);
         
         Portfolio[i].Symbol = symbols[i];
         Portfolio[i].Magic_Number = base_magic + i;
         
         Portfolio[i].H1_ATR_Handle = iATR(symbols[i], PERIOD_H1, 14);
         
         if(Portfolio[i].H1_ATR_Handle == INVALID_HANDLE)
         {
            Print("Warning: Failed to load handles for ", symbols[i]);
         }
      }
   }

   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   
   int total_assets = ArraySize(Portfolio);
   for(int i = 0; i &lt; total_assets; i++)
   {
      if(Portfolio[i].H1_ATR_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].H1_ATR_Handle);
   }
}

void OnTick() {}

void OnTimer()
{
   Run_Trend_Executor();
   Run_Trend_Manager();
}</code></pre></div>]]></content:encoded></item><item><title><![CDATA[Building a Multi-Strategy Portfolio (Part 1): Sizing Fast Engines vs. Patient Setups]]></title><description><![CDATA[Why pairing an intraday breakout bot with a daily dip-buyer breaks on equal risk, and how diversification actually behaves in live markets.]]></description><link>https://mechanicalpremia.substack.com/p/building-a-multi-strategy-portfolio</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/building-a-multi-strategy-portfolio</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Tue, 01 Sep 2026 10:37:50 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c35c3ad6-28bf-4a9c-b593-cdf9c4d1ee8c_2816x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to a new series on portfolio building.</p><p>We have been building and validating individual trading strategies here for a while. The natural next question is: how do you actually combine them? You&#8217;ve probably heard diversification is the holy grail, it&#8217;s the free lunch, it&#8217;s this, it&#8217;s that. They are right tbh, that&#8217;s why this series exists: to show you how to combine multiple systems into one portfolio. This is my own modest retail setup, nothing too complicated, no complicated maths or institutional terminologies. We are going to use the exact systems I have already shared on this Substack. As we build more setups over time, we will create bigger, more diverse portfolios</p><p>I execute everything on MT5. It is what connects me directly to prop firms and standard retail brokers, so the code I share is in MQL5, but the underlying concepts and math translate easily no matter what platform or language you prefer to use.</p><p>To kick things off, we are pairing two systems we discussed previously. The code and parameters are right here in the post, so you do not have to worry about paywalls. and if your are new and like this kind of content please subscribe below lets start.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><h3>The Two Engines</h3><p>The first system is a <strong>Daily Mean Reversion</strong> model trading equity indices (US500, US100, DE30, and EU50). The core thesis is buying quiet, high-probability dips in an established bull market. We look for the daily price to be above the 100 EMA, with the previous day&#8217;s ATR below its 100-day median to make sure volatility is calm. When the daily %B drops below 0.2 (stretching near the lower 10-period, 3.0 standard deviation Bollinger Band), we buy. We exit when the snapback resolves and %B climbs back above 0.8.</p><p>The second system is a <strong>1-Hour Volatility Breakout</strong> model trading the US500, US100, and DE30. It evaluates the market strictly at the close of every 1-hour bar. If the 14-period ATR is below its 100-period median, we buy a close above the upper 40-period Bollinger Band (2.0 standard deviations) and trail a stop 2x ATR below the bid.</p><p>People often say indicators like Bollinger Bands do not work anymore. But at the end of the day, a Bollinger Band is literally just a rolling standard deviation band around a mean. It was invented decades before I was even born, but it is just a descriptive tool. One uses it to catch an intraday momentum surge; the other uses it to buy a stretched pullback.</p><h3>The Reality of Live Diversification</h3><p>Why do we combine these? Very simple: no one system works all the time. If you had a single system that did, I am probably the one that should be subscribed to you instead.</p><p>Take the last stretch of trading. The 1-hour breakout bot, which had been reliable for years, basically hit a wall around mid-2025 and started underperforming. Meanwhile, the daily mean reversion system stepped up and carried the overall book.</p><p>Why did the breakout system slow down? Who knows for sure. Donald Trump returned to office, sweeping tariffs and policy shifts hit the headlines, and intraday market structure shifted. Trying to forecast macro politics is not our job as systematic traders. Our job is to run uncorrelated systems so that when one engine hits an unavoidable dry patch, the other keeps the portfolio afloat.</p><p>In fact, if you ran this combined portfolio, you probably would not even realize the breakout bot was struggling. Combined, the portfolio ended up with zero losing years across the backtest period, even while the individual systems went through their own messy patches.</p><h3>The Combined Equity Curve</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y1a1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y1a1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 424w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 848w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 1272w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!y1a1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png" width="1456" height="671" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:671,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39784,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/213679128?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y1a1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 424w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 848w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 1272w, https://substackcdn.com/image/fetch/$s_!y1a1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb40053b-878c-407b-9e7f-885f0dadd080_1587x731.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Clean curve but nasty multi-timeframe friction</figcaption></figure></div><p>When you plot the combined portfolio against the individual systems, you immediately see the smoothing effect. While the breakout system flatlined and gave back gains through the choppy macro stretches, the daily dip-buyer picked up the slack. The individual drawdowns get absorbed, resulting in a significantly cleaner upward trajectory and zero losing calendar years across the 137-month test period.</p><h3>The Sizing Trap and the Math</h3><p>Where most traders run into trouble is equal risk sizing. If you naively risk 0.5% on both systems because you like both backtests, you will accidentally blow up your risk profile.</p><p>Over an 11-year run (137 months), the daily mean reversion system triggered 126 times. That is only about 0.92 trades per month. The 1-hour breakout system fired 2,493 times&#8212;roughly 18.20 trades per month.</p><p>If both carry the same risk per trade, the 1-hour bot will generate over 3 times the monthly volatility impact of the daily system. It will completely hijack your equity curve, which is dangerous if you are managing a live account or trying not to breach daily loss limits on a prop firm evaluation.</p><p>To balance them under a total 1.00% risk budget, we calculate risk based on trade velocity and historical loss size:</p><ol><li><p><strong>Monthly Frequency (<span>N</span>):</strong> Strategy 1 is 0.92 trades/month; Strategy 2 is 18.20 trades/month.</p></li><li><p><strong>Volatility Impact (<span>V = Avg_Loss * sqrt{N}</span>):</strong> Using average losses of $326.54 and $240.89 respectively, Strategy 1 has an impact factor of 313.16, while Strategy 2 comes in at 1027.59.</p></li><li><p><strong>Inverse Weighting (<span>1/V</span>):</strong> Inverting those factors and normalizing them gives Strategy 1 a 76.64% share and Strategy 2 a 23.36% share.</p></li></ol><p>Under a 1.00% total risk budget, the daily dip-buyer gets <strong>0.77% risk per trade</strong>, while the fast 1-hour breakout bot gets <strong>0.23% risk per trade</strong>. Any increased attention to risk management like this will save you endless headaches on live accounts.</p><h3>A Honest Caveat: Holding Period Friction</h3><p>Diversification comes in grades.</p><p>As you know from some of my notes, I am working on an intraday mean reversion system. I will share it when I have the time, I promise. You will see the grades of diversification I am talking about. It is not only about uncorrelated return streams; as you can see from here, holding period matters.</p><p>Even these two bots are both long-only. My actual live systems are all intraday long and short, and you will see the difference when I write those future articles. When you mix a daily strategy with a 1-hour strategy, you run into holding period friction: the 1-hour system takes its hit and cuts the trade quickly, while the daily mean reversion system holds trades over multiple sessions, meaning its drawdowns feel much more prominent on your account balance while you wait for the dip to revert.</p><h3>The MQL5 Code</h3><p>Here is the implementation code you can paste into MetaTrader 5 to test and run these systems.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;d2a54cca-caab-4d38-af8d-94e0baa23cec&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">#include &lt;Trade/Trade.mqh&gt;
CTrade Trading_Function;

input group "--- Strategy 1: H1 Bollinger Bands Breakout ---";
input bool   Run_H1_BB_Strategy       = true;
input string H1_BB_Asset_Universe     = "US500,US100,DE30";
input int    H1_BB_Base_Magic         = 800000;
input double H1_BB_Risk_Perc          = 1.0;
input int    H1_BB_Bands_Period       = 40;
input double H1_BB_Bands_Width        = 2.0;
input double H1_BB_SL_Multiplier      = 2.0;

input group "--- Strategy 2: Daily %B Pullback (Long Only) ---";
input bool   Run_D1_PctB_Strategy     = true;
input string D1_PctB_Asset_Universe   = "US500,US100,DE30,EU50";
input int    D1_PctB_Base_Magic       = 300000;
input double D1_PctB_Risk_Perc        = 1.0;
input int    D1_PctB_EMA_Period       = 100;
input int    D1_PctB_BB_Period        = 10;
input double D1_PctB_BB_Deviation     = 3.0;
input double D1_PctB_Buy_Level        = 0.2;
input double D1_PctB_Sell_Level       = 0.8;

struct H1_BB_Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    H1_BB_Handle;
   int    H1_ATR_Handle;
};
H1_BB_Asset_State H1_BB_Portfolio[];

struct D1_PctB_Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    D1_ATR_Handle;
   int    D1_BB_Handle;
   int    D1_EMA_Handle;
};
D1_PctB_Asset_State D1_PctB_Portfolio[];

bool Position_State_Checker(string symbol_name, int magic_number)
{
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      if(PositionGetTicket(i) &lt;= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == symbol_name &amp;&amp; PositionGetInteger(POSITION_MAGIC) == magic_number) return true;
   }
   for(int i = OrdersTotal() - 1; i &gt;= 0; i--)
   {
      if(OrderGetTicket(i) &lt;= 0) continue;
      if(OrderGetString(ORDER_SYMBOL) == symbol_name &amp;&amp; OrderGetInteger(ORDER_MAGIC) == magic_number) return true;
   }
   return false;
}

double Calculate_Robust_Volume(string symbol, double entry_price, double stop_loss, double risk_percent)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   if (balance &lt;= 0.0) return 0.0;
   
   double tick_size   = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tick_value  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   double min_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double max_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   if (tick_size == 0.0 || tick_value == 0.0 || volume_step == 0.0) return 0.0;
   if (entry_price == stop_loss) return 0.0;

   double sl_distance_ticks = MathAbs(entry_price - stop_loss) / tick_size;
   if (sl_distance_ticks == 0.0) return 0.0;
   
   double risk_per_lot = sl_distance_ticks * tick_value;
   if (risk_per_lot == 0.0) return 0.0;

   double final_lot = MathFloor((balance * (risk_percent / 100.0) / risk_per_lot) / volume_step) * volume_step;
   if (final_lot &lt; min_volume) final_lot = min_volume;
   if (final_lot &gt; max_volume) final_lot = max_volume;

   int vol_digits = (volume_step == 0.1) ? 1 : (volume_step == 0.01) ? 2 : (volume_step == 0.001) ? 3 : (volume_step == 0.0001) ? 4 : 0;
   return NormalizeDouble(final_lot, vol_digits);
}

void Run_H1_BB_Executor()
{
   static datetime Last_H1_Time = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == Last_H1_Time) return;
   if(Current_H1 == 0) return;
   
   Last_H1_Time = Current_H1;
   
   int Total_Assets = ArraySize(H1_BB_Portfolio);
   
   for(int i = 0; i &lt; Total_Assets; i++)
   {
      string Sym = H1_BB_Portfolio[i].Symbol;
      int Magic = H1_BB_Portfolio[i].Magic_Number;
      
      int BB_Handle = H1_BB_Portfolio[i].H1_BB_Handle;
      int Atr_Handle = H1_BB_Portfolio[i].H1_ATR_Handle;
      
      if(BB_Handle == INVALID_HANDLE || Atr_Handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(Sym, Magic)) continue; 
      if(!SeriesInfoInteger(Sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      double Atr_100[];
      ArraySetAsSeries(Atr_100, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 100, Atr_100) &lt; 100) continue;
      
      double Previous_ATR = Atr_100[0];
      
      double Atr_Sorted[];
      ArrayResize(Atr_Sorted, 100);
      for(int k = 0; k &lt; 100; k++)
      {
         Atr_Sorted[k] = Atr_100[k];
      }
      ArraySort(Atr_Sorted);
      double Median_ATR = Atr_Sorted[50]; 
      
      if(Previous_ATR &gt;= Median_ATR) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Sym, PERIOD_H1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double BB_Upper[];
      ArraySetAsSeries(BB_Upper, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue;
      
      if(Close_Arr[0] &gt; BB_Upper[0])
      {
         double Live_Ask = SymbolInfoDouble(Sym, SYMBOL_ASK);
         int Digits = (int)SymbolInfoInteger(Sym, SYMBOL_DIGITS);
         
         double Buy_Sl = NormalizeDouble(Live_Ask - (Previous_ATR * H1_BB_SL_Multiplier), Digits);
         
         if(Live_Ask &gt; Buy_Sl)
         {
            double Buy_Vol = Calculate_Robust_Volume(Sym, Live_Ask, Buy_Sl, H1_BB_Risk_Perc);
            if(Buy_Vol &gt; 0.0)
            {
               double Buy_Margin = 0.0;
               if(OrderCalcMargin(ORDER_TYPE_BUY, Sym, Buy_Vol, Live_Ask, Buy_Margin) &amp;&amp; Buy_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
               {
                  Trading_Function.SetExpertMagicNumber(Magic);
                  Trading_Function.Buy(Buy_Vol, Sym, Live_Ask, Buy_Sl, 0.0, "H1_BB_Breakout");
               }
            }
         }
      }
   }
}

void Run_H1_BB_Manager()
{
   static datetime last_bar_time = 0;
   datetime current_time = TimeCurrent();
   if(current_time &lt; last_bar_time + 60) return;
   last_bar_time = current_time;

   int Total_Assets = ArraySize(H1_BB_Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong Ticket = PositionGetTicket(i);
      if(Ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(Ticket)) continue;
      if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
      
      long Pos_Magic = PositionGetInteger(POSITION_MAGIC);
      string Pos_Sym = PositionGetString(POSITION_SYMBOL);
      
      int Asset_Idx = -1;
      for(int j = 0; j &lt; Total_Assets; j++)
      {
         if(H1_BB_Portfolio[j].Magic_Number == Pos_Magic &amp;&amp; H1_BB_Portfolio[j].Symbol == Pos_Sym)
         {
            Asset_Idx = j;
            break;
         }
      }
      
      if(Asset_Idx == -1) continue;
      
      int Atr_Handle = H1_BB_Portfolio[Asset_Idx].H1_ATR_Handle;
      if(Atr_Handle == INVALID_HANDLE) continue;
      
      double Atr_Val[];
      ArraySetAsSeries(Atr_Val, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 1, Atr_Val) &lt;= 0) continue;
      
      double Bid = SymbolInfoDouble(Pos_Sym, SYMBOL_BID);
      int Digits = (int)SymbolInfoInteger(Pos_Sym, SYMBOL_DIGITS);
      double Point_Size = SymbolInfoDouble(Pos_Sym, SYMBOL_POINT);
      double Min_Stop_Distance = 2 * Point_Size;
      
      double Current_Sl = PositionGetDouble(POSITION_SL);
      double Current_Tp = PositionGetDouble(POSITION_TP);
      
      double Target_Sl = NormalizeDouble(Bid - (Atr_Val[0] * H1_BB_SL_Multiplier), Digits);
      
      if(Target_Sl &gt; Current_Sl + Min_Stop_Distance || Current_Sl == 0.0)
      {
         Trading_Function.SetExpertMagicNumber((int)Pos_Magic);
         Trading_Function.PositionModify(Ticket, Target_Sl, Current_Tp);
      }
   }
}

void Run_D1_PctB_Executor()
{
   static datetime Last_H1_Time = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == Last_H1_Time) return;
   if(Current_H1 == 0) return;
   
   Last_H1_Time = Current_H1;
   
   int Total_Assets = ArraySize(D1_PctB_Portfolio);
   
   for(int i = 0; i &lt; Total_Assets; i++)
   {
      string Sym = D1_PctB_Portfolio[i].Symbol;
      int Magic = D1_PctB_Portfolio[i].Magic_Number;
      
      int Atr_Handle = D1_PctB_Portfolio[i].D1_ATR_Handle;
      int BB_Handle = D1_PctB_Portfolio[i].D1_BB_Handle;
      int Ema_Handle = D1_PctB_Portfolio[i].D1_EMA_Handle;
      
      if(Atr_Handle == INVALID_HANDLE || BB_Handle == INVALID_HANDLE || Ema_Handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(Sym, Magic)) continue; 
      if(!SeriesInfoInteger(Sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      double Atr_100[];
      ArraySetAsSeries(Atr_100, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 100, Atr_100) &lt; 100) continue;
      
      double Yesterday_ATR = Atr_100[0];
      
      double Atr_Sorted[];
      ArrayResize(Atr_Sorted, 100);
      for(int k = 0; k &lt; 100; k++)
      {
         Atr_Sorted[k] = Atr_100[k];
      }
      ArraySort(Atr_Sorted);
      double Median_ATR = Atr_Sorted[50];
      
      if(Yesterday_ATR &gt;= Median_ATR) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Sym, PERIOD_D1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double Ema_Val[];
      ArraySetAsSeries(Ema_Val, true);
      if(CopyBuffer(Ema_Handle, 0, 1, 1, Ema_Val) &lt;= 0) continue;
      
      double BB_Upper[], BB_Lower[];
      ArraySetAsSeries(BB_Upper, true);
      ArraySetAsSeries(BB_Lower, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue; 
      if(CopyBuffer(BB_Handle, 2, 1, 1, BB_Lower) &lt;= 0) continue; 
      
      double upper = BB_Upper[0];
      double lower = BB_Lower[0];
      double close = Close_Arr[0];
      double Pct_B = (upper - lower == 0.0) ? 0.5 : (close - lower) / (upper - lower);
      
      if(close &gt; Ema_Val[0] &amp;&amp; Pct_B &lt; D1_PctB_Buy_Level)
      {
         double Ask = SymbolInfoDouble(Sym, SYMBOL_ASK);
         double Ghost_Sl = Ask - Yesterday_ATR;
         
         double Buy_Vol = Calculate_Robust_Volume(Sym, Ask, Ghost_Sl, D1_PctB_Risk_Perc);
         if(Buy_Vol &gt; 0.0)
         {
            double Buy_Margin = 0.0;
            if(OrderCalcMargin(ORDER_TYPE_BUY, Sym, Buy_Vol, Ask, Buy_Margin) &amp;&amp; Buy_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
            {
               Trading_Function.SetExpertMagicNumber(Magic);
               Trading_Function.Buy(Buy_Vol, Sym, Ask, 0.0, 0.0, "D1_PctB_Long");
            }
         }
      }
   }
}

void Run_D1_PctB_Manager()
{
   static datetime manager_last = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == manager_last) return;
   if(Current_H1 == 0) return;
   
   manager_last = Current_H1;

   int Total_Assets = ArraySize(D1_PctB_Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong Ticket = PositionGetTicket(i);
      if(Ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(Ticket)) continue;
      if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
      
      long Pos_Magic = PositionGetInteger(POSITION_MAGIC);
      string Pos_Sym = PositionGetString(POSITION_SYMBOL);
      
      int Asset_Idx = -1;
      for(int j = 0; j &lt; Total_Assets; j++)
      {
         if(D1_PctB_Portfolio[j].Magic_Number == Pos_Magic &amp;&amp; D1_PctB_Portfolio[j].Symbol == Pos_Sym)
         {
            Asset_Idx = j;
            break;
         }
      }
      
      if(Asset_Idx == -1) continue;
      
      int BB_Handle = D1_PctB_Portfolio[Asset_Idx].D1_BB_Handle;
      if(BB_Handle == INVALID_HANDLE) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Pos_Sym, PERIOD_D1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double BB_Upper[], BB_Lower[];
      ArraySetAsSeries(BB_Upper, true);
      ArraySetAsSeries(BB_Lower, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue;
      if(CopyBuffer(BB_Handle, 2, 1, 1, BB_Lower) &lt;= 0) continue;
      
      double upper = BB_Upper[0];
      double lower = BB_Lower[0];
      double close = Close_Arr[0];
      double Pct_B = (upper - lower == 0.0) ? 0.5 : (close - lower) / (upper - lower);
      
      if(Pct_B &gt; D1_PctB_Sell_Level)
      {
         Trading_Function.PositionClose(Ticket);
      }
   }
}

int OnInit()
{
   ushort sep = StringGetCharacter(",", 0);

   if(Run_H1_BB_Strategy)
   {
      string h1_symbols[];
      int num_h1 = StringSplit(H1_BB_Asset_Universe, sep, h1_symbols);
      if(num_h1 &gt; 0)
      {
         ArrayResize(H1_BB_Portfolio, num_h1);
         
         for(int i = 0; i &lt; num_h1; i++)
         {
            StringTrimLeft(h1_symbols[i]);
            StringTrimRight(h1_symbols[i]);
            
            SymbolSelect(h1_symbols[i], true);
            
            H1_BB_Portfolio[i].Symbol = h1_symbols[i];
            H1_BB_Portfolio[i].Magic_Number = H1_BB_Base_Magic + i;
            
            H1_BB_Portfolio[i].H1_BB_Handle = iBands(h1_symbols[i], PERIOD_H1, H1_BB_Bands_Period, 0, H1_BB_Bands_Width, PRICE_CLOSE);
            H1_BB_Portfolio[i].H1_ATR_Handle = iATR(h1_symbols[i], PERIOD_H1, 14);
            
            if(H1_BB_Portfolio[i].H1_BB_Handle == INVALID_HANDLE || H1_BB_Portfolio[i].H1_ATR_Handle == INVALID_HANDLE)
            {
               Print("Warning: Failed to load H1_BB handles for ", h1_symbols[i]);
            }
         }
      }
   }

   if(Run_D1_PctB_Strategy)
   {
      string d1_symbols[];
      int num_d1 = StringSplit(D1_PctB_Asset_Universe, sep, d1_symbols);
      if(num_d1 &gt; 0)
      {
         ArrayResize(D1_PctB_Portfolio, num_d1);
         
         for(int i = 0; i &lt; num_d1; i++)
         {
            StringTrimLeft(d1_symbols[i]);
            StringTrimRight(d1_symbols[i]);
            
            SymbolSelect(d1_symbols[i], true);
            
            D1_PctB_Portfolio[i].Symbol = d1_symbols[i];
            D1_PctB_Portfolio[i].Magic_Number = D1_PctB_Base_Magic + i;
            
            D1_PctB_Portfolio[i].D1_ATR_Handle = iATR(d1_symbols[i], PERIOD_D1, 20);
            D1_PctB_Portfolio[i].D1_BB_Handle  = iBands(d1_symbols[i], PERIOD_D1, D1_PctB_BB_Period, 0, D1_PctB_BB_Deviation, PRICE_CLOSE);
            D1_PctB_Portfolio[i].D1_EMA_Handle = iMA(d1_symbols[i], PERIOD_D1, D1_PctB_EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
            
            if(D1_PctB_Portfolio[i].D1_ATR_Handle == INVALID_HANDLE || D1_PctB_Portfolio[i].D1_BB_Handle == INVALID_HANDLE || D1_PctB_Portfolio[i].D1_EMA_Handle == INVALID_HANDLE)
            {
               Print("Warning: Failed to load D1_PctB handles for ", d1_symbols[i]);
            }
         }
      }
   }

   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   
   int total_h1 = ArraySize(H1_BB_Portfolio);
   for(int i = 0; i &lt; total_h1; i++)
   {
      if(H1_BB_Portfolio[i].H1_BB_Handle != INVALID_HANDLE) IndicatorRelease(H1_BB_Portfolio[i].H1_BB_Handle);
      if(H1_BB_Portfolio[i].H1_ATR_Handle != INVALID_HANDLE) IndicatorRelease(H1_BB_Portfolio[i].H1_ATR_Handle);
   }

   int total_d1 = ArraySize(D1_PctB_Portfolio);
   for(int i = 0; i &lt; total_d1; i++)
   {
      if(D1_PctB_Portfolio[i].D1_ATR_Handle != INVALID_HANDLE) IndicatorRelease(D1_PctB_Portfolio[i].D1_ATR_Handle);
      if(D1_PctB_Portfolio[i].D1_BB_Handle != INVALID_HANDLE)  IndicatorRelease(D1_PctB_Portfolio[i].D1_BB_Handle);
      if(D1_PctB_Portfolio[i].D1_EMA_Handle != INVALID_HANDLE) IndicatorRelease(D1_PctB_Portfolio[i].D1_EMA_Handle);
   }
}

void OnTick() {}

void OnTimer()
{
   if(Run_H1_BB_Strategy)
   {
      Run_H1_BB_Executor();
      Run_H1_BB_Manager();
   }
   
   if(Run_D1_PctB_Strategy)
   {
      Run_D1_PctB_Executor();
      Run_D1_PctB_Manager();
   }
}</code></pre></div>]]></content:encoded></item><item><title><![CDATA[Strategy Invalidation & When to Pull the Plug]]></title><description><![CDATA[How to know if a trading algo is just in normal drawdown or if the edge is dead, without panicking or guessing]]></description><link>https://mechanicalpremia.substack.com/p/strategy-invalidation-and-when-to</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/strategy-invalidation-and-when-to</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Tue, 25 Aug 2026 09:35:10 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/cc66f5ed-d6f5-4b02-92ef-7a025e22da6a_2816x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi there, welcome back to the Substack.</p><p>Today I want to share an honest story about one of my own trading algos, what happened when it hit an ugly patch in live trading, and how I actually decide when to de-risk, tune, or completely retire a system.</p><p>A while back, I built an intraday mean-reversion algo for the Nasdaq 100. It was a clean, relatively simple system. The historical testing was solid, passing the usual checks like parameter sensitivity, spread and slippage testing, and running across different instruments. Over a ten-year backtest it took somewhere around 1,700 trades, give or take, with a Sharpe ratio around 1.3ish. Nothing felt forced or over-optimized.</p><p>I deployed it live, and for a good stretch, it did its job well.</p><p>Then trade tariff headlines hit the news. The index only pulled back maybe 6% or so from the highs, but my long-only algo took a massive hit. The drawdown it took during that small 6% dip was the kind of loss I only expected to see during a deep 20% market drop.</p><p>The only thing that saved my entire portfolio from a severe drawdown was an index short-only volatility breakout algo running alongside it. The returns on that short system during the drop were so outsized that, even looking at my lifetime portfolio stats today, my short setups average out to be roughly 6 times more profitable than my long setups. It is a crazy reminder of how massive market outliers completely distort historical averages.</p><p>Even with the hedge doing its job, the Nasdaq long algo was clearly misbehaving. I pulled the plug and moved it over to a demo account to stop the bleeding. Funnily enough, the system eventually bounced back on demo and made all the money back. But even after that recovery, I made the call to scrap it permanently.</p><p>Why? Quite simply, because I had better.</p><p>That experience forced me to rethink how I classify live performance. Most people look at automated trading as a simple binary choice: either an algo is working fine, or the edge is completely broken and you pull the plug in a panic. In practice, viewing things as just black and white does not work. I look at my trading algos through a traffic light framework: Green, Yellow, and Red.</p><h3>Green Light: Expected Regime Behavior</h3><p>Green does not mean the algo is printing money every day or never takes a loss. It just means the algo is behaving within its normal statistical baseline for the current market environment.</p><p>Every system has regimes where it makes money and regimes where it gives money back. If you run a breakout system during a tight range, it will take small paper cuts. If a mean-reversion system takes expected losses during a strong, one-directional trend, that is completely normal. As long as the losses stay within the expected scale for that kind of market move, the light stays green and you leave the algo alone.</p><h3>Yellow Light: Outsized Pain, Logic Checks, and the Discretionary Reality</h3><p>Yellow is where things get tricky. This is when an algo is losing in a bad regime, but the losses are noticeably outsized compared to what the market is actually doing.</p><p>My Nasdaq story was a classic Yellow. A 6% market dip should not have produced a drawdown meant for a 20% crash. You see the same thing happen on forex pairs like USDJPY when central bank interventions start happening. On the daily chart, the overall trend might look smooth and clean to the upside, but down on the intraday charts, the price action turns into a chaotic mess of chop that repeatedly whipsaws breakout stops.</p><p>When an algo trips the yellow light, it does not mean the whole idea is dead. Often, the sizing logic did not account for that specific spike in volatility, or the entry levels are getting caught in unusual chop.</p><p>To diagnose what is happening, I run a grid of nearby parameters in the tester. If a wide plateau of settings still shows consistent, viable results, then the underlying market logic is still sound. It just means the live parameter set needs tuning or the risk needs to be turned down. Since I only validate algos that show a broad parameter plateau rather than a single lucky peak during initial research, adjusting within that band is safe.</p><p>During this Yellow phase, I de-risk the system, adjust the inputs, or move it to a demo account &#8220;penalty box.&#8221;</p><p>People love to view systematic trading as a complete hands-off removal of human decision-making, but that is simply not true. You cannot realistically code every single macro variable into an algo. As a human running the portfolio, you can look at the options chain, check implied volatility to see what the market is pricing in, read news sentiment, and gauge macro shifts. While I never make trade-by-trade discretionary calls anymore, deciding how long an algo sits in the penalty box and when to step in is a portfolio management call that only comes with experience.</p><h3>Red Light: Strategy Retirement and the Pipeline</h3><p>For me, Red is not an emotional blowup where an edge suddenly drops to absolute zero. When you put real effort into testing, systems rarely die completely overnight.</p><p>Red is really an opportunity cost decision. Building and testing algos is an ongoing process. I always have new setups, cleaner code, and better ideas sitting in incubation.</p><p>An algo hits the Red light when its ongoing performance drops below the new ideas I have waiting on the bench. &#8220;Better&#8221; is defined by your own portfolio metrics: it might be a system with a simpler parameter set, a more robust statistical edge, or better non-correlation to your active book.</p><p>When that happens, keeping the lagging system on the live book makes no financial sense. Since I trade a diversified portfolio across different assets, retiring one underperforming algo is not a disaster. I just dial down its risk, take it off the book, and replace it with a fresh setup built with the lessons learned from the previous one.</p><p>The post-mortem is pretty simple: look at what broke, see what could have been handled better, accept the flaws that cannot be fixed, and move on.</p><p>How do you handle your trading algos when they hit an ugly patch? Do you have a hard cutoff rule, or do you step in and make portfolio-level calls as market conditions change? Let me know in the comments.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Evolution of My Risk Model: From Fixed Lots to Volatility Parity]]></title><description><![CDATA[An honest look at the flaws of trade-level ATR sizing on MT5 and the napkin math I use to balance fast and slow strategies.]]></description><link>https://mechanicalpremia.substack.com/p/the-evolution-of-my-risk-model-from</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/the-evolution-of-my-risk-model-from</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Tue, 18 Aug 2026 18:03:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/15504b11-ebf1-4bca-9064-f8339f65e78d_2752x1536.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi there, welcome back to the Substack.</p><p>Today, I want to take a quick break from posting backtest equity curves and entry rules to talk about the part of trading that actually dictates whether an account survives: sizing.</p><p>Most trading forums obsess over finding an edge. But once you start running automated setups on MetaTrader 5 with real money, you realize your sizing model dictates your drawdown far more than any indicator. A fellow writer <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Karanveeir Handa, CFA&quot;,&quot;id&quot;:459727398,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49a376d1-822e-4140-bac8-4d8420e41a86_960x960.jpeg&quot;,&quot;uuid&quot;:&quot;5aaf5c7e-b5d9-405a-82c7-253e6e81fcda&quot;}" data-component-name="MentionToDOM"></span> , wrote a piece recently about sizing the risk rather than the position. It is a great point, but if you run multiple algorithmic or systematic setups on MT5, you quickly discover that trade-level risk sizing is only the first step in a much bigger problem.</p><p>Here is an honest breakdown of the mistakes I made with sizing, where each method broke down, and the practical math I use to balance different strategies today.</p><p><strong>Mistake 1: The Fixed Lot Trap</strong></p><p>When I first started deploying EAs on MT5, I did what almost everyone does: traded fixed lots. I had an index mean-reversion setup, a forex breakout bot, and a trend-following system, all opening 1.0 lot whenever a signal fired. It took very few trades to realize how broken that was. A 1.0 lot position on EURUSD moving 40 pips is a completely different animal than a 1.0 lot CFD contract on the DAX or US500 moving 40 points. A single bad day on an index contract wiped out weeks of steady gains from the currency setups. You think you are keeping things simple, but in reality, you are letting the raw, unadjusted volatility of the contract dictate your dollar losses.</p><p><strong>Mistake 2: Sizing the Trade, but Ignoring the Portfolio</strong></p><p>The obvious fix was decoupling lot size from risk. Instead of an arbitrary 1.0 lot, I switched to fixed-dollar risk sizing using ATR and chart invalidation points:</p><p><strong>Trade Lot Size = Fixed Dollar Risk / (Stop Distance in Points &#215; Point Value)</strong></p><p>If I have a $10,000 account and want to risk a flat $100 (1%) per trade, the EA calculates the exact contract size:</p><ul><li><p>Strategy A (tight 20-point stop) opens a larger lot size. If it loses, I lose $100.</p></li><li><p>Strategy B (wide 80-point stop) opens a much smaller lot size. If it loses, I lose $100.</p></li></ul><p>On paper, this felt like solved math. But in practice, running multiple strategies broke it immediately. Treating every trade as an isolated $100 risk only works if all your systems trade at the exact same speed. What actually happened on my account was completely lopsided:</p><ul><li><p><strong>Strategy A (Index Mean Reversion):</strong> A patient system taking about 9 trades a month with a high 70% win rate.</p></li><li><p><strong>Strategy B (Forex Breakout):</strong> An active bot taking roughly 144 trades a month with a 40% win rate.</p></li><li><p><strong>Strategy C (Index Trend):</strong> A mid-frequency system taking about 36 trades a month with a 55% win rate.</p></li></ul><p>By setting a flat $100 risk on everything, Strategy B took 16 times more trades than Strategy A. Even though each trade technically risked $100, Strategy B&#8217;s sheer trade velocity and inevitable losing streaks caused massive drawdown clusters that overwhelmed the entire balance. Meanwhile, Strategy A could win five trades in a row and barely move the equity curve. Sizing trades equally created an accidental monster where the fastest, lowest win-rate EA hijacked the entire account.</p><p><strong>The Practical Fix: Strategy-Level Frequency and Volatility Budgeting</strong></p><p>To make a multi-strategy account behave sensibly, you have to budget risk to each <em>system</em>, not just each trade. The goal is simple: an active, noisy breakout bot should get a smaller monthly risk allocation so it does not drown out a slower, higher-conviction system. Here is the quick napkin math I use to balance them across a total monthly risk budget (say, $1,000 across a $10,000 account):</p><p><strong>Step 1: Monthly Trade Count</strong></p><p>Monthly Trade Count = Total Strategy Trades / Total Backtest Months</p><p><strong>Step 2: Strategy Volatility Impact</strong></p><p>Strategy Volatility Impact = Average Dollar Loss &#215; Square Root of Monthly Trade Count</p><p><em>(Scaling the average loss by the square root of frequency uses standard volatility scaling over time so active strategies are dialed back fairly without getting completely strangled).</em></p><p><strong>Step 3: Inverse Volatility Share</strong></p><p>Inverse Volatility Share = (1 / Strategy Volatility Impact) / Sum of All Inverse Impacts Across Portfolio</p><p><strong>Step 4: Strategy Risk Budget</strong></p><p>Strategy Risk Budget = Inverse Volatility Share &#215; Total Portfolio Risk Budget</p><p>Walking through our three systems:</p><ul><li><p><strong>Strategy A:</strong> 9 trades/month, $100 average loss</p><p>Strategy Volatility Impact = 100 &#215; Square Root of 9 = <strong>300</strong></p></li><li><p><strong>Strategy B:</strong> 144 trades/month, $50 average loss</p><p>Strategy Volatility Impact = 50 &#215; Square Root of 144 = <strong>600</strong></p></li><li><p><strong>Strategy C:</strong> 36 trades/month, $100 average loss</p><p>Strategy Volatility Impact = 100 &#215; Square Root of 36 = <strong>600</strong></p></li></ul><p>When you calculate the inverse shares across all three, the $1,000 monthly risk pool divides up cleanly:</p><ul><li><p><strong>Strategy A:</strong> Gets roughly <strong>51.3%</strong> of the risk budget (<strong>$513</strong> for the month, or about <strong>$57.00 risk per trade</strong> across its 9 trades).</p></li><li><p><strong>Strategy B:</strong> Gets roughly <strong>25.6%</strong> of the risk budget (<strong>$256</strong> for the month, or about <strong>$1.78 risk per trade</strong> across its 144 trades).</p></li><li><p><strong>Strategy C:</strong> Gets roughly <strong>23.1%</strong> of the risk budget (<strong>$231</strong> for the month, or about <strong>$6.41 risk per trade</strong> across its 36 trades).</p></li></ul><p>The math mechanically chokes down Strategy B&#8217;s trade size so its rapid turnover doesn&#8217;t burn the account, while giving Strategy A enough room so its high win rate actually pays for the VPS hosting and time spent testing it.</p><p><strong>The Correlation Problem (And Why I Keep It Simple)</strong></p><p>Even with frequency-adjusted budgeting, there is an obvious theoretical blind spot: the formula assumes each EA operates on an island. If Strategy A is buying the S&amp;P 500 on pullbacks and Strategy C is buying the Nasdaq on breakouts, they look like two independent systems in your MT5 Navigator window. But when a surprise inflation print hits or liquidity dries up across US equities, both systems will hit their stop losses at the exact same second. Inverse-volatility weighting balances trade speed and average loss, but it won&#8217;t protect you when multiple bots share the same underlying market direction.</p><p>The textbook quant solution is to build dynamic correlation matrices and continuous covariance rebalancing into your code. But in practice, you don&#8217;t need complicated math to fix this. I avoid the entire issue at the portfolio design stage: I simply refuse to deploy strategies that are correlated to my existing book. If I already have an index mean-reversion setup, my next system has to trade a completely different asset class or structural inefficiency&#8212;like an Asian-session forex breakout or a commodity trend model.</p><p>By enforcing strict, structural non-correlation before a single dollar is risked, I get real diversification without drowning in complex matrix calculations. The simpler inverse-volatility model becomes more than sufficient to keep the account stable. Managing risk on an automated account is not about finding one immaculate formula that solves markets forever. It is just a continuous process of finding where your baseline assumptions fail and putting real-world guardrails in place. If you run multiple EAs or manual strategies on MT5, how do you handle allocation across systems with completely different trade frequencies? Drop your thoughts in the comments.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Fading the Edges: A Structural Mean-Reversion System for Forex Crosses]]></title><description><![CDATA[An 8-hour range-fade model for AUDCAD, EURCAD, AUDNZD, EURAUD, and GBPCAD]]></description><link>https://mechanicalpremia.substack.com/p/fading-the-edges-a-structural-mean</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/fading-the-edges-a-structural-mean</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Tue, 11 Aug 2026 13:38:49 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3ecd3830-741d-4ec5-8b94-97193f88c8fc_2816x1536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone. Welcome back to our third strategy breakdown.</p><p>In this post, we shift focus from stock index momentum and daily index pullbacks to mean reversion in foreign exchange cross pairs.</p><p>Unlike major equity indices that exhibit long-term upward drift, currency cross pairs (such as AUDCAD or EURAUD) reflect the relative pricing between two economies. Because these pairs lack a single structural bias, extreme price moves often experience liquidity exhaustion and return toward their rolling baseline.</p><p>This strategy identifies when price reaches a 100-bar extreme on the 8-Hour (H8) timeframe and executes a counter-trend position. Trades are managed with a rolling moving average exit and a time-based stop to limit exposure to sustained trend shifts.</p><h2>The Hypothesis</h2><p>Currency cross pairs frequently trade within defined ranges over multi-week horizons. When price reaches a 100-bar high or low on the 8-Hour chart (representing roughly 33 days of price action), short-term directional momentum often loses momentum.</p><p>The hypothesis is that taking counter-trend entries at these 100-bar boundaries provides a statistical edge. Risk is controlled by exiting as soon as price reverts to the 40-period EMA or when a maximum holding period of 20 bars (~1 week or 6.6 days) is reached.</p><h2>1. Baseline Performance</h2><p><strong>Instruments:</strong> AUDCAD, EURCAD, NZDCAD, EURAUD, GBPCAD</p><p><strong>Timeframe:</strong> 8-Hour (H8)</p><p><strong>Testing Period:</strong> 1 Jan 2015 to 1 Jun 2026</p><p>MT5 full sample Equity Curve</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iP0g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iP0g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 424w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 848w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 1272w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!iP0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png" width="1456" height="625" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:625,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42365,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/210713342?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iP0g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 424w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 848w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 1272w, https://substackcdn.com/image/fetch/$s_!iP0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0aee0-7006-41a8-b611-414ad708c83e_1586x681.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MT5 Full Sample Equity Curve</figcaption></figure></div><p></p><p><strong>Key Metrics:</strong></p><ul><li><p><strong>Total Net Profit:</strong> $15,372.35 (153.72% return on a $10,000 initial balance)</p></li><li><p><strong>Sharpe Ratio:</strong> 1.33</p></li><li><p><strong>Max Equity Drawdown:</strong> 19.98% ($5,075.26)</p></li><li><p><strong>Win Rate:</strong> 59.16% (368 winning trades out of 622 total)</p></li><li><p><strong>Total Trades:</strong> 622</p></li><li><p><strong>Profit Factor:</strong> 1.33</p></li><li><p><strong>Recovery Factor:</strong> 3.03</p></li></ul><h2>2. The Logic &amp; Ruleset</h2><p>The system is a long/short mean-reversion model evaluated strictly at the open of every new 8-Hour (H8) candle.</p><p><strong>Indicators Used:</strong> 100-Bar Highest High / Lowest Low Lookback, 40-Period Exponential Moving Average (EMA), and a 14-Period Average True Range (ATR), all calculated on the H8 timeframe.</p><p><strong>Entry Trigger:</strong></p><ul><li><p><strong>Lookback Window:</strong> The system measures the highest high and lowest low over the preceding 100 H8 bars (excluding the open bar).</p></li><li><p><strong>Buy Signal:</strong> Open a Long position if the previous H8 candle close is less than or equal to the 100-bar Lowest Low.</p></li><li><p><strong>Sell Signal:</strong> Open a Short position if the previous H8 candle close is greater than or equal to the 100-bar Highest High.</p></li></ul><p><strong>Exit Trigger:</strong></p><ul><li><p><strong>Mean-Reversion Exit:</strong></p><ul><li><p><strong>Long Positions:</strong> Closed when the H8 Close reaches or exceeds the 40-period EMA or the 100-bar Highest High.</p></li><li><p><strong>Short Positions:</strong> Closed when the H8 Close drops to or below the 40-period EMA or the 100-bar Lowest Low.</p></li></ul></li><li><p><strong>Time-Based Exit:</strong> Positions are force-closed if they remain open for 20 consecutive H8 bars (~6.6 trading days or 1 week).</p></li></ul><p><strong>Position Sizing &amp; Capital Allocation:</strong></p><ul><li><p>Fixed risk allocation of <strong>0.5%</strong> of free equity per trade.</p></li><li><p>Position sizing uses a synthetic risk distance based on 1x H8 ATR(14) to maintain uniform volatility exposure across all five pairs.</p></li><li><p>Includes an automated pre-execution margin check (<code>OrderCalcMargin</code>) before order submission.</p></li></ul><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h2>3. In-Sample vs. Out-of-Sample Testing</h2><p><strong>In-Sample (Optimization Period):</strong> 1 Jan 2015 to 31 Dec 2020</p><p><strong>Tested Parameters:</strong></p><ul><li><p><strong>Lookback_Bars:</strong> Held static at <strong>100</strong></p></li><li><p><strong>Exit_Bars (Time Stop):</strong> Tested from 10 to 50 (in steps of 10)</p></li><li><p><strong>EMA_Period (Trend/Exit Filter):</strong> Tested from 10 to 50 (in steps of 10)</p></li></ul><p><strong>Selection Rationale:</strong></p><p>The goal of optimization is not to cherry-pick an isolated, hyper-fitted peak, but to identify a broad, stable parameter region. To isolate the impact of trade management, the entry lookback was kept fixed at 100 bars, risk per trade was held at 0.5%, and the ATR volatility period remained at 14.</p><p>In Sample Result Optimization</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IO_d!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IO_d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 424w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 848w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 1272w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!IO_d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png" width="1456" height="602" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:602,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58791,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/210713342?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IO_d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 424w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 848w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 1272w, https://substackcdn.com/image/fetch/$s_!IO_d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd55948f-2ba9-4288-9da9-9a0bf554a989_1600x662.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Optimization Table, As you can see everything is positive </figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tr-o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tr-o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 424w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 848w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 1272w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tr-o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png" width="1027" height="532" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:532,&quot;width&quot;:1027,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:116560,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/210713342?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tr-o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 424w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 848w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 1272w, https://substackcdn.com/image/fetch/$s_!tr-o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F943ac4fd-00a4-497a-8a26-a8c4f1f66399_1027x532.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Optimization Surface (Lower exit bars is better, higher ema period is better)</figcaption></figure></div><p>Looking at the optimization results and the 3D surface chart, performance is primarily driven by a lower holding period and a longer ema period from this parameter selection for the final system was determined an ema period of 40 which is close the optimal and an exit bar period of 20 which is a little longer than the optimal period but it was chosen to reduce excessive trade count .</p><p><strong>Out-of-Sample (Validation Period):</strong> 1 Jan 2021 to 1 Jun 2026</p><p>Out of Sample Equity Curve</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bz8K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bz8K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 424w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 848w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 1272w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bz8K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png" width="1456" height="661" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:661,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:45829,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/210713342?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bz8K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 424w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 848w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 1272w, https://substackcdn.com/image/fetch/$s_!Bz8K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe640e20a-44fa-4b66-b41d-b8769e5220f0_1582x718.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p><strong>Performance:</strong> Although not as decent as the insample period sharpe dropped from 1.44 to 0.56 the performance of the system is still strong reaching equity highs even 5 years after selecting the initial parameters.</p><h2>4. The Weak Spot</h2><p>The system&#8217;s primary failure mode is a strong, sustained macro trend.</p><p>Because the entry logic actively fades 100-bar extremes, extended single direction moves such as those driven by divergent central bank interest rate policies will lead to sequential losing trades as price repeatedly sets new highs or lows without reverting to the mean.</p><p>The 20-bar time exit limits duration risk during trending regimes by closing trades that fail to mean-revert within the specified window.</p><h2><strong>5. The Source Code</strong></h2><blockquote><p>Ready-to-run MT5 script below.</p></blockquote><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;9a4d3de9-ed8c-4553-b665-0bc8defa93ce&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">#include &lt;Trade/Trade.mqh&gt;
CTrade Trading_Function;

input group "--- H8 Extremes Fade Strategy ---"
input string Asset_Universe = "AUDCAD,EURCAD,AUDNZD,EURAUD,GBPCAD";
input int    Base_Magic     = 700000;
input double Risk_Perc      = 1.0;
input int    Lookback_Bars  = 100;
input int    Exit_Bars      = 20;
input int    EMA_Period     = 40;

struct Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    H8_ATR_Handle;
   int    H8_EMA_Handle;
};
Asset_State Portfolio[];

bool Position_State_Checker(string symbol_name, int magic_number)
{
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      if(PositionGetTicket(i) &lt;= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == symbol_name &amp;&amp; PositionGetInteger(POSITION_MAGIC) == magic_number) return true;
   }
   for(int i = OrdersTotal() - 1; i &gt;= 0; i--)
   {
      if(OrderGetTicket(i) &lt;= 0) continue;
      if(OrderGetString(ORDER_SYMBOL) == symbol_name &amp;&amp; OrderGetInteger(ORDER_MAGIC) == magic_number) return true;
   }
   return false;
}

double Calculate_Robust_Volume(string symbol, double entry_price, double stop_loss, double risk_percent)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   if (balance &lt;= 0.0) return 0.0;
   
   double tick_size   = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tick_value  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   double min_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double max_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   if (tick_size == 0.0 || tick_value == 0.0 || volume_step == 0.0) return 0.0;
   if (entry_price == stop_loss) return 0.0;

   double sl_distance_ticks = MathAbs(entry_price - stop_loss) / tick_size;
   if (sl_distance_ticks == 0.0) return 0.0;
   
   double risk_per_lot = sl_distance_ticks * tick_value;
   if (risk_per_lot == 0.0) return 0.0;

   double final_lot = MathFloor((balance * (risk_percent / 100.0) / risk_per_lot) / volume_step) * volume_step;
   if (final_lot &lt; min_volume) final_lot = min_volume;
   if (final_lot &gt; max_volume) final_lot = max_volume;

   int vol_digits = (volume_step == 0.1) ? 1 : (volume_step == 0.01) ? 2 : (volume_step == 0.001) ? 3 : (volume_step == 0.0001) ? 4 : 0;
   return NormalizeDouble(final_lot, vol_digits);
}

void Run_H8_Extremes_Executor()
{
   static datetime Last_H8_Time = 0;
   datetime Current_H8 = iTime(_Symbol, PERIOD_H8, 0);
   
   if(Current_H8 == Last_H8_Time) return;
   if(Current_H8 == 0) return;
   
   Last_H8_Time = Current_H8;
   
   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = 0; i &lt; Total_Assets; i++)
   {
      string Sym = Portfolio[i].Symbol;
      int Magic = Portfolio[i].Magic_Number;
      int Atr_Handle = Portfolio[i].H8_ATR_Handle;
      int Ema_Handle = Portfolio[i].H8_EMA_Handle;
      
      if(Atr_Handle == INVALID_HANDLE || Ema_Handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(Sym, Magic)) continue; 
      if(!SeriesInfoInteger(Sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      double Atr_Val[];
      ArraySetAsSeries(Atr_Val, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 1, Atr_Val) &lt;= 0) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Sym, PERIOD_H8, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double High_Arr[], Low_Arr[];
      ArraySetAsSeries(High_Arr, true);
      ArraySetAsSeries(Low_Arr, true);
      
      if(CopyHigh(Sym, PERIOD_H8, 2, Lookback_Bars, High_Arr) &lt; Lookback_Bars) continue;
      if(CopyLow(Sym, PERIOD_H8, 2, Lookback_Bars, Low_Arr) &lt; Lookback_Bars) continue;
      
      double highest_high = High_Arr[0];
      double lowest_low = Low_Arr[0];
      
      for(int k = 1; k &lt; Lookback_Bars; k++)
      {
         if(High_Arr[k] &gt; highest_high) highest_high = High_Arr[k];
         if(Low_Arr[k] &lt; lowest_low) lowest_low = Low_Arr[k];
      }
      
      double close = Close_Arr[0];
      
      if(close &lt;= lowest_low)
      {
         double Ask = SymbolInfoDouble(Sym, SYMBOL_ASK);
         double Ghost_Sl = Ask - Atr_Val[0];
         
         double Buy_Vol = Calculate_Robust_Volume(Sym, Ask, Ghost_Sl, Risk_Perc);
         if(Buy_Vol &gt; 0.0)
         {
            double Buy_Margin = 0.0;
            if(OrderCalcMargin(ORDER_TYPE_BUY, Sym, Buy_Vol, Ask, Buy_Margin) &amp;&amp; Buy_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
            {
               Trading_Function.SetExpertMagicNumber(Magic);
               Trading_Function.Buy(Buy_Vol, Sym, Ask, 0.0, 0.0, "H8_Fade_Buy");
            }
         }
      }
      else if(close &gt;= highest_high)
      {
         double Bid = SymbolInfoDouble(Sym, SYMBOL_BID);
         double Ghost_Sl = Bid + Atr_Val[0];
         
         double Sell_Vol = Calculate_Robust_Volume(Sym, Bid, Ghost_Sl, Risk_Perc);
         if(Sell_Vol &gt; 0.0)
         {
            double Sell_Margin = 0.0;
            if(OrderCalcMargin(ORDER_TYPE_SELL, Sym, Sell_Vol, Bid, Sell_Margin) &amp;&amp; Sell_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
            {
               Trading_Function.SetExpertMagicNumber(Magic);
               Trading_Function.Sell(Sell_Vol, Sym, Bid, 0.0, 0.0, "H8_Fade_Sell");
            }
         }
      }
   }
}

void Run_H8_Extremes_Manager()
{
   static datetime manager_last = 0;
   datetime Current_H8 = iTime(_Symbol, PERIOD_H8, 0);
   
   if(Current_H8 == manager_last) return;
   if(Current_H8 == 0) return;
   
   manager_last = Current_H8;

   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong Ticket = PositionGetTicket(i);
      if(Ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(Ticket)) continue;
      
      long Pos_Type = PositionGetInteger(POSITION_TYPE);
      long Pos_Magic = PositionGetInteger(POSITION_MAGIC);
      string Pos_Sym = PositionGetString(POSITION_SYMBOL);
      datetime Open_Time = (datetime)PositionGetInteger(POSITION_TIME);
      
      int Asset_Idx = -1;
      for(int j = 0; j &lt; Total_Assets; j++)
      {
         if(Portfolio[j].Magic_Number == Pos_Magic &amp;&amp; Portfolio[j].Symbol == Pos_Sym)
         {
            Asset_Idx = j;
            break;
         }
      }
      
      if(Asset_Idx == -1) continue;
      
      Trading_Function.SetExpertMagicNumber((int)Pos_Magic);
      
      int bars_held = iBarShift(Pos_Sym, PERIOD_H8, Open_Time);
      if(bars_held &gt;= Exit_Bars)
      {
         Trading_Function.PositionClose(Ticket);
         continue;
      }
      
      int Ema_Handle = Portfolio[Asset_Idx].H8_EMA_Handle;
      if(Ema_Handle == INVALID_HANDLE) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Pos_Sym, PERIOD_H8, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double Ema_Val[];
      ArraySetAsSeries(Ema_Val, true);
      if(CopyBuffer(Ema_Handle, 0, 1, 1, Ema_Val) &lt;= 0) continue;
      
      double High_Arr[], Low_Arr[];
      ArraySetAsSeries(High_Arr, true);
      ArraySetAsSeries(Low_Arr, true);
      
      if(CopyHigh(Pos_Sym, PERIOD_H8, 2, Lookback_Bars, High_Arr) &lt; Lookback_Bars) continue;
      if(CopyLow(Pos_Sym, PERIOD_H8, 2, Lookback_Bars, Low_Arr) &lt; Lookback_Bars) continue;
      
      double highest_high = High_Arr[0];
      double lowest_low = Low_Arr[0];
      
      for(int k = 1; k &lt; Lookback_Bars; k++)
      {
         if(High_Arr[k] &gt; highest_high) highest_high = High_Arr[k];
         if(Low_Arr[k] &lt; lowest_low) lowest_low = Low_Arr[k];
      }
      
      double close = Close_Arr[0];
      double ema = Ema_Val[0];
      
      if(Pos_Type == POSITION_TYPE_BUY)
      {
         if(close &gt;= ema || close &gt;= highest_high)
         {
            Trading_Function.PositionClose(Ticket);
         }
      }
      else if(Pos_Type == POSITION_TYPE_SELL)
      {
         if(close &lt;= ema || close &lt;= lowest_low)
         {
            Trading_Function.PositionClose(Ticket);
         }
      }
   }
}

int OnInit()
{
   ushort sep = StringGetCharacter(",", 0);
   string symbols[];
   
   int num_symbols = StringSplit(Asset_Universe, sep, symbols);
   if(num_symbols &gt; 0)
   {
      ArrayResize(Portfolio, num_symbols);
      
      for(int i = 0; i &lt; num_symbols; i++)
      {
         StringTrimLeft(symbols[i]);
         StringTrimRight(symbols[i]);
         
         SymbolSelect(symbols[i], true);
         
         Portfolio[i].Symbol = symbols[i];
         Portfolio[i].Magic_Number = Base_Magic + i;
         
         Portfolio[i].H8_ATR_Handle = iATR(symbols[i], PERIOD_H8, 14);
         Portfolio[i].H8_EMA_Handle = iMA(symbols[i], PERIOD_H8, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
      }
   }

   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   
   int total_assets = ArraySize(Portfolio);
   for(int i = 0; i &lt; total_assets; i++)
   {
      if(Portfolio[i].H8_ATR_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].H8_ATR_Handle);
      if(Portfolio[i].H8_EMA_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].H8_EMA_Handle);
   }
}

void OnTick() {}

void OnTimer()
{
   Run_H8_Extremes_Executor();
   Run_H8_Extremes_Manager();
}</code></pre></div><h2>6. Verification Notes</h2><p><strong>Trading Cost (Full backtest):</strong> Rollover swaps and execution costs were strictly accounted for across multi-day holding periods.</p><p><strong>Data Source:</strong> FBS Markets (MT5 Historical Data)</p><p><strong>Slippage/Commissions:</strong> 1 pip slippage, $1 per standard lot commission per trade across all instruments (AUDCAD, EURCAD, NZDCAD, EURAUD, GBPCAD).</p><p><strong>Timezone:</strong> UTC+2</p><p>Want to access more robust systems and build your trading portfolio? Subscribe for free to get complete strategy breakdowns, unclouded logic, and ready-to-run MetaTrader scripts delivered straight to your inbox.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[Catching the Snapback: A Daily Mean-Reversion Model for Stock Indices]]></title><description><![CDATA[A Daily %B pullback system for US500, US100, DE30 and EU50]]></description><link>https://mechanicalpremia.substack.com/p/catching-the-snapback-a-daily-mean</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/catching-the-snapback-a-daily-mean</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Mon, 03 Aug 2026 12:00:58 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/024bb5f6-cbd7-4978-9c60-74c4099404c6_2528x1688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone. Welcome back to the second strategy breakdown.</p><p>While our first model focused on capturing quiet breakouts, today we are switching gears entirely. Instead of chasing momentum at new highs, we are looking at how to systematically buy deep, sharp sell-offs within strong uptrends without getting caught in major crashes.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Mechanical Premia! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Catching pullbacks sounds great in theory, but the practical execution is where most traders fail. The instinct is often to buy every dip, which exposes you to violent downtrends when market conditions shift. The main challenge is not finding a market that has recently dropped, it&#8217;s quantifying when a dip or pullback has hit an extreme oversold level while the broader trend remains strictly intact.</p><p>To make a mean-reversion edge work, we need two distinct structural filters: macro trend direction and entry volatility. By requiring the market to sit comfortably above its long-term moving average while entering only when short term volatility is low, we buy the right dips and avoid long term bear markets.</p><h2>The Hypothesis</h2><p>The core idea of this system is to exploit temporary short side dips on major stock indices using the <strong>%B indicator</strong> derived from Bollinger Bands on the daily timeframe.</p><p>We hypothesize that when an index is in a confirmed long-term bull market (Close &gt; 100 EMA), short-term drops below the lower boundary of a 10-period, 3.0 standard deviation Bollinger Band (%B &lt; 0.2 (default value)) represents temporary overextensions rather than true market downturns.</p><p>To protect against severe market crashes, we layer on a strict volatility threshold: we only execute the buy signal if the previous day&#8217;s ATR is below its 100-day median. This ensures we are buying quiet, controlled dips in ongoing bull markets, completely avoiding high volatility regimes where small dips turn into sustained bear trends. Once the price snaps back toward the upper band environment (%B &gt; 0.8), the statistical imbalance is resolved, and we exit the position.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h2><strong>1. Baseline Performance</strong></h2><blockquote><p><strong>Instruments:</strong><span> US500, US100, DE30, EU50</span></p><p><strong>Timeframe:</strong><span> Daily</span></p><p><strong>Testing Period:</strong><span> 1 Jan 2015 to 1 Jun 2026</span></p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a8kj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a8kj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 424w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 848w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 1272w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!a8kj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png" width="1456" height="620" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:620,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44878,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/209610112?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!a8kj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 424w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 848w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 1272w, https://substackcdn.com/image/fetch/$s_!a8kj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941d0a8d-6f78-4aec-ab1e-df9ad5979e07_1584x674.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MT5 full sample Equity Curve</figcaption></figure></div><blockquote><p><strong>Key Metrics:</strong></p></blockquote><ul><li><p><strong>Total Return:</strong><span> 80.03%</span></p></li><li><p><strong>Sharpe Ratio:</strong><span> 0.93</span></p></li><li><p><strong>Max Drawdown:</strong><span> 18.52%</span></p></li><li><p><strong>Win Rate:</strong><span> 72.22%</span></p></li><li><p><strong>Total Trades:</strong><span> 126</span></p></li><li><p><strong>Profit Factor:</strong><span> 2.91</span></p></li></ul><h2>The Logic &amp; Ruleset</h2><p>The system is a long-only daily mean-reversion model executed on the Daily chart to handle trade management and execution seamlessly.</p><p><strong>Indicators Used:</strong> 10-Period Bollinger Bands (3.0 Standard Deviations, Applied to Close), 100-Period Exponential Moving Average (EMA), and a 20-Period Average True Range (ATR), all calculated on the Daily (D1) timeframe.</p><p><strong>Entry Trigger:</strong></p><ul><li><p><strong>Trend Filter:</strong> The previous Daily Close must be strictly above the 100-period Daily EMA.</p></li><li><p><strong>Volatility Filter:</strong> Calculate the 50th percentile (median) of the last 100 readings of the Daily ATR(20). Verify that yesterday&#8217;s Daily ATR(20) is strictly less than this median value.</p></li><li><p><strong>Over-Extended Dip:</strong> Calculate Daily %B using the formula:</p><p>%B = (Close - Lower Band) / (Upper Band - Lower Band)</p></li><li><p>Open a Long position on the open of the next candle if %B drops strictly below <strong>0.2</strong> (oversold condition).</p></li></ul><p><strong>Exit Trigger:</strong></p><ul><li><p>The position is managed continuously on the open of each new candle.</p></li><li><p>The trade is closed when the Daily %B value pushes back strictly above <strong>0.8</strong> (rebound toward the upper band environment).</p></li><li><p><em>Note:</em> Initial position sizing uses a &#8220;ghost&#8221; risk distance derived from yesterday&#8217;s Daily ATR, but the primary trade exit relies on the statistical rebound of the %B indicator.</p></li></ul><p><strong>Position Sizing &amp; Capital Allocation:</strong></p><ul><li><p>Position sizing is based on 1x Daily ATR. Rather than placing a hard stop loss on the trade, the EA uses yesterday&#8217;s 20-period ATR distance as a dynamic volatility baseline.</p></li><li><p>The position size is calculated so that a 1x ATR move against the entry price equals exactly the risk percent parameter. This normalizes risk across varying assets while allowing the statistical %B exit rule to manage trade duration organically.</p></li><li><p>Every trade passes through a pre-execution margin check to verify that the dynamic lot size fits within available free margin before sending the order to the market.</p></li></ul><h2>3. In-Sample vs. Out-of-Sample Testing</h2><p><strong>In-Sample (Optimization Period):</strong> 1 Jan 2015 to 31 Dec 2020</p><p><strong>Tested Parameters:</strong></p><ul><li><p><strong>Bollinger Bands Period:</strong> Tested from 10 to 100 (in steps of 10).</p></li><li><p><strong>Bollinger Bands Deviation:</strong> Tested at 2.0 and 3.0.</p></li><li><p><strong>EMA Period:</strong> Tested from 50 to 200 (in steps of 50).</p></li></ul><p><strong>Selection Rationale:</strong> The goal of optimization is not to cherry pick the single highest return parameter combination, but to identify a stable region of parameters that withstands changing regimes.</p><p>I deliberately kept key structural variables static to protect against curve fitting the volatility lookback was held at a standard 20-period Daily ATR, the ATR percentile lookback remained at 100 days (to ensure a robust baseline median), and entry/exit %B thresholds were fixed at 0.2 and 0.8 respectively.</p><p>By testing broad step intervals across the band period and trend filters, we ensure that the strategy&#8217;s edge stems from the underlying mean-reversion effect rather than fragile parameter fine-tuning.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ns6o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ns6o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 424w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 848w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 1272w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ns6o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png" width="1456" height="399" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:399,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:46857,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/209610112?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ns6o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 424w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 848w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 1272w, https://substackcdn.com/image/fetch/$s_!ns6o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3dacc41-4311-4024-a14a-c92077fa456d_1593x437.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">In Sample Result Optimization. the only sensitive parameter is BB period</figcaption></figure></div><p>Looking at the optimization results ema period and bb deviation tend not to have a big impact on the strategy Sharpe and returns, the only sensitive parameter here is BB period which degrades linearly in performance as the number increases. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!399N!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!399N!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 424w, https://substackcdn.com/image/fetch/$s_!399N!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 848w, https://substackcdn.com/image/fetch/$s_!399N!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 1272w, https://substackcdn.com/image/fetch/$s_!399N!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!399N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png" width="834" height="387" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:387,&quot;width&quot;:834,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103443,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/209610112?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!399N!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 424w, https://substackcdn.com/image/fetch/$s_!399N!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 848w, https://substackcdn.com/image/fetch/$s_!399N!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 1272w, https://substackcdn.com/image/fetch/$s_!399N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f5f550f-088f-48a1-83fe-43992db8c93f_834x387.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">3D optimization surface</figcaption></figure></div><p>Crucially, the 3D optimization surface chart confirms this stability. Notice the smooth gradient sloping downward; there are no sharp, isolated spikes indicating a hyper-optimized, curve-fit anomaly. The parameters are robust across a wide surface area.</p><p><strong>Out-of-Sample (Validation Period):</strong><span> 1 Jan 2021 to 1 Jun 2026</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MjqO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MjqO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 424w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 848w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 1272w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MjqO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png" width="1456" height="594" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:594,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36631,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/209610112?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MjqO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 424w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 848w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 1272w, https://substackcdn.com/image/fetch/$s_!MjqO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abb65fe-5c09-4bcd-8f70-5af6f5129809_1574x642.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Out of Sample Equity Curve</figcaption></figure></div><ul><li><p><strong>OOS Sharpe Ratio:</strong><span> 0.93</span></p></li><li><p><strong>OOS Max Drawdown:</strong><span> 10.11%</span></p></li><li><p><strong>Performance :</strong><span> The system maintained its edge well in unseen data. While there appears to be a small improvement even in OOS data that might simply be because the filters worked well the last 5 years</span></p></li></ul><h2>4. The Weak Spot</h2><p>Every mechanical edge has a cost, and for this daily mean-reversion model, the failure mode is a strong, relentless downtrend or a severe market regime shift.</p><p>Because the system specifically buys extreme oversold pullbacks (%B &lt; 0.2), its primary vulnerability occurs when a routine market correction turns into a full-blown structural bear market. If an index breaks down below its long-term moving average or experiences sustained selling pressure that outpaces historical volatility, the strategy can take repeated losses on the way down as price stays compressed near the lower band.</p><p>Additionally, in low-volatility, runaway bull markets where price steadily grinds higher without ever pulling back deep enough, the model will sit completely on the sidelines and miss gains. That is simply the toll we pay to avoid buying overextended highs and to ensure we only deploy capital when the odds of a mean-reverting snapback are heavily in our favor.</p><h2><strong>5. The Source Code</strong></h2><blockquote><p>Ready-to-run MT5 script below.</p></blockquote><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;2b69d3c8-401a-4211-b183-43404e9310fe&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">#include &lt;Trade/Trade.mqh&gt;
CTrade Trading_Function;

input group "--- Daily %B Pullback Strategy (Long Only) ---"
input string Asset_Universe   = "US500,US100,DE30,EU50";
input int    Base_Magic       = 300000;
input double Risk_Perc        = 1.0;
input int    EMA_Period       = 100;
input int    BB_Period        = 10;
input double BB_Deviation     = 3.0;
input double Buy_Level        = 0.2;
input double Sell_Level       = 0.8;

struct Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    D1_ATR_Handle;
   int    D1_BB_Handle;
   int    D1_EMA_Handle;
};
Asset_State Portfolio[];

bool Position_State_Checker(string symbol_name, int magic_number)
{
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      if(PositionGetTicket(i) &lt;= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == symbol_name &amp;&amp; PositionGetInteger(POSITION_MAGIC) == magic_number) return true;
   }
   for(int i = OrdersTotal() - 1; i &gt;= 0; i--)
   {
      if(OrderGetTicket(i) &lt;= 0) continue;
      if(OrderGetString(ORDER_SYMBOL) == symbol_name &amp;&amp; OrderGetInteger(ORDER_MAGIC) == magic_number) return true;
   }
   return false;
}

double Calculate_Robust_Volume(string symbol, double entry_price, double stop_loss, double risk_percent)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   if (balance &lt;= 0.0) return 0.0;
   
   double tick_size   = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tick_value  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   double min_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double max_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   if (tick_size == 0.0 || tick_value == 0.0 || volume_step == 0.0) return 0.0;
   if (entry_price == stop_loss) return 0.0;

   double sl_distance_ticks = MathAbs(entry_price - stop_loss) / tick_size;
   if (sl_distance_ticks == 0.0) return 0.0;
   
   double risk_per_lot = sl_distance_ticks * tick_value;
   if (risk_per_lot == 0.0) return 0.0;

   double final_lot = MathFloor((balance * (risk_percent / 100.0) / risk_per_lot) / volume_step) * volume_step;
   if (final_lot &lt; min_volume) final_lot = min_volume;
   if (final_lot &gt; max_volume) final_lot = max_volume;

   int vol_digits = (volume_step == 0.1) ? 1 : (volume_step == 0.01) ? 2 : (volume_step == 0.001) ? 3 : (volume_step == 0.0001) ? 4 : 0;
   return NormalizeDouble(final_lot, vol_digits);
}

void Run_D1_PctB_Executor()
{
   static datetime Last_H1_Time = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == Last_H1_Time) return;
   if(Current_H1 == 0) return;
   
   Last_H1_Time = Current_H1;
   
   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = 0; i &lt; Total_Assets; i++)
   {
      string Sym = Portfolio[i].Symbol;
      int Magic = Portfolio[i].Magic_Number;
      
      int Atr_Handle = Portfolio[i].D1_ATR_Handle;
      int BB_Handle = Portfolio[i].D1_BB_Handle;
      int Ema_Handle = Portfolio[i].D1_EMA_Handle;
      
      if(Atr_Handle == INVALID_HANDLE || BB_Handle == INVALID_HANDLE || Ema_Handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(Sym, Magic)) continue; 
      if(!SeriesInfoInteger(Sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      double Atr_100[];
      ArraySetAsSeries(Atr_100, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 100, Atr_100) &lt; 100) continue;
      
      double Yesterday_ATR = Atr_100[0];
      
      double Atr_Sorted[];
      ArrayResize(Atr_Sorted, 100);
      for(int k = 0; k &lt; 100; k++)
      {
         Atr_Sorted[k] = Atr_100[k];
      }
      ArraySort(Atr_Sorted);
      double Median_ATR = Atr_Sorted[50];
      
      if(Yesterday_ATR &gt;= Median_ATR) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Sym, PERIOD_D1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double Ema_Val[];
      ArraySetAsSeries(Ema_Val, true);
      if(CopyBuffer(Ema_Handle, 0, 1, 1, Ema_Val) &lt;= 0) continue;
      
      double BB_Upper[], BB_Lower[];
      ArraySetAsSeries(BB_Upper, true);
      ArraySetAsSeries(BB_Lower, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue; 
      if(CopyBuffer(BB_Handle, 2, 1, 1, BB_Lower) &lt;= 0) continue; 
      
      double upper = BB_Upper[0];
      double lower = BB_Lower[0];
      double close = Close_Arr[0];
      double Pct_B = (upper - lower == 0.0) ? 0.5 : (close - lower) / (upper - lower);
      
      if(close &gt; Ema_Val[0] &amp;&amp; Pct_B &lt; Buy_Level)
      {
         double Ask = SymbolInfoDouble(Sym, SYMBOL_ASK);
         double Ghost_Sl = Ask - Yesterday_ATR;
         
         double Buy_Vol = Calculate_Robust_Volume(Sym, Ask, Ghost_Sl, Risk_Perc);
         if(Buy_Vol &gt; 0.0)
         {
            double Buy_Margin = 0.0;
            if(OrderCalcMargin(ORDER_TYPE_BUY, Sym, Buy_Vol, Ask, Buy_Margin) &amp;&amp; Buy_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
            {
               Trading_Function.SetExpertMagicNumber(Magic);
               Trading_Function.Buy(Buy_Vol, Sym, Ask, 0.0, 0.0, "D1_PctB_Long");
            }
         }
      }
   }
}

void Run_D1_PctB_Manager()
{
   static datetime manager_last = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == manager_last) return;
   if(Current_H1 == 0) return;
   
   manager_last = Current_H1;

   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong Ticket = PositionGetTicket(i);
      if(Ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(Ticket)) continue;
      if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
      
      long Pos_Magic = PositionGetInteger(POSITION_MAGIC);
      string Pos_Sym = PositionGetString(POSITION_SYMBOL);
      
      int Asset_Idx = -1;
      for(int j = 0; j &lt; Total_Assets; j++)
      {
         if(Portfolio[j].Magic_Number == Pos_Magic &amp;&amp; Portfolio[j].Symbol == Pos_Sym)
         {
            Asset_Idx = j;
            break;
         }
      }
      
      if(Asset_Idx == -1) continue;
      
      int BB_Handle = Portfolio[Asset_Idx].D1_BB_Handle;
      if(BB_Handle == INVALID_HANDLE) continue;
      
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Pos_Sym, PERIOD_D1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      double BB_Upper[], BB_Lower[];
      ArraySetAsSeries(BB_Upper, true);
      ArraySetAsSeries(BB_Lower, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue;
      if(CopyBuffer(BB_Handle, 2, 1, 1, BB_Lower) &lt;= 0) continue;
      
      double upper = BB_Upper[0];
      double lower = BB_Lower[0];
      double close = Close_Arr[0];
      double Pct_B = (upper - lower == 0.0) ? 0.5 : (close - lower) / (upper - lower);
      
      if(Pct_B &gt; Sell_Level)
      {
         Trading_Function.PositionClose(Ticket);
      }
   }
}

int OnInit()
{
   ushort sep = StringGetCharacter(",", 0);
   string symbols[];
   
   int num_symbols = StringSplit(Asset_Universe, sep, symbols);
   if(num_symbols &gt; 0)
   {
      ArrayResize(Portfolio, num_symbols);
      
      for(int i = 0; i &lt; num_symbols; i++)
      {
         StringTrimLeft(symbols[i]);
         StringTrimRight(symbols[i]);
         
         SymbolSelect(symbols[i], true);
         
         Portfolio[i].Symbol = symbols[i];
         Portfolio[i].Magic_Number = Base_Magic + i;
         
         Portfolio[i].D1_ATR_Handle = iATR(symbols[i], PERIOD_D1, 20);
         Portfolio[i].D1_BB_Handle  = iBands(symbols[i], PERIOD_D1, BB_Period, 0, BB_Deviation, PRICE_CLOSE);
         Portfolio[i].D1_EMA_Handle = iMA(symbols[i], PERIOD_D1, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
         
         if(Portfolio[i].D1_ATR_Handle == INVALID_HANDLE || Portfolio[i].D1_BB_Handle == INVALID_HANDLE || Portfolio[i].D1_EMA_Handle == INVALID_HANDLE)
         {
            Print("Warning: Failed to load handles for ", symbols[i]);
         }
      }
   }

   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   
   int total_assets = ArraySize(Portfolio);
   for(int i = 0; i &lt; total_assets; i++)
   {
      if(Portfolio[i].D1_ATR_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].D1_ATR_Handle);
      if(Portfolio[i].D1_BB_Handle != INVALID_HANDLE)  IndicatorRelease(Portfolio[i].D1_BB_Handle);
      if(Portfolio[i].D1_EMA_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].D1_EMA_Handle);
   }
}

void OnTick() {}

void OnTimer()
{
   Run_D1_PctB_Executor();
   Run_D1_PctB_Manager();
}</code></pre></div><h2> <strong>6. Verification Notes</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EPAO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EPAO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 424w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 848w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 1272w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!EPAO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png" width="1456" height="575" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:575,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:90241,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/209610112?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EPAO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 424w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 848w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 1272w, https://substackcdn.com/image/fetch/$s_!EPAO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f264625-c4e8-41b8-aa29-4b98a63e2fe9_1600x632.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Trading Cost(Full back test) Swaps are brutal on CFD brokers for daily chart strategies</figcaption></figure></div><ul><li><p><strong>Data Source:</strong><span> [Dukascopy via JForex Historical Download Manager]</span></p></li><li><p><strong>Slippage/Commissions:</strong><span> [1p slippage, 8$ per standard lot(US100), 8$ per standard lot(DE30), 8$ per standard lot EU50, 2$ per standard lot(US500), charged both at entry and at exit]</span></p></li><li><p><strong>Timezone:</strong><span> [UTC]</span></p></li></ul><blockquote><p><strong>Want to access more robust systems and build your trading portfolio?</strong><span> Subscribe for free to get complete strategy breakdowns, unclouded logic, and ready-to-run MetaTrader scripts delivered straight to your inbox.</span></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Mechanical Premia! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Signal vs. Noise: Why Stock Indices Reward Quiet Breakouts]]></title><description><![CDATA[A basic Bollinger band momentum system for DE30, US100 and US500]]></description><link>https://mechanicalpremia.substack.com/p/signal-vs-noise-why-stock-indices</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/signal-vs-noise-why-stock-indices</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Mon, 27 Jul 2026 08:40:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!H_iK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone. Welcome to my very first system breakdown. I&#8217;m excited to finally open up my process and share the actual quantitative models I use, rather than just discussing theory.</p><p>Buying at the highs feels inherently uncomfortable, which is why so many traders gravitate toward pullback strategies. It is tough to hit the buy button when an asset is already breaking new levels. But simple breakout models have always worked&#8212;provided you know how to filter out the noise. The issue isn&#8217;t the breakout itself; it&#8217;s the environment in which it happens.</p><p>Most breakouts fail because they trigger in choppy, already-volatile environments where price simply whipsaws back and forth. If you buy a breakout when the market is already wild, you are exposing yourself to massive stop-outs. The mechanical edge lies in finding moments of quiet. By demanding that volatility is strictly below its historical average, we filter out the erratic noise. We are still buying the highs, but only when the market has proven it is calm enough to actually sustain a new direction.</p><p><strong>The Hypothesis</strong> The idea here is to quantify this &#8220;quiet state&#8221; using the Average True Range (ATR) and only act when an 80-period Bollinger Band is breached. We are betting that if a long-term high is broken while the current volatility is mathematically suppressed, we are capturing the true start of a trend rather than a noisy false breakouts</p><h2>1. Baseline Performance</h2><p><strong>Instruments:</strong> US500, DE30, US100</p><p><strong>Timeframe:</strong> 1-Hour</p><p><strong>Testing Period:</strong> 1 Jan 2015 to 1 Jun 2026</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H_iK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H_iK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 424w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 848w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 1272w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H_iK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png" width="1456" height="680" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:680,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42005,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/208654181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!H_iK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 424w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 848w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 1272w, https://substackcdn.com/image/fetch/$s_!H_iK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78219e7d-034d-4a84-a18d-7e7a317aa1e0_1582x739.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MT5 Full sample equity curve</figcaption></figure></div><p></p><p><strong>Key Metrics:</strong></p><ul><li><p><strong>Total Return:</strong> 71.01%</p></li><li><p><strong>Sharpe Ratio:</strong> 2.14</p></li><li><p><strong>Max Drawdown:</strong> 3.84%</p></li><li><p><strong>Win Rate:</strong> 40.04%</p></li><li><p><strong>Total Trades:</strong> 2495</p></li><li><p><strong>Profit Factor:</strong> 1.29</p><p></p></li></ul><h2>2. The Logic &amp; Ruleset</h2><p>The system is a long-only volatility breakout model evaluated strictly at the close of the 1-hour candle.</p><ul><li><p><strong>Indicators Used:</strong> 40-Period Bollinger Bands (2.0 Standard Deviations, Applied to Close) and a 14-Period Average True Range (ATR).</p></li><li><p><strong>Entry Trigger:</strong></p><ol><li><p>Calculate the median of the last 100 readings of the 1-hour ATR(14).</p></li><li><p>Verify that the previous hour&#8217;s ATR(14) is strictly less than this 100-period median.</p></li><li><p>If the volatility condition is met, open a Long position if the previous 1-hour candle closes strictly above the upper 40-period Bollinger Band.</p></li></ol></li><li><p><strong>Exit Trigger:</strong> There is no hard profit target. The initial Stop Loss is placed at 2x the previous hour&#8217;s ATR below the entry price. The trade is managed via a dynamic trailing stop that continuously updates to sit exactly 2x ATR below the current Bid price. The trailing stop only moves up; it never widens.</p></li><li><p><strong>Position Sizing:</strong> Risk is strictly capped at 0.2% of the account balance per trade. The lot size is dynamically calculated based on the distance to the initial 2x ATR stop loss.</p></li></ul><p></p><h2>3. In-Sample vs. Out-of-Sample Testing</h2><p><strong>In-Sample (Optimization Period):</strong> 1 Jan 2015 to 31 Dec 2020</p><ul><li><p><strong>Tested Parameters:</strong> The Bollinger Bands Period (tested from 20 to 200) and the SL Multiplier (tested from 2 to 4).</p></li><li><p><strong>Selection Rationale:</strong> The goal of optimization is not to find the single highest return, but to find a stable &#8220;neighborhood&#8221; of parameters to avoid curve-fitting. I deliberately kept several variables completely static to ensure robustness: the ATR period remained at the standard 14, the Band Deviation at 2.0, and the ATR percentile at 100 (as a longer lookback provides a more reliable median).</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FErM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FErM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 424w, https://substackcdn.com/image/fetch/$s_!FErM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 848w, https://substackcdn.com/image/fetch/$s_!FErM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 1272w, https://substackcdn.com/image/fetch/$s_!FErM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FErM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png" width="1189" height="697" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:697,&quot;width&quot;:1189,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53324,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/208654181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FErM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 424w, https://substackcdn.com/image/fetch/$s_!FErM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 848w, https://substackcdn.com/image/fetch/$s_!FErM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 1272w, https://substackcdn.com/image/fetch/$s_!FErM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5149213c-1404-42e6-b1bf-e308ad918be7_1189x697.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">In sample optimization result table(most results being positive is a good sign)</figcaption></figure></div><p>Looking at the optimization results, a 60-period band produced the absolute highest Sharpe ratio, while a 20-period band produced the highest number of trades. I selected a 40-period band as the optimal blend, balancing a high frequency of opportunities with a strong risk-adjusted return profile.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lhfj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lhfj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 424w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 848w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 1272w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!lhfj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png" width="1218" height="513" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:513,&quot;width&quot;:1218,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:157651,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/208654181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lhfj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 424w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 848w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 1272w, https://substackcdn.com/image/fetch/$s_!lhfj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c2ad89b-5ed0-4c81-b202-c333f04b023b_1218x513.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">3D parameter optimization surface</figcaption></figure></div><p>Crucially, the 3D optimization surface chart confirms this stability. Notice the smooth gradient sloping downward; there are no sharp, isolated spikes indicating a hyper-optimized, curve-fit anomaly. The parameters are robust across a wide surface area.</p><p><strong>Out-of-Sample (Validation Period):</strong> 1 Jan 2021 to 1 Jun 2026</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Mdx_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mdx_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 424w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 848w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 1272w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mdx_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png" width="1456" height="668" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:668,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42619,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/208654181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Mdx_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 424w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 848w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 1272w, https://substackcdn.com/image/fetch/$s_!Mdx_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23a5d-4b2f-437e-9ada-a08408659b73_1578x724.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Out of Sample Equity Curve</figcaption></figure></div><ul><li><p><strong>OOS Sharpe Ratio:</strong> 1.85</p></li><li><p><strong>OOS Max Drawdown:</strong> 3.28%</p></li><li><p><strong>Performance Degradation:</strong> The system maintained its edge well in unseen data. While there is a slight, expected degradation in risk-adjusted returns compared to the optimized in-sample data, the logic holds up robustly in live market conditions without falling apart.</p></li></ul><h2>4. The Weak Spot</h2><p>Every mechanical edge has a cost, and for this volatility breakout model, the kryptonite is a prolonged, mean-reverting market. Because the system specifically hunts for low-volatility environments to trigger a trade, it can occasionally get caught in &#8220;false starts&#8221; where the market breaks the 40-period Bollinger Band but lacks the fundamental momentum to follow through. If the indices enter a multi-month, sideways grind, this strategy will experience a slow bleed of small, paper-cut losses as the tight trailing stop is repeatedly clipped. That is simply the toll we pay to position ourselves for massive, low-risk expansions.</p><h2>5. The Source Code</h2><p>Ready-to-run MT5 script below.</p><pre><code><code>#include &lt;Trade/Trade.mqh&gt;
CTrade Trading_Function;

input group "--- Strategy Parameters ---"
input string Asset_Universe      = "US500,US100,US30";
input int    Base_Magic          = 800000;
input double Risk_Perc           = 1.0;

input group "--- Entry Parameters ---"
input int    Bands_Period        = 80;
input double Bands_Width         = 2.0;

input group "--- Risk &amp; Exit Parameters ---"
input double SL_Multiplier       = 2.0;

struct Asset_State
{
   string Symbol;
   int    Magic_Number;
   int    H1_BB_Handle;
   int    H1_ATR_Handle;
};
Asset_State Portfolio[];

bool Position_State_Checker(string symbol_name, int magic_number)
{
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      if(PositionGetTicket(i) &lt;= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == symbol_name &amp;&amp; PositionGetInteger(POSITION_MAGIC) == magic_number) return true;
   }
   for(int i = OrdersTotal() - 1; i &gt;= 0; i--)
   {
      if(OrderGetTicket(i) &lt;= 0) continue;
      if(OrderGetString(ORDER_SYMBOL) == symbol_name &amp;&amp; OrderGetInteger(ORDER_MAGIC) == magic_number) return true;
   }
   return false;
}

double Calculate_Robust_Volume(string symbol, double entry_price, double stop_loss, double risk_percent)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   if (balance &lt;= 0.0) return 0.0;
   
   double tick_size   = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
   double tick_value  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   double min_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double max_volume  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   if (tick_size == 0.0 || tick_value == 0.0 || volume_step == 0.0) return 0.0;
   if (entry_price &lt;= stop_loss) return 0.0; 

   double sl_distance_ticks = (entry_price - stop_loss) / tick_size;
   if (sl_distance_ticks &lt;= 0.0) return 0.0;
   
   double risk_per_lot = sl_distance_ticks * tick_value;
   if (risk_per_lot == 0.0) return 0.0;

   double final_lot = MathFloor((balance * (risk_percent / 100.0) / risk_per_lot) / volume_step) * volume_step;
   if (final_lot &lt; min_volume) final_lot = min_volume;
   if (final_lot &gt; max_volume) final_lot = max_volume;

   int vol_digits = (volume_step == 0.1) ? 1 : (volume_step == 0.01) ? 2 : (volume_step == 0.001) ? 3 : (volume_step == 0.0001) ? 4 : 0;
   return NormalizeDouble(final_lot, vol_digits);
}

void Run_H1_BB_Executor()
{
   // Evaluate strictly on the H1 clock
   static datetime Last_H1_Time = 0;
   datetime Current_H1 = iTime(_Symbol, PERIOD_H1, 0);
   
   if(Current_H1 == Last_H1_Time) return;
   if(Current_H1 == 0) return;
   
   Last_H1_Time = Current_H1;
   
   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = 0; i &lt; Total_Assets; i++)
   {
      string Sym = Portfolio[i].Symbol;
      int Magic = Portfolio[i].Magic_Number;
      
      int BB_Handle = Portfolio[i].H1_BB_Handle;
      int Atr_Handle = Portfolio[i].H1_ATR_Handle;
      
      if(BB_Handle == INVALID_HANDLE || Atr_Handle == INVALID_HANDLE) continue;
      if(Position_State_Checker(Sym, Magic)) continue; 
      if(!SeriesInfoInteger(Sym, PERIOD_CURRENT, SERIES_SYNCHRONIZED)) continue;
      
      // Pull the last 100 H1 ATR values starting from Index 1
      double Atr_100[];
      ArraySetAsSeries(Atr_100, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 100, Atr_100) &lt; 100) continue;
      
      double Previous_ATR = Atr_100[0]; // Index 1
      
      // Calculate the 50th percentile (median) of the last 100 periods
      double Atr_Sorted[];
      ArrayResize(Atr_Sorted, 100);
      for(int k = 0; k &lt; 100; k++)
      {
         Atr_Sorted[k] = Atr_100[k];
      }
      ArraySort(Atr_Sorted);
      double Median_ATR = Atr_Sorted[50]; 
      
      // Volatility Filter: Only trade if previous H1 was relatively quiet
      if(Previous_ATR &gt;= Median_ATR) continue;
      
      // Pull H1 Close from Index 1
      double Close_Arr[];
      ArraySetAsSeries(Close_Arr, true);
      if(CopyClose(Sym, PERIOD_H1, 1, 1, Close_Arr) &lt;= 0) continue;
      
      // Pull H1 BB Upper from Index 1
      double BB_Upper[];
      ArraySetAsSeries(BB_Upper, true);
      if(CopyBuffer(BB_Handle, 1, 1, 1, BB_Upper) &lt;= 0) continue;
      
      // Entry Logic (Close[1] &gt; BB Upper[1])
      if(Close_Arr[0] &gt; BB_Upper[0])
      {
         double Live_Ask = SymbolInfoDouble(Sym, SYMBOL_ASK);
         int Digits = (int)SymbolInfoInteger(Sym, SYMBOL_DIGITS);
         
         // Set Initial Stop Loss for Dynamic Sizing and Trailing Base
         double Buy_Sl = NormalizeDouble(Live_Ask - (Previous_ATR * SL_Multiplier), Digits);
         
         if(Live_Ask &gt; Buy_Sl)
         {
            double Buy_Vol = Calculate_Robust_Volume(Sym, Live_Ask, Buy_Sl, Risk_Perc);
            if(Buy_Vol &gt; 0.0)
            {
               double Buy_Margin = 0.0;
               if(OrderCalcMargin(ORDER_TYPE_BUY, Sym, Buy_Vol, Live_Ask, Buy_Margin) &amp;&amp; Buy_Margin &lt; AccountInfoDouble(ACCOUNT_MARGIN_FREE))
               {
                  Trading_Function.SetExpertMagicNumber(Magic);
                  Trading_Function.Buy(Buy_Vol, Sym, Live_Ask, Buy_Sl, 0.0, "H1_BB_Breakout"); // 0.0 TP since we are trailing
               }
            }
         }
      }
   }
}

void Run_H1_BB_Manager()
{
   static datetime last_bar_time = 0;
datetime current_time = TimeCurrent();
if(current_time &lt; last_bar_time + 60) return;
last_bar_time = current_time;

   int Total_Assets = ArraySize(Portfolio);
   
   for(int i = PositionsTotal() - 1; i &gt;= 0; i--)
   {
      ulong Ticket = PositionGetTicket(i);
      if(Ticket &lt;= 0) continue;
      if(!PositionSelectByTicket(Ticket)) continue;
      if(PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue; // Long only
      
      long Pos_Magic = PositionGetInteger(POSITION_MAGIC);
      string Pos_Sym = PositionGetString(POSITION_SYMBOL);
      
      int Asset_Idx = -1;
      for(int j = 0; j &lt; Total_Assets; j++)
      {
         if(Portfolio[j].Magic_Number == Pos_Magic &amp;&amp; Portfolio[j].Symbol == Pos_Sym)
         {
            Asset_Idx = j;
            break;
         }
      }
      
      if(Asset_Idx == -1) continue;
      
      int Atr_Handle = Portfolio[Asset_Idx].H1_ATR_Handle;
      if(Atr_Handle == INVALID_HANDLE) continue;
      
      // Pull H1 ATR strictly from the completed candle (Index 1) for stable trailing
      double Atr_Val[];
      ArraySetAsSeries(Atr_Val, true);
      if(CopyBuffer(Atr_Handle, 0, 1, 1, Atr_Val) &lt;= 0) continue;
      
      double Bid = SymbolInfoDouble(Pos_Sym, SYMBOL_BID);
      int Digits = (int)SymbolInfoInteger(Pos_Sym, SYMBOL_DIGITS);
      double Point_Size = SymbolInfoDouble(Pos_Sym, SYMBOL_POINT);
      double Min_Stop_Distance = 2 * Point_Size;
      
      double Current_Sl = PositionGetDouble(POSITION_SL);
      double Current_Tp = PositionGetDouble(POSITION_TP);
      
      // Calculate dynamic trailing SL
      double Target_Sl = NormalizeDouble(Bid - (Atr_Val[0] * SL_Multiplier), Digits);
      
      // Trail SL upwards only
      if(Target_Sl &gt; Current_Sl + Min_Stop_Distance || Current_Sl == 0.0)
      {
         Trading_Function.SetExpertMagicNumber((int)Pos_Magic);
         Trading_Function.PositionModify(Ticket, Target_Sl, Current_Tp);
      }
   }
}

int OnInit()
{
   ushort sep = StringGetCharacter(",", 0);
   string symbols[];
   
   int num_symbols = StringSplit(Asset_Universe, sep, symbols);
   if(num_symbols &gt; 0)
   {
      ArrayResize(Portfolio, num_symbols);
      
      for(int i = 0; i &lt; num_symbols; i++)
      {
         StringTrimLeft(symbols[i]);
         StringTrimRight(symbols[i]);
         
         SymbolSelect(symbols[i], true);
         
         Portfolio[i].Symbol = symbols[i];
         Portfolio[i].Magic_Number = Base_Magic + i;
         
         Portfolio[i].H1_BB_Handle = iBands(symbols[i], PERIOD_H1, Bands_Period, 0, Bands_Width, PRICE_CLOSE);
         Portfolio[i].H1_ATR_Handle = iATR(symbols[i], PERIOD_H1, 14); // Hardcoded ATR length 14
         
         if(Portfolio[i].H1_BB_Handle == INVALID_HANDLE || Portfolio[i].H1_ATR_Handle == INVALID_HANDLE)
         {
            Print("Warning: Failed to load handles for ", symbols[i]);
         }
      }
   }

   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   EventKillTimer();
   
   int total_assets = ArraySize(Portfolio);
   for(int i = 0; i &lt; total_assets; i++)
   {
      if(Portfolio[i].H1_BB_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].H1_BB_Handle);
      if(Portfolio[i].H1_ATR_Handle != INVALID_HANDLE) IndicatorRelease(Portfolio[i].H1_ATR_Handle);
   }
}

void OnTick() {}

void OnTimer()
{
   Run_H1_BB_Executor();
   Run_H1_BB_Manager();
}
</code></code></pre><h2>6. Verification Notes</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7epM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7epM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 424w, https://substackcdn.com/image/fetch/$s_!7epM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 848w, https://substackcdn.com/image/fetch/$s_!7epM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 1272w, https://substackcdn.com/image/fetch/$s_!7epM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!7epM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png" width="1456" height="663" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:663,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112509,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://mechanicalpremia.substack.com/i/208654181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7epM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 424w, https://substackcdn.com/image/fetch/$s_!7epM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 848w, https://substackcdn.com/image/fetch/$s_!7epM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 1272w, https://substackcdn.com/image/fetch/$s_!7epM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c7a8a5d-b307-48bf-98d7-2ec3f141777c_1579x719.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Trading Costs (Out of Sample)</figcaption></figure></div><ul><li><p><strong>Data Source:</strong> [Dukascopy via JForex Historical Download Manager]</p></li><li><p><strong>Slippage/Commissions:</strong> [1p slippage, 8$ per standard lot(US100), 8$ per standard lot(DE30), 2$ per standard lot(US500), charged both at entry and at exit]</p></li><li><p><strong>Timezone:</strong> [UTC]</p><p></p></li></ul><p><strong>Want to access more robust systems and build your trading portfolio?</strong> Subscribe for free to get complete strategy breakdowns, unclouded logic, and ready-to-run MetaTrader scripts delivered straight to your inbox. </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Welcome to Mechanical Premia]]></title><description><![CDATA[Turning structural market behavior into mechanical rules you can actually trade.]]></description><link>https://mechanicalpremia.substack.com/p/welcome-to-mechanical-premia</link><guid isPermaLink="false">https://mechanicalpremia.substack.com/p/welcome-to-mechanical-premia</guid><dc:creator><![CDATA[Mechanical Risk Premia]]></dc:creator><pubDate>Tue, 21 Jul 2026 10:24:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gX2g!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e41d6f2-4dc3-434a-8016-cb5d3708f374_1280x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://mechanicalpremia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p>Welcome to my publication. This is a place where we turn structural market behavior into mechanical rules that you can actually trade.</p><h3><strong>The Problem with Most Systematic Research</strong></h3><p>If you read financial research papers, you will notice a common problem. The systematic strategies they present are incredibly complicated. They usually require expensive data feeds, complex institutional infrastructure, and heavy mathematics just to get started. These academic papers are designed for large hedge funds, not for independent traders. They leave you with theories that are nearly impossible to apply in the real markets on your own.</p><h3><strong>Building Practical and Simple Systems</strong></h3><p>We are here to cut through that noise and remove the complexity. The main goal of this publication is to provide trading systems that are easy to implement. We will focus entirely on known structural anomalies and simple market behaviors. There is absolutely no discretionary guessing involved in what we do. Instead, we use pure, mechanical logic that you can easily set up and run on standard retail platforms.</p><h3><strong>What You Will Receive</strong></h3><p>Every week, I will publish a complete guide to a new mechanical trading system. Here is exactly what you will get:</p><ul><li><p><strong>The Market Edge:</strong> A clear and simple explanation of a structural anomaly and why it continues to work.</p></li><li><p><strong>The Proof:</strong> Honest and unfiltered backtests, including maximum drawdowns and out of sample data, so you know exactly what the risks are.</p></li><li><p><strong>The Execution:</strong> Ready to run MetaTrader logic so you can easily implement the systems on your own charts.</p></li></ul><p>Subscribe now so you do not miss the first system drop coming next week.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://mechanicalpremia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Mechanical Premia! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item></channel></rss>