<?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[financialnoob: Vectorbt]]></title><description><![CDATA[Experiments with vectorbtpro]]></description><link>https://financialnoob.substack.com/s/vectorbt</link><image><url>https://substackcdn.com/image/fetch/$s_!y1jQ!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Ffinancialnoob.substack.com%2Fimg%2Fsubstack.png</url><title>financialnoob: Vectorbt</title><link>https://financialnoob.substack.com/s/vectorbt</link></image><generator>Substack</generator><lastBuildDate>Mon, 25 May 2026 14:38:15 GMT</lastBuildDate><atom:link href="https://financialnoob.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Alexander Pavlov]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[financialnoob@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[financialnoob@substack.com]]></itunes:email><itunes:name><![CDATA[Alexander Pavlov]]></itunes:name></itunes:owner><itunes:author><![CDATA[Alexander Pavlov]]></itunes:author><googleplay:owner><![CDATA[financialnoob@substack.com]]></googleplay:owner><googleplay:email><![CDATA[financialnoob@substack.com]]></googleplay:email><googleplay:author><![CDATA[Alexander Pavlov]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Trading Signal Analysis with Marimo and VectorBT Pro]]></title><description><![CDATA[Building an interactive dashboard for signal projection analysis]]></description><link>https://financialnoob.substack.com/p/trading-signal-analysis-with-marimo</link><guid isPermaLink="false">https://financialnoob.substack.com/p/trading-signal-analysis-with-marimo</guid><dc:creator><![CDATA[Alexander Pavlov]]></dc:creator><pubDate>Fri, 03 Apr 2026 22:22:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!UMxZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article I will describe how to build an interactive dashboard for signal analysis with Marimo and VectorBT Pro.</p><p>VectorBT Pro is a high performance backtesting and signal analysis library. It can process large amounts of data very quickly and has extensive built-in support for signal analysis, projections, and portfolio simulation &#8212; most of what we need for this dashboard is already implemented. Note that VectorBT Pro is a paid library &#8212; you can find pricing information on its <a href="https://vectorbt.pro">website</a>.</p><p>Marimo is a reactive python notebook where cells update automatically when their dependencies change. Compared to Jupyter, it has a better editor, is less prone to errors caused by running cells out of order, and its reactive model makes it a natural fit for interactive dashboards &#8212; changing a parameter instantly updates all dependent outputs without manually re-running anything. Marimo notebooks can also be run as standalone web apps using <code>marimo run</code>, which hides the code and presents only the outputs and interactive controls.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://financialnoob.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading financialnoob! 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><p>The notebook consists of several blocks, each with its own mini-dashboard and UI controls. Overall there are 5 blocks:</p><ul><li><p><strong>Signal Summary</strong> &#8212; shows basic trade statistics and UI controls for signal parameters.</p></li><li><p><strong>Projection Bands</strong> &#8212; shows how prices develop after entry, exit, and random signals, allowing us to compare them and see if the signal has any edge over a random baseline.</p></li><li><p><strong>Shrink vs Stretch</strong> &#8212; examines the role of exit timing by comparing price paths cut to a fixed length vs extended beyond the opposite signal.</p></li><li><p><strong>Random Projections</strong> &#8212; shows a random sample of individual price paths without quantile bands, allowing us to see actual projections rather than aggregated statistics.</p></li><li><p><strong>Portfolio Simulation</strong> &#8212; runs two portfolio simulations to confirm the findings from the previous blocks with actual performance metrics.</p></li></ul><div><hr></div><p>The notebook uses daily OHLCV data for 50 USDT pairs from Binance, provided in the corresponding <a href="https://github.com/financialnoob/vbt-experiments/blob/bb7d4083a8f3f88419f00fd8120fd8ff50f0512a/data.h5">github repository</a>. Trading signals are based on the RSI indicator, but the notebook can be easily adapted to analyze any other signals. The signals are calculated as follows:</p><ul><li><p>Entry signal is generated when RSI crosses above the entry threshold (oversold recovery).</p></li><li><p>Exit signal is generated when RSI crosses below the exit threshold (overbought recovery).</p></li></ul><p>Thus we have 3 signal parameters: time period used for calculating RSI, entry threshold, and exit threshold. The code below implements this: it calculates RSI using open prices to avoid look-ahead bias, generates raw entry and exit signals from crossovers, cleans them to ensure entries and exits alternate correctly, and runs a portfolio simulation.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python"># prepare indicator
rsi = vbt.talib("RSI").run(
    data.open, # use open prices to avoid look-ahead bias
    timeperiod=timeperiod.value, 
    hide_params=True
)

