<?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[Quantreo]]></title><description><![CDATA[Real-life quant trading tips.
All Friday by mail.]]></description><link>https://www.newsletter.quantreo.com</link><image><url>https://substackcdn.com/image/fetch/$s_!Y0GG!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5709b73-08d5-47ec-9254-66545ec25261_512x512.png</url><title>Quantreo</title><link>https://www.newsletter.quantreo.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 04 Jun 2026 06:21:15 GMT</lastBuildDate><atom:link href="https://www.newsletter.quantreo.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Lucas]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[quantreo@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[quantreo@substack.com]]></itunes:email><itunes:name><![CDATA[Lucas]]></itunes:name></itunes:owner><itunes:author><![CDATA[Lucas]]></itunes:author><googleplay:owner><![CDATA[quantreo@substack.com]]></googleplay:owner><googleplay:email><![CDATA[quantreo@substack.com]]></googleplay:email><googleplay:author><![CDATA[Lucas]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[ML trading or data mining?]]></title><description><![CDATA[The line is thinner than you think]]></description><link>https://www.newsletter.quantreo.com/p/ml-trading-or-data-mining</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/ml-trading-or-data-mining</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 29 May 2026 14:31:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e79480ed-a7a4-4d46-b567-6bb9cfe40790_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Everyone runs ML trading. <strong>Almost no one can tell when it quietly turns into data mining</strong>.</p><p>The code is identical. The tools are the same: XGBoost, cross-validation, feature engineering. Yet one produces alpha, the other produces a statistical illusion that dies in the first week of live trading.</p><p>I see this line crossed every day. Not out of incompetence. Out of habit.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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"></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><div><hr></div><h2>1. The line is not technical, it&#8217;s methodological</h2><p><strong>ML trading</strong>: you start from an economic hypothesis, you build a model to test it.<br><strong>Data mining</strong>: you start from the data, you search for what works, you rationalize after.</p><p><strong>The honest test</strong>: can you explain why your feature should work BEFORE seeing the backtest? If the justification shows up after the equity curve, you haven&#8217;t found alpha. You&#8217;ve found a correlation.</p><p></p><div><hr></div><h2>2. The red flags</h2><p>A few patterns that should trigger an alarm in your research:</p><ul><li><p>Sharpe climbing with every iteration</p></li><li><p>Hyperparameters tuned on the out-of-sample period</p></li><li><p>Lookback window chosen through grid search</p></li><li><p>Holdout set &#8220;checked&#8221; more than once</p></li><li><p>Sharpe above 3 on a simple strategy, on a handful of assets</p></li><li><p>You trade BTC because &#8220;it doesn&#8217;t work as well on ETH&#8221;</p></li></ul><p>Two boxes checked, you&#8217;re likely data mining. Three, you definitely are.</p><p></p><div><hr></div><h2>3. The validation framework that closes the door</h2><p>Three tools, no less:</p><ul><li><p><strong>CPCV</strong> (Combinatorial Purged Cross-Validation) instead of naive K-fold</p></li><li><p><strong>Deflated Sharpe Ratio</strong> (Bailey and L&#243;pez de Prado), which explicitly adjusts for the number of trials</p></li><li><p>A holdout set that stays untouched. <strong>Truly untouched</strong>.</p></li></ul><blockquote><p>The rule that stings: testing 20 strategies at a 5% threshold is a near-guarantee of one false discovery. If you don&#8217;t know how many variants you&#8217;ve tested, you&#8217;re data mining without knowing it.</p></blockquote><p></p><p>Edge comes from the hypothesis, not from the algorithm.</p><p>ML is an alpha extraction tool, not an alpha generator. No library, no model, no feature creates an edge from nothing. If the economic thesis isn&#8217;t there before the code, the code won&#8217;t make it appear.</p><p>The discipline that separates the quant from the data miner: <strong>pre-registering hypotheses, the way academic research does</strong>. Writing down what you&#8217;re looking for before you start looking.</p><p>It&#8217;s uncomfortable. That&#8217;s exactly why so few do it.</p><p></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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[Live Crypto Data in 15 Lines of Python]]></title><description><![CDATA[No account, no API key, no cost. Just an open socket and Python.]]></description><link>https://www.newsletter.quantreo.com/p/live-crypto-data-in-15-lines-of-python</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/live-crypto-data-in-15-lines-of-python</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 22 May 2026 14:30:43 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/2821f59a-1b9a-4c7a-8185-496de52e8827_267x219.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You want live crypto data. No account, no key, no cost. Binance gives it away through a WebSocket, and the whole thing fits in 15 lines of Python.</p><p>Here is the minimum that works.</p><blockquote><p>This is a quick tutorial. If you want the <strong>full stack</strong> (ingestion, storage, time travel, alt-data, <strong>meteo</strong>, <strong>satellite images</strong>&#8230;), <strong>QuantLake is live</strong>: <a href="https://www.quantreo.com/quantlake-program/">https://www.quantreo.com/quantlake-program/</a></p></blockquote><div><hr></div><h2>1. What you need</h2><p>One library.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;6f23bde7-97e8-4107-b524-9c99db296ce0&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">pip install websockets</code></pre></div><p>That&#8217;s it. No Binance account. No API key. Public market streams are open.</p><p></p><div><hr></div><h2>2. The connection</h2><p>Binance exposes one URL per stream. Format is simple:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;46bf3c5e-0750-442a-afb3-4e00574bfeff&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">wss://stream.binance.com:9443/ws/&lt;symbol&gt;@&lt;stream&gt;</code></pre></div><p><em><strong>symbol</strong></em> in lowercase (<em><strong>btcusdt</strong></em>, <em><strong>ethusdt</strong></em>), <em><strong>stream</strong></em> is what you want to receive (<em><strong>trade</strong></em>, <em><strong>kline_1m</strong></em>, <em><strong>depth</strong></em>, <em><strong>aggTrade</strong></em>).</p><p>Open the socket, read messages, parse JSON. Done.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;33193964-b4ce-4703-b714-736ebca8ab27&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">import json
import asyncio
import websockets

async def stream_trades(symbol="btcusdt"):
    url = f"wss://stream.binance.com:9443/ws/{symbol}@trade"
    async with websockets.connect(url) as ws:
        async for msg in ws:
            trade = json.loads(msg)
            price = float(trade["p"])
            qty   = float(trade["q"])
            ts    = trade["T"]
            print(f"{ts}  {price:.2f}  {qty:.4f}")

asyncio.run(stream_trades())</code></pre></div><p>Run it. Every trade on BTC/USDT prints in your terminal, the moment it happens.</p><p></p><div><hr></div><h2>3. What the fields mean</h2><p>The JSON payload for <em><strong>@trade</strong></em> looks like this:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;fe59286c-58bc-402a-8ab9-ba81073aab25&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">{
  "e": "trade",
  "E": 1716384000000,
  "s": "BTCUSDT",
  "p": "67432.10",
  "q": "0.00125",
  "T": 1716383999998,
  "m": false
}</code></pre></div><p></p><h2>4. Want 1-minute bars instead?</h2><p>Same code, one line changes. Replace <em><strong>@trade</strong></em> with <em><strong>@kline_1m</strong></em>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;cef59707-76c7-47c5-8e79-9bfaab5faf22&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">url = f&#8221;wss://stream.binance.com:9443/ws/{symbol}@kline_1m&#8221;</code></pre></div><p>Binance pushes the current bar on every update, and marks it closed when it&#8217;s done. The field <em><strong>k.x</strong></em> is <em><strong>true</strong></em> only on the final tick of the bar. That&#8217;s your signal to persist it.`</p><p></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;93f6a2ec-f4a9-495f-8133-45a0b3032eff&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">kline = json.loads(msg)["k"]
if kline["x"]:
    print("closed bar:", kline["t"], kline["o"], kline["h"], kline["l"], kline["c"])</code></pre></div><p>Other useful streams, same pattern: <em><strong>@aggTrade</strong></em> for aggregated trades, <code>@depth</code> for order book diffs, <em><strong>@kline_5m</strong></em>, <em><strong>@kline_1h</strong></em>, etc.</p><p></p><div><hr></div><h2>5. The practical rule</h2><p>This script will run, and it will fail. Sockets disconnect. Binance forces a reset every 24 hours, your network drops, your laptop sleeps. The 15-line version is for learning, not for production.</p><p>The real stack needs three things on top: auto-reconnect, persistence to a proper database, and a schema that doesn&#8217;t get corrupted on every restart.</p><p>Open the socket today. Watch the data come in. Then think about where it goes next.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><item><title><![CDATA[90% of retail quants don't have a database. Just files.]]></title><description><![CDATA[The fix costs &#8364;0. The bug costs you months of research.]]></description><link>https://www.newsletter.quantreo.com/p/90-of-retail-quants-dont-have-a-database</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/90-of-retail-quants-dont-have-a-database</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 15 May 2026 14:30:59 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0f14a273-5acb-45fe-ad7f-45efee401e39_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here&#8217;s the setup nobody questions. You download data and you save it as a .csv, maybe a .parquet if you&#8217;re &#8220;serious.&#8221; Then you add a folder, then ten more. That&#8217;s not a database, that&#8217;s a drawer you throw things into.</p><p>And it breaks your research in three ways.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. No history</h2><p>Every update overwrites the last one, so your history is whatever your last script run decided it would be. If your data provider silently revised last month&#8217;s values, you&#8217;ll never know. And the exact backtest you ran in March? You can&#8217;t replay it. That data is already gone.</p><p></p><div><hr></div><h2>2. Writes aren&#8217;t atomic</h2><p>Your update script crashes halfway through, and half the data is written while the other half isn't. So you rerun it, and now you've got duplicates. Your base is quietly corrupted, and you won't find out until it's already in your results.</p><p></p><div><hr></div><h2>3. No clean incremental updates</h2><p>Adding today&#8217;s data means rewriting the whole file, or bolting on a fragile append that has no idea what&#8217;s already there. New rows, existing rows, your files can&#8217;t tell the difference, so every update is a small gamble.</p><p></p><p>A file is not a database.</p><p>The fix isn&#8217;t expensive. It costs &#8364;0. It&#8217;s called Delta Lake: a transactional layer on top of Parquet. ACID writes, time travel, clean incremental updates, the things you actually need.</p><p><strong>Next week, I&#8217;ll show you how to feed it: crypto and CFDs, live, for &#8364;0. That&#8217;s QuantLake. More in a few days.</strong></p>]]></content:encoded></item><item><title><![CDATA[The Clip Effect: Is Your Backtest Real, or Just Lucky?]]></title><description><![CDATA[A 60-second robustness check that kills most backtests.]]></description><link>https://www.newsletter.quantreo.com/p/the-clip-effect-is-your-backtest</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/the-clip-effect-is-your-backtest</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 08 May 2026 14:31:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Ez1_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You ran a grid search. Lookback = 20 gives you a Sharpe of 2.1. You smile. You start writing the strategy doc.</p><p>Then you check 19 and 21. Both at 0.4.</p><p>Welcome to the clip effect.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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">Weekly notes from inside a quant research workflow. Subscribe, it is free.</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><h2></h2><div><hr></div><h2>1. What it actually means</h2><p>When you optimize a strategy, you scan parameters across a range. If your &#8220;best&#8221; parameter sits as an isolated peak surrounded by mediocre or losing values, <strong>the result is almost certainly noise</strong>. A real edge produces a plateau, not a pixel.</p><p>A backtest is a sample of one path. With enough parameter combinations, <strong>some of them will look great by accident</strong>. The clip effect is the visual signature of that accident.</p><blockquote><p>The vocabulary varies in the literature (parameter stability, neighborhood robustness), but the test is the same: does the strategy survive small changes in its inputs?</p></blockquote><p></p><div><hr></div><h2>2. A concrete example</h2><p>Basic moving average crossover on EUR/USD, daily bars, 2015 to 2024. Fast MA fixed at 5, slow MA varied from 18 to 22. Two strategies, both peaking at lookback = 20.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ez1_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ez1_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 424w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 848w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 1272w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ez1_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic" width="736" height="436" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:436,&quot;width&quot;:736,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18903,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/196748508?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ez1_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 424w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 848w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 1272w, https://substackcdn.com/image/fetch/$s_!Ez1_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf9f356f-9155-4867-85b0-dc0920c1a804_736x436.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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>Same optimum. Opposite stories.</p><p>The red line is the trap. Sharpe 2.07 at lookback 20, but 0.42 at 19 and 0.38 at 21. If you stop at &#8220;Sharpe 2 on lookback 20&#8221;, you have learned nothing about the market. <strong>You have learned that a specific number aligned with a specific sequence of trades</strong>. Move one step left or right, the alpha is gone.</p><p>The blue line is what real structure looks like. Lower peak (1.78), but 1.61 and 1.65 right next to it. <strong>The signal exists before, at, and after the optimum</strong>.</p><p>Compare the peaks in isolation, the red strategy wins. Compare the surfaces, the choice is obvious.</p><p></p><div><hr></div><h2>3. Going 2D: the heatmap test</h2><p>One parameter is rarely enough. Most strategies have at least two: a feature window and a target horizon, two moving averages, a volatility filter and a signal threshold. The proper version of the clip test is a 2D heatmap of Sharpe across the parameter grid.</p><p>What you want to see: a connected zone of green, smooth gradients, the optimum sitting inside a region of similar values.</p><p>What kills the strategy: scattered green pixels in a sea of red, or a single bright square with nothing around it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QqQu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QqQu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 424w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 848w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 1272w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QqQu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic" width="856" height="458" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:458,&quot;width&quot;:856,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:40960,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/196748508?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QqQu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 424w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 848w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 1272w, https://substackcdn.com/image/fetch/$s_!QqQu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91ee9be2-fbf8-49d4-b478-598bdfc1fee3_856x458.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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 2D, the eye does the work. With five parameters and ten possible slices, you need a quantitative metric: average Sharpe in the &#177;1 neighborhood, peak-to-mean ratio, or fraction of the grid above a threshold. Visualization is a starting point, not the test itself.</p><p></p><div><hr></div><h2>4. The practical rule</h2><p>Before you trust any optimum, ask one question:</p><p><strong>Does Sharpe degrade by more than 30 to 40% when I move &#177;1 on each parameter?</strong></p><p>If yes, drop the strategy. If no, you have passed the first filter, not the last one.</p><p>The clip test will not save you from every form of overfitting. Scanning 50 parameter pairs and selecting the best plateau is still cherry picking, just better dressed. But this is the cheapest, most visual robustness check you can run, and it kills the majority of bad backtests in seconds.</p><p>Run it on every strategy you build. You will discard more than you keep.</p><p>That is the point.</p><p></p><p>&#8594; Speaking of robustness, the next bottleneck most retail quants hit is data. Next week I am opening up <strong>Quantlake</strong>, the program I have been building on creating quant database for 0$: weather, crypto alt-data, CFD, spot markets. Stay tuned!</p><p></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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">One robustness check, one piece of code, one idea you can use. Every week, in your inbox.</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><p></p>]]></content:encoded></item><item><title><![CDATA[Building a Clean Research Environment with Oryon]]></title><description><![CDATA[How to combine features and targets in one dataframe before doing exploratory data analysis.]]></description><link>https://www.newsletter.quantreo.com/p/building-a-clean-research-environment</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/building-a-clean-research-environment</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 01 May 2026 14:30:39 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/aaa254ff-50be-4271-a3f5-e1b27d92f6e9_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Exploratory data analysis in quant often <strong>becomes messy much faster than expected</strong>.</p><p>Features are computed in one place, targets in another, and then everything has to be aligned manually before any real analysis can begin. That usually means extra joins, shifting logic, duplicated code, and a <strong>higher risk of silent mistakes</strong>.</p><p>The issue is not computing features or targets. The issue is creating a research dataset where both live together cleanly and can be analyzed immediately.</p><div><hr></div><h2>1. The Oryon Approach</h2><p>With <a href="https://oryonlib.dev">Oryon</a>, the process stays simple. You build a <code>FeaturePipeline</code>, a <code>TargetPipeline</code>, run both on the same market data, and join the outputs into a single dataframe.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;0f58385f-33c6-4fad-97bf-ea962d7cbd76&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon.datasets import load_sample_bars