# generate signals
entries = rsi.rsi.vbt.crossed_above(entry_thr.value)
exits = rsi.rsi.vbt.crossed_below(exit_thr.value)

# clean signals
clean_entries, clean_exits = entries.vbt.signals.clean(exits)

# run portfolio simulation
pf = vbt.Portfolio.from_signals(
    data.close, 
    entries=clean_entries, 
    exits=clean_exits
)</code></pre></div><div><hr></div><p><strong>Signal Summary</strong></p><p>The first block consists of three components: signal description, signal parameters, and trade statistics. Each component is created separately and then assembled by stacking them horizontally or vertically using Marimo&#8217;s layout functions.</p><p>To visually separate the components I use two types of borders &#8212; an outer border around each block and an inner border around components within a block. Their parameters are defined once at the top of the notebook to avoid repetition:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">outer_border = {"border": "1px solid darkgray", "padding": "8px", 
                "border-radius": "8px", "height":"100%", "width":"100%"}
inner_border = {"border": "1px solid lightgray", "padding": "8px", 
                "height":"100%", "width":"100%"}
</code></pre></div><p>The final block is assembled with the following code:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">signal_summary_block = mo.hstack([
    mo.vstack([signal_descr, signal_params], align="center"),
    stats_block
], widths=[1,2], align="stretch").style({**outer_border})</code></pre></div><p>The resulting dashboard is shown below. It displays signal rules, adjustable parameters, and a trade statistics table side by side. Changing any of the signal parameters instantly updates the statistics and all other parts of the notebook. The next block takes advantage of this reactivity to explore how prices develop after each type of 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_!IVMv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IVMv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 424w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 848w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 1272w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IVMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png" width="1456" height="549" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:549,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:180480,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IVMv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 424w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 848w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 1272w, https://substackcdn.com/image/fetch/$s_!IVMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3647fe-43a0-4126-9043-d91cbbee0caa_2170x818.png 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><figcaption class="image-caption">Signal parameters and summary statistics</figcaption></figure></div><div><hr></div><p><strong>Projection Bands</strong></p><p>This block analyzes how prices develop after each type of signal. The main concept here is projections &#8212; normalized price paths of a fixed length starting from a signal. Each projection starts at 1 and shows how the price evolves over the next N bars relative to the signal point, making projections from different symbols and time periods directly comparable.</p><p>To generate projections we first create delta ranges &#8212; index ranges that start at each signal and end after a fixed number of bars. An example of delta ranges is shown below &#8212; you can see that each range starts at a signal and lasts for 7 days.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zkAj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zkAj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 424w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 848w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 1272w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zkAj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png" width="1456" height="663" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:663,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:232663,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!zkAj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 424w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 848w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 1272w, https://substackcdn.com/image/fetch/$s_!zkAj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f3f27d-e9e6-4770-bb8c-cc037267f4ac_2218x1010.png 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><figcaption class="image-caption">Entry Ranges</figcaption></figure></div><p>Delta ranges are then used to extract projections. An example of projections is shown below. All projections start at 1 and show normalized price development over the projection period.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WtVH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WtVH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 424w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 848w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 1272w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WtVH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png" width="1456" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:230613,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WtVH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 424w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 848w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 1272w, https://substackcdn.com/image/fetch/$s_!WtVH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F506ebbb7-4557-4bae-bfb7-d6b6f3d47a0a_2198x866.png 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>We can confirm this by looking at the first projection &#8212; it is indeed the normalized price of AAVEUSDT starting from 2024-04-15.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OCa7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OCa7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 424w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 848w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 1272w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OCa7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png" width="1456" height="509" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:509,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:165663,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!OCa7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 424w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 848w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 1272w, https://substackcdn.com/image/fetch/$s_!OCa7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba30ae05-ea13-4b6c-95d9-01d31b6212e9_2212x774.png 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>We generate projections for three signal types: entry, exit, and random. Random signals are generated using the same entry probability as real signals for each symbol, which ensures a fair comparison. The code for generating random signals is shown below.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python"># calculate entry probability per symbol
entry_probs = entries[~data.close.isna()].mean() # use only indeces with valid data
# generate random signals
rand_entries = vbt.pd_acc.signals.generate_random(
    clean_entries.vbt.wrapper, 
    prob=vbt.to_2d_pc_array(entry_probs.astype(float).values), 
    seed=42
)
# keep signals only at indices with valid data
rand_entries[data.close.isna()] = False</code></pre></div><p>Now we can calculate projections for all three signal types and build the dashboard.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;26997fc4-120e-4607-a59d-6060ab20c580&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">entry_ranges = clean_entries.vbt.signals.delta_ranges(proj_length.value, close=data.close)
entry_ranges = entry_ranges.status_closed
rand_ranges = rand_entries.vbt.signals.delta_ranges(proj_length.value, close=data.close)
rand_ranges = rand_ranges.status_closed
exit_ranges = clean_exits.vbt.signals.delta_ranges(proj_length.value, close=data.close)
exit_ranges = exit_ranges.status_closed

entry_projections = entry_ranges.get_projections()
rand_projections = rand_ranges.get_projections()
exit_projections = exit_ranges.get_projections()</code></pre></div><p>The block has four components: a description, a slider for controlling projection length, a chart showing 20/50/80 quantile bands for each signal type, and a table with summary statistics at the final bar.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Nb_p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nb_p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 424w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 848w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 1272w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nb_p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png" width="1456" height="1182" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1182,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:388927,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Nb_p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 424w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 848w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 1272w, https://substackcdn.com/image/fetch/$s_!Nb_p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33610974-e657-48b5-a44d-ccb234bef72c_2158x1752.png 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><figcaption class="image-caption">Projections Bands Block</figcaption></figure></div><p>Any group can be hidden by clicking on it in the legend. For example, looking at only entry and random projections, we can see that entry projections consistently outperform random in the lower and middle quantiles.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jOJC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jOJC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 424w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 848w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 1272w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jOJC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png" width="1456" height="524" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:524,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:159048,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c22cfa6-2fd7-400a-95d9-f311fe6fb186_2106x758.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!jOJC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 424w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 848w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 1272w, https://substackcdn.com/image/fetch/$s_!jOJC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bbf2bfc-d047-45be-adb9-209385558022_2106x758.png 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><figcaption class="image-caption">Entry and Random projections</figcaption></figure></div><p>The table confirms this &#8212; mean and median projection values are higher for entry signals than for random. The signal seems to have some edge, but so far we haven't taken exit signals into account. The next block does that by looking at what happens between consecutive signals.</p><div><hr></div><p><strong>Shrink vs Stretch</strong></p><p>This block uses a different approach to generating projections. Instead of fixed-length delta ranges, we use <code>between_ranges </code>- ranges that span from one signal to the opposite signal. This gives us two types of projections: entry&#8594;exit (price path of a long trade) and exit&#8594;entry (price path between closing one trade and opening the next). Exit&#8594;entry projections would correspond to short trades if we traded both directions.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python"># trade ranges: entry-&gt;exit and exit-&gt;entry
entry_exit_ranges = clean_entries.vbt.signals.between_ranges(clean_exits, close=data.close).status_closed
exit_entry_ranges = clean_exits.vbt.signals.between_ranges(clean_entries, close=data.close).status_closed

# trade projections
entry_exit_projections = entry_exit_ranges.get_projections()
exit_entry_projections = exit_entry_ranges.get_projections()</code></pre></div><p>Unlike delta ranges, these projections have varying lengths since trades have different durations. Because shorter projections are padded with NaNs beyond their end point, and shorter trades are more common than longer ones, the bands at later bars are calculated from fewer observations. Vectorbt provides two ways to work with such non-uniform projections &#8212; shrinking and stretching. Shrinking trims projections to a fixed number of bars, letting you focus on what happens in the first N bars regardless of trade length. Stretching extends shorter projections beyond the opposite signal &#8212; effectively asking: what would have happened if we hadn't exited?</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">shrink_entry_proj = entry_exit_ranges.get_projections(proj_period=proj_period.value)
stretch_entry_proj = entry_exit_ranges.get_projections(proj_period=proj_period.value, extend=True)