from oryon import FeaturePipeline
from oryon.features import Sma, ParkinsonVolatility, Correlation, ShannonEntropy, Adf
from oryon.scalers import RollingZScore
from oryon.adapters import run_features_pipeline_pandas


# Import sample data (OHLCV bars)
df = load_sample_bars()

# Create the features list
features_list = [
    Correlation(inputs=["close", "volume"], window=30, outputs=["close_volume_corr_30"]),
    ParkinsonVolatility(inputs=["high","low"], window=50, outputs=["close_pvol_50"]),
    Adf(inputs=["close"], window=100, outputs=["close_adf_100", "close_adf_pval_100"])
]

# Create the scalers list to apply z-score to all the wanted features
scalers_list = [RollingZScore(inputs=[col], window=2000, outputs=[f"z_{col}"]) for col in [
    "close_volume_corr_30", "close_pvol_50", "close_adf_pval_100"
]]

# Combine both list
features_list.extend(scalers_list)

# Create the pipeline object (that can run to on live trading)
pipe = FeaturePipeline(features_list, input_columns=["close", "high", "low", "volume"])

# Run the pipeline on the sample data
df_features = run_features_pipeline_pandas(pipe, df)</code></pre></div><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;85f2498c-aee9-4211-82a8-63485b9ef1a2&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon import TargetPipeline
from oryon.adapters import run_targets_pipeline_pandas
from oryon.targets import FutureReturn, FutureLinearSlope

# Essential for the FutureLinearSlope (x=time, y=price)
df["constant_time"] = [i for i in range(len(df))] # Essential for the FutureLinearSlope (x=time, y=price)

# Create the targets list
targets_list = [
    FutureLinearSlope(inputs=["constant_time", "close"], horizon=20, outputs=["future_slope_20", "r2_future_slope_20"]),
    FutureLinearSlope(inputs=["constant_time", "close"], horizon=50, outputs=["future_slope_50", "r2_future_slope_50"]),
    FutureReturn(inputs=["close"], horizon=10, outputs=["future_returns_2"])
]

# Create the target pipeline object
target_pipe = TargetPipeline(targets_list, input_columns=["constant_time", "close"])

# Run the pipeline
df_targets = run_targets_pipeline_pandas(target_pipe, df)

# Ready-to-use dataframe
df_research = df_features.join(df_targets)</code></pre></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!V7JA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V7JA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 424w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 848w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 1272w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!V7JA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic" width="1095" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1095,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44051,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/193702920?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!V7JA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 424w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 848w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 1272w, https://substackcdn.com/image/fetch/$s_!V7JA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6be16963-1cf9-4de3-ac97-2d1e58e4fa23_1095x378.heic 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"><svg role="img" 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"><g><title></title><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"><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"><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>The result is a single research table where engineered features and forward-looking targets are already aligned and <strong>ready to explore</strong>.</p><div><hr></div><h2>3. Why This Matters</h2><p>Once everything is in the same dataframe, <strong>EDA becomes much easier</strong>.</p><p>You can immediately start testing simple relationships between inputs and outputs, whether through correlation, mutual information, or more advanced selection methods. Instead of spending time preparing the dataset, you can focus on extracting useful structure from it.</p><p>That is the real value of a clean research environment: <strong>less plumbing, more analysis</strong>.</p><p></p><blockquote><p><strong>If you want to take this further and connect feature pipelines with AI agents, you can take a look at <a href="https://www.quantreo.com/ai-trading-lab/">AI Trading Lab</a>.</strong></p></blockquote><p></p><p><a href="https://oryonlib.dev">Oryon</a> is now available in beta.</p><p>If you want to take a closer look at the library and its design, you can explore it directly on <a href="https://github.com/lucasinglese/oryon">GitHub</a>.</p><p>And if you find it useful, consider adding a star. it helps more than it seems.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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"><em><strong>Subscribe to follow the ideas, tools, and production-grade systems shaping modern quantitative trading.</strong></em></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><item><title><![CDATA[Standardizing Features Without Breaking Your Pipeline]]></title><description><![CDATA[A More Coherent Way to Standardize Features in Quantitative Pipelines]]></description><link>https://www.newsletter.quantreo.com/p/standardizing-features-without-breaking</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/standardizing-features-without-breaking</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 24 Apr 2026 14:31:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9400db4c-7e2a-45d2-9a38-b5a53242df18_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In quantitative trading, <strong>standardizing features</strong> is almost a reflex.</p><p>It helps stabilize distributions, improves model convergence, and makes signals comparable across time. Whether you work with returns, volatility, or engineered indicators, <strong>scaling is everywhere</strong>.</p><p>In practice, most pipelines rely on <code>StandardScaler</code> from scikit-learn.</p><p>That is perfectly <strong>acceptable in research</strong>. But as soon as a pipeline becomes more serious, this setup <strong>starts to create unnecessary friction</strong>.</p><div><hr></div><h2>1. The Real Issue Is Not the Math</h2><p>The problem is not standardization itself. <strong>The problem is fragmentation</strong>.</p><p>A typical quant stack quickly becomes a mix of unrelated components. Features may come from one library, transformations from another, and scaling from yet another. You might compute signals with <a href="https://oryonlib.dev">Oryon</a>, apply an operator from SciPy, then standardize everything with scikit-learn.</p><p>Each piece works in isolation. But the overall system becomes harder to reason about.</p><p>You end up <strong>mixing different APIs</strong>, different update models, and different assumptions about how computations should behave through time. In a notebook, this may still feel manageable. In a real feature pipeline, <strong>it becomes cumbersome</strong>.</p><div><hr></div><h2>2. A More Coherent Design</h2><p>The idea behind the scalers added in <a href="https://oryonlib.dev">Oryon</a> is straightforward: scaling should behave exactly like any other feature. Instead of treating it as a separate preprocessing step, it becomes <strong>part of the pipeline itself</strong>, built on the same assumptions, with the same interface.</p><p>This means:</p><ul><li><p>same update logic</p></li><li><p>same state management</p></li><li><p>same behavior in research and live</p></li></ul><p>A rolling standard deviation, for instance, is no longer something you compute &#8220;outside&#8221; your pipeline. <strong>It is a feature, updated incrementally</strong>.</p><div><hr></div><h2>3. From Raw Prices to Standardized Signal</h2><p>Below is a pipeline that computes several market features and standardizes them directly inside Oryon using a <a href="https://oryonlib.dev/api/scalers/#rolling-z-score">rolling z-score</a>.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;4289c521-66d4-4e38-ac98-0676fe8f7f99&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon.datasets import load_sample_bars
from oryon import FeaturePipeline
from oryon.features import Sma, ParkinsonVolatility, Correlation, ShannonEntropy, Adf
from oryon.scalers import RollingZScore
from oryon.adapters import run_features_pipeline_pandas


# Import sample data (OHLCV bars)
df = load_sample_bars()

# Create the features list
features_list = [
    Correlation(inputs=["close", "volume"], window=30, outputs=["close_volume_corr_30"]),
    ParkinsonVolatility(inputs=["high","low"], window=50, outputs=["close_pvol_50"]),
    Adf(inputs=["close"], window=100, outputs=["close_adf_100", "close_adf_pval_100"])
]

# Create the scalers list to apply z-score to all the wanted features
scalers_list = [RollingZScore(inputs=[col], window=2000, outputs=[f"z_{col}"]) for col in [
    "close_volume_corr_30", "close_pvol_50", "close_adf_pval_100"
]]

# Combine both list
features_list.extend(scalers_list)

# Create the pipeline object (that can run to on live trading)
pipe = FeaturePipeline(features_list, input_columns=["close", "high", "low", "volume"])

# Run the pipeline on the sample data
df_features = run_features_pipeline_pandas(pipe, df)</code></pre></div><p>What matters here is not only the rolling normalization itself. It is the fact that the scaler is defined exactly like any other component in the pipeline.</p><p>There is <strong>no handoff to another library</strong>, no separate preprocessing object to maintain, and no conceptual break between feature computation and feature standardization.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dS4Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dS4Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 424w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 848w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 1272w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dS4Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic" width="1456" height="487" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:487,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:199407,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/193696915?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dS4Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 424w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 848w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 1272w, https://substackcdn.com/image/fetch/$s_!dS4Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d7483f4-fa11-41b7-9428-ab4c57c7c3c1_2685x898.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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>The chart says it all: before scaling, <strong>the variables do not really live in the same space</strong>. After scaling, <strong>they do</strong>.</p><div><hr></div><h2>4. Why This Matters</h2><p>A quant pipeline should <strong>not feel like an assembly of disconnected utilities</strong>.</p><p>As soon as features, operators, and scalers obey different conventions, every extension becomes slightly more fragile. The code becomes harder to read, harder to debug, and harder to move from research to something more robust.</p><p><strong>Keeping standardization inside Oryon solves a very practical problem</strong>: it removes one more external dependency from the feature workflow and replaces it with a component that behaves exactly like the rest of the system.</p><p>The gain is <strong>not only speed</strong>, even if the implementation is also significantly faster. The deeper gain is consistency.</p><p></p><p>If you are interested in building <strong>cleaner research pipelines</strong>, with feature engineering components that are designed to work together rather than coexist by accident, Oryon is exactly the kind of framework worth exploring.</p><p></p><p><a href="https://oryonlib.dev">Oryon</a> is now available in beta.</p><p>If you want to take a closer look at the library and its design, you can explore it directly on <a href="https://github.com/lucasinglese/oryon">GitHub</a>.</p><p><em>And if you find it useful, consider adding a star. it helps more than it seems.</em></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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"><em><strong>Subscribe to follow the ideas, tools, and production-grade systems shaping modern quantitative trading.</strong></em></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><item><title><![CDATA[Build once. Run live.]]></title><description><![CDATA[A unified approach to feature pipelines across research and production]]></description><link>https://www.newsletter.quantreo.com/p/build-once-run-live</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/build-once-run-live</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 17 Apr 2026 14:30:51 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b7fd6461-aa53-4bab-8f06-1e4941f1a2c7_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most pipelines break when they leave research.</p><p>Not because they are incorrect, but because <strong>they were never designed to run incrementally</strong>. They assume full history, they assume recomputation, and they assume a static environment where everything can be rebuilt at each step.</p><p><strong>Live systems operate under very different constraints</strong>. Data arrives sequentially, latency accumulates, and every inefficiency becomes persistent. In that context, the feature pipeline is no longer a preprocessing step. It becomes part of the system itself.</p><div><hr></div><h2>1. A pipeline that works in both worlds</h2><p>With <a href="https://oryonlib.dev">Oryon</a>, the same pipeline object can be <strong>used across both research and production environments</strong> without modification.</p><p>It can be applied on full historical datasets in batch mode, and <strong>it can continue updating in a streaming setting using the exact same logic</strong>. There is no distinction between the two modes, no hidden adaptation layer, and no change in behavior.</p><p>This is not a convenience feature. It is a design constraint. <strong>The pipeline is built to behave identically regardless of how it is fed</strong>.</p><p>To keep the example simple, we can start from one of the sample datasets available directly in Oryon.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;451573a2-eb9a-4c4a-956c-37e14a02c924&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon.datasets import load_sample_bars

df = load_sample_bars()
historical_bars, live_bars = df.iloc[:-10, :], df.iloc[-10:, :]</code></pre></div><p>For the rest of this example, the idea is straightforward: we use the <strong>historical portion to initialize</strong> and validate the pipeline in research conditions, then we use the last ten bars to simulate a <strong>live stream and observe the updates one step at a time</strong>.</p><div><hr></div><h2>2. Defining a feature pipeline</h2><p>We start by defining a set of features <strong>as a structured pipeline</strong>. Each component is <strong>stateful and designed to update</strong> incrementally.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;aa54d9a4-bcab-451c-ba90-e114ff95d0a3&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon import FeaturePipeline
from oryon.features import Sma, ParkinsonVolatility, Correlation, ShannonEntropy, Adf


features_list = [
    Sma(inputs=["close"], window=10, outputs=["close_sma_10"]),
    Sma(inputs=["close"], window=50, outputs=["close_sma_50"]),
    ParkinsonVolatility(inputs=["high", "low"], window=20, outputs=["close_pvol_20"]),
    ParkinsonVolatility(inputs=["high", "low"], window=100, outputs=["close_pvol_100"]),
    Correlation(inputs=["close", "volume"], window=30, outputs=["close_volume_corr_30"]),
    ShannonEntropy(inputs=["close"], window=50, outputs=["close_entropy_50"]),
    Adf(inputs=["close"], window=100, outputs=["close_adf_100", "close_adf_pval_100"])
]

pipe = FeaturePipeline(features_list, input_columns=["high", "low", "close", "volume"])</code></pre></div><p>This is not a collection of independent indicators. It is a coherent system that maintains its own internal state and evolves as new data arrives.</p><div><hr></div><h2>3. Applying the pipeline in research</h2><p>Once the pipeline is defined, we can apply it on historical data to inspect the outputs in research conditions.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;58d861fd-5aa9-4bee-a8dd-bab37c742e37&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon.adapters import run_features_pipeline_pandas
df_features = run_features_pipeline_pandas(pipe, historical_bars)</code></pre></div><p>Under the hood, the pipeline is designed to consume data as a list of lists rather than as a DataFrame directly. This may look slightly less convenient at first, but it comes from the same <strong>architectural choice that makes the system efficient</strong> in live trading: the update path is built around a minimal, streaming-oriented input structure.</p><p>In practice, this means the research interface stays aligned with the production one. Instead of introducing a separate batch-only abstraction, <strong>Oryon keeps the same core design and provides adapters to make research workflows</strong> easier to use.</p><p>That is exactly what <code>run_features_pipeline_pandas</code> does here. It converts the DataFrame into the internal list-of-lists format and applies the pipeline sequentially, so the historical execution remains fully consistent with the live update model.</p><p>The <strong>same idea is also available for Polars</strong>, which makes it easy to keep the same workflow regardless of the dataframe engine used upstream.</p><div><hr></div><h2>4. Switching to streaming</h2><p>Once the historical pass is complete, the same pipeline can continue operating in streaming mode.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;a6a703e7-a8f5-4863-af60-275f9cb3e8d0&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">for bar in live_bars.itertuples():
  input_values = [bar.high, bar.low, bar.close, bar.volume] # pipe needs a list for the inputs
  output = pipe.update(input_values)
  print(output)

# [102.03397795639191, 102.41105040279119, 0.001373007598669601, 0.0018930289783861594, -0.21026851276116704, 0.948176332443655, -1.800248586774662, 0.380344996295653]
# ...
# [102.03397795639194, 102.25925749878635, 0.001373007598669601, 0.0018768715423311845, -0.1494113110563763, 0.8844888723968832, -4.77931213498186, 6.212151160126344e-05]</code></pre></div><div><hr></div><h2>5. Why this matters</h2><p>In most trading systems, the pipeline is effectively implemented twice. Once in research, often using batch-oriented tools, and once again in production, using a different stack optimized for streaming.</p><p><strong>This duplication introduces divergence</strong>. Subtle differences appear, edge cases behave differently, and the system becomes harder to validate as a whole.</p><p><strong>Oryon removes that duplication entirely</strong>. The pipeline is defined once, validated once, and then used as-is in production.</p><p></p><blockquote><p><strong>If you want to take this further and connect feature pipelines with AI agents, you can take a look at <a href="https://www.quantreo.com/ai-trading-lab/">AI Trading Lab</a>.</strong></p></blockquote><p></p><p><a href="https://oryonlib.dev">Oryon</a> is now available in beta.</p><p>If you want to take a closer look at the library and its design, you can explore it directly on <a href="https://github.com/lucasinglese/oryon">GitHub</a>.</p><p>And if you find it useful, consider adding a star. it helps more than it seems.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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"><em><strong>Subscribe to follow the ideas, tools, and production-grade systems shaping modern quantitative trading.</strong></em></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><item><title><![CDATA[From Quantreo to Oryon]]></title><description><![CDATA[Latency does not start at execution. It starts upstream, in the feature pipeline.]]></description><link>https://www.newsletter.quantreo.com/p/from-quantreo-to-oryon</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/from-quantreo-to-oryon</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 10 Apr 2026 14:30:48 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e6499621-e8a4-4c3b-bbf1-7318f7b1ba93_1280x640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most trading systems do not lose performance at execution time. They <strong>lose it upstream</strong>, in the way features are computed, updated, and maintained. In research, full recomputation is acceptable. In production, <strong>it becomes a structural inefficiency</strong>.</p><p>Every unnecessary pass over the data, every oversized state, every hidden dependency in the pipeline introduces latency that compounds over time. Not always visible, but always present.</p><p><strong>Oryon was designed to remove that layer entirely</strong>.</p><p>Not by optimizing it. By redefining it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TzKp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TzKp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TzKp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg" width="1280" height="640" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:640,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:61236,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/193673294?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1abdf4af-d1bf-46ed-96d1-4f9460ac8ca3_1280x640.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TzKp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TzKp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fd1045-3ab7-434e-91f9-639035964a4f_1280x640.jpeg 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"><svg role="img" 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"><g><title></title><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"><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"><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><div><hr></div><h2>1. Rethinking Feature Computation</h2><p>Oryon is the beta 2 of Quantreo, but more importantly, it introduces a different abstraction. Features are no longer batch transformations. They are <strong>stateful, incremental objects</strong>.</p><p>Each update processes only the newest observation, maintains only the strictly required state, and returns the current value immediately.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;a81cbfc0-4163-40ee-b2ec-eb225a84ecfd&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from oryon.features import Sma

sma = Sma(["close"], window=3, outputs=["sma_3"])