shrink_exit_proj = exit_entry_ranges.get_projections(proj_period=proj_period.value)
stretch_exit_proj = exit_entry_ranges.get_projections(proj_period=proj_period.value, extend=True)</code></pre></div><p>The key insight is what stretching reveals. If stretched projections perform better than shrunk ones, it means the price continued moving favorably after the exit signal &#8212; in other words, the exits are hurting performance rather than helping it.</p><p>The plot for this block shows shrunk and stretched projections side by side with adjustable quantile bands. There are two tabs &#8212; one for entry&#8594;exit and one for exit&#8594;entry projections. By default the lower and upper bands are set to 0.2 and 0.8, meaning the bands cover 60% of all projections. The quantile controls let you adjust this range depending on how much of the distribution you want to see. They are created with marimo&#8217;s number inputs and stacked horizontally:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;97274e0e-aac3-40a9-bb2f-208f036c48ec&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">proj_period = mo.ui.number(value=7, start=5, stop=200, step=1, label=&#8221;proj_period&#8221;)
lower_qq = mo.ui.number(value=0.2, start=0.01, stop=0.5, step=0.01, label=&#8221;lower_qq&#8221;)
upper_qq = mo.ui.number(value=0.8, start=0.5, stop=0.99, step=0.01, label=&#8221;upper_qq&#8221;)
controls = mo.hstack([proj_period, lower_qq, upper_qq]).style({**inner_border})
</code></pre></div><p>The plotting function creates a two-panel subplot using vectorbt's <code>make_subplots</code> and wraps the result in a marimo plotly element:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def shrink_stretch_plot(shrink_proj, stretch_proj, lower_qq, upper_qq):
    fig = vbt.make_subplots(rows=1, cols=2, shared_yaxes=True, subplot_titles=["Shrink", "Stretch"])
    shrink_proj.vbt.plot_projections(
        plot_lower=f"Q={lower_qq}",
        plot_upper=f"Q={upper_qq}",
        plot_projections=False, 
        add_trace_kwargs=dict(row=1, col=1), 
        fig=fig, 
    )
    stretch_proj.vbt.plot_projections(
        plot_lower=f"Q={lower_qq}",
        plot_upper=f"Q={upper_qq}",
        plot_projections=False,
        add_trace_kwargs=dict(row=1, col=2), 
        fig=fig, 
    )
    fig.update_layout(
        template="plotly_white", 
        width=None, 
        autosize=True, 
        showlegend=False, 
        yaxis_showticklabels=True, 
        yaxis2_showticklabels=True
    )
    return mo.ui.plotly(fig)</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_!j5cT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j5cT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 424w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 848w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 1272w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j5cT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png" width="1456" height="803" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:803,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:228711,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!j5cT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 424w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 848w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 1272w, https://substackcdn.com/image/fetch/$s_!j5cT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e30ad06-eb49-4d7e-b9c9-bf39be1a94a7_2150x1186.png 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><figcaption class="image-caption">Shrink vs Stretch Entry&#8594;Exit Projections</figcaption></figure></div><p>Looking at the entry&#8594;exit plot, we can see that stretched projections perform better than shrunk ones. Since stretching extends the price path beyond the exit signal, this means prices continued rising after we exited &#8212; our exits are cutting trades short and reducing performance.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FeaX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FeaX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 424w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 848w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 1272w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FeaX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png" width="1456" height="804" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:804,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:222089,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FeaX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 424w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 848w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 1272w, https://substackcdn.com/image/fetch/$s_!FeaX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e2b285-41ac-4deb-a79d-cd72e1e24776_2154x1190.png 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><figcaption class="image-caption">Shrink vs Stretch Exit&#8594;Entry Projections</figcaption></figure></div><p>The exit&#8594;entry plot tells a different story. Here shrunk projections perform better, and prices tend to rise rather than fall after exit signals. This means exit&#8594;entry ranges are not good candidates for short trades, but they may actually be better candidates for long trades than the original entry&#8594;exit trades. The next block lets us look at individual projections to see whether these patterns hold consistently across different samples.</p><div><hr></div><p><strong>Random Projections</strong></p><p>This block shows individual price paths rather than aggregated quantile bands. Plotting all projections at once would be too slow and hard to read, so instead we randomly sample 20 of them. Entry&#8594;exit and exit&#8594;entry projections are shown side by side, and pressing the refresh button draws a new random sample. The function for sampling and plotting random projections is straightforward:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;b5b01f4f-3a58-4276-a205-2cda182dd208&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def plot_rand_proj(proj, n=20):
    rand_cols = np.random.choice(proj.shape[1], n, replace=False)
    fig = proj.iloc[:, rand_cols].vbt.plot_projections(plot_bands=False)
    fig.update_layout(
        template=&#8221;plotly_white&#8221;, 
        width=None, 
        autosize=True, 
        showlegend=False
    )
    return mo.ui.plotly(fig)</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_!UMxZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UMxZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 424w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 848w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 1272w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UMxZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png" width="1456" height="780" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:780,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:311287,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!UMxZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 424w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 848w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 1272w, https://substackcdn.com/image/fetch/$s_!UMxZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5412f36e-3242-4461-b9d0-de2e509aa265_2164x1160.png 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><figcaption class="image-caption">Random Projections Block</figcaption></figure></div><p>As noted in the vectorbt&#8217;s projections tutorial, repeatedly refreshing and looking at different samples is itself a form of validation &#8212; if the patterns we observed in the previous block are real, they should appear consistently across different samples. In this case, exit&#8594;entry projections do tend to show more upward movement than entry&#8594;exit projections, which is consistent with our earlier findings. To confirm this with actual numbers, we run two portfolio simulations.</p><div><hr></div><p><strong>Portfolio Simulation</strong></p><p>The last block runs two portfolio simulations to confirm what we observed in the previous blocks. The first portfolio trades entry&#8594;exit signals as usual. The second swaps them &#8212; it enters at exit signals and exits at entry signals, effectively treating exit&#8594;entry ranges as long trades.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">pf_en = vbt.Portfolio.from_signals(
    data.close, 
    entries=clean_entries, 
    exits=clean_exits
)

pf_ex = vbt.Portfolio.from_signals(
    data.close, 
    entries=clean_exits, 
    exits=clean_entries
)</code></pre></div><p>Each symbol is simulated separately. Calling <code>stats()</code> without arguments aggregates results by taking the mean across all symbols. To also see median statistics we call <code>stats(agg_func=None)</code> which returns per-symbol stats, and then take the median manually. Both are displayed in a tabbed interface so they can be compared easily. </p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">
pf_stats_mean = pd.DataFrame(columns=["entry_exit", "exit_entry"])
pf_stats_mean["entry_exit"] = pf_en.stats()
pf_stats_mean["exit_entry"] = pf_ex.stats()

pf_stats_median = pd.DataFrame(columns=["entry_exit", "exit_entry"])
pf_stats_median["entry_exit"] = pf_en.stats(agg_func=None).median()
pf_stats_median["exit_entry"] = pf_ex.stats(agg_func=None).median()

mo.ui.tabs({
    "mean": mo.ui.table(pf_stats_mean, pagination=False, selection=None),
    "median": mo.ui.table(pf_stats_median, pagination=False, selection=None)
}).style(**outer_border)</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_!fQIk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fQIk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 424w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 848w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 1272w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fQIk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png" width="1456" height="1282" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1282,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:414753,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://financialnoob.substack.com/i/186709328?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fQIk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 424w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 848w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 1272w, https://substackcdn.com/image/fetch/$s_!fQIk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64424b2-2832-4be8-b609-d09e2e2d78aa_2160x1902.png 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><figcaption class="image-caption">Aggregate Portfolio Statistics (median)</figcaption></figure></div><p>Let's take a look at the median aggregate statistics shown on the screenshot above. Both strategies have similar Sharpe and Sortino ratios, but entry_exit has higher expectancy and a much higher win rate (67% vs 29%). The key difference is trade duration &#8212; exit_entry wins less often but winning trades last much longer (83 days on average vs 32 days), while losing trades are shorter. This suggests that exit signals are not clearly harmful, but the two strategies behave very differently in terms of trade structure.</p><div><hr></div><p>The dashboard we developed makes signal analysis much more interactive than a static notebook. Instead of manually regenerating plots for each parameter combination, the UI controls let you explore any combination instantly &#8212; changing the RSI period, thresholds, or projection length updates all blocks at once. The modular block structure also means each block can be reused in other dashboards with minimal changes.</p><p>In the following articles I will build more interactive dashboards covering other aspects of trading signal analysis and introduce more vectorbt features along the way.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://financialnoob.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading financialnoob! 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><p>Marimo notebook with source code is available <a href="https://github.com/financialnoob/vbt-experiments/blob/main/1.intro_signals_dashboard/intro_signal_dashboard.py">here</a>. A non-reactive version of the notebook is also available <a href="https://static.marimo.app/static/intro-signal-dashboard-45lw">here</a>.</p><p>If you have any questions, suggestions or corrections please post them in the comments. Thanks for reading.</p><div><hr></div>]]></content:encoded></item></channel></rss>