sma.update([100.0])  # &#8594; [nan]
sma.update([101.0])  # &#8594; [nan]
sma.update([102.0])  # &#8594; [101.0]
sma.update([103.0])  # &#8594; [102.0]</code></pre></div><p>The important part is not the indicator itself. A 3-period moving average stores exactly three values. No history, <strong>no recomputation</strong>, <strong>no hidden overhead</strong>.</p><p>This same design extends consistently across the library:</p><ul><li><p>entropy-based features</p></li><li><p>ADF-style statistical tests</p></li><li><p>multiple volatility estimators</p></li><li><p>rolling and dynamic correlations</p></li><li><p>operators, transformations, and scalers</p></li></ul><p>All built around the same constraint:</p><p><strong>&#8594; Compute once, update incrementally, stay minimal in memory.</strong></p><div><hr></div><h2>2. Performance where it actually matters</h2><p>Oryon is built on a Rust-backed core, exposed through a minimal Python interface.</p><p>This is not an implementation detail. It is a design requirement.</p><p>Under production conditions:</p><ul><li><p>fast paths run below <strong>1 microsecond</strong></p></li><li><p>the slowest feature update remains under <strong>19 microseconds</strong></p></li><li><p>a full feature state can be refreshed in <strong>less than 1 millisecond</strong></p></li></ul><p>This is where the difference becomes tangible.</p><p>Not in isolated benchmarks, but in continuous pipelines running live, where every microsecond accumulates.</p><div><hr></div><h2>3. One pipeline, from research to production</h2><p>The <strong>same abstraction is used everywhere</strong>. The same objects.<br>The same update logic. The same behavior. There is <strong>no distinction between a research pipeline and a production pipeline</strong>. No reimplementation, no hidden mismatch, no translation layer.</p><blockquote><p>What you build is what you run. This removes an entire class of errors that typically appears when moving from notebooks to live systems.</p></blockquote><p>And it forces a discipline. Features must be correct, incremental, and production-ready from the start.</p><p>&#8658; <strong>In the next newsletter, we&#8217;ll build a research pipeline that is natively streaming-ready and can be deployed as-is in production.</strong></p><p></p><p><a href="https://oryonlib.dev">Oryon</a> is now available in beta.</p><p>If you want to take a closer look at the library and its design, you can explore it directly on <a href="https://github.com/lucasinglese/oryon">GitHub</a>.</p><p>And if you find it useful, consider adding a star. it helps more than it seems.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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"><em><strong>Subscribe to follow the ideas, tools, and production-grade systems shaping modern quantitative trading.</strong></em></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><item><title><![CDATA[Why intra-bar features matter]]></title><description><![CDATA[How to enrich higher-timeframe bars with lower-timeframe information without changing your full research workflow.]]></description><link>https://www.newsletter.quantreo.com/p/why-intra-bar-features-matter</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/why-intra-bar-features-matter</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 03 Apr 2026 14:30:46 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d5e5cc5a-95f9-4fff-bfd5-c30db31224f0_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When we work with hourly or daily bars, we usually keep only OHLCV.</p><p>But two hourly bars with the same OHLCV can hide very different internal behaviors.</p><p>One may trend smoothly.</p><p>Another may be noisy, mean-reverting, or <strong>highly asymmetric inside the bar</strong>.</p><div class="pullquote"><p>That is exactly where intra-bar features become useful.</p></div><p>Instead of treating each bar as a simple summary, we can rebuild it from a lower timeframe and <strong>compute additional metrics</strong> inside the bar, such as <em><strong>slope</strong></em>, <em><strong>skewness</strong></em>, <em><strong>kurtosis</strong></em>, or other <strong>microstructural statistics</strong>. <a href="https://docs.quantreo.com/data-aggregation/bar-metrics/">Quantreo&#8217;s bar metrics</a> are designed for that workflow through the `<em>additional_metrics</em>` mechanism, which adds custom columns computed from the data inside each bar. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. The Core Idea</h2><p>The idea is simple.</p><p>If you trade on a higher timeframe, for example 1H, you can use a lower timeframe, for example 1 minute, to reconstruct each hourly bar and compute what happened inside it.</p><p>This gives you extra information that standard OHLCV cannot capture.</p><p>In Quantreo, these bar-level metrics are meant to <strong>enrich traditional bars</strong> with statistical and microstructural information extracted from the data inside each bar. </p><p>The documentation explicitly mentions examples such as <strong>skewness, kurtosis, Hurst exponent, volume-profile-type features, and other custom indicators</strong>. </p><div><hr></div><h2>2. Why This Matters</h2><p>A bar is a compression of information.</p><p>And <strong>sometimes</strong>, that compression removes <strong>exactly the behavior you care about</strong>.</p><p>With intra-bar metrics, you can start distinguishing:</p><p>- smooth vs noisy bars<br>- directional vs unstable bars<br>- balanced vs asymmetric internal price action<br>- ordinary bars vs bars with unusual internal structure</p><blockquote><p><strong>This is often where extra signal can appear</strong>, especially when many strategies rely only on the final OHLCV snapshot.</p></blockquote><div><hr></div><h2>3. Examples Of Useful Intra-Bar Features</h2><p>Some useful examples are:</p><p>- linear slope inside the bar<br>- skewness<br>- kurtosis<br>- volume concentration features<br>- custom metrics derived from price or price-volume distributions</p><p><a href="https://docs.quantreo.com/data-aggregation/bar-metrics/">Quantreo</a> already documents built-in bar metrics such as `<em>skewness</em>`, `<em>kurtosis</em>`, `<em>volume_profile_features</em>`, and `<em>max_traded_volume</em>`, and also allows fully custom metrics through `<em>additional_metrics</em>`. </p><div><hr></div><h2>4. The Practical Workflow</h2><p>A clean workflow looks like this:</p><p>- choose your trading timeframe, for example 1H<br>- take a lower timeframe or raw tick data<br>- rebuild the higher-timeframe bars<br>- compute intra-bar metrics during aggregation<br>- use these new columns as additional features in your research pipeline</p><p>In Quantreo, each metric is attached through an `<em>additional_metrics</em>` <strong>tuple</strong> that specifies the function, the input source (`price`, `volume`, or `price_volume`), and the output column names. </p><div><hr></div><h2>5. Why I Like This Approach</h2><p>I like this approach because it adds information <strong>without forcing you to redesign your whole pipeline</strong>.</p><blockquote><p>You still work with bars.</p><p>You still keep a structured dataframe.</p><p>But your bars become much richer.</p></blockquote><p>So instead of changing the whole strategy framework, <strong>you improve the quality of the representation</strong>.</p><div><hr></div><h2>6. Performance Matters Too</h2><p>This kind of idea is only useful if it remains practical at scale.</p><p>Quantreo recommends using <strong>Numba</strong> for <strong>custom metrics</strong> because bar building can involve <strong>millions of ticks</strong>, and the documentation notes that pure Python or Pandas implementations can be <strong>20x to 100x slower than Numba-compiled functions</strong>. </p><div><hr></div><h2>7. Who This Is For</h2><p>This is especially useful for people who:</p><p>- already use bar-based workflows<br>- want more signal without jumping directly to raw tick models<br>- care about microstructure, but still want a clean research pipeline<br>- want to enrich higher-timeframe features with lower-timeframe behavior</p><p></p><p></p><p>OHLCV is often a good starting point, but it is still a compression.</p><p><strong>And sometimes, alpha lives inside what that compression removes.</strong></p><p>That is why intra-bar features are so interesting.</p><p>They let you keep the simplicity of bar-based research while injecting part of the information hidden inside each bar.</p><p></p><p>&#128073; Want to learn from A to Z how to <strong>build and use intra-bar features in a real quantitative research workflow</strong>? That&#8217;s exactly what the <strong><a href="https://www.quantreo.com/ml4trading-course/">ML4Trading</a></strong> Program is designed for.</p>]]></content:encoded></item><item><title><![CDATA[Why I always try to simplify my alpha formulas]]></title><description><![CDATA[Simpler formulas will miss some cases. But in many situations, that is exactly what makes them more robust.]]></description><link>https://www.newsletter.quantreo.com/p/why-i-always-try-to-simplify-my-alpha</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/why-i-always-try-to-simplify-my-alpha</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 27 Mar 2026 15:30:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c07ec044-50b4-4525-bcb5-47f9199247dc_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I work on an alpha, I almost always try to simplify the formula as much as possible.</p><p>Not because simple models are always better.<br>Not because complexity is useless.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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>But because every unnecessary degree of freedom increases the risk of overfitting.</p><p>In practice, I often prefer very simple structures such as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y = \\beta_0 + \\beta_1 x_1 + ... + \\beta_n x_n&quot;,&quot;id&quot;:&quot;WJXJLUBNDO&quot;}" data-component-name="LatexBlockToDOM"></div><p>and sometimes a square or cubic term when it is clearly justified.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y = \\beta_0 + \\beta_1 x_1 +  \\beta_{1*} x_{1}^2 + ... + \\beta_n x_n&quot;,&quot;id&quot;:&quot;FBCUWSRGIA&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><p>Of course, the goal is not to destroy the alpha just to end up with a pretty equation.</p><p>The real objective is to find the sweet spot between simplicity and performance.</p><div><hr></div><p><strong>1. Why Simplicity Matters</strong></p><p>A formula that is too flexible can fit noise very easily.</p><p>The more parameters, interactions, nonlinearities, and transformations you add, the easier it becomes to explain the past.</p><p>But explaining the past <strong>is not the same as capturing a repeatable market effect</strong>.</p><p>A simpler formula usually gives you three major benefits:</p><p>- <strong>lower overfitting</strong> risk<br>- easier interpretation<br>- easier <strong>monitoring in live</strong> trading</p><p>And in many cases, that last point matters more than people think.</p><p>If an alpha starts degrading, a simple structure is much easier to diagnose than a black box.<br></p><div><hr></div><h2>2. Simple Does Not Mean Naive</h2><p>This is where many people get the message wrong.</p><p>The goal is <strong>not to force every alpha into a linear model</strong> just because it looks cleaner.<br>The goal is to <strong>remove unnecessary complexity while preserving the core market logic</strong>.</p><p>Sometimes the signal is already captured well by a linear combination (with or without linear expansion).</p><p>And sometimes the real structure is more complex, and <strong>oversimplifying it would simply kill the alpha</strong>.</p><p>So the real question is not: &#8220;Can I make it simple?&#8221;</p><p>It is: &#8220;<strong>How much complexity is truly necessary to preserve the signal?</strong>&#8221;</p><div><hr></div><h2>3. The Types Of Formulas I Prefer</h2><p>In most cases, I start by testing whether the alpha can be expressed through a very compact structure.</p><p>Typically:</p><p>- linear terms<br>- maybe one or two polynomial terms<br>- very limited interactions<br>- very few input variables</p><p>That gives me a model that is <strong>easier to understand</strong>, easier to stress test, and much harder to overfit than a more flexible alternative.</p><p></p><p>Only when this simplification fails do I consider a machine learning model.</p><p>And even then, I usually keep that for situations where:</p><p>- the number of input variables is small<br>- the relationship looks real but not easily compressible into a simple equation<br>- the added complexity is justified by out-of-sample behavior, not just in-sample fit</p><div><hr></div><h2>4. A Case Where Simplification Helps</h2><p>Imagine a signal that depends mostly on:</p><p>- short-term return<br>- recent volatility<br>- distance from a local mean</p><p>A complex model may build a tangled nonlinear response with many interactions.</p><p>But in practice, you may find that something as simple as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\alpha =  \\beta_0 +  \\beta_1 return + \\beta_2 volatility^2 + \\beta_3*dist^3&quot;,&quot;id&quot;:&quot;THKHNZZFQO&quot;}" data-component-name="LatexBlockToDOM"></div><p>already captures most of the usable signal.</p><p>Will it miss some edge cases? <strong>Yes</strong>.</p><p>But if the simplified version keeps most of the predictive power while being much more stable, that is often the better trade-off.</p><div><hr></div><p>5. A Case Where Simplification Fails</p><p>Now imagine a signal where the effect only appears under a <strong>specific conditional structure</strong>.</p><p>For example:</p><p>- feature A matters <strong>only</strong> when volatility is high<br>- feature B becomes relevant <strong>only</strong> when liquidity is thin<br>- the relationship changes sharply across regimes</p><p>In that case, <strong>forcing everything into one clean linear equation</strong> may remove exactly what makes the alpha work.</p><p>This is where a slightly more flexible model, or even a small machine learning model, can be justified.</p><p><strong>But the key point is that complexity should come from necessity, not from habit.</strong></p><div><hr></div><h2>6. The Real Objective: Find The Sweet Spot</h2><p>This is how I think about it:</p><p>- too simple, and you may t<strong>hrow away real structure</strong><br>- too complex, and you <strong>may fit noise</strong><br>- somewhere in between, there is a level of complexity that <strong>preserves the alpha while keeping it robust</strong></p><p>That is the sweet spot.</p><p>And in my experience, most people start too far on the complex side.</p><div><hr></div><h2>7. A Practical Checklist I Use</h2><p>Before keeping a more complex formula, I usually ask:</p><ul><li><p>Does the extra complexity improve out-of-sample results?</p></li><li><p>Does it survive across periods and regimes?</p></li><li><p>Can I explain why this extra term should exist economically or behaviorally?</p></li><li><p>Can I monitor it properly in live trading?</p></li><li><p>If I simplify it, how much signal do I really lose?</p></li><li><p>If complexity does not clearly earn its place, I usually remove it.</p></li></ul><p></p><p></p><p>A good alpha is not the most sophisticated equation you can write.</p><p>It is a signal that keeps working when reality stops being friendly.</p><p>That is why I usually start with the simplest valid structure I can build, and only add complexity when the data clearly proves it is needed.</p><p></p><p>&#128073; If you want to go <strong>deeper into the strategy design process</strong> and use AI to generate, structure, and refine trading ideas faster, that&#8217;s exactly what <strong><a href="https://www.quantreo.com/ai-trading-lab/">AI Trading Lab</a></strong> is built for.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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[Finding Alphas. A solid map of alpha research.]]></title><description><![CDATA[A concise review of what the book does well, where it falls short, and which chapters are worth reading first.]]></description><link>https://www.newsletter.quantreo.com/p/finding-alphas-a-solid-map-of-alpha</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/finding-alphas-a-solid-map-of-alpha</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 20 Mar 2026 15:30:58 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e389dffc-e35f-45c1-9000-fd33f1b0e873_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently read <strong>Finding Alphas</strong>, edited by Igor Tulchinsky and contributors from WorldQuant.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GfVI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GfVI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 424w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 848w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 1272w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GfVI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic" width="246" height="380" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:380,&quot;width&quot;:246,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28299,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/190610639?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GfVI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 424w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 848w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 1272w, https://substackcdn.com/image/fetch/$s_!GfVI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29b91614-4864-4f69-8c32-fb5cf04640ce_246x380.heic 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"><svg role="img" 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"><g><title></title><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"><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"><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>This is not a deep technical monograph, and it is not a book that will hand you a ready-to-trade edge. It is better understood as a structured overview of how professional alpha research is framed: idea generation, data selection, backtesting, robustness, turnover, correlation, bias control, risk, and portfolio thinking.</p><p>That is also its main strength. The book gives a broad and practical map of the research process, with many short chapters written from the perspective of practitioners rather than academics. </p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. What The Book Does Well</h2><p>Its biggest strength is breadth with structure.</p><p>The book covers the full <strong>alpha research pipeline</strong> rather than obsessing over one narrow topic. The strongest part is clearly the &#8220;<strong>Design and Evaluation</strong>&#8221; section, where the discussion moves through alpha design, data, turnover, correlation, overfitting, biases, robustness, risk factors, drawdowns, and automated search. For someone building research habits, this is much more valuable than yet another book full of isolated signals. </p><p>Another strong point is that the book repeatedly <strong>brings the reader back to the same core reality</strong>: alpha research is not only about finding a signal, but about testing whether it survives costs, bias, crowding, instability, and implementation constraints. That emphasis appears throughout the book, especially in the chapters on turnover, backtest overfitting, controlling biases, robustness, and risk. </p><p>The tone is also pragmatic. The objective is not to impress with theory, but to give a framework for <strong>thinking like a systematic researcher</strong>.</p><p></p><div><hr></div><h2>2. Where The Book Is Weaker</h2><p>The main limitation is also obvious: this is a WorldQuant-style book.</p><p>That makes it useful, but it also gives it a specific lens. You get many high-level principles, many conceptual tools, and many short examples, but <strong>not the level of implementation detail needed</strong> to go from &#8220;good research mindset&#8221; to a fully deployable institutional strategy.</p><p>In other words, the book is strong on framework, weaker on depth.</p><p>It also reads more like a collection of essays than a single tightly argued book. That makes it accessible, but it also means some chapters feel more useful than others, and the overall depth is uneven.</p><p>Finally, if you already have a strong background in robust backtesting, data engineering, portfolio construction, and production constraints, <strong>a fair part of the material will feel familiar</strong>.</p><div><hr></div><h2>3. The Most Useful Chapters</h2><p>If you read only a subset, I would prioritize these:</p><p>- <strong>Chapter 4</strong>, Alpha Design<br>- <strong>Chapter 6</strong>, Data and Alpha Design<br>- <strong>Chapter 7</strong>, Turnover<br>- <strong>Chapter 9</strong>, Backtest. Signal or Overfitting?<br>- <strong>Chapter 10</strong>, Controlling Biases<br>- <strong>Chapter 12</strong>, Techniques for Improving the Robustness of Alphas<br>- <strong>Chapter 14</strong>, Risk and Drawdowns<br>- <strong>Chapter 15</strong>, Alphas from Automated Search</p><p>Together, these chapters capture the real value of the book: not &#8220;a list of alpha ideas,&#8221; but a way of thinking about signal design under real-world constraints. </p><div><hr></div><h2>4. Who Should Read It</h2><p>This book is especially useful for:</p><p>- beginners who want a <strong>structured map</strong> of alpha research<br>- intermediate quants who already test ideas <strong>but need a cleaner framework</strong><br>- researchers who think too much about signals and not enough about <strong>implementation risk</strong></p><p>For very advanced readers, I would see it more as a compact refresher than a game-changing text.</p><div><hr></div><h2>5. Final Take</h2><p>My overall view is simple.</p><p>Finding Alphas is a good professional overview of the alpha research process. Its value is not that it reveals secret signals. Its value is that it helps you think more clearly about how alphas are actually designed, evaluated, stress-tested, and organized inside a systematic research workflow.</p><p>So no, this is not the one book that will teach you how to print money.</p><p>But yes, it is a book that can help you build a much better research mindset. And in quant, that is often more valuable than one extra idea. </p><p>&#128073; If you want to go <strong>deeper into the strategy design process</strong> and use AI to generate, structure, and refine trading ideas faster, that&#8217;s exactly what <strong><a href="https://www.quantreo.com/ai-trading-lab/">AI Trading Lab</a></strong> is built for.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Quantreo 0.2.0. We rebuild of the foundations. ]]></title><description><![CDATA[A major step forward to make the library more robust, more scalable, and closer to production-grade quantitative research standards.]]></description><link>https://www.newsletter.quantreo.com/p/quantreo-020-we-rebuild-of-the-foundations</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/quantreo-020-we-rebuild-of-the-foundations</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 13 Mar 2026 15:31:18 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0a263319-ba6d-4c73-8da6-74d11e756d7a_2406x1518.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Quantreo 0.2.0 Beta is not a simple update. It is a complete rebuild of the foundations behind the library.<br>The goal was clear: create a <strong>stronger base for research</strong>, simplify the creation of new features, <strong>raise engineering standards</strong>, and prepare the project for what comes next.<br>And yes, the project name will also change soon. More on that at the right time.</p><div><hr></div><h2>1. A New Foundation</h2><p>A new version, but more importantly, a new foundation.<br><br>Quantreo 0.2.0 Beta is not about adding a few new features on top of the existing codebase. It is about <strong>rebuilding the foundations properly</strong>, so the project can grow with more structure, more robustness, and a much higher standard of development.<br><br>This release also opens the door to a broader evolution of the project, including a future name change.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>2. Some News</h2><p>Here are three important changes behind this new beta.</p><p>First, the project is <strong>now opening its contributing process</strong>. The goal is not just to make the library public, but to make it <strong>easier to extend</strong>, cleaner to navigate, and stronger as an <strong>open quantitative research project</strong>.</p><p>Second, <strong>a new pipeline</strong> has been introduced to automate and simplify the creation of many features. This makes feature engineering more scalable, more consistent, and much easier to maintain as the library grows.</p><p>Third, the library now includes more tests and more safeguards across the codebase. The objective is clear: push the project toward a much higher level of reliability and engineering quality, with standards inspired by what serious research environments require.</p><p></p><p></p><p>And this is only part of the work.</p><p>Many other improvements and additions are already on the way. Some are focused on usability, others on architecture, reliability, and the long-term direction of the project.</p><p>Quantreo 0.2.0 Beta is not the end of a rebuild. It is the beginning of a much stronger version of the library.</p><p>The new version is not available yet, however, <strong>I will share more about the release date soon.</strong><br><br>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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[The 7 Mistakes I See Every Week (ML)]]></title><description><![CDATA[Most ML failures are not about models. They are about problem framing, uncertainty, and turning a score into a tradable portfolio.]]></description><link>https://www.newsletter.quantreo.com/p/the-7-mistakes-i-see-every-week-ml</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/the-7-mistakes-i-see-every-week-ml</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 06 Mar 2026 15:30:53 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/628c8867-8881-483b-bf4c-504f110ccbe4_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most beginners treat machine learning like a magic button.</p><p>They train a model, get a prediction, and convert it straight into a buy or sell. The backtest looks clean. Then live trading happens, and the edge evaporates.</p><p>Here are the seven mistakes behind most ML misuse in trading, and what experienced quants do instead.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><h3>1) Predicting a point instead of modeling uncertainty</h3><p>A single number feels precise. It is usually fragile.</p><p>In markets, what matters is not &#8220;the next return.&#8221; It is the distribution of outcomes given today&#8217;s context.</p><p>If you cannot answer &#8220;how uncertain is this?&#8221; you do not have a signal. You have a guess. (<strong>To go further on this point, you should check conformal forecasting</strong>)</p><div><hr></div><h3>2) Optimizing accuracy instead of optimizing decisions</h3><p><strong>High accuracy can still lose money.</strong></p><p>Why? Because trading is not a classification contest. Costs, slippage, tail losses, and error clustering dominate. A model that is right slightly more often can still be wrong exactly when it hurts.</p><p>What you actually want is a decision rule that survives reality. That means evaluating ML with trading-oriented metrics and stress tests, not just standard ML scores.</p><div><hr></div><h3>3) Thinking &#8220;ML model &#8594; signal&#8221;</h3><p>This shortcut is the biggest conceptual error.</p><p>A model output is not a trade. It is an input to a process.</p><p>A robust pipeline looks like this:<br><strong>Problem &#8594; ML model &#8594; alpha &#8594; position sizing &#8594; strategy rules &#8594; portfolio</strong></p><p>If you skip the middle, you are not trading a model. You are trading noise with confidence.</p><div><hr></div><h3>4) Treating the model as the edge</h3><p>ML does not create an edge out of thin air. It amplifies what you feed it.</p><p>If your data has no stable structure, the model will still fit something. That &#8220;something&#8221; is often a backtest-only pattern.</p><p>In practice, <strong>edge comes from market structure, behavior, flows, constraints, and regimes</strong>. ML helps you measure or express that edge. It does not replace it.</p><div><hr></div><h3>5) Getting the target wrong</h3><p>Most ML blowups start here.</p><p>A fancy architecture cannot fix a target that is unstable, ambiguous, or mismatched to execution.</p><p>Common failures:</p><ul><li><p>horizons that do not match your average holding period</p></li><li><p>labels that are too close to price noise</p></li><li><p>targets that drift as volatility regimes change</p></li></ul><p>A clean target is not &#8220;more ML.&#8221; <strong>It is better research</strong>.</p><div><hr></div><h3>6) Validation that leaks reality</h3><p>Random splits, improper scaling, peeking at the future, tuning on the same regime you test on. <strong>This is the silent killer</strong>.</p><p>In trading, the only validation that matters is forward-looking, regime-aware evaluation.</p><p>If your process does not answer &#8220;<strong>does this survive different market conditions?</strong>&#8221; your performance is a story, not evidence.</p><div><hr></div><h3>7) Ignoring what happens when the model is wrong</h3><p>This is where senior quants spend most of their time.</p><p>The key question is not average performance. It is conditional behavior:</p><ul><li><p>When the model is wrong, how wrong is it?</p></li><li><p>Do errors cluster?</p></li><li><p>Does it fail in specific regimes?</p></li><li><p>What happens to the portfolio in those periods?</p></li></ul><p>A model that is &#8220;good on average&#8221; but collapses in a few scenarios is not robust. It is a hidden tail bet.</p><div><hr></div><h3>The practical takeaway</h3><p>Machine learning is not a trading strategy. It is a tool for conditional estimation under uncertainty.</p><p>If you want to use ML correctly, stop asking: &#8220;What will the market do?&#8221;<br>Start asking: &#8220;Given what I know now, what is the distribution, how reliable is it, and how should my risk respond?&#8221;</p><p><strong>That is the difference between a model that looks smart and a system that survives.</strong></p><p>&#128073; If you want to go deeper, build smarter features, understand signal reliability, and master techniques like <strong>features selection, features engineering, or feature conditioning</strong>, that&#8217;s exactly what we cover in <strong><a href="https://www.quantreo.com/ml4trading-course/">ML4Trading</a></strong>.</p>]]></content:encoded></item><item><title><![CDATA[Kalman Filter in Trading (2/2)]]></title><description><![CDATA[A Volatility-based Position Sizing]]></description><link>https://www.newsletter.quantreo.com/p/kalman-filter-in-trading-22</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/kalman-filter-in-trading-22</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 27 Feb 2026 15:30:53 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/27bfdf7f-24fc-44a6-aaa2-04a18ffd80fd_708x369.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the first part of this series, we introduced the Kalman filter from a theoretical perspective and discussed why it is a natural tool for online estimation problems.</p><p>In this second part, we move from theory to practice and show how a Kalman filter can be used in a real trading context. Not to predict returns, but to <strong>control risk dynamically</strong>.</p><p>The goal is simple: estimate volatility online and transform it into a stable, realistic position sizing rule.</p><p>Find all the codes <a href="https://colab.research.google.com/drive/1XcwG_jfYvTaHQovBiFTUgv76ziZKfoy9?usp=sharing">here</a>.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. What problem are we actually solving?</h2><p>Volatility is not constant. It changes over time, often abruptly, and usually when it matters the most.</p><p>Most traders rely on rolling volatility estimates. These approaches <strong>suffer from two major issues</strong>:</p><ul><li><p>they react too slowly to regime changes,</p></li><li><p>they are extremely noisy at short horizons.</p></li></ul><p>In live trading, what we really need is: an <strong>online</strong> estimate, reasonably <strong>smooth</strong>, but able to <strong>adapt</strong> when market conditions change.</p><p>This is a risk management problem, not a forecasting one.</p><div><hr></div><h2>2. Volatility as a latent variable</h2><p><strong>Volatility is not directly observable</strong>. What we observe are returns, which are highly noisy at the single-period level.</p><p>We therefore model volatility as a latent state variable. More precisely, we work with the <strong>log-variance</strong>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;x_t&#8203;=log(&#963;_t^2&#8203;)&quot;,&quot;id&quot;:&quot;JDRKSNTVSI&quot;}" data-component-name="LatexBlockToDOM"></div><p>This choice has three advantages:</p><ul><li><p>it enforces positivity,</p></li><li><p>it leads to additive dynamics,</p></li><li><p>it is compatible with a linear Kalman filter.</p></li></ul><div><hr></div><h2>3. From returns to an observable proxy</h2><p>Since volatility cannot be observed directly, we construct a noisy proxy from returns:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y_t&#8203;=log(r_t^2&#8203;+&#949;)&quot;,&quot;id&quot;:&quot;SZHCKXYRTY&quot;}" data-component-name="LatexBlockToDOM"></div><p>Under a conditional Gaussian assumption, this quantity can be interpreted as a noisy observation of the latent log-variance.</p><p>This is clearly an approximation. However, our objective is not statistical inference, but <strong>stable risk control</strong>, which makes this approach both acceptable and effective in practice.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vfDr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vfDr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 424w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 848w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 1272w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vfDr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic" width="1197" height="377" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:377,&quot;width&quot;:1197,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54759,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/187407774?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vfDr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 424w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 848w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 1272w, https://substackcdn.com/image/fetch/$s_!vfDr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5ec107f-2123-4b16-aba7-5c1cca4db5cd_1197x377.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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>The visual difference already highlights the benefit of filtering.</p><div><hr></div><h2>4. Kalman filtering the log-variance</h2><p>We model the latent state with a simple random walk:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;x_t=x_{t&#8722;1}+&#951;_t&quot;,&quot;id&quot;:&quot;QZMTIQOXMU&quot;}" data-component-name="LatexBlockToDOM"></div><p>and the observation equation:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y_t&#8203;=x_t&#8203;+&#1013;_t&#8203;&quot;,&quot;id&quot;:&quot;XLNOBNYGAW&quot;}" data-component-name="LatexBlockToDOM"></div><p>Both noise terms are assumed Gaussian.</p><p>The two key parameters of the filter are:</p><ul><li><p><strong>Q</strong>, which controls how fast volatility is allowed to evolve,</p></li><li><p><strong>R</strong>, which reflects how noisy the observation log&#8289;(rt2) is.</p></li></ul><p>In practice, <strong>R is kept relatively large</strong>, because squared returns are extremely noisy at short horizons.</p><div><hr></div><h2>5. From volatility estimation to position sizing</h2><p>At this stage, we have an online estimate of volatility:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;&#963;^t=\\sqrt{e^{\\hat{x}_t}}&quot;,&quot;id&quot;:&quot;ZXAVBOZTTL&quot;}" data-component-name="LatexBlockToDOM"></div><p>The key idea is to use this estimate to scale exposure such that portfolio risk remains approximately constant over time.</p><p>This leads to the target-volatility sizing rule:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_t=\\frac{&#963;_{target}}{\\hat{&#963;_t}}&quot;,&quot;id&quot;:&quot;GAQSKEVCIT&quot;}" data-component-name="LatexBlockToDOM"></div><p>This equation captures the core intuition:</p><ul><li><p>when volatility increases, exposure is reduced,</p></li><li><p>when volatility decreases, exposure is increased.</p></li></ul><p>Importantly, w_t&#8203; is <strong>not a signal</strong>. It does not tell us which direction to trade. It only determines <strong>how much risk to take</strong>.</p><div><hr></div><h2>6. Practical constraints for live trading</h2><p>In real trading systems, several safeguards are required.</p><p>First, a volatility floor prevents excessive leverage when estimated volatility becomes too small.</p><p>Second, exposure is capped to remain within acceptable leverage limits.</p><p>Finally, position weights are smoothed to reduce turnover and transaction costs:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_t^{smooth&#8203;} =(1&#8722;&#945;)w_{t&#8722;1&#8203;}+&#945;w_t&#8203;&quot;,&quot;id&quot;:&quot;AIPAIVYORD&quot;}" data-component-name="LatexBlockToDOM"></div><p>This smoothing introduces a small delay, but significantly improves stability in practice.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bV8p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bV8p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 424w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 848w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 1272w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bV8p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic" width="1197" height="377" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:377,&quot;width&quot;:1197,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51010,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/187407774?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bV8p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 424w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 848w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 1272w, https://substackcdn.com/image/fetch/$s_!bV8p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f53b5bc-55fd-4c7c-8bd6-5bfb362d3016_1197x377.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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><hr></div><h2>7. What this approach does (and does not)</h2><p>This framework works well because it:</p><ul><li><p>stabilizes portfolio risk,</p></li><li><p>adapts to changing volatility regimes,</p></li><li><p>is simple, robust, and computationally efficient,</p></li><li><p>can be combined with any alpha signal.</p></li></ul><p>However, it is important to be clear about its limitations:</p><ul><li><p>it does not predict returns,</p></li><li><p>it does not perform market timing.</p></li></ul><p>It is a <strong>risk controller</strong>, not an alpha generator.</p><div><hr></div><p>Kalman filters are often presented as complex mathematical tools. In practice, their strength lies in their simplicity and flexibility.</p><p>Used correctly, they provide a clean and effective way to control risk in environments where volatility is unstable and noisy.</p><p>In systematic trading, improving risk control is often more impactful than improving return forecasts.</p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p>]]></content:encoded></item><item><title><![CDATA[Kalman Filter in Trading (1/2)]]></title><description><![CDATA[A simple mental model to blend predictions and noisy observations]]></description><link>https://www.newsletter.quantreo.com/p/kalman-filter-in-trading-12</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/kalman-filter-in-trading-12</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 20 Feb 2026 15:30:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!17Jh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In trading, almost everything you touch is noisy. Prices jump because of microstructure, spreads widen for a few prints, volatility spikes just because your window is short. If you react to every wiggle, you trade randomness. If you smooth too much, you react too late.</p><p></p><p>The Kalman filter is a clean way to sit in the middle. It estimates a &#8220;true signal&#8221; behind noisy observations by doing the same two-step loop every time: predict what should happen, then correct using what you observed. The correction is not arbitrary. It is weighted by uncertainty, which is why Kalman feels both smooth and responsive.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1) The problem, in one minute</h2><p>Markets are messy. <strong>Your indicators are messier</strong>.</p><p>A price series mixes real moves with microstructure <strong>noise</strong>. A rolling volatility mixes real regime shifts with estimation error. </p><p>Same story <strong>for any feature built on finite windows</strong>. Feed that raw signal into a strategy and you get false triggers, unstable sizing, and lots of noise masquerading as information.</p><blockquote><p>What we want is simple. Keep the information, drop the useless wiggles.</p></blockquote><p></p><div><hr></div><h2>2) The key idea. Two realities</h2><p>Kalman starts with a clean separation.</p><ul><li><p>What you observe: <strong>y_t</strong> (noisy)</p></li><li><p>What you want: <strong>x_t</strong> (latent state, hidden signal)</p></li></ul><p>You assume:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y_t = x_t + v_t&quot;,&quot;id&quot;:&quot;SRBADWNZWB&quot;}" data-component-name="LatexBlockToDOM"></div><p>where <strong>v_t</strong> is measurement noise.</p><p>The &#8220;latent state&#8221; is not a mystical fair value. It is simply the signal you choose to model: a smoother price level, a latent volatility, a stable trend component, a cleaner spread.</p><p><strong>A tiny example (with a simulated &#8220;latent signal&#8221;)</strong></p><p>To make this concrete, we can build a toy signal.</p><ul><li><p>First, we create a latent state x_t&#8203;. Think of it as the clean underlying level we wish we could observe.</p></li><li><p>Then we generate what the market actually shows us:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;y_t=x_t+noise&quot;,&quot;id&quot;:&quot;LNPKAJSFMO&quot;}" data-component-name="LatexBlockToDOM"></div><p>This mimics noisy prints, bid ask bounce, and random micro wiggles.</p></li></ul><p>In a simulation, we can plot both x_t&#8203; and y_t&#8203;. This lets us visually check whether the Kalman estimate&#8203; is actually recovering the hidden signal.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!17Jh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!17Jh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 424w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 848w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 1272w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!17Jh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic" width="1104" height="455" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:455,&quot;width&quot;:1104,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51786,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/187381181?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!17Jh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 424w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 848w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 1272w, https://substackcdn.com/image/fetch/$s_!17Jh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c8077aa-df95-46bd-b807-cacdce954e21_1104x455.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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><strong>Important</strong>: In real trading, <strong>we never see x_t&#8203;</strong>. That is the whole point. The filter is valuable precisely because it produces an estimation of x_t&#8203;, a disciplined estimate of what might be behind y_t&#8203;.</p><blockquote><p><strong>We do not trade y. We trade an estimate of what is behind y.</strong></p></blockquote><p></p><div><hr></div><h2>3) Kalman is a two-step loop</h2><p>Kalman is a loop with one question repeated forever:</p><p><strong>What did I expect? What did I see? How much should I adjust?</strong></p><p></p><h4>Predict</h4><p>You start each step with a belief about the hidden signal. Then you move it forward using a simple model.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat x_{t|t-1} = \\hat x_{t-1|t-1}\n&quot;,&quot;id&quot;:&quot;MYEPUDANMD&quot;}" data-component-name="LatexBlockToDOM"></div><p>This is your <strong>prior</strong>. It is what you believe before seeing the new data point.</p><blockquote><p>t&#8739;t&#8722;1 means: estimate at time t using information up to t&#8722;1 (before seeing y_t&#8203;)</p><p>My best guess for the hidden <strong>level today is yesterday&#8217;s filtered estimate</strong>.</p></blockquote><p></p><h4>Update</h4><p>Then you look at the new observation and measure the surprise:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{innovation}_t \\;=\\; y_t - \\hat x_{t|t-1}\n&quot;,&quot;id&quot;:&quot;CWAYVXVZNO&quot;}" data-component-name="LatexBlockToDOM"></div><p>Finally you adjust toward the observation:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat x_{t|t} \\;=\\; \\hat x_{t|t-1} + K_t \\cdot \\text{innovation}_t\n&quot;,&quot;id&quot;:&quot;WUWNBRDHKV&quot;}" data-component-name="LatexBlockToDOM"></div><p>The updated estimate is always &#8220;between&#8221; the prediction and the observation. The only thing that decides where you land is the <strong>gain K_t&#8203;</strong>.</p><p><strong>K_t&#8203; is the trust weight you give to the new observation.</strong></p><ul><li><p>K_t&#8203;&#8776;1 means &#8220;I trust the data&#8221;. Fast reaction, little smoothing.</p></li><li><p>K_t&#8776;0 means &#8220;I trust the model&#8221;. Slow reaction, strong smoothing.</p></li></ul><div><hr></div><h2>4) Focus on the Kalman Gain K_t</h2><p>The gain K_t is the adaptive weight that controls the update. It answers one question:</p><p><strong>Do I trust the new observation, or do I trust my current belief?</strong></p><p>In the simplest 1D case, the gain is computed from two sources of uncertainty:</p><ul><li><p><strong>Prediction uncertainty</strong> (how unsure you are before seeing the new point)</p></li><li><p><strong>Measurement noise</strong> (how noisy the observation is)</p></li></ul><p>Here are the two key equations.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P_{t|t-1} = P_{t-1|t-1} + Q\n&quot;,&quot;id&quot;:&quot;TKWCSIUUCJ&quot;}" data-component-name="LatexBlockToDOM"></div><p>Each step forward adds uncertainty. <strong>Q is how much you allow the hidden signal to &#8220;wander&#8221;</strong> between two observations. Bigger Q means &#8220;the state can move fast&#8221;, so you become more willing to adjust.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;K_t = \\frac{P_{t|t-1}}{P_{t|t-1} + R}\n&quot;,&quot;id&quot;:&quot;YFYWCWMJNI&quot;}" data-component-name="LatexBlockToDOM"></div><p>The gain compares how uncertain your prediction is versus how noisy the observation is.</p><ul><li><p>Bigger <strong>R means noisier data</strong>. The gain shrinks. You smooth more.</p></li><li><p>Bigger Q makes your prediction less certain (through P). The gain grows. You adapt faster.</p></li></ul><p>So the only real knobs you set in practice are <strong>Q</strong> and <strong>R</strong>:</p><ul><li><p>R controls how much you distrust the data.</p></li><li><p>Q controls how flexible the hidden signal is.</p></li></ul><p></p><p>In the next newsletter, we will walk through a simple trading example and show how to use the Kalman estimate in a real signal.</p><p>Yes, there were a few equations here, but the goal is not to memorize them. <strong>The goal is to internalize the intuition: predict, measure the surprise, and adjust by an uncertainty weighted amount.</strong></p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p>]]></content:encoded></item><item><title><![CDATA[Quant never predict... They quantify uncertainty!]]></title><description><![CDATA[Why serious quants think in distributions, not forecasts]]></description><link>https://www.newsletter.quantreo.com/p/quant-never-predict-they-quantify</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/quant-never-predict-they-quantify</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 13 Feb 2026 15:30:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!hME9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It&#8217;s a sentence everyone has heard. It sounds smart. <strong>It is often misunderstood</strong>.</p><p>Many people take it to mean that quants refuse to say anything about the future. Others use it as a kind of intellectual shield, a way to avoid being wrong. Both readings miss the point.</p><p>The issue is not prediction itself.<br>The issue is <strong>believing that a single prediction can be treated as truth</strong>.</p><p>This distinction matters because markets are not difficult just because they are noisy. They are difficult because they punish certainty far more than they punish error.</p><p>This is what this newsletter is about. Not repeating a slogan, but explaining what experienced quants actually do <strong>when they say they &#8220;quantify uncertainty.&#8221;</strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. The real problem is not prediction, but believing in a prediction</h2><p>Prediction is not the enemy.</p><p>When people say &#8220;the market will go up&#8221; or &#8220;this strategy works&#8221;, they are not just making an estimate. They are implicitly choosing a <strong>single future</strong> and treating it as if it were reliable.</p><p>Even when numbers are involved, the mental model is usually the same. One central scenario. One expected outcome. <strong>Everything else pushed to the background</strong>.</p><p>The human brain is very good at constructing a coherent story. It is much worse at holding multiple incompatible futures at the same time.</p><p>This is where most mistakes start.<br>Not because the forecast is wrong, but because its uncertainty is ignored.</p><p>A trader who knows they can be wrong by a wide margin <strong>will size positions differently</strong>, manage risk differently, and <strong>survive longer</strong>. A trader who believes their prediction will hold tends to discover the tails the hard way.</p><p>For a quant, the question is never &#8220;what will happen?&#8221;.<br>It is &#8220;<strong>how wrong can I be, and what happens to my system when I am</strong>?&#8221;.</p><div><hr></div><h2>2. What experienced quants do instead</h2><p>An experienced quant replaces a point estimate <strong>with a distribution</strong>.</p><p>This is a critical shift. Not cosmetic. Structural.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hME9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hME9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 424w, https://substackcdn.com/image/fetch/$s_!hME9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 848w, https://substackcdn.com/image/fetch/$s_!hME9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 1272w, https://substackcdn.com/image/fetch/$s_!hME9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hME9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic" width="1456" height="316" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:316,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16950,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/187371169?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hME9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 424w, https://substackcdn.com/image/fetch/$s_!hME9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 848w, https://substackcdn.com/image/fetch/$s_!hME9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 1272w, https://substackcdn.com/image/fetch/$s_!hME9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa2ee557-c40b-4ea0-b899-bc7b45987d59_1934x420.heic 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>A single metric, a Sharpe ratio, a Calmar ratio, a CAGR, always looks clean in isolation. It gives the illusion of precision. But taken alone, it tells you almost nothing about <strong>how fragile the result is</strong>.</p><p>One number cannot tell you whether performance is repeatable or accidental.<br>It cannot tell you whether the strategy is robust or just lucky once.</p><p>This is why mature quant workflows never stop at a single backtest outcome. They generate <strong>distributions of outcomes</strong>.</p><p>Different subsamples. Different start dates. Different regimes. Different perturbations.</p><p>What matters is no longer the best result, but the <strong>shape of the distribution</strong>.</p><p>Is performance concentrated around a stable core, or carried by a few extreme runs?<br><strong>Are drawdowns consistently manageable, or occasionally catastrophic?</strong><br>Does the strategy degrade gracefully, or collapse when conditions shift?</p><p>A strategy with a lower average metric but a tight, well-behaved distribution is often far superior to one with a spectacular headline number driven by lucky randomness.</p><p>This is what quantifying uncertainty looks like in practice.<br>You stop asking &#8220;how good is this strategy?&#8221; and start asking &#8220;<strong>how often does this strategy behave acceptably?</strong>&#8221;</p><blockquote><p>Once you see the distribution, you cannot unsee it.<br>And from that point on, single-number metrics feel dangerously incomplete.</p></blockquote><p></p><div><hr></div><h2>3. Why this matters in real trading and machine learning</h2><p>In trading, an edge is not a guarantee.<br>It is a small statistical bias that only exists under specific conditions.</p><p>A machine learning model does not &#8220;predict&#8221; the market. It outputs a conditional estimate based on past data. <strong>Treating that output as a forecast is where most mistakes begin</strong>.</p><p>What really matters is not average accuracy. It is how the model behaves when it is wrong.</p><p>Take a simple example.<br>Two strategies show the same Sharpe ratio on a backtest. One <strong>delivers steady, repeatable performance across many subsamples</strong>. The other makes most of its profits in a handful of runs and collapses in the rest.</p><p>On paper, they look identical. In reality, one is robust. The other likely driven by luck or highly risky.</p><p>This is why experienced quants care more about <strong>distributions than point metrics</strong>. They want to know how often a strategy behaves acceptably, not how good it looks in the best case.</p><blockquote><p>&#8220;<strong>A model is not a crystal ball. It is a noisy sensor in an unstable environment.<br>The goal is not to remove uncertainty. The goal is to build systems that can live with it.</strong>&#8221;</p></blockquote><div><hr></div><p></p><p>Quantifying uncertainty is not about being cautious. It is about being realistic.</p><p>Markets are not difficult because they are unpredictable. They are difficult because <strong>they punish systems that are built around fragile assumptions and single-scenario thinking</strong>.</p><p>Experienced quants do not avoid prediction out of intellectual modesty. They move past it because they understand that <strong>robustness matters more than being right</strong>, and that survival comes before precision.</p><p>Once you start thinking in distributions, <strong>your entire process changes</strong>. How you backtest. How you size risk. How you interpret models. How you react when things break, which they inevitably do.</p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p><p></p>]]></content:encoded></item><item><title><![CDATA[False negatives are better than false positives...]]></title><description><![CDATA[Why false negatives are often preferable to false positives in trading]]></description><link>https://www.newsletter.quantreo.com/p/false-negatives-are-better-than-false</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/false-negatives-are-better-than-false</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 06 Feb 2026 15:30:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!J4oZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In trading, <strong>not all mistakes are equal</strong>. Machine learning metrics often treat false positives and false negatives as symmetric errors. <strong>Markets do not</strong>&#8230;</p><p>A false positive creates a trade where no real opportunity exists. A false negative simply means staying out.</p><p>This asymmetry changes how models should be evaluated and how signals should be used in practice.</p><p>Understanding this difference is essential when dealing with noisy markets and rare trading opportunities.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. False positives and false negatives are different by nature</h2><p>In any decision system, two types of errors can occur.</p><p>A <strong>false positive</strong> happens when a system signals that something is happening, while in reality nothing is happening.<br>A <strong>false negative</strong> happens when something is happening, but the system fails to detect it.</p><p>These two errors are not interchangeable.</p><p>Their impact depends entirely on the context and on what happens <strong>after</strong> the decision is made.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J4oZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J4oZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 424w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 848w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 1272w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J4oZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic" width="747" height="441" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:441,&quot;width&quot;:747,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28358,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/184773562?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!J4oZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 424w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 848w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 1272w, https://substackcdn.com/image/fetch/$s_!J4oZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F681bb9f8-b140-4186-b6a3-a525c04c4f28_747x441.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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 some domains, <strong>false positives</strong> are preferred:</p><ul><li><p>In natural disaster monitoring, issuing a <strong>tsunami alert</strong> that turns out to be unnecessary is often acceptable compared to missing a real one.</p></li><li><p>In medical screening, <strong>early detection systems</strong> may tolerate false alarms to avoid missing critical conditions.</p></li></ul><p>In other domains, <strong>false negatives</strong> are preferred:</p><ul><li><p>In <strong>credit risk decisions</strong>, rejecting a good borrower is often less costly than approving a bad one.</p></li><li><p>In legal and <strong>compliance systems</strong>, a false accusation can cause irreversible damage, while a missed case can often be reviewed later.</p></li></ul><p>The key point is simple.<br><strong>The cost of an error is not symmetric</strong>, and the preferred type of error depends on the consequences of acting or not acting.</p><p>Understanding this distinction is essential before choosing metrics, thresholds, or optimization objectives.</p><div><hr></div><h2>2. In Trading, acting has a cost</h2><p>The critical difference between false positives and false negatives in trading appears <strong>after</strong> the signal is generated. A signal is not just a prediction. It is a <strong>decision to allocate capital</strong>.</p><p>When a false positive occurs, the system acts: a <strong>position is opened</strong>, <strong>costs are paid</strong>, <strong>capital is exposed</strong> to randomness, <strong>risk accumulates</strong> over time. Each false positive adds friction and noise to the strategy. These effects compound.</p><p>By contrast, when a false negative occurs, nothing happens: no position is taken, no cost is paid, no drawdown is created. <strong>The opportunity is missed</strong>, but the system remains stable.</p><p>This is why trading systems are fundamentally different from pure prediction systems.<br>The cost is not attached to being wrong. The cost is attached to <strong>acting when you should not</strong>.</p><p>This is also why being more selective often leads to more robust strategies, <em><strong>even if fewer opportunities are captured</strong></em>.</p><blockquote><p>In trading, stability comes from controlling actions, not from predicting more events.</p></blockquote><div><hr></div><h2>3. Why evaluation metrics push trading systems in the wrong direction</h2><p>The problem is not only how trading systems behave, but also <strong>how they are evaluated</strong>.</p><blockquote><p>Most machine learning metrics are designed for prediction tasks, not for decision systems with asymmetric costs.</p></blockquote><p>Accuracy is the most common example. <strong>When events are rare</strong>, accuracy is largely driven by true negatives. A model can appear excellent simply by predicting &#8220;no signal&#8221; most of the time.</p><p><strong>This gives a false sense of reliability.</strong></p><p><strong>Recall</strong> can be more informative, as it measures how many real opportunities are detected. </p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;Recall = \\frac{True Positives}{True Positives + False Negatives}&quot;,&quot;id&quot;:&quot;EYASCYVNXW&quot;}" data-component-name="LatexBlockToDOM"></div><p>However, <strong>recall ignores what happens when the model is wrong in the other direction</strong>.</p><p>By construction, increasing recall often increases false positives. In trading, <strong>this trade-off is rarely neutral</strong>. Optimizing a metric in isolation pushes the system toward <strong>more actions</strong>, not necessarily toward better decisions.</p><p>This is why trading systems must be evaluated with metrics that reflect <strong>when capital is exposed</strong>, not just how often predictions are correct.</p><p></p><blockquote><p><strong>In trading, the objective is not to maximize precision or recall.<br>It is to trade only when acting is justified, and to act often enough for the strategy to matter.</strong></p></blockquote><p></p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p>]]></content:encoded></item><item><title><![CDATA[Bayes in Trading (3/3)]]></title><description><![CDATA[Bayes in practice. What actually matters for rare-event signals]]></description><link>https://www.newsletter.quantreo.com/p/bayes-in-trading-33</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/bayes-in-trading-33</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 30 Jan 2026 15:30:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/13a2f50f-fa76-4742-bba3-680fccaa83a2_990x490.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a href="https://open.substack.com/pub/quantreo/p/bayes-in-trading-23?r=1o765i&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=true">previous newsletters</a>, we applied the <strong>exact Bayes computation</strong> for a rare-event trading signal.</p><p>Now, instead of adding more math, we will vary the key parameters one by one and observe what really moves the probability that a signal is correct.</p><p>The goal is simple: <strong>identify which levers matter in practice, and which ones are often overestimated.</strong></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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>For reference, the model parameters are fixed to the same values as in <em><strong><a href="https://open.substack.com/pub/quantreo/p/bayes-in-trading-23?r=1o765i&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=true">Bayes in Trading (2/3)</a></strong></em>:</p><ul><li><p>The event occurs <strong>2%</strong> of the time. P(E)=2%.</p></li><li><p>When the event is present, the model detects it <strong>90%</strong> of the time. P(S&#8739;E)=90%.</p></li><li><p>When the event is not present, the model still triggers a signal <strong>12%</strong> of the time. P(S&#8739;E bar)=12%.</p></li></ul><p>In the following sections, each parameter will be varied <strong>one at a time</strong> to isolate its effect.</p><div><hr></div><h2>1. False positives dominate everything</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jqfK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jqfK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 424w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 848w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jqfK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic" width="1456" height="479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:479,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19133,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/184677057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jqfK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 424w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 848w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!jqfK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84db1dff-998d-4bd9-97d5-4f524efd03cf_1490x490.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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>This first plot <strong>isolates the impact of the false positive rate</strong>, while keeping all other parameters fixed. The effect is immediate and severe. Even small increases in P(S&#8739;E bar) lead to a sharp collapse in the probability that a signal is actually correct.</p><p>When the event is rare, <strong>most observations belong to the &#8220;no-event&#8221; regime</strong>.<br>As a result, false positives quickly outnumber true signals, even if the model performs well when the event is present.</p><p>This is why many strategies fail not because they miss opportunities, but because they <strong>trigger too often when nothing is happening</strong>.</p><blockquote><p>Reducing false positives is usually far more important than improving accuracy.</p></blockquote><div><hr></div><h2>2. Event rarity is a structural constraint</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SAD_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SAD_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 424w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 848w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SAD_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic" width="1456" height="479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:479,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21763,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/184677057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SAD_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 424w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 848w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!SAD_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F804e8386-5e5d-4c67-bdb1-4ef8b271837d_1490x490.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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 this second experiment, we keep the model behavior fixed and vary only the frequency of the event itself. The detection accuracy remains at <strong>90%</strong>, and the false positive rate at <strong>12%</strong>, exactly as before. Only the base rate P(E) changed.</p><p>The result is unambiguous.</p><p>When the event is extremely rare, even a well-behaved model produces signals that are mostly noise. As the event becomes more frequent, the same model suddenly appears far more reliable.</p><p>Nothing about the model changed. <strong>Only the market context did</strong>.</p><p>This highlights an <strong>important limitation of rare-event strategies</strong>.<br>Below a certain frequency, signal quality is structurally capped, regardless of how good the classifier is.</p><blockquote><p>Sometimes the main problem is not the model, but the rarity of the event being traded.</p></blockquote><div><hr></div><h2>3. Accuracy helps, but far less than expected</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Q95W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Q95W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 424w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 848w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Q95W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic" width="1456" height="479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:479,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22158,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.newsletter.quantreo.com/i/184677057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Q95W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 424w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 848w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 1272w, https://substackcdn.com/image/fetch/$s_!Q95W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ff9cec-8f9a-44bd-88b0-07df75922de2_1489x490.heic 1456w" sizes="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"><svg role="img" 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"><g><title></title><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"><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"><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 this final experiment, we vary only the detection accuracy of the model.</p><p>The event frequency is fixed at <strong>2%</strong>, and the false positive rate remains at <strong>12%</strong>, exactly as in the previous sections. Only P(S&#8739;E) is allowed to change.</p><p>The improvement is real, but modest. <strong>Even large increases in detection accuracy</strong> translate into relatively <strong>small gains</strong> in the probability that a signal is actually correct.<br><em><strong>This is a direct consequence of event rarity and persistent noise.</strong></em></p><p>This explains why strategies that aggressively optimize accuracy often fail to deliver meaningful improvements in live trading.</p><blockquote><p>Accuracy is rarely the dominant lever in rare-event strategies.</p></blockquote><p></p><h2>Conclusion. What to remember</h2><ul><li><p>For rare events, <strong>accuracy is not the right metric</strong>.</p></li><li><p>Signal quality is driven first by <strong>false positives</strong>, then by <strong>event frequency</strong>.</p></li><li><p>Detection accuracy helps, but <strong>far less than most people expect</strong>.</p></li><li><p>A strong model can still produce mostly noise if the base rate is low.</p></li><li><p>Bayes is not optional. It defines the ceiling of what a signal can achieve.</p></li></ul><p></p><p>Before trusting any trading signal, always ask:</p><ul><li><p>How rare is the event?</p></li><li><p>How often does the model fire when nothing happens?</p></li><li><p>What is the resulting probability that a signal is actually correct?</p></li></ul><p>If these questions are not answered explicitly, the signal is likely misleading.</p><p></p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p>]]></content:encoded></item><item><title><![CDATA[Bayes in Trading (2/3)]]></title><description><![CDATA[This newsletter is a direct continuation of the previous one.]]></description><link>https://www.newsletter.quantreo.com/p/bayes-in-trading-23</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/bayes-in-trading-23</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 23 Jan 2026 15:31:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/49796362-b81e-41b7-b058-793e22bb2acd_927x498.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This newsletter is a direct continuation of the <strong><a href="https://open.substack.com/pub/quantreo/p/bayes-in-trading-13?r=1o765i&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=true">previous one</a></strong>.</p><p>Last week, we discussed a very common problem in trading and machine learning: <strong>predicting a rare event</strong>.</p><p>We saw that even models with high reported accuracy can be misleading when the event itself occurs infrequently.</p><p>Now, we will go through the computation explicitly and show how Bayes quantifies this effect.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. Restating the problem and identifying the quantities</h2><p>We consider a binary classification problem applied to trading. A model attempts to detect a specific market pattern that occurs rarely.</p><p>We define two events:</p><ul><li><p><strong>E</strong>: the pattern is truly present in the market</p></li><li><p><strong>S</strong>: the model triggers a signal</p></li></ul><p></p><p>The available information is the following:</p><ul><li><p>When the pattern truly occurs, the model detects it with a 90% reliability.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(S\\mid E) = 0.90&quot;,&quot;id&quot;:&quot;AKQKGDZCRQ&quot;}" data-component-name="LatexBlockToDOM"></div><p></p></li><li><p>The pattern occurs 2% of the time.</p></li></ul><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(E) = 0.02&quot;,&quot;id&quot;:&quot;VNOVYUNIXI&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><ul><li><p>The model still produces signals even when the pattern is not present with a probability of 12%.</p></li></ul><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(S \\mid \\bar E) = 0.12&quot;,&quot;id&quot;:&quot;ACXNVAKDVK&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><p>Our goal is not to evaluate the model conditionally,<br>but to answer the trading-relevant question:</p><blockquote><p><strong>When the model triggers a signal, what is the probability that the pattern is actually real?</strong></p></blockquote><p>This corresponds to computing a posterior probability. In other words, with a prior probability (2% that it can occur), how knowing that the model predict a signal will impact the posterior probability.</p><div><hr></div><h2>2. What information is required and why</h2><p>At this point, it is important to pause and clarify something.</p><p>With only:</p><ul><li><p>the base rate of the event,</p></li><li><p>and the model&#8217;s detection rate when the event occurs,</p></li></ul><p>the problem is <strong>not solvable</strong>.</p><p>To compute the probability that a signal is actually correct, we need <strong>three distinct pieces of information</strong>:</p><ul><li><p>How often the event occurs in general.</p></li><li><p>How often the model detects the event when it is truly present.</p></li><li><p>How often the model produces a signal when the event is not present.</p></li></ul><p>The last quantity is usually overlooked.<br>Yet it is the one that dominates the result when events are rare.</p><p>This is why reported accuracy alone is insufficient in trading applications.</p><p></p><div><hr></div><h2>3. Bayes formula</h2><p>Bayes&#8217; theorem provides a direct relationship between these quantities.</p><p>It allows us to invert the question from &#8220;<strong>how good is the model when the event happens?</strong>&#8221; to &#8220;<strong>how likely is the event when the model fires?</strong>&#8221;</p><p>Formally, Bayes&#8217; rule gives:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(E \\mid S)\n= \\frac{P(S \\mid E)\\,P(E)}\n{P(S \\mid E)\\,P(E) + P(S \\mid \\bar E)\\,P(\\bar E)}\n\n&quot;,&quot;id&quot;:&quot;NEQBBOXFKA&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><div><hr></div><h2>4. Applying the formula</h2><p>We now substitute the values from the problem:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(E \\mid S)\n= \\frac{0.9 \\times 0.02}\n{0.9 \\times 0.02 + 0.12 \\times 0.98} = \\frac{0.018}{0.1356}\n\\approx 13.27\\%&quot;,&quot;id&quot;:&quot;FCCMDQXTDK&quot;}" data-component-name="LatexBlockToDOM"></div><p>The result is simple to interpret. Even with a <strong>high detection rate</strong> <strong>when the pattern is real</strong>, and a <strong>seemingly reasonable</strong> false positive rate, only about <strong>1 signal out of 7</strong> corresponds to a true pattern.</p><p>This outcome is not caused by a bad model. It is caused by the combination of:</p><ul><li><p>a <em><strong>low base rate</strong></em>,</p></li><li><p>and <em><strong>non-negligible false positives</strong></em>.</p></li></ul><p></p><p><strong>In the next newsletter</strong>, we will stop computing and start reasoning. We will vary the base rate, the false positive rate, and the detection rate, to understand <strong>which quantities truly matter</strong>, and which ones are often overemphasized.</p><p><em><strong>This is where Bayes becomes a practical trading reflex rather than a formula.</strong></em></p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p>]]></content:encoded></item><item><title><![CDATA[Bayes in Trading (1/3)]]></title><description><![CDATA[Rare events may not be your friend in trading...]]></description><link>https://www.newsletter.quantreo.com/p/bayes-in-trading-13</link><guid isPermaLink="false">https://www.newsletter.quantreo.com/p/bayes-in-trading-13</guid><dc:creator><![CDATA[Lucas]]></dc:creator><pubDate>Fri, 16 Jan 2026 15:30:34 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b2abd5d1-5339-4332-b7b6-c5ce54784238_764x406.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You often see trading or ML models online claiming <strong>90% accuracy</strong>. On common events, that can be meaningful. On <strong>rare events</strong>, it is often useless.</p><p>Many models try to predict chart patterns, breakouts, or specific market regimes that occur only a small fraction of the time. Even with very high conditional accuracy, these models can still lose money. Why?</p><p>Because accuracy is not the right question to ask. And <strong>Bayes explains exactly why</strong>.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.newsletter.quantreo.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 Quantreo! 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><div><hr></div><h2>1. A quick reminder on conditional probability</h2><p>A conditional probability answers a simple question:</p><blockquote><p><em>Given that A happened, how likely is B?</em></p></blockquote><p>In trading and machine learning, this often appears as:</p><blockquote><p><strong>P(Signal | Event)</strong><br>When the event truly occurs, how often does the model detect it?</p></blockquote><p>This is what most people mean when they talk about model accuracy.</p><p>The problem is that this is <strong>not</strong> the probability traders actually care about.</p><p>What matters in practice is the inverse question:</p><blockquote><p><strong>P(Event | Signal)</strong><br>When the model triggers a signal, how likely is it that the event is real?</p></blockquote><p>These two probabilities are not the same.<br>And when events are rare, the difference can be massive.</p><p>This inversion of perspective is exactly what Bayes forces you to confront.</p><p></p><div><hr></div><h2>2. Rare events break intuition</h2><p>Most trading signals are built to detect <strong>unusual situations</strong>.</p><p>Breakouts, chart patterns, volatility expansions, regime shifts. By definition, they do not happen often. This already changes how probabilities should be interpreted.</p><p>When an event is rare, the main risk is not missing it. The main risk is <strong>seeing it everywhere</strong>. A model can be very good at detecting the event <em>when it happens</em>,<br>and still generate mostly useless signals in practice.</p><p>This is not a modeling issue.<br>It is a <strong>base rate issue</strong>.</p><p></p><div><hr></div><h2>3. The wrong performance metric</h2><p>Most models are evaluated using metrics that answer the wrong question.</p><p>They focus on:</p><ul><li><p>Accuracy</p></li><li><p>Recall</p></li><li><p>Detection rate <em>when the event is present</em></p></li></ul><p>All of these describe <strong>P(Signal | Event)</strong>.</p><p></p><p>But trading performance depends on:</p><ul><li><p>How often you trade</p></li><li><p>How often those trades correspond to real opportunities</p></li><li><p>How much noise you are exposed to</p></li></ul><p>In other words, trading cares about <strong>P(Event | Signal)</strong>.</p><p>Bayes is simply the formal way of forcing this inversion.</p><p></p><div><hr></div><h2>4. Why this matters in practice</h2><p>When <strong>base rates are low</strong>, false positives dominate.</p><p>That leads to:</p><ul><li><p>Overtrading</p></li><li><p>Higher transaction costs</p></li><li><p>Unstable equity curves</p></li></ul><p>The model is not necessarily wrong. <strong>The interpretation is</strong>.</p><p></p><div><hr></div><h2>A concrete example</h2><p>Assume the following:</p><ul><li><p>A trading model detects a specific market pattern.</p></li><li><p>When the pattern truly occurs, the model is correct <strong>90% of the time</strong>.</p></li><li><p>The pattern itself occurs in only <strong>2% of market observations</strong>.</p></li><li><p>When the pattern is <strong>not</strong> present, the model still triggers a signal <strong>12% of the time</strong>.</p></li></ul><p></p><p><strong>Question</strong>: When the model triggers a signal, what is the probability that the pattern is actually real?</p><p>Answer: <strong>13,27%.</strong></p><p>&#8212;&gt; </p><p>With such a low signal reliability, an extremely high risk-reward ratio would be required just to break even.</p><p></p><p><em><strong>In the next newsletter, we will go through the exact calculations and show how these numbers combine, using Bayes, step by step.</strong></em></p><p>&#128073; If you want to go deeper into each step of the strategy building process, with real-life projects, ready-to-use templates, and 1:1 mentoring, that&#8217;s exactly what the <strong><a href="https://www.quantreo.com">Alpha Quant Program</a></strong> is for.</p><p></p>]]></content:encoded></item></channel></rss>