<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Okeke Jenny</title>
    <description>The latest articles on DEV Community by Okeke Jenny (@elitepropx).</description>
    <link>https://dev.to/elitepropx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4146774%2F8417bc66-3280-4a43-b614-4965407e6b53.png</url>
      <title>DEV Community: Okeke Jenny</title>
      <link>https://dev.to/elitepropx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elitepropx"/>
    <language>en</language>
    <item>
      <title>VPS latency is a trading rule, not an infrastructure detail</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 18:34:31 +0000</pubDate>
      <link>https://dev.to/elitepropx/vps-latency-is-a-trading-rule-not-an-infrastructure-detail-4gm0</link>
      <guid>https://dev.to/elitepropx/vps-latency-is-a-trading-rule-not-an-infrastructure-detail-4gm0</guid>
      <description>&lt;p&gt;The connection between your trading terminal and the broker's server is usually filed under "infrastructure". On a prop firm evaluation it is a rule, because several of the rules that end accounts are enforced on &lt;em&gt;time&lt;/em&gt; rather than on price. A stop that triggers on your chart and a stop that triggers on the firm's server are two different events, and latency is the distance between them.&lt;/p&gt;

&lt;p&gt;This is worth taking seriously because the failure it produces is invisible in a backtest and looks like bad luck in a journal: the price never touched your stop, yet you were stopped out; or the daily loss limit fired and the loss you see is larger than the loss you sized.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three rules that are actually clocks
&lt;/h2&gt;

&lt;p&gt;Almost every drawdown rule that causes a surprise has a time component:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The daily loss limit reset.&lt;/strong&gt; It resets at a fixed server time — often the firm's midnight, sometimes the market's daily close in a specific timezone. The exact instant your "day" starts and ends is a server-defined boundary, not the one on your wall clock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The news window.&lt;/strong&gt; Restrictions on opening or holding positions are defined as intervals around an event (e.g. "two minutes either side of a high-impact release"). The window is measured on the server's clock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The maximum trade duration / overnight cutoff.&lt;/strong&gt; Some programmes require positions to be closed within a session or before a cutoff time. The cutoff is a server timestamp.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your terminal's clock, your VPS's clock and the broker's clock disagree, a trade you believe is inside the window can be outside it — and there is no "close enough". The rule evaluates a timestamp.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a home connection is the wrong reference
&lt;/h2&gt;

&lt;p&gt;Two distinct problems, and it is worth separating them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency.&lt;/strong&gt; The round-trip time between your terminal and the server. On a routed home connection in a different region this can be tens of milliseconds with high variance. That variance is the issue, not the absolute number: a variable delay means a stop order that arrives late by exactly the amount the price moved in that window, which on a fast instrument during a release can be the difference between a $200 loss and a $600 one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timing.&lt;/strong&gt; Most prop-firm rule enforcement happens server-side, so latency does not change &lt;em&gt;whether&lt;/em&gt; the rule fired — it changes the price at which your order filled relative to the trigger. But a home connection with an unstable clock can also change what your terminal &lt;em&gt;thinks&lt;/em&gt; the time is, which matters for a manual decision near a cutoff.&lt;/p&gt;

&lt;p&gt;A VPS fixes both by placing the client in the same datacentre region as the broker, cutting round-trip time to single-digit milliseconds and removing the domestic-connection jitter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The arithmetic of a late fill
&lt;/h2&gt;

&lt;p&gt;The reason this matters to the account rather than to comfort is that the loss from a late fill is proportional to size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extra loss = slippage_per_unit × size (in units)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a scenario: during a news release, price moves 8 pips in the 40 ms between your stop triggering and your order reaching the server under a home connection, versus 1 pip on a co-located VPS. On a position where one pip is worth $10:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home connection: 8 pips × $10 = &lt;strong&gt;$80 of slippage&lt;/strong&gt; on that single exit.&lt;/li&gt;
&lt;li&gt;Co-located VPS: 1 pip × $10 = &lt;strong&gt;$10&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither fills at the stop price, so both are worse than the chart suggests. The difference is $70 on one trade. Repeat it across a strategy that exits several times a day and the VPS is not a luxury — it is a direct reduction in the slippage that eats into a drawdown budget already measured in dollars.&lt;/p&gt;

&lt;p&gt;The second-order effect is worse. A stop that fills 8 pips late is 8 pips closer to the floor than planned, and the trader's sizing assumed the &lt;em&gt;planned&lt;/em&gt; stop. The trade was correctly sized for one loss and delivered a larger one. Over a series, that drift is exactly what "my account died earlier than my backtest" looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the firms require
&lt;/h2&gt;

&lt;p&gt;Many firms make a VPS mandatory for automated trading (EAs and bots), for two reasons: to keep the strategy's latency predictable, and to satisfy the firm's own requirement that the client runs continuously. The requirement is usually stated in the automated-trading or technical section of the rules rather than on the pricing page, which is why it surprises traders who read only the marketing.&lt;/p&gt;

&lt;p&gt;The practical checklist before running anything automated on an evaluation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Location.&lt;/strong&gt; The VPS region should match the broker's server region. Latency is a function of geography, not of how much RAM you bought.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always-on.&lt;/strong&gt; The client must not sleep. A dropped connection during an open position is a rule risk (some firms treat a dropped EA as a violation).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clock sync.&lt;/strong&gt; NTP synchronisation, so the terminal's timestamps agree with the server's for window-based rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standby power and redundancy.&lt;/strong&gt; A VPS that reboots on the daily boundary can miss the cutoff. The failure mode is a position held through a window that should have been closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to do this week
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure your actual round-trip latency&lt;/strong&gt; to the broker's server, not to a generic internet host, and note the &lt;em&gt;variance&lt;/em&gt; over a session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find the firm's reset time and news windows in server time&lt;/strong&gt;, and convert them into the timezone your terminal displays. Put the conversions on the chart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price the slippage you are currently paying.&lt;/strong&gt; If it is a meaningful fraction of your daily drawdown allowance, co-location pays for itself faster than any strategy tweak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size from the realistic stop, not the ideal one.&lt;/strong&gt; If you know your exits slip, the budget should include the slip.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this is alpha. It is the difference between a rule that fires on the server at the moment it is written to fire and a rule that fires on your side of the connection at a moment you did not choose. On an account whose entire margin is a few thousand dollars of drawdown, that difference is not infrastructure — it is risk.&lt;/p&gt;

&lt;p&gt;The practical setup — which programmes require a VPS, what region to pick for each broker, and how the timing rules are written — is in the &lt;a href="https://elitepropx.com/blog/prop-firm-vps-requirements.html" rel="noopener noreferrer"&gt;VPS requirements breakdown&lt;/a&gt;. If you would rather model the cost of slippage on your own sizing before choosing, the &lt;a href="https://elitepropx.com/tools/prop-firm-profit-calculator.html" rel="noopener noreferrer"&gt;prop firm profit calculator&lt;/a&gt; works in the same account currency.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>javascript</category>
      <category>finance</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Multiple funded accounts are one position, not several</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 18:33:55 +0000</pubDate>
      <link>https://dev.to/elitepropx/multiple-funded-accounts-are-one-position-not-several-377c</link>
      <guid>https://dev.to/elitepropx/multiple-funded-accounts-are-one-position-not-several-377c</guid>
      <description>&lt;p&gt;A trader runs three funded accounts at the same firm, same instrument, same strategy, and treats them as three independent shots at a payout. Then a single bad session takes all three at once. The accounts were not three positions. They were one position, tripled, with three drawdown floors reporting the same loss.&lt;/p&gt;

&lt;p&gt;The diversification a trader thinks they own from multiple accounts is a function of &lt;em&gt;correlation between the account strategies&lt;/em&gt;, not the number of accounts. Getting this wrong is one of the most expensive modelling errors available, because it converts what looks like risk reduction into concentrated risk with three times the fee surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the independence assumption is so tempting
&lt;/h2&gt;

&lt;p&gt;Three accounts feels safer than one for an obvious reason: three floors means three separate opportunities for at least one to survive. That intuition is correct &lt;em&gt;if the strategies are independent&lt;/em&gt;. The arithmetic is the same as any portfolio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One account, probability of breach on a given day: &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Three accounts, probability that &lt;em&gt;all&lt;/em&gt; breach on a given day: &lt;code&gt;p³&lt;/code&gt; (if independent).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At &lt;code&gt;p = 0.2&lt;/code&gt;, that is 0.8% — reassuring. But the same three accounts trading the &lt;em&gt;same strategy on the same instrument in the same session&lt;/em&gt; have correlated daily returns. In the limit of perfect correlation, all three breach together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Three perfectly correlated accounts, probability all breach: &lt;code&gt;p&lt;/code&gt; = 20%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two scenarios have identical account counts and identical per-account risk. They differ only in correlation, and the difference in joint-breach probability is a factor of twenty-five.&lt;/p&gt;

&lt;p&gt;That is the whole point: &lt;strong&gt;accounts are not the unit of diversification; strategies are.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the correlation actually comes from
&lt;/h2&gt;

&lt;p&gt;It is worth naming the sources, because they are all avoidable and none of them is visible on a dashboard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Same instrument, same direction.&lt;/strong&gt; Two accounts long the same index in the same session is one bet, expressed twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same strategy, same signals.&lt;/strong&gt; A mean-reversion system run on three accounts generates the same entries. The trades are duplicates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same session.&lt;/strong&gt; Two different edges traded in the same overlapping hours share the market regime, and regimes are the dominant risk factor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same firm's shared constraint.&lt;/strong&gt; If the firm applies a portfolio-level or per-trader rule, three accounts at one firm are not even independent at the &lt;em&gt;rule&lt;/em&gt; level.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only the first is obvious. The second and third are the ones that actually bite, because a trader running a breakout strategy on three accounts in the same 90-minute window is, mechanically, running one breakout strategy at triple size.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurable version
&lt;/h2&gt;

&lt;p&gt;If you keep trade logs per account, the correlation is computable and it is not hard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pearson correlation of daily returns between two accounts.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;corr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;da&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;mb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;xa&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;xb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;da&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;xa&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;xa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;xb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;xb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;da&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it on the daily P&amp;amp;L of account A against account B. A value near &lt;code&gt;1.0&lt;/code&gt; means the two accounts are one position. A value near &lt;code&gt;0&lt;/code&gt; means the second account is genuinely diversifying. Most "multiple accounts" setups measure above 0.8, which is why the downside arrives correlated even when the accounts look independent on paper.&lt;/p&gt;

&lt;p&gt;For more than two accounts, the object you want is the correlation matrix, and the useful summary is its largest eigenvalue: if one factor explains most of the variance, you have one strategy wearing several hats.&lt;/p&gt;

&lt;h2&gt;
  
  
  The consequences for drawdown
&lt;/h2&gt;

&lt;p&gt;Correlation does not just change the probability of a joint breach. It changes the &lt;em&gt;shape&lt;/em&gt; of the loss you have to survive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Independent accounts:&lt;/strong&gt; losses arrive at different times. One account can be funded and paying while another is recovering. The equity curve of the &lt;em&gt;portfolio of accounts&lt;/em&gt; is smooth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correlated accounts:&lt;/strong&gt; losses arrive together. Every account is down on the same day, against floors that are all measured from peaks that all rose together. The worst day in one account is the worst day in all of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because drawdown is a function of the worst &lt;em&gt;path&lt;/em&gt;, not the average, correlated accounts concentrate exactly the event that ends them. The trailing-floor mechanic makes this worse: a good run raises all three floors simultaneously, so all three accounts are at maximum vulnerability at the same moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do about it
&lt;/h2&gt;

&lt;p&gt;None of this means multiple accounts are a mistake. It means the diversification has to be engineered rather than assumed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure the correlation before adding the third account.&lt;/strong&gt; Two accounts at 0.9 are one account with double fees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diversify the &lt;em&gt;strategy family&lt;/em&gt;, not the instrument.&lt;/strong&gt; Two correlated instruments (an index and its futures) are not diversifying; an intraday momentum system and an overnight mean-reversion system may be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stagger the session, not just the signal.&lt;/strong&gt; If both accounts trade the same hours, they share the regime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the firm's portfolio-level rules.&lt;/strong&gt; Some firms cap aggregate risk across a trader's accounts, which makes the accounts correlated by policy regardless of strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reserve the uncorrelated account for the worst day.&lt;/strong&gt; The value of the second account is highest when it is the one &lt;em&gt;not&lt;/em&gt; in the drawdown. That only happens if it holds a different bet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A funded account is a small business with a hard floor. Running three of them is running three businesses — and three businesses selling the same thing in the same market on the same day are one business with three sets of overheads. Correlation is the number that tells you which you have.&lt;/p&gt;

&lt;p&gt;The practical firm-level detail — per-trader account caps, whether one firm's accounts share a risk limit, and how the rules treat multiple accounts at the same or different firms — is in the &lt;a href="https://elitepropx.com/blog/multiple-accounts-one-prop-firm.html" rel="noopener noreferrer"&gt;multiple accounts at one firm breakdown&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>statistics</category>
      <category>finance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Weekend holding: what an overnight gap does to a funded account</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 18:33:20 +0000</pubDate>
      <link>https://dev.to/elitepropx/weekend-holding-what-an-overnight-gap-does-to-a-funded-account-4pdl</link>
      <guid>https://dev.to/elitepropx/weekend-holding-what-an-overnight-gap-does-to-a-funded-account-4pdl</guid>
      <description>&lt;p&gt;Here is a rule that costs more accounts than almost any other and gets discussed the least: what happens to an open position between Friday's close and Monday's open. Many prop firms restrict or forbid holding across the weekend. The restriction is easy to read and easy to ignore, because a backtest rarely tells you it exists — and because the strategy that violates it often looks &lt;em&gt;better&lt;/em&gt; than one that respects it.&lt;/p&gt;

&lt;p&gt;This is about the gap: why overnight and weekend exposure is a different instrument from intraday exposure, and how to decide whether your edge can live inside the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap is not a bigger candle
&lt;/h2&gt;

&lt;p&gt;An overnight gap is a discontinuity, and discontinuity behaves differently from volatility in one specific way: it cannot be stopped out at a price.&lt;/p&gt;

&lt;p&gt;Consider a long on an instrument that closes at $1.0000 on Friday. Over a weekend, news moves the open to $0.9800 on Sunday night. A stop at $0.9950 did not get you out at $0.9950. It got you out at the first available price, which is $0.9800 — 150 pips below your intended exit, on a single bar, with no chance to react.&lt;/p&gt;

&lt;p&gt;That difference matters most in exactly the situation a funded account is most vulnerable: right after a good run. A trader who is up $6,000 on a $50,000 account with a $2,500 trailing floor has a floor that has climbed to $53,500. A weekend gap of 180 pips on a size that translates to 3% of the account is not a loss on the weekend. It is a &lt;strong&gt;hard breach at the open&lt;/strong&gt;, before the first trade of the new week.&lt;/p&gt;

&lt;p&gt;The gap did not exceed the drawdown. It exceeded the &lt;em&gt;stops&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the rule exists at the firm
&lt;/h2&gt;

&lt;p&gt;Two reasons, and it is worth understanding both because they shape how tightly firms enforce it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Risk control across the book.&lt;/strong&gt; A firm holding hundreds of accounts cannot hedge a shared directional exposure that every account carries into a weekend. Forbidding the hold removes a correlated tail risk from the entire portfolio at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accountability for the gap.&lt;/strong&gt; A gap is un-hedgeable and uncontrollable, which makes it the worst possible event for a firm that has to defend a maximum drawdown. It is the one loss that cannot be managed by skill, so the rule removes it by construction.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is why the rule is usually a hard restriction with no fee-based workaround, unlike a daily-loss soft breach. Firms are not selling you a product you can pay to keep; they are removing an unmanageable risk from their book.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two shapes of the rule
&lt;/h2&gt;

&lt;p&gt;"Don't hold over the weekend" is written in at least three different ways, and they are not equivalent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No positions held through Friday's close.&lt;/strong&gt; You must be flat before the close. The strictest form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No positions opened within a window before the close.&lt;/strong&gt; You may hold a position opened earlier, but cannot add near the close. This is a hedging of the same risk, and it interacts with your entry timing rather than your holding policy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instrument-specific.&lt;/strong&gt; Some firms ban weekend holds on indices and FX but allow them on others, or vice versa. The restriction is in the instrument list, not the general rulebook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assume the strictest interpretation until you have read the firm's specific account-type rules. A general marketing page saying "swing trading allowed" frequently refers to the &lt;em&gt;funded&lt;/em&gt; account, not the evaluation, or to a specific programme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is your edge actually a gap edge?
&lt;/h2&gt;

&lt;p&gt;The question that decides everything: strip the overnight moves out of your backtest and look at what is left.&lt;/p&gt;

&lt;p&gt;A quick way to do it — recompute the strategy using only the intraday path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Does the edge survive without the gap?&lt;/span&gt;
&lt;span class="c1"&gt;// Take the same signals, but close the position before the session ends&lt;/span&gt;
&lt;span class="c1"&gt;// and re-enter at the next open instead of holding through it.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withoutGaps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Replace the overnight return with zero: the position is flat across the gap.&lt;/span&gt;
    &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pnlIntraday&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withGaps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pnlIntraday&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overnight&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the difference between &lt;code&gt;withGaps&lt;/code&gt; and &lt;code&gt;withoutGaps&lt;/code&gt; is most of the strategy's total return, the edge lives in the gap. That is not a flaw in the strategy — it is information. It means the strategy is incompatible with any firm that forbids the hold, and the correct response is to filter the firm list by that constraint &lt;em&gt;before&lt;/em&gt; comparing anything else, not to try to trade it anyway.&lt;/p&gt;

&lt;p&gt;If the difference is small, the strategy has an intraday core and the overnight component is noise. In that case the rule costs you little and you can ignore it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode to guard against
&lt;/h2&gt;

&lt;p&gt;The dangerous version of this is a trader who knows the rule, believes the overnight component is small, and is wrong — because the backtest understated it. Backtests frequently misprice overnight exposure in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They fill at the close rather than the open, silently avoiding the gap.&lt;/li&gt;
&lt;li&gt;They assume the stop was honoured at its price on the gap bar.&lt;/li&gt;
&lt;li&gt;They use continuous synthetic bars that do not have gaps at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those turns a real weekend risk into a modelled non-event. The fix is to reconstruct the strategy on actual session-boundary data, with the open price as the only fill available after a gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to write down
&lt;/h2&gt;

&lt;p&gt;Before buying any evaluation, three numbers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The rule, in the firm's exact wording.&lt;/strong&gt; Which instruments, which programme, which account type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The overnight share of your edge.&lt;/strong&gt; The &lt;code&gt;withGaps&lt;/code&gt; minus &lt;code&gt;withoutGaps&lt;/code&gt; difference, as a fraction of total P&amp;amp;L.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gap risk in account currency.&lt;/strong&gt; The worst historical weekend gap in your instrument, times your typical size — expressed in the drawdown's units, not pips.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If (2) is large, the rule is disqualifying for that firm and no sizing fixes it. If (3) is large relative to your remaining room, the same is true even for a small gap edge. The rule is not a formality you sign past; it is a constraint that eliminates some strategies and some firms, and the arithmetic that decides which is short and knowable in advance.&lt;/p&gt;

&lt;p&gt;The firm-by-firm version of the rule — which programmes permit weekend holds, which ban them outright, and where the instruments differ — is in the &lt;a href="https://elitepropx.com/blog/prop-firm-weekend-holding-rules.html" rel="noopener noreferrer"&gt;weekend holding rules breakdown&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>javascript</category>
      <category>finance</category>
      <category>statistics</category>
    </item>
    <item>
      <title>A soft breach and a hard breach are different failures</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 18:32:44 +0000</pubDate>
      <link>https://dev.to/elitepropx/a-soft-breach-and-a-hard-breach-are-different-failures-9g1</link>
      <guid>https://dev.to/elitepropx/a-soft-breach-and-a-hard-breach-are-different-failures-9g1</guid>
      <description>&lt;p&gt;Two traders each lose an evaluation. One is told their account is closed with a balance of $96,000 on a $100,000 starting account with a $10,000 drawdown. The other is told their account is "soft breached" and they may continue for a fee. Both headlines say "failed". They are not the same event, and the difference decides whether you have any money left to attack the problem with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the two
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;hard breach&lt;/strong&gt; is a terminal event. Equity touches the floor — the maximum drawdown level, or the daily loss limit measured intraday. The account is closed, the evaluation is over, and nothing you do afterwards matters for that account.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;soft breach&lt;/strong&gt; (sometimes called a &lt;em&gt;warning&lt;/em&gt;, &lt;em&gt;violation&lt;/em&gt;, or &lt;em&gt;soft breach fee&lt;/em&gt;) is a non-terminal violation. The firm flags a rule that was bent — most often the daily loss limit, a news window, or an overnight hold — and offers to continue the account for a fee, or takes a slice of the eventual profit, without closing it outright.&lt;/p&gt;

&lt;p&gt;The distinction sounds procedural. It is actually structural, because the two events leave you in different states:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Hard breach&lt;/th&gt;
&lt;th&gt;Soft breach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Account state&lt;/td&gt;
&lt;td&gt;Closed&lt;/td&gt;
&lt;td&gt;Continues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Full evaluation fee, again&lt;/td&gt;
&lt;td&gt;A fee, or a profit haircut&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trader's equity&lt;/td&gt;
&lt;td&gt;Zero (of that attempt)&lt;/td&gt;
&lt;td&gt;Preserved or partially preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optionality&lt;/td&gt;
&lt;td&gt;Buy a new attempt&lt;/td&gt;
&lt;td&gt;Keep the existing one&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two attempts that both read "failed" in a statistics table are, in this framing, a total loss and a discounted continuation. Averaging them into one failure rate destroys exactly the information that would help a trader.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanic that makes soft breaches dangerous
&lt;/h2&gt;

&lt;p&gt;The trap is that a soft breach looks like a reprieve and behaves like a debt.&lt;/p&gt;

&lt;p&gt;Suppose the daily loss limit on a $100,000 account is 5%, and you breach it by $400 — you lose $5,400 on a day whose limit was $5,000. A soft-breach rulebook may let you continue for a $150 fee. The account survives. But consider what you have just bought:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You are now $5,400 below the day's starting equity, and that loss is real. The profit target, measured from the starting balance, has grown by $5,400.&lt;/li&gt;
&lt;li&gt;If the drawdown trails, your peak has not moved but your equity has — so your room to the floor is now smaller than it was.&lt;/li&gt;
&lt;li&gt;You have paid a fee to hold an account that is materially harder to pass than a fresh one at the same price.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the arithmetic, a soft breach is not "get out of jail free". It is a new attempt bought at a discount, and the discount is paid for by carrying a loss that the fresh attempt does not have. If a fresh evaluation costs $500 and a soft-breach continuation costs $150, the comparison is not $150 versus $500 — it is $150-plus-a-$5,400-deficit versus $500 on a level field.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a soft breach is genuinely worth taking
&lt;/h2&gt;

&lt;p&gt;The continuation is worth it when the violation is &lt;em&gt;accounting-shaped&lt;/em&gt; rather than &lt;em&gt;equity-shaped&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A news-window violation&lt;/strong&gt; where the position was profitable and the loss is zero. You have a procedural mark against you but your equity curve is intact. Continuing is close to free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A minimum-day or hold-time violation&lt;/strong&gt; that cost nothing in P&amp;amp;L. Same logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A daily-loss breach on a day that closed well above the floor.&lt;/strong&gt; Here the loss is real but small relative to the remaining room, and the fee is cheaper than a reset.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is &lt;em&gt;not&lt;/em&gt; worth it when the loss that triggered the breach has eaten a large fraction of the remaining drawdown. At that point you are paying to trade a smaller, harder account than the one you could buy fresh.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision rule
&lt;/h2&gt;

&lt;p&gt;Write two numbers before you decide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remaining room&lt;/strong&gt; = current equity − current floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effective cost&lt;/strong&gt; = continuation fee + the loss you are carrying.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If &lt;code&gt;effective cost&lt;/code&gt; is below a fresh evaluation fee &lt;em&gt;and&lt;/em&gt; your remaining room is at least, say, seventy percent of the original budget, continue. If the breach consumed your room, the continuation is a worse product than a reset even when its sticker price is lower.&lt;/p&gt;

&lt;p&gt;The reason traders get this wrong is that they compare sticker prices, not states. The fresh account is often the cheaper instrument precisely because it is the only one that arrives with a full drawdown budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for the failure statistic
&lt;/h2&gt;

&lt;p&gt;If you are trying to build a real model of challenge difficulty, a single binary "passed/failed" output is the wrong data model. The correct one has at least three states — &lt;code&gt;PASSED&lt;/code&gt;, &lt;code&gt;HARD_BREACH&lt;/code&gt;, &lt;code&gt;SOFT_BREACH&lt;/code&gt; — plus a cost field, because a soft breach that costs $150 on an intact curve and one that costs $150 on a drained curve are different events with the same label.&lt;/p&gt;

&lt;p&gt;The simulator trap is identical to the one that catches drawdown models: if your state machine can only express "the account ended", you will conclude that all failures are alike and that the only lever is the underlying edge. Once you separate the states, the levers multiply — you can act on the daily-loss margin, on the news calendar, on the hold rule, and on the room-left-before-continuing decision, and each of those is a bookkeeping choice rather than a trading skill.&lt;/p&gt;

&lt;p&gt;A challenge is not a test with a pass mark. It is a system with several distinct ways to stop, and the cheapest failure to avoid is the one you did not have to take at all. The full side-by-side of how hard and soft rules are written — and which firms punish which — is in the &lt;a href="https://elitepropx.com/blog/prop-firm-soft-breach-vs-hard-breach-explained.html" rel="noopener noreferrer"&gt;soft breach versus hard breach breakdown&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>finance</category>
      <category>javascript</category>
      <category>risk</category>
    </item>
    <item>
      <title>Where the 87% failure rate actually comes from</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 18:32:08 +0000</pubDate>
      <link>https://dev.to/elitepropx/where-the-87-failure-rate-actually-comes-from-1hh1</link>
      <guid>https://dev.to/elitepropx/where-the-87-failure-rate-actually-comes-from-1hh1</guid>
      <description>&lt;p&gt;Almost every prop firm page quotes the same headline: most funded-account challenges fail. Depending on who you ask it is 80%, 87% or "nine in ten". The number is repeated far more often than it is explained, and the explanation matters, because the causes are not one thing. They are four or five mechanically different events that get averaged into a single figure — and only some of them are things a trader can actually control.&lt;/p&gt;

&lt;p&gt;This is an attempt to take the number apart rather than cite it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four ways an account ends
&lt;/h2&gt;

&lt;p&gt;Take every way a challenge can conclude and sort them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The profit target is reached and the account passes.&lt;/strong&gt; The only outcome the marketing counts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hard breach.&lt;/strong&gt; Equity touches the floor — the max drawdown, or the daily loss limit measured intraday. The account is closed immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A soft breach or a stalled account.&lt;/strong&gt; Nothing was breached, the target was never reached, and the evaluation expires or the trader abandons it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A pass that is not payable.&lt;/strong&gt; The target was reached, but a consistency rule or a payout condition blocks the withdrawal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Almost every published failure rate collapses groups 2, 3 and 4 into one bucket. But they have almost nothing in common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Group 2 is a &lt;strong&gt;path&lt;/strong&gt; event. It happens at a specific moment, at a specific price, and it is usually the direct result of position sizing.&lt;/li&gt;
&lt;li&gt;Group 3 is a &lt;strong&gt;duration&lt;/strong&gt; event. It is the absence of a result, and it is dominated by the trader's own pacing.&lt;/li&gt;
&lt;li&gt;Group 4 is a &lt;strong&gt;distribution&lt;/strong&gt; event. The account was traded well enough to pass and is still ineligible, because of the &lt;em&gt;shape&lt;/em&gt; of the profit rather than its size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single "87% fail" number tells you nothing about which of these is happening, and therefore nothing about what to change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the decomposition changes the answer
&lt;/h2&gt;

&lt;p&gt;Here is the useful part. The groups respond to completely different interventions.&lt;/p&gt;

&lt;p&gt;If failures were mostly group 3 — never reaching the target — the fix would be a better edge or more time. But that is not where the accounts die. On a typical rulebook, the profit target is a modest move: 6% to 10% of the account. The drawdown is often larger in percentage terms than the target. The trap is not that the target is hard to reach; it is that the floor acts on the &lt;em&gt;path&lt;/em&gt; the whole way there.&lt;/p&gt;

&lt;p&gt;Consider a $100,000 account, 10% profit target, 10% drawdown. That reads like a 1:1 risk-reward on the account level. But the drawdown is measured from a different reference than the target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;target&lt;/strong&gt; is measured from the starting balance: you need equity at $110,000.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;trailing floor&lt;/strong&gt; is measured from the peak: at a starting balance of $100,000 with a $10,000 trail, the floor sits at $90,000 and &lt;em&gt;rises with every new high&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the moment you are up $5,000 — halfway to the target — the floor has risen to $95,000. Your remaining risk budget is not the original $10,000. It is $5,000, because the room that got you halfway is now behind a floor that moved. Give back $5,000 from that peak and the account is gone &lt;em&gt;while it is still in profit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That single mechanic is a large share of group 2. It is also invisible in the headline failure rate, because "the account was closed" is reported identically whether the trader was down 10% or up 5%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked arithmetic: room left as a function of progress
&lt;/h2&gt;

&lt;p&gt;Run the trailing floor forward on the same account:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Equity&lt;/th&gt;
&lt;th&gt;Trailing floor (peak − $10,000)&lt;/th&gt;
&lt;th&gt;Room left&lt;/th&gt;
&lt;th&gt;Progress to target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$100,000&lt;/td&gt;
&lt;td&gt;$90,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$102,000&lt;/td&gt;
&lt;td&gt;$92,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$105,000&lt;/td&gt;
&lt;td&gt;$95,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$108,000&lt;/td&gt;
&lt;td&gt;$98,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;80%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$110,000&lt;/td&gt;
&lt;td&gt;$100,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100% — but the floor is now at the starting balance&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the room column. On a trailing floor it is &lt;em&gt;constant&lt;/em&gt; at $10,000 no matter how far you have travelled — the gain bought you nothing in risk terms, it only moved the floor up behind you. Compare that with a static floor fixed at $90,000:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Equity&lt;/th&gt;
&lt;th&gt;Static floor&lt;/th&gt;
&lt;th&gt;Room left&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$100,000&lt;/td&gt;
&lt;td&gt;$90,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$105,000&lt;/td&gt;
&lt;td&gt;$90,000&lt;/td&gt;
&lt;td&gt;$15,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$110,000&lt;/td&gt;
&lt;td&gt;$90,000&lt;/td&gt;
&lt;td&gt;$20,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same number on the marketing page, "10% drawdown", and a completely different instrument. On the static account, profit &lt;em&gt;increases&lt;/em&gt; your buffer. On the trailing account it does not. A single failure statistic that lumps both rulebooks together is averaging two different games.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the statistic is measured, and where it is not
&lt;/h2&gt;

&lt;p&gt;There is a second problem with the number, and it is a sampling one. The failure rate you see is usually measured on accounts &lt;em&gt;sold&lt;/em&gt;, not on trades &lt;em&gt;taken&lt;/em&gt;. That introduces selection at both ends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Survivorship in the numerator.&lt;/strong&gt; Traders who fail quietly, buy a reset, and fail again are counted once each; traders who pass once and trade for years are counted once. The denominator is challenges, not traders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The reset multiplier.&lt;/strong&gt; A firm with a cheap reset converts one struggling trader into several challenge records. If most resets also fail, the headline rate rises for structural reasons that have nothing to do with the underlying difficulty of a single attempt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a reason to distrust the direction of the statistic — most attempts genuinely fail — but it is a reason not to treat it as a probability. It is a &lt;em&gt;rate over a population of purchases&lt;/em&gt;, and a purchase is not an attempt at a well-defined problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually moves the number, per group
&lt;/h2&gt;

&lt;p&gt;If you want to improve your own odds, the decomposition tells you which lever to pull:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Group 2 (hard breach):&lt;/strong&gt; position sizing and know-your-floor discipline. The failure is arithmetic — stop distance in account currency versus remaining room — not prediction. A trade whose adverse excursion exceeds your remaining budget cannot be rescued by being right about direction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group 3 (never reached):&lt;/strong&gt; pacing. Break the target into daily increments and refuse to chase it. The account usually dies from a size that was calibrated to the &lt;em&gt;exit&lt;/em&gt; rather than to the &lt;em&gt;entry&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group 4 (not payable):&lt;/strong&gt; the consistency ratio. Track &lt;code&gt;largest day / running total&lt;/code&gt; continuously, and if it is above the cap, plan the dilution deliberately instead of discovering it at withdrawal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those three is "be a better trader". All three are bookkeeping, and all three are knowable before the fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest summary
&lt;/h2&gt;

&lt;p&gt;The headline number is real in direction and useless in detail. What it hides is that the biggest single cause of failure is not a losing strategy — it is a floor that moves, a size that ignores the floor, and a missing number at the moment of entry. Those are all learnable, and none of them show up in an 87%.&lt;/p&gt;

&lt;p&gt;I walk through how each of these failure modes is written across the major firms, and where two rulebooks look identical and are not, in the fuller &lt;a href="https://elitepropx.com/blog/why-87-percent-fail-prop-firm-challenges.html" rel="noopener noreferrer"&gt;breakdown of why prop firm challenges fail&lt;/a&gt;. If you would rather compute your own remaining room than estimate it, the &lt;a href="https://elitepropx.com/tools/prop-firm-profit-calculator.html" rel="noopener noreferrer"&gt;prop firm profit calculator&lt;/a&gt; does the arithmetic for both a static and a trailing floor.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>finance</category>
      <category>statistics</category>
      <category>data</category>
    </item>
    <item>
      <title>Size positions from a drawdown budget, not a percentage</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:42:03 +0000</pubDate>
      <link>https://dev.to/elitepropx/size-positions-from-a-drawdown-budget-not-a-percentage-1npf</link>
      <guid>https://dev.to/elitepropx/size-positions-from-a-drawdown-budget-not-a-percentage-1npf</guid>
      <description>&lt;p&gt;Most position-size advice is expressed as a percentage of equity. That is a fine convention and a poor specification, because it never says what the percentage is &lt;em&gt;for&lt;/em&gt;. A drawdown rule gives you a much better handle: it hands you a budget, and the interesting question is how many consecutive losses that budget has to survive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The arithmetic
&lt;/h2&gt;

&lt;p&gt;Risk a fixed fraction &lt;code&gt;r&lt;/code&gt; of equity per trade. After &lt;code&gt;N&lt;/code&gt; consecutive losses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;equity = start * (1 - r)^N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set that equal to the floor and solve for &lt;code&gt;N&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;N = ln(floor / start) / ln(1 - r)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a $50,000 account with a $2,500 drawdown, the floor is $47,500 and &lt;code&gt;floor/start = 0.95&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk per trade&lt;/th&gt;
&lt;th&gt;After 5 losses&lt;/th&gt;
&lt;th&gt;After 10 losses&lt;/th&gt;
&lt;th&gt;After 15 losses&lt;/th&gt;
&lt;th&gt;Consecutive losses before the floor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.5%&lt;/td&gt;
&lt;td&gt;$48,762&lt;/td&gt;
&lt;td&gt;$47,556&lt;/td&gt;
&lt;td&gt;$46,378&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10.2&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.0%&lt;/td&gt;
&lt;td&gt;$47,550&lt;/td&gt;
&lt;td&gt;$45,219&lt;/td&gt;
&lt;td&gt;$43,003&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.1&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.5%&lt;/td&gt;
&lt;td&gt;$46,361&lt;/td&gt;
&lt;td&gt;$42,987&lt;/td&gt;
&lt;td&gt;$39,858&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.4&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.0%&lt;/td&gt;
&lt;td&gt;$45,196&lt;/td&gt;
&lt;td&gt;$40,854&lt;/td&gt;
&lt;td&gt;$36,928&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.5&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.0%&lt;/td&gt;
&lt;td&gt;$42,937&lt;/td&gt;
&lt;td&gt;$36,871&lt;/td&gt;
&lt;td&gt;$31,663&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the last column as a specification, because that is what it is. At 2% risk you are betting that you will not lose &lt;strong&gt;three&lt;/strong&gt; trades in a row. That is the entire risk statement, and it is much easier to argue with than "2% is a safe size."&lt;/p&gt;

&lt;p&gt;The relationship is not linear either. Going from 1% to 2% does not halve your buffer — it cuts consecutive-loss tolerance from 5.1 to 2.5. The buffer is a logarithm of the risk fraction, so the second percent costs much more than the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the number is not 10
&lt;/h2&gt;

&lt;p&gt;A buffer of 5.1 consecutive losses sounds comfortable. It is worth stating what it assumes, because the calculation above is deterministic and the world is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It assumes losses are independent and identical.&lt;/strong&gt; Real losing runs are correlated. In a volatile regime, the correlation is exactly when it hurts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It assumes you risk &lt;code&gt;r&lt;/code&gt; of &lt;em&gt;current&lt;/em&gt; equity&lt;/strong&gt;, so each successive loss is slightly smaller. That is the &lt;em&gt;more&lt;/em&gt; forgiving of the two conventions. If you size from a fixed notional instead, the arithmetic is linear and the buffer is shorter, not longer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It counts consecutive losses only.&lt;/strong&gt; A drawdown can also be produced by a sequence of smaller losses interleaved with wins, and a trailing floor rises while you do it — so the budget available late in an attempt is different from the budget available at the start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It ignores the daily loss limit.&lt;/strong&gt; If the rulebook has one, the binding constraint may be intraday and smaller than the overall drawdown. For a $50,000 account a common daily limit is $1,250, which at 1% risk is 2.5 losses &lt;em&gt;in one day&lt;/em&gt;, not five in a row.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;Deterministic arithmetic, so the function is short enough to verify by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                       &lt;span class="c1"&gt;// 47500&lt;/span&gt;

&lt;span class="c1"&gt;// equity multiplier after n consecutive losses at risk fraction r&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// how many consecutive losses until the floor is touched&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;after 5:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;after 10:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;buffer:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to notice about the implementation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is a binary search you should not write.&lt;/strong&gt; There is no need to simulate. &lt;code&gt;buffer(r)&lt;/code&gt; is closed-form, so the answer is exact and the "simulation" would only add sampling error to a quantity you can compute. Reach for a Monte Carlo when the quantity depends on the ordinal path; not when it is a logarithm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The floor is an input, not an output.&lt;/strong&gt; Notice that &lt;code&gt;floor&lt;/code&gt; is derived from the rulebook, not from the amount you would &lt;em&gt;like&lt;/em&gt; to risk. If you start from "I want to risk 2%" and then ask whether the account survives, you have the causality backwards. The budget fixes the risk; the risk does not fix the budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning the buffer into a trade size
&lt;/h2&gt;

&lt;p&gt;The calculation above gives a fraction, not a lot size. To get from one to the other you need the instrument's value per point and the distance to your stop, which is a separate problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;r * equity  =  size (in points) * value per point per contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an index future with a known point value, &lt;code&gt;size = (r * equity) / (stop_distance * point_value)&lt;/code&gt;. The drawdown budget tells you the maximum &lt;code&gt;r&lt;/code&gt;; the stop distance and point value tell you how to express that as contracts. If you find yourself choosing between two sizes that differ by more than the granularity of the contract, you are no longer sizing from the budget — you are rounding, and the rounding is the decision.&lt;/p&gt;

&lt;p&gt;This is the part that most sizing calculators get wrong in practice: they accept an account size and a risk percentage, produce a lot size, and never mention that the drawdown rule is what should have set the percentage in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would actually do with this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compute the buffer for your rulebook before your first trade.&lt;/strong&gt; Three numbers — account size, drawdown, risk fraction — and one logarithm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State the assumption out loud.&lt;/strong&gt; "2% risk means I am betting against three consecutive losses" is a falsifiable claim. "2% is conservative" is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check which constraint binds first.&lt;/strong&gt; If the daily limit is $1,250 and your overall drawdown is $2,500, the daily rule may be the binding one, and sizing to the overall drawdown will overstate your real buffer by a factor of two.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer the convention that makes the arithmetic conservative.&lt;/strong&gt; Sizing from current equity is more forgiving than sizing from a fixed notional. If you are unsure which one a platform or tool uses, assume the stricter.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is deterministic by construction.&lt;/strong&gt; This is not a criticism of the result — it is a warning against adding simulation to it and gaining only noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independence of losses is assumed and is false.&lt;/strong&gt; The buffer column is a &lt;em&gt;necessary&lt;/em&gt; condition, not a sufficient one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The floor is treated as fixed.&lt;/strong&gt; Under a trailing rule the floor rises with the peak, so your buffer is not constant over the life of the account — it shrinks as you get closer to the target, which is the opposite of what most traders assume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The daily limit is handled as an aside.&lt;/strong&gt; It should be a separate budget with its own buffer, and the binding constraint is whichever is smaller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The useful reframing is that a drawdown rule is not a limit you bump into. It is a &lt;strong&gt;budget you spend&lt;/strong&gt;, and the risk per trade is the rate at which you spend it. Expressing size as "how many consecutive losses can this survive" turns an intuition into an assertion you can check against your actual loss distribution.&lt;/p&gt;

&lt;p&gt;If the constraint that matters most in your rulebook is the daily one rather than the overall drawdown, &lt;a href="https://elitepropx.com/blog/prop-firm-daily-drawdown-explained.html" rel="noopener noreferrer"&gt;how daily drawdown is enforced&lt;/a&gt; goes through the different measurement conventions — from balance or from equity, reset at midnight or at the first trade — which change the buffer by more than the risk fraction does.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>finance</category>
    </item>
    <item>
      <title>A challenge fee is a geometric series, not a price</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:41:25 +0000</pubDate>
      <link>https://dev.to/elitepropx/a-challenge-fee-is-a-geometric-series-not-a-price-3a4j</link>
      <guid>https://dev.to/elitepropx/a-challenge-fee-is-a-geometric-series-not-a-price-3a4j</guid>
      <description>&lt;p&gt;The advertised price of a trading challenge is a fee. The real cost is a random variable, and its expectation is not the fee. It is the fee divided by your probability of passing — and that division is where the interesting arithmetic lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model, stated before it is used
&lt;/h2&gt;

&lt;p&gt;Assume you retry until you pass, then collect one payout. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;attempts needed until the first pass  ~  Geometric(p),   E[attempts] = 1/p
E[total fees]   =  fee * (1/p)  =  fee / p
E[net]          =  payout - fee / p
break-even p    =  fee / payout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things follow immediately, and both are easy to skip past:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The cost multiplier is exactly &lt;code&gt;1/p&lt;/code&gt;.&lt;/strong&gt; If you pass one time in three, you will &lt;em&gt;on average&lt;/em&gt; pay for three challenges. The multiplier is not a small correction — at p = 0.35 it is 2.8×.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is a break-even pass rate that does not depend on your skill at all.&lt;/strong&gt; With a $500 fee and a $3,000 first payout it is &lt;code&gt;500/3000 = 16.67%&lt;/code&gt;. Below that, the arithmetic is negative no matter how good the strategy is; above it, positive. It is a property of the price list.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Point 2 is the useful one, because it inverts the usual question. Traders ask "can I pass?" The arithmetic asks "what is the cheapest rulebook whose pass rate clears the break-even by the widest margin?"&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement
&lt;/h2&gt;

&lt;p&gt;Four rulebooks, one generator, 50,000 accounts each, $50,000 account, $2,500 drawdown, $6,000 target. Fee $500, first payout $3,000.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rulebook&lt;/th&gt;
&lt;th&gt;p(pass)&lt;/th&gt;
&lt;th&gt;E[attempts]&lt;/th&gt;
&lt;th&gt;E[fees paid]&lt;/th&gt;
&lt;th&gt;Cost vs fee&lt;/th&gt;
&lt;th&gt;E[net] after fees&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;static drawdown&lt;/td&gt;
&lt;td&gt;78.31%&lt;/td&gt;
&lt;td&gt;1.28&lt;/td&gt;
&lt;td&gt;$638&lt;/td&gt;
&lt;td&gt;1.28×&lt;/td&gt;
&lt;td&gt;$2,362&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trails to breakeven&lt;/td&gt;
&lt;td&gt;70.33%&lt;/td&gt;
&lt;td&gt;1.42&lt;/td&gt;
&lt;td&gt;$711&lt;/td&gt;
&lt;td&gt;1.42×&lt;/td&gt;
&lt;td&gt;$2,289&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trails, above breakeven&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;1.65&lt;/td&gt;
&lt;td&gt;$827&lt;/td&gt;
&lt;td&gt;1.65×&lt;/td&gt;
&lt;td&gt;$2,173&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trails intraday&lt;/td&gt;
&lt;td&gt;35.66%&lt;/td&gt;
&lt;td&gt;2.80&lt;/td&gt;
&lt;td&gt;$1,402&lt;/td&gt;
&lt;td&gt;2.80×&lt;/td&gt;
&lt;td&gt;$1,598&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything clears the 16.67% break-even. That is worth being suspicious of, and the suspicion is correct — I will come back to it, because it is the most important limitation in this article.&lt;/p&gt;

&lt;p&gt;The defensible finding is the &lt;strong&gt;spread&lt;/strong&gt;: the same trader on the same strategy pays an expected &lt;strong&gt;$638&lt;/strong&gt; under one rulebook and &lt;strong&gt;$1,402&lt;/strong&gt; under another. That is a 2.2× difference in expected cost, driven entirely by the floor of the drawdown — not by the strategy, not by the trader, and not by the advertised fee, which is identical across all four columns.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanism, in one function
&lt;/h2&gt;

&lt;p&gt;The whole difference between the columns is a single expression for the floor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// never moves&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                    &lt;span class="c1"&gt;// follows the peak&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// stops at breakeven&lt;/span&gt;
                                  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                        &lt;span class="c1"&gt;// keeps trailing&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three lines, and the pass rate moves from 78.31% to 35.66%. The rest of the simulator — the target, the trade generation, the iteration — is byte-identical. When a single expression moves an expected cost by 2.2×, that expression is the thing to understand, not the marketing copy around it.&lt;/p&gt;

&lt;p&gt;There is a bug in this neighbourhood worth flagging because I shipped it and it produced a plausible-looking table. I first wrote the lock as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// WRONG - does nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;peak &amp;gt;= start&lt;/code&gt; always, so &lt;code&gt;peak - dd &amp;gt;= start - dd&lt;/code&gt; always, so the &lt;code&gt;max&lt;/code&gt; always returns &lt;code&gt;f&lt;/code&gt;. The clamp was a no-op and "trails to breakeven" came out &lt;em&gt;identical&lt;/em&gt; to the unclamped trailing rule — 35.66% on both rows. Two rulebooks, one number, and nothing in the output to suggest a problem. A rule that clamps the floor &lt;strong&gt;at&lt;/strong&gt; breakeven is a minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// correct&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same character count. Opposite direction. One row in the table above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the naive model is too generous
&lt;/h2&gt;

&lt;p&gt;The table says all four rulebooks are profitable. That follows from the assumptions, and the assumptions are doing more work than the measurements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unlimited retries.&lt;/strong&gt; &lt;code&gt;E[attempts] = 1/p&lt;/code&gt; requires that attempts are independent draws. If a blown account teaches you something, the attempts are not independent and the geometric model is wrong about the &lt;em&gt;variance&lt;/em&gt; — usually optimistically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No time cost.&lt;/strong&gt; Each attempt consumes weeks of calendar time. The model prices the fee and ignores the opportunity cost entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The payout is collected once and never lost.&lt;/strong&gt; Real funded accounts can be breached &lt;em&gt;after&lt;/em&gt; passing, which ends the sequence with fees paid and no payout. Adding a funded-account failure probability is the single change most likely to invert the ordering in the table, because it interacts with the drawdown mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fee is constant.&lt;/strong&gt; Many firms scale the fee with account size and discount on repeat purchases, so &lt;code&gt;fee/p&lt;/code&gt; is a weighted average, not a simple division.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;p&lt;/code&gt; is treated as known.&lt;/strong&gt; It is estimated from a model. At the bottom of the table, a plausible error bar on 35.66% spans a large multiple of &lt;code&gt;1/p&lt;/code&gt;, and the cost is a &lt;em&gt;reciprocal&lt;/em&gt; function, so estimation error in &lt;code&gt;p&lt;/code&gt; is amplified non-linearly into cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest summary: the &lt;em&gt;spread&lt;/em&gt; across rulebooks is a robust finding, because all four share the same assumptions. The absolute profits are an artifact of assuming unlimited retries of an unbreached, fee-only challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code for the cost side
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FEE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PAYOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fees&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FEE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PAYOUT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;FEE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clearsBreakEven&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;FEE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;PAYOUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five lines, and every number in the table is a call to it with a &lt;code&gt;p&lt;/code&gt; that came from a simulation rather than an estimate. That separation is the discipline worth keeping: &lt;strong&gt;the simulation produces &lt;code&gt;p&lt;/code&gt;; the cost model consumes it.&lt;/strong&gt; They are different models with different assumptions, and merging them into one script is how a modelling assumption in the price logic gets attributed to the strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single seed per rulebook.&lt;/strong&gt; Reproducible, not an ensemble; unquantified sampling error on every &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One trade per day, 80 days maximum.&lt;/strong&gt; A real challenge spans longer, and the tail of the attempt-length distribution — the traders who take six attempts — is exactly the tail the geometric model is being used to price.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;p&lt;/code&gt; measured in isolation.&lt;/strong&gt; The pass rates come from four separate runs with the same generator, not from a paired comparison, so part of the spread could be seed noise rather than the floor rule. The ordering is monotone and large enough to be convincing; the individual values are not precise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The payout is $3,000 for everyone.&lt;/strong&gt; Firms tie the first payout to account size and profit share, so the break-even pass rate is rulebook-specific in reality and not the single 16.67% used here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical takeaway is not "pick the static drawdown" — that ignores every other difference between firms. It is that &lt;strong&gt;cost is a function of &lt;code&gt;1/p&lt;/code&gt;, so the cheapest rulebook is the one you are most likely to pass, and the difference is multiplicative, not additive.&lt;/strong&gt; A 20-point swing in pass rate is a 2.2× swing in expected spend on an identical fee.&lt;/p&gt;

&lt;p&gt;I broke down &lt;a href="https://elitepropx.com/blog/how-much-does-ftmo-challenge-cost.html" rel="noopener noreferrer"&gt;what a prop firm challenge actually costs&lt;/a&gt; end to end — fee tiers, reset pricing and the payout schedule that sets the break-even — for anyone who wants the price-list side of this rather than the simulation.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>finance</category>
      <category>javascript</category>
      <category>statistics</category>
    </item>
    <item>
      <title>Why an i.i.d. bootstrap lies about drawdown</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:40:49 +0000</pubDate>
      <link>https://dev.to/elitepropx/why-an-iid-bootstrap-lies-about-drawdown-3eim</link>
      <guid>https://dev.to/elitepropx/why-an-iid-bootstrap-lies-about-drawdown-3eim</guid>
      <description>&lt;p&gt;Resampling is the cheapest way to answer "how much of my backtest is luck?" It is also, in the specific case of drawdown survival, biased in a direction that flatters the result — and the fix is not more samples. It is fewer, longer ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The claim being tested
&lt;/h2&gt;

&lt;p&gt;Suppose you have a strategy's daily P&amp;amp;L. You want a distribution of outcomes, so you resample: draw days independently, with replacement, and simulate the rulebook on each synthetic sequence. This is the bootstrap, and it is a good tool for a lot of questions.&lt;/p&gt;

&lt;p&gt;It assumes the days are exchangeable — that shuffling them changes nothing that matters. Under that assumption, a shuffled series is a valid draw from the same process.&lt;/p&gt;

&lt;p&gt;For a drawdown rule, that assumption is false in a way that matters, because &lt;strong&gt;the order of the days is the mechanism&lt;/strong&gt;. A floor is breached by a &lt;em&gt;run&lt;/em&gt;. Shuffle the days and you do not preserve the runs; you shred them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement
&lt;/h2&gt;

&lt;p&gt;One generator, one rulebook, three resampling schemes. The generator is a two-state regime process — a chop state with a 40% win rate and a trend state with a 62% win rate, switching with 4% probability per day. The rulebook is a trailing drawdown that locks at breakeven, on a $50,000 account with a $2,500 drawdown and a $6,000 target. 50,000 simulated accounts per row.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resampling scheme&lt;/th&gt;
&lt;th&gt;Pass rate&lt;/th&gt;
&lt;th&gt;vs true path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;true path (ground truth)&lt;/td&gt;
&lt;td&gt;82.23%&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;i.i.d. days from the same pool&lt;/td&gt;
&lt;td&gt;92.52%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+10.29 pp&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;contiguous blocks, B = 5&lt;/td&gt;
&lt;td&gt;89.90%&lt;/td&gt;
&lt;td&gt;+7.67 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;contiguous blocks, B = 10&lt;/td&gt;
&lt;td&gt;87.68%&lt;/td&gt;
&lt;td&gt;+5.45 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;contiguous blocks, B = 20&lt;/td&gt;
&lt;td&gt;85.85%&lt;/td&gt;
&lt;td&gt;+3.62 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every scheme draws from the &lt;strong&gt;same 20,000-day pool&lt;/strong&gt;. They differ only in how they pick from it. And the i.i.d. row is wrong by more than ten percentage points — in the direction of "your strategy is safe."&lt;/p&gt;

&lt;p&gt;That number is a statement about the rulebook, not about the market: for a rule that can be breached by a losing streak, destroying the streaks &lt;em&gt;is&lt;/em&gt; the error. It is not a minor statistical infelicity. It is modelling a different rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why blocks help, and why block size is the actual decision
&lt;/h2&gt;

&lt;p&gt;A block bootstrap draws contiguous stretches of days rather than single days, so within a block the temporal structure survives. The table shows the error falling monotonically as the block grows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;B = 5   +7.67 pp
B = 10  +5.45 pp
B = 20  +3.62 pp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason to stop is not that larger is bad. It is that &lt;strong&gt;a block cannot meaningfully exceed the length of the history you are drawing from.&lt;/strong&gt; With a 20,000-day pool, a 20-day block is already reusing the same stretches across draws, so increasing it further starts to convert sampling error into mere repetition. The honest statement of the rule is: use the longest block your pool supports, and if that is still too short to contain the runs you care about, your pool is the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;The whole difference between the correct and incorrect version is the inner loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// i.i.d. bootstrap — shreds streaks. Biased for any rule breached by a run.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;iidSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nDays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nDays&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// block bootstrap — keeps runs together.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;blockSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nDays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nDays&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nDays&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the comparison, with the true path as the reference rather than as an afterthought:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;mulberry32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SEED&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;switchP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bigP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;truth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;mulberry32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SEED&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;switchP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bigP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CFG&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;truth&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;iid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;iidSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CFG&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;iid&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// truth = 82.23%   iid = 92.52%&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worth stating plainly: the "ground truth" here is ground truth &lt;em&gt;relative to the generator&lt;/em&gt;. It is not a claim about real markets. The experiment measures whether a resampling scheme recovers the process it was given, and i.i.d. does not — it cannot, because the process has persistence and the scheme deletes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that generalises
&lt;/h2&gt;

&lt;p&gt;This is a member of a family of mistakes that all share a shape: &lt;strong&gt;applying a resampling scheme whose null hypothesis contradicts the mechanism you are testing.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resampling individual trades to test a &lt;strong&gt;drawdown&lt;/strong&gt; rule assumes the losing run is not the thing that kills you. It is.&lt;/li&gt;
&lt;li&gt;Resampling to test a &lt;strong&gt;consistency rule&lt;/strong&gt; assumes the concentration of profit is not the thing that disqualifies you. It is — and, incidentally, i.i.d. resampling &lt;em&gt;understates&lt;/em&gt; concentration risk by averaging the fat days out.&lt;/li&gt;
&lt;li&gt;Resampling with the wrong block length in the presence of &lt;strong&gt;volatility clustering&lt;/strong&gt; reproduces the same error with extra steps, because the thing that clusters is the variance, not the mean.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cheap check before trusting any bootstrap: &lt;strong&gt;ask what property of the ordering your resampling scheme destroys, and whether the rule you are testing depends on it.&lt;/strong&gt; If yes, single-day resampling cannot be used, and the block length has become a real modelling parameter that deserves to be chosen rather than defaulted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The regime process is invented.&lt;/strong&gt; Two states with symmetric switch probabilities is a caricature of trend/chop. Real persistence is asymmetric — trends decay faster than they build — and that asymmetry would push the numbers further apart, not closer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One trade per day&lt;/strong&gt;, up to 80 days, so "runs" are at most 80 long and the pool is 20,000 days. Both are small enough that the block estimates carry their own sampling error, which I have not quantified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Survivorship in the pool.&lt;/strong&gt; The pool is generated once from the process; it is not refreshed, so all block draws are conditional on that one realisation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symmetric win/loss magnitudes.&lt;/strong&gt; Every day is drawn from the same payoff family regardless of regime, so the regime affects only the win probability, not the size distribution. Real trend regimes change both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you just want the practical version: for a rule that fails on a streak, resample &lt;strong&gt;contiguous blocks&lt;/strong&gt;, report the block length, and sanity-check the estimate against a simulation of the actual process when you have one. A bootstrap that cannot represent your worst run is not a risk estimate.&lt;/p&gt;

&lt;p&gt;I keep a &lt;a href="https://elitepropx.com/tools/prop-firm-profit-calculator.html" rel="noopener noreferrer"&gt;prop firm profit calculator&lt;/a&gt; that runs the cost side of this arithmetic — expected attempts, expected fees and the break-even pass rate for a given payout — for anyone who wants the numbers rather than the method.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>statistics</category>
      <category>javascript</category>
      <category>data</category>
    </item>
    <item>
      <title>Look-ahead bias hides in the bars you did not load</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:40:12 +0000</pubDate>
      <link>https://dev.to/elitepropx/look-ahead-bias-hides-in-the-bars-you-did-not-load-554d</link>
      <guid>https://dev.to/elitepropx/look-ahead-bias-hides-in-the-bars-you-did-not-load-554d</guid>
      <description>&lt;p&gt;There is a class of backtest bug that leaves no stack trace, produces plausible numbers, and is invisible in a code review. It happens when your simulator uses a price it could not have known at the time it needed to act — and the most common instance in trading code is subtler than the usual "using tomorrow's close to decide today's trade."&lt;/p&gt;

&lt;p&gt;This one is about &lt;strong&gt;the open, the high, the low and the close being four different facts&lt;/strong&gt;, and what happens when you keep only one of them.&lt;/p&gt;

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

&lt;p&gt;Take a trailing drawdown. The floor follows your peak profit upward, and if equity touches the floor you fail. Then note something about which price drives each half of that sentence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;peak&lt;/strong&gt; is set by the &lt;em&gt;high&lt;/em&gt; — the best the account ever looked.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;floor&lt;/strong&gt; is touched by the &lt;em&gt;low&lt;/em&gt; — the worst the account looked while open.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A daily bar gives you both. A daily close gives you neither. It gives you one point, and the two quantities the rule depends on are the extremes on either side of it.&lt;/p&gt;

&lt;p&gt;If you simulate a trailing drawdown using closes only, you are asking "what would have happened if the only price that existed was the settlement" — which is not a model of your account. It is a model of a different account.&lt;/p&gt;

&lt;h2&gt;
  
  
  How big is the error?
&lt;/h2&gt;

&lt;p&gt;I generated 50,000 accounts with identical closing P&amp;amp;L, then varied only one thing: &lt;strong&gt;how far below the close the price travelled at its worst point during the day.&lt;/strong&gt; The closes are byte-identical across every row. Nothing about the outcome series changes. Only the unseen part of each bar changes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Intraday range (unseen)&lt;/th&gt;
&lt;th&gt;Pass rate, close-only rule&lt;/th&gt;
&lt;th&gt;Pass rate, true path&lt;/th&gt;
&lt;th&gt;Overstatement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.2×&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;43.75%&lt;/td&gt;
&lt;td&gt;16.7 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.5×&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;41.08%&lt;/td&gt;
&lt;td&gt;19.4 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.0×&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;35.66%&lt;/td&gt;
&lt;td&gt;24.8 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.0×&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;11.32%&lt;/td&gt;
&lt;td&gt;49.1 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.0×&lt;/td&gt;
&lt;td&gt;60.46%&lt;/td&gt;
&lt;td&gt;0.48%&lt;/td&gt;
&lt;td&gt;60.0 pp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The close-only column is &lt;strong&gt;60.46% on every row&lt;/strong&gt;. That is not a coincidence — it is the definition. A close-only simulator cannot respond to a variable it cannot see, so its estimate is a constant while the truth falls away from it.&lt;/p&gt;

&lt;p&gt;At the reference range, the overstatement is &lt;strong&gt;24.8 percentage points&lt;/strong&gt;: 60.46% claimed against 35.66% real. That is the difference between "this rulebook is comfortably passable" and "this rulebook kills roughly two out of three accounts."&lt;/p&gt;

&lt;p&gt;And here is the part that should worry you more than the size of the error: &lt;strong&gt;the error grows with the range, and the range is exactly what your data doesn't contain.&lt;/strong&gt; You cannot compute a confidence interval on a quantity you did not sample. A close-only backtest has no way to tell you that it is off by 16 points or 60.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal reproduction
&lt;/h2&gt;

&lt;p&gt;The whole effect is in what the simulator is allowed to read. Both modes below run the same day objects; the only difference is two &lt;code&gt;if&lt;/code&gt; conditions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 'trailing_closed' never reads high or low. That is the entire bug.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closedOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_closed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// trailing floor&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;closedOnly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// peak is set by the HIGH&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// the LOW touches the floor&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                              &lt;span class="c1"&gt;// the close moves equity&lt;/span&gt;
    &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note where &lt;code&gt;peak&lt;/code&gt; is updated in the closed-only branch: only on the close. Note that the low is never consulted. Both are necessary simplifications if you only have a daily close — and both bias the result upward, because the high that raises your floor and the low that breaches it are systematically discarded.&lt;/p&gt;

&lt;p&gt;The generator that isolates the effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;win&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;high&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="na"&gt;low&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.45&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;high&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;low&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The invariant worth enforcing is &lt;code&gt;high &amp;gt;= close &amp;gt;= low&lt;/code&gt;. My first version of this broke it: a strongly winning day could be given a &lt;code&gt;low&lt;/code&gt; far below its own open, which meant a big up day both raised the floor enormously &lt;em&gt;and&lt;/em&gt; breached it on the same bar. Every trailing account in the run died instantly, and the output was nonsense in a way that looked like a finding. An inconsistent bar is worse than a missing one, because you will believe it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The general rule this is an instance of
&lt;/h2&gt;

&lt;p&gt;Look-ahead bias is usually taught as "don't use information from the future." The durable version is broader:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any quantity your strategy reacts to must be computed from data at or finer than the resolution at which the decision is made.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A trailing drawdown is a decision made &lt;strong&gt;intraday&lt;/strong&gt; — it is enforced the moment the low touches the floor, not at settlement. Therefore it must be simulated with intraday extremes. A close-only model is not a lower-resolution approximation of that rule. It is a different rule, and a strictly more permissive one.&lt;/p&gt;

&lt;p&gt;The same test applies to other common cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The daily loss limit&lt;/strong&gt; is enforced intraday, so it needs the low. Daily closes will always under-count breaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A time limit&lt;/strong&gt; counted in trading days can be modelled on daily bars, because the decision is made at day resolution. Not every rule needs ticks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A trailing floor that locks at breakeven&lt;/strong&gt; stops depending on the high once it locks, so the error shrinks after the lock — the bias is not uniform over the life of the account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to do instead
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;If you have intraday data, use it.&lt;/strong&gt; The gap above is 24.8 points at the reference range; there is no correction factor that recovers it from closes alone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you only have daily bars, report the limitation as a bound, not a point estimate.&lt;/strong&gt; A close-only result is an &lt;em&gt;upper&lt;/em&gt; bound on the pass rate for any intraday-enforced rule. Say so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconstruct at least the extremes.&lt;/strong&gt; A daily OHLC series is usually easier to obtain than intraday ticks, and it is enough to get the high and the low. That removes most of this error class for a fraction of the data cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert your bar invariants.&lt;/strong&gt; &lt;code&gt;high &amp;gt;= max(open, close)&lt;/code&gt;, &lt;code&gt;low &amp;lt;= min(open, close)&lt;/code&gt;. A one-line assertion at generation time would have caught the bug in my first version before it produced a single number.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scaling the intraday range uniformly is a modelling choice.&lt;/strong&gt; Real ranges are heteroskedastic; they widen with volatility and are not proportional across accounts. The monotone trend in the table is robust to that, but the specific percentage points are not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The other rulebooks in the run are not varied.&lt;/strong&gt; Static drawdowns are largely insensitive to this bias — the floor doesn't move — so the 24.8pp figure is a statement about &lt;em&gt;trailing&lt;/em&gt; rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One trade per day again.&lt;/strong&gt; A day object with one high and one low understates how many times the low can touch the floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single seed.&lt;/strong&gt; The runs are reproducible but not an ensemble, so the point estimates carry unquantified sampling error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The uncomfortable property of this bias is that it never announces itself. A close-only backtest of an intraday-enforced rule produces a clean, confident, wrong number, and the wrongness scales with the volatility of the instrument — so it will look most trustworthy exactly where it is most wrong.&lt;/p&gt;

&lt;p&gt;I wrote up the underlying mechanics of &lt;a href="https://elitepropx.com/blog/prop-firm-trailing-drawdown-vs-static-drawdown-explained.html" rel="noopener noreferrer"&gt;trailing vs static drawdown&lt;/a&gt; separately, including how each mode's floor is defined across different firms, if you want the rulebook side rather than the simulation side.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>javascript</category>
      <category>testing</category>
      <category>statistics</category>
    </item>
    <item>
      <title>The consistency rule is a constraint, not a number</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:40:07 +0000</pubDate>
      <link>https://dev.to/elitepropx/the-consistency-rule-is-a-constraint-not-a-number-5ddf</link>
      <guid>https://dev.to/elitepropx/the-consistency-rule-is-a-constraint-not-a-number-5ddf</guid>
      <description>&lt;p&gt;A trader passes the evaluation. Target hit, drawdown never breached, every rule respected. Then the payout request comes back refused, because one day carried 46% of the total profit and the firm's consistency rule allows 40%.&lt;/p&gt;

&lt;p&gt;That is not a bug in their paperwork. It is two rules measuring unrelated things, and one of them is silently a filter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule, stated precisely
&lt;/h2&gt;

&lt;p&gt;Most prop firms express the consistency rule as a ratio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;largest single day's profit / total profit &amp;lt;= cap        (cap is typically 0.25 - 0.6)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subtlety is what this expression is a function &lt;em&gt;of&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;pass decision&lt;/strong&gt; is a function of the equity path: did you reach the target before the floor?&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;consistency cap&lt;/strong&gt; is a function of the &lt;em&gt;shape&lt;/em&gt; of the profit, not its size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can reach the target and still be ineligible. You can be wildly profitable over six weeks and still be ineligible, if the profit arrived in one afternoon. Nothing about the way you reached the target protects you from the second check, because the second check never looks at the path — only at the concentration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring how often that actually happens
&lt;/h2&gt;

&lt;p&gt;I ran 50,000 simulated $50,000 accounts against a static $2,500 drawdown and a $6,000 target, one trade per day, up to 80 days. The generator produces normal days for the most part, with &lt;strong&gt;6% of days outsized&lt;/strong&gt; — a fat right tail, because real trading profit is not gaussian.&lt;/p&gt;

&lt;p&gt;Result: &lt;strong&gt;39,155 of 50,000 accounts passed (78.31%)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then I applied the consistency cap to the accounts that had already passed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Consistency cap&lt;/th&gt;
&lt;th&gt;Passes that violate it&lt;/th&gt;
&lt;th&gt;Effective pass rate&lt;/th&gt;
&lt;th&gt;Extra profit needed (median)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;td&gt;38,400 of 39,155 (98.1%)&lt;/td&gt;
&lt;td&gt;1.51%&lt;/td&gt;
&lt;td&gt;$6,343&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;td&gt;37,416 of 39,155 (95.6%)&lt;/td&gt;
&lt;td&gt;3.48%&lt;/td&gt;
&lt;td&gt;$4,162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40%&lt;/td&gt;
&lt;td&gt;30,475 of 39,155 (77.8%)&lt;/td&gt;
&lt;td&gt;17.36%&lt;/td&gt;
&lt;td&gt;$1,727&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;td&gt;15,448 of 39,155 (39.5%)&lt;/td&gt;
&lt;td&gt;47.41%&lt;/td&gt;
&lt;td&gt;$737&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60%&lt;/td&gt;
&lt;td&gt;3,130 of 39,155 (8.0%)&lt;/td&gt;
&lt;td&gt;72.05%&lt;/td&gt;
&lt;td&gt;$213&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the 40% row again. &lt;strong&gt;Nearly four fifths of the accounts that passed are ineligible to be paid&lt;/strong&gt; under a cap of 40%.&lt;/p&gt;

&lt;p&gt;And the control run matters just as much: with the same drawdown, the same target and the same 50,000 accounts, but &lt;strong&gt;no outsized days&lt;/strong&gt;, violations at a 40% cap = &lt;strong&gt;0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That contrast is the whole insight. The rule does not bite on ordinary trading. It bites exactly when a trader has one very good session — which is the thing a discretionary trader most wants to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the naive simulation misses this
&lt;/h2&gt;

&lt;p&gt;If you backtest a challenge by asking "did equity reach the target before the floor", your model returns a single bit. The consistency rule needs a second, orthogonal output: the &lt;strong&gt;distribution&lt;/strong&gt; of the daily contributions to the total.&lt;/p&gt;

&lt;p&gt;That distinction is easy to get wrong, and I got it wrong the first time I built this. My first version produced zero violations at every cap from 25% to 60%, which I read as "the rule is harmless." The real cause was a generator bug: my winning days were small relative to the target, so the largest day was never more than 13% of the total. The rule looked harmless because the data could not possibly violate it.&lt;/p&gt;

&lt;p&gt;If you are testing whether a rule hurts, you have to make sure your generator can violate it. Otherwise you have measured nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;The pass decision and the eligibility check are separate functions. Only the second one needs the daily series.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PASS DECISION: only needs the equity path.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closedOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_closed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;closedOnly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;high&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;up&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;low&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dn&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ELIGIBILITY: a pure function of the daily P&amp;amp;L series. No path, no equity.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;consistencyViolation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;worst&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                 &lt;span class="c1"&gt;// true = cannot be paid&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extraProfitNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;dayPnl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// solve worst / (total + x) = cap  -&amp;gt;  x = worst/cap - total&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worst&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the measurement is a filter over the accounts that already passed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20261013&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bigP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                 &lt;span class="c1"&gt;// 78.31%&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;violators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;consistencyViolation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;effective&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;violators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;violators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;effective&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;effective&lt;/code&gt; is the number that matters and it is not the pass rate. It is the probability that an account both reaches the target &lt;em&gt;and&lt;/em&gt; remains payable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diluting the violation, and what it costs
&lt;/h2&gt;

&lt;p&gt;The standard remedy is not to stop trading. It is to keep trading until the offending day is a smaller share of a larger total. The arithmetic is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;largest_day / (total + x) = cap        =&amp;gt;        x = largest_day / cap - total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the violating accounts in the 40% bucket, the median extra profit required is &lt;strong&gt;$1,727&lt;/strong&gt; — on a $50,000 account with a $6,000 target, that is roughly another 29% of the target in profit, produced under the same drawdown constraint that just tried to kill the account.&lt;/p&gt;

&lt;p&gt;That is the real cost of the consistency rule: not a rejection, but a forced extension. You are still trading, your floor is still rising if the drawdown trails, and you now need to manufacture additional profit &lt;em&gt;specifically to dilute a number&lt;/em&gt;, with no risk budget set aside for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would actually do with this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Track the ratio continuously, not at payout.&lt;/strong&gt; If &lt;code&gt;largest_day / running_total&lt;/code&gt; is above the cap, you know before you submit. Most platforms show the daily breakdown; the calculation is a division.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide the dilution trade size deliberately.&lt;/strong&gt; If you need $1,727 more to clear a 40% cap, that is a target, not a vibe. Size it as you would any other target, against the room you have left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do not confuse the two failure modes.&lt;/strong&gt; A drawdown breach is a path failure. A consistency violation is a &lt;em&gt;distribution&lt;/em&gt; failure. Different causes, different fixes. Software that models only one of them will tell you that you are fine when you are not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the cap on your specific firm&lt;/strong&gt;, because 25% and 60% are different sports. The 25% row above — 98.1% of passes ineligible — is a genuinely different experience from the 60% row at 8.0%.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One trade is not one day.&lt;/strong&gt; I collapsed a day into a single trade for tractability. A real day contains many trades, and the intraday peak matters for trailing drawdowns in a way a daily aggregate cannot represent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profit is not the only input.&lt;/strong&gt; Several firms apply consistency to lots, trade count or session, not just dollars. The shape of the constraint changes; the independence from the pass decision does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The generator's fat tail is a choice.&lt;/strong&gt; &lt;code&gt;6% of days outsized&lt;/code&gt; is a modelled assumption, not a measurement of your trading. The control row (zero violations with no outsized days) exists precisely to show how much the answer depends on that assumption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic seed.&lt;/strong&gt; Every figure above comes from one fixed seed, so runs are reproducible but not an ensemble. The point estimates carry unquantified sampling error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The consistency rule is usually described as a rule about consistency. In the model it is better described as a filter applied &lt;em&gt;after&lt;/em&gt; the challenge has already been cleared, on a property — profit concentration — that the challenge never tested.&lt;/p&gt;

&lt;p&gt;If you want to run these numbers against your own rulebook rather than the one I modelled, the &lt;a href="https://elitepropx.com/blog/prop-firm-consistency-rule-guide.html" rel="noopener noreferrer"&gt;prop firm consistency rule guide&lt;/a&gt; covers how the caps are written across the major firms and where the definitions quietly differ.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>javascript</category>
      <category>statistics</category>
      <category>finance</category>
    </item>
    <item>
      <title>Trailing vs static drawdown: simulating why the same trades pass one prop firm account and fail another</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:59:45 +0000</pubDate>
      <link>https://dev.to/elitepropx/trailing-vs-static-drawdown-simulating-why-the-same-trades-pass-one-prop-firm-account-and-fail-4meg</link>
      <guid>https://dev.to/elitepropx/trailing-vs-static-drawdown-simulating-why-the-same-trades-pass-one-prop-firm-account-and-fail-4meg</guid>
      <description>&lt;p&gt;Two traders take the same trades on a $50,000 evaluation with a $6,000 target and a $2,500 drawdown. One account ends the week down $400 and is still alive. Another is dead — while &lt;strong&gt;up $2,700&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nobody made a different decision. The rulebooks were different shapes.&lt;/p&gt;

&lt;p&gt;I keep seeing this described as "risk management," which is not quite it. Risk management is a discipline you apply to a position. This is arithmetic applied to an &lt;em&gt;account&lt;/em&gt;, and it is fully modellable. So rather than argue about it, let's simulate it — and then run the simulation 200,000 times instead of trusting the one walk that happened to be in front of us.&lt;/p&gt;

&lt;p&gt;Every number below is real output from the script in this post, with a fixed random seed so you get byte-identical results when you run it. All code is at the end of the relevant section.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three drawdown modes firms actually use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Static drawdown.&lt;/strong&gt; The floor is fixed below the starting balance. A $50k account with a $2.5k limit has a floor at $47,500 that never moves. Profit is pure gain, because the reference point is fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trailing drawdown, measured on closed equity.&lt;/strong&gt; The floor rises with the high-water mark of the &lt;em&gt;closed&lt;/em&gt; balance. Close at $55,000 and the floor becomes $52,500 permanently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trailing drawdown, measured on unrealised equity.&lt;/strong&gt; The floor rises with the highest equity touched &lt;em&gt;during&lt;/em&gt; a trade. A position that prints +$2,200 of open profit ratchets the floor immediately — even if it later closes flat. Or at a loss.&lt;/p&gt;

&lt;p&gt;There's a fourth variant worth knowing: &lt;strong&gt;trailing until break-even&lt;/strong&gt;, where the floor trails your peak but is never allowed above your starting balance. It sounds like a minor detail. It turns out to be the most interesting result in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The simulator
&lt;/h2&gt;

&lt;p&gt;The whole thing is about 45 lines. Two modelling choices matter and I'll flag both:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each trade visits its &lt;strong&gt;favourable extreme first, then its adverse extreme, then closes&lt;/strong&gt;. That "gives back from the peak" shape is precisely what a trailing floor punishes, so this is the conservative assumption.&lt;/li&gt;
&lt;li&gt;The trade can die &lt;strong&gt;at any of those three moments&lt;/strong&gt; — on the spike, on the give-back, or at the close — which is what makes the intraday rule formally distinct from the on-close rule.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CFG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;floorFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// trails the peak, but the floor never rises above break-even&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// trails until the account reaches start + lockProfit, then locks&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_lock3k&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// trails indefinitely&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CFG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trades&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upEq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. favourable excursion — only the intraday rule sees this&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing_intraday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upEq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;floorFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worstRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upEq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upEq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;intratrade-up&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upEq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. the give-back — can breach the intraday rule on its own&lt;/span&gt;
    &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;floorFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worstRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;give-back&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. daily loss limit, measured from this day's starting equity&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;daily&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;daily-limit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dnEq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. close&lt;/span&gt;
    &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;floorFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worstRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ALIVE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;floorFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockProfit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;worstRoom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now feed one fixed trade sequence through all four rulebooks. &lt;code&gt;up&lt;/code&gt; is the favourable excursion, &lt;code&gt;down&lt;/code&gt; the adverse one, &lt;code&gt;close&lt;/code&gt; the settled result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TRADES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1300&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// spike, then give back 1000 of it&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1400&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailing_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing→breakeven&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailing_closed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing on close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailing_intraday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trailing intraday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;simulate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRADES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pnl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pnl&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;padEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BREACHED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; day &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) equity $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; vs floor $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | P&amp;amp;L then: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; equity $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | P&amp;amp;L &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pnl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | peak $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;peak&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | thinnest room $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;worstRoom&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start $50000 | target +$6000 | drawdown $2500 | 11 trades | fee $500

static               ALIVE     equity $49600 | P&amp;amp;L -$400 | peak $55600 | thinnest room $2100
trailing→breakeven   BREACHED  day 11 (give-back) equity $49600 vs floor $50000 | P&amp;amp;L then: -$400
trailing on close    BREACHED  day  8 (give-back) equity $52900 vs floor $53100 | P&amp;amp;L then: +$2900
trailing intraday    BREACHED  day  4 (give-back) equity $52700 vs floor $52700 | P&amp;amp;L then: +$2700
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the last two lines twice. &lt;strong&gt;Both full-trail accounts were up thousands of dollars when they died.&lt;/strong&gt; The trader was not losing. The trader was winning, and still lost the account — while the static account, on identical trades, ended down $400 and perfectly alive.&lt;/p&gt;

&lt;p&gt;And note the break-even row: it survived to day 11, dying at break-even rather than at +$2,900. It lagged the full trail. Why it never dies in profit is the most interesting finding below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the intraday account died on day 4
&lt;/h3&gt;

&lt;p&gt;The mechanism isn't obvious, so here it is at position level:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Entry equity&lt;/th&gt;
&lt;th&gt;Peak touched&lt;/th&gt;
&lt;th&gt;Floor after the peak&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$50,000&lt;/td&gt;
&lt;td&gt;$51,000&lt;/td&gt;
&lt;td&gt;$48,500&lt;/td&gt;
&lt;td&gt;closed +$900, alive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;$50,900&lt;/td&gt;
&lt;td&gt;$51,800&lt;/td&gt;
&lt;td&gt;$49,300&lt;/td&gt;
&lt;td&gt;closed +$800, alive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$51,700&lt;/td&gt;
&lt;td&gt;$53,100&lt;/td&gt;
&lt;td&gt;$50,600&lt;/td&gt;
&lt;td&gt;closed +$1,300, alive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;$53,000&lt;/td&gt;
&lt;td&gt;$55,200&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$52,700&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;a pullback to $52,700 &lt;strong&gt;ended the account&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Trade four printed $55,200 of open profit. That alone dragged the failure floor to $52,700. The position then pulled back to that level and the account was gone — on a trade that, measured from its entry, was never close to being a loser.&lt;/p&gt;

&lt;p&gt;Note what's absent: no bad market call, no revenge trade, no broken stop. The trade &lt;em&gt;worked&lt;/em&gt;. The failure was administrative — the reference point moved while the trader was still measuring risk from the entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now the part that matters: 200,000 accounts
&lt;/h2&gt;

&lt;p&gt;One walk proves a mechanism exists. It says nothing about how often it fires. So I ran each rulebook over 200,000 independent accounts, using the &lt;strong&gt;same seeded trade generator for all four&lt;/strong&gt; — only the rule changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rulebook              passed   breached   still open   breach-while-ahead
static                57.01%    20.40%       22.58%                 0.0%
trailing→breakeven    47.77%    44.15%        8.08%                 0.0%
trailing on close     38.34%    60.12%        1.54%                40.9%
trailing intraday     22.02%    77.93%        0.05%                46.2%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four findings, in order of how much they should change your behaviour:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The spread is enormous.&lt;/strong&gt; Same trades, same target — pass rates from &lt;strong&gt;22% to 57%&lt;/strong&gt;. If you believe you have "a 50% pass rate," you don't. You have a pass rate &lt;em&gt;against one rulebook&lt;/em&gt;, and it can more than double without you changing anything about how you trade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. About 4 in 10 full-trail breaches happen while the account is in profit&lt;/strong&gt; (40.9%, 46.2%). The day-4 story is not an unlucky anecdote — it is the largest failure mode of the trailing rule, at population scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The two rulebooks whose floor cannot rise above break-even both show 0.0%.&lt;/strong&gt; Not just static — also &lt;code&gt;trailing→breakeven&lt;/code&gt;, which genuinely does trail your peak and is measurably harder than static (47.77% vs 57.01%).&lt;/p&gt;

&lt;p&gt;That's the finding I didn't expect, and it isolates the mechanism exactly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Died while winning" is not a property of trailing drawdown. It happens &lt;strong&gt;if and only if the floor is allowed to rise above your starting balance.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a firm says the floor stops at break-even, that one sentence deletes the entire failure category responsible for ~4 in 10 trailing breaches. Worth more than any comparison-table column.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The 0.0% is by construction, not by discipline.&lt;/strong&gt; No skill is being measured in that column. It's a property of the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  What that spread costs
&lt;/h2&gt;

&lt;p&gt;Feed the measured pass rates into &lt;code&gt;E[attempts] = 1/p&lt;/code&gt; with the same $500 fee:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rulebook             pass rate p   E[attempts]   E[fee spend]   vs advertised fee
static                    0.5701          1.75          $877              1.75x
trailing→breakeven        0.4777          2.09        $1,047              2.09x
trailing on close         0.3834          2.61        $1,304              2.61x
trailing intraday         0.2202          4.54        $2,270              4.54x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identical headline price. Expected bill differing &lt;strong&gt;by a factor of 2.5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Choosing a static account over an intraday-trailing one is a &lt;strong&gt;bigger financial decision than choosing a $500 account over a $1,250 one&lt;/strong&gt; — and nobody advertises it that way, because the fee is the number that fits on a button.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pass rate isn't a number, it's a distribution
&lt;/h2&gt;

&lt;p&gt;Twenty independent runs of the intraday rulebook, 5,000 accounts each:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;min 20.82%   median 22.04%   max 23.32%
mean 22.05%   SD 0.68pp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things here, pointing in opposite directions.&lt;/p&gt;

&lt;p&gt;Reassuring: the run-to-run spread is under a percentage point, so the 22%-vs-57% gap above is &lt;strong&gt;real signal, not sampling noise&lt;/strong&gt;. The ordering is robust.&lt;/p&gt;

&lt;p&gt;Uncomfortable: a pass rate isn't a fact about a firm you can look up. It's the output of a distribution that shifts when &lt;em&gt;you&lt;/em&gt; shift. The only pass rate worth planning around is one you've measured on your own record against the specific rulebook you're about to trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  The daily loss limit, which dominates everything else
&lt;/h2&gt;

&lt;p&gt;Real evaluations usually carry a daily loss limit as well as a maximum drawdown. I modelled it separately, because the interaction is not obvious. Same $50,000 account, same $2,500 maximum drawdown. The worst single loss in the generator is $600 and the worst adverse excursion is $1,000.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daily limit                static   trailing on close   trailing intraday   binding-limit share of breaches
none                      57.01%              38.34%              22.02%   0.0% / 0.0% / 0.0%
$1250                     57.01%              38.34%              22.02%   0.0% / 0.0% / 0.0%
$1000                     57.01%              38.34%              22.02%   0.0% / 0.0% / 0.0%
$900                      27.75%              21.60%              14.44%   83.4% / 55.4% / 36.4%
$800                       5.60%               5.32%               4.60%   97.0% / 91.5% / 79.8%
$700                       1.04%               1.04%               1.02%   99.7% / 99.3% / 96.8%
$600                       0.24%               0.24%               0.24%   100.0% / 100.0% / 99.8%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a phase change here, and it happens inside a very narrow band.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At $1,000 and above the limit is completely inert&lt;/strong&gt; — pass rates identical to the no-limit run, 0.0% of breaches. A limit that far from your normal loss size is decoration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Between $900 and $800 it becomes the dominant failure mode.&lt;/strong&gt; At $900 it explains 83% of static breaches and halving pass rates. By $800 it explains 79–97% of all breaches and the static pass rate collapses from 57% to 5.6%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By $600 the drawdown rule stops mattering at all.&lt;/strong&gt; All three rulebooks converge on 0.24% — within rounding error — and 100% of breaches are the daily limit. Static, trailing-on-close and intraday become &lt;em&gt;the same product&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The reading is uncomfortable and useful in equal measure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A daily loss limit set anywhere near the size of your worst single loss doesn't add a constraint to the drawdown rule; &lt;strong&gt;it replaces it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything on the comparison table becomes irrelevant, and you've spent real effort choosing between rulebooks while the rule that actually ends your account sat underneath all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the trail stops: the highest-value fact on your dashboard
&lt;/h2&gt;

&lt;p&gt;I ran the two trailing rulebooks with the trail stopping at a +$3,000 profit lock, against trailing indefinitely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trailing on close      full trail  38.34%  →  locked at +$3,000  45.99%   (+7.66pp)
   E[fee spend]  $1,304  →  $1,087
trailing intraday      full trail  22.02%  →  locked at +$3,000  45.99%   (+23.97pp)
   E[fee spend]  $2,270  →  $1,087
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locking at +$3,000 takes the intraday pass rate from &lt;strong&gt;22% to 46%&lt;/strong&gt; and cuts expected fee spend from &lt;strong&gt;$2,270 to $1,087&lt;/strong&gt; — more than halving the cost of the same account at the same price.&lt;/p&gt;

&lt;p&gt;Note the two rows converge on exactly 45.99%. Once the floor is locked, the intraday/on-close distinction stops existing: a floor that can't move can't be breached by an intratrade excursion. &lt;strong&gt;Reaching the lock is not a milestone on the way to the target — it is the objective&lt;/strong&gt;, and treating it that way is a different trading plan to "hit $6,000."&lt;/p&gt;

&lt;h2&gt;
  
  
  Does skill help equally under every rulebook?
&lt;/h2&gt;

&lt;p&gt;This decides whether rulebook-shopping substitutes for getting better. Same rulebooks, five win rates, identical trade sizes so the only variable is decision quality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;win rate   static   trailing on close   trailing intraday   static minus intraday
    40%      8.02%                4.98%                2.63%                  5.4pp
    45%     27.10%               16.94%                9.01%                 18.1pp
    50%     57.01%               38.34%               22.02%                 35.0pp
    55%     82.67%               62.51%               40.46%                 42.2pp
    60%     95.03%               81.01%               60.10%                 34.9pp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Skill is worth more than the rulebook — on the easy rulebooks.&lt;/strong&gt; Going 50% → 55% takes the static pass rate from 57% to 83%, a 26-point swing, larger than the entire 35-point static-vs-intraday gap at 50%. If you can improve, improving is the higher-return activity. Nothing here argues for settling for a bad rulebook instead of trading better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But harder rulebooks convert skill into pass rate less efficiently.&lt;/strong&gt; At 55% the gap is the widest in the table: 82.67% static versus 40.46% intraday. A trader at that skill level gets less than half the benefit from their own improvement on a trailing-intraday account, because a large share of their good outcomes is being consumed by a floor that rises while they win.&lt;/p&gt;

&lt;p&gt;The 40% row is worth reading separately: all three rulebooks are in the single digits, because the model is running at slightly negative expectancy there. &lt;strong&gt;Rulebook choice is a second-order question for a trader whose edge isn't yet positive.&lt;/strong&gt; Get the edge first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The buffer result that surprises people
&lt;/h2&gt;

&lt;p&gt;Trailing $2,500 on a $50,000 account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;peak equity   floor    room from peak   room if 1,500 off the peak
        +$0   $47500      $2500                             $1000
     +$1000   $48500      $2500                             $1000
     +$2000   $49500      $2500                             $1000
     +$2500   $50000      $2500                             $1000
     +$3000   $50500      $2500                             $1000
     +$5000   $52500      $2500                             $1000
    +$10000   $57500      $2500                             $1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every row is identical. &lt;strong&gt;An account up $10,000 has exactly the same room as one at break-even&lt;/strong&gt;, provided both sit $1,500 below their own peak.&lt;/p&gt;

&lt;p&gt;That's the formal statement of the whole post. On a static account a buffer is defensive capital you can spend down. On a full trail it isn't, because the floor has already risen to match it. The only variable that helps is your distance from your own high-water mark — at every moment, including intratrade. Or, better, holding an account where the floor isn't allowed above break-even, which makes the whole category of failure arithmetically impossible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning the threshold into a position size
&lt;/h2&gt;

&lt;p&gt;The useful thing about a trailing threshold is that it converts into contract counts exactly, because futures ticks are fixed-dollar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contracts = (risk fraction × threshold) ÷ (stop distance in ticks × value per tick)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On $50,000 with a $2,500 threshold, a 10% risk budget is $250. Ten-point stops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract   stop (pts)   $/contract   contracts allowed   verdict
MES                10        $50.00                   5        ok
ES                 10       $500.00                   0   not tradeable at this risk
MNQ                10        $20.00                  12        ok
NQ                 10       $200.00                   1        ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why &lt;strong&gt;micros are not a beginner's concession&lt;/strong&gt; on a trailing account — they're the only instruments where a $250 risk budget exists at all. On ES the permitted size is zero, and one contract is double your entire per-trade budget against a floor that's still moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode this model doesn't cover: the consistency rule
&lt;/h2&gt;

&lt;p&gt;Everything above stops at the profit target, which is why it models the drawdown rules well and the consistency rule not at all. That's a real gap, because consistency is a &lt;em&gt;separate&lt;/em&gt; failure mode with a different shape: it doesn't breach your account — it blocks your payout after the account is already passed.&lt;/p&gt;

&lt;p&gt;The typical rule: no single day (or single trade, depending on the firm) may account for more than a set share of your total profit — commonly 30% to 50%. The arithmetic that follows is not obvious and it is brutal.&lt;/p&gt;

&lt;p&gt;Take a $6,000 target with a 40% consistency cap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;target                 $6,000
consistency cap        40% of total profit
day one result         +$6,000  (target hit — and the payout is blocked)

to satisfy the cap:  best day ÷ total profit ≤ 0.40
                      6,000 ÷ total ≤ 0.40
                           total ≥ 15,000

profit still required:
  $15,000 − $6,000 = $9,000 more, after already hitting the target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hitting the target in one good day doesn't just fail to finish the job — it raises the finish line by 150%. You finish that account at $15,000 instead of $6,000, and every one of those extra dollars is traded on a floor that has been ratcheting up the whole time.&lt;/p&gt;

&lt;p&gt;The practical consequence is that the target and the finish line are different numbers, and they diverge most for the traders who are best at the thing the challenge measures. Someone who can put together one exceptional day is penalised by exactly that skill. This is why "paced to a payout-ready distribution" and "hit the target" are two different plans, and why an account that shows a pass can still be weeks away from paying.&lt;/p&gt;

&lt;h2&gt;
  
  
  A five-minute check on your own account
&lt;/h2&gt;

&lt;p&gt;Before you apply any of the above, pull your actual rulebook and answer five things. Write the numbers down — a rule you can't quote from memory is one you'll misread at the moment it matters.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Daily loss limit&lt;/strong&gt; — the figure, and whether it is measured from the day's starting equity or including open float. Compare it to your worst normal single loss. If it's within a stone's throw, it's your real failure line, and nothing else on this list matters as much.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drawdown type&lt;/strong&gt; — static, trailing on close, or trailing intraday. Look for "trailing," "high-water," "follows your highest balance." The wording is often indirect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where the trail stops&lt;/strong&gt; — break-even, a stated lock level, or never. If the rulebook doesn't say it stops, assume it doesn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The lock level&lt;/strong&gt; — because reaching it changes which rulebook you're effectively trading. Getting there is the first objective, not a milestone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The consistency rule&lt;/strong&gt; — the percentage and the measurement period. Multiply it out the way I did above to find your true finish line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Five numbers, five minutes, and they determine your expected cost more than the account size or the fee ever will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this model is wrong
&lt;/h2&gt;

&lt;p&gt;A simulation you can't audit is just an opinion with numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trades are independent and identically distributed.&lt;/strong&gt; Real trading clusters, and a rule that punishes give-back punishes clustering &lt;em&gt;harder&lt;/em&gt; than independence predicts. This makes the trailing figures &lt;strong&gt;conservative&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The winner/loser mix is fixed&lt;/strong&gt; at 50/50, winners $300–800, losers −$200 to −$600 — plausible but arbitrary. Low win rate with large winners will look worse on trailing rules, because big winners are exactly what ratchet the floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Favourable-then-adverse is an assumption.&lt;/strong&gt; Real trades sometimes reverse first, which would flatter the intraday rule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The lock is modelled at two specific values&lt;/strong&gt; (break-even and +$3,000). Real firms pick their own; the measured gap between those two is large, which is the point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The daily limit is a fixed dollar figure from the day's starting equity.&lt;/strong&gt; Some real rules include the day's open float, which is stricter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most assumptions push the same way: the true spread between rulebooks is &lt;strong&gt;wider&lt;/strong&gt; than shown. The percentages are illustrative. The ordering isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd actually do with this
&lt;/h2&gt;

&lt;p&gt;Before comparing any two firms on price, check two rules, in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The daily loss limit.&lt;/strong&gt; If it's anywhere near your worst single loss, it &lt;em&gt;is&lt;/em&gt; your failure line and everything else is colour. This is the highest-value line on the dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can the drawdown floor rise above your starting balance?&lt;/strong&gt; If no, you cannot be killed while in profit. If yes, ask where it stops — break-even, a profit lock, or never.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then, and only then, compare fees. Get either of the first two wrong and you'll size a position correctly for a different account than the one you're trading — which is the failure this post describes, expressed in dollars instead of trades.&lt;/p&gt;

&lt;p&gt;Two things worth doing before you commit to a rulebook. Run your own numbers through the &lt;a href="https://elitepropx.com/tools/prop-firm-profit-calculator.html" rel="noopener noreferrer"&gt;drawdown and challenge-cost calculator&lt;/a&gt; — it turns a measured pass rate into an expected fee across all four rulebooks above. And if you would rather not put your own evaluation through a rising floor at all, the &lt;a href="https://elitepropx.com/services/passing-prop-firm-services.html" rel="noopener noreferrer"&gt;done-for-you evaluation passing service&lt;/a&gt; trades the account for a flat $220.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Every figure in this post is the actual stdout of the simulator above, at a fixed seed. Paste the two code blocks into a file and run it: set &lt;code&gt;CFG.dd&lt;/code&gt; to a static-account value and watch every trailing breach in the single walk vanish, or set &lt;code&gt;CFG.daily = 600&lt;/code&gt; and watch all three rulebooks collapse to the same number.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>trading</category>
    </item>
    <item>
      <title>The expected value of a prop firm challenge, in Python</title>
      <dc:creator>Okeke Jenny</dc:creator>
      <pubDate>Mon, 28 Sep 2026 09:34:39 +0000</pubDate>
      <link>https://dev.to/elitepropx/the-expected-value-of-a-prop-firm-challenge-in-python-5g9i</link>
      <guid>https://dev.to/elitepropx/the-expected-value-of-a-prop-firm-challenge-in-python-5g9i</guid>
      <description>&lt;p&gt;Most "is this challenge worth it" comparisons stop at fee vs account size. That comparison is missing the two numbers that actually decide it: &lt;strong&gt;how many attempts you will need&lt;/strong&gt;, and &lt;strong&gt;what the whole exercise averages out to&lt;/strong&gt;. Both are easy to compute, and computing them changes the answer more often than any firm comparison does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;

&lt;p&gt;Four inputs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;challenge fee — &lt;strong&gt;per attempt&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;profit target in dollars (account size x target %)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;your profit split (the share you keep)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;your probability of passing a single attempt&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything else is derived:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;net payout &lt;code&gt;N = T * s&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;expected attempts &lt;code&gt;E = 1 / p&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;expected fee outlay &lt;code&gt;C = F * E&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;expected value of the venture &lt;code&gt;V = N - C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;expected value per attempt &lt;code&gt;v = p * N - F&lt;/code&gt; (which is &lt;code&gt;V * p&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting &lt;code&gt;V = 0&lt;/code&gt; gives a result worth memorising: the &lt;strong&gt;break-even pass rate&lt;/strong&gt; is &lt;code&gt;p* = F / N&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;challenge_ev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_pct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Expected value of buying a prop firm challenge until you pass.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;target_pct&lt;/span&gt;
    &lt;span class="n"&gt;net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;
    &lt;span class="n"&gt;e_attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;pass_rate&lt;/span&gt;
    &lt;span class="n"&gt;expected_fees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;e_attempts&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;net_payout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e_attempts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_fee_outlay&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;expected_fees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ev_venture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expected_fees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ev_per_attempt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pass_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;break_even_pass_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.70&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;challenge_ev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;550&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_fee_outlay&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ev_venture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A $100k account, an 8% target ($8,000 gross), an 80% split, a $550 fee:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20%  E=5.00  fees=$2,750  EV=$3,650
35%  E=2.86  fees=$1,571  EV=$4,829
50%  E=2.00  fees=$1,100  EV=$5,300
70%  E=1.43  fees=$786    EV=$5,614
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the numbers say
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The break-even pass rate is much lower than people assume.&lt;/strong&gt; With a $6,400 net payout and a $550 fee, &lt;code&gt;p* = 8.6%&lt;/code&gt;. You do not need to be good, you need to be better than one attempt in twelve. That is the useful way to read a challenge: not "is this hard", but "am I above 8.6%".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The fee is per attempt, and the expected outlay is a multiple of it.&lt;/strong&gt; At a 35% pass rate you will buy 2.86 challenges on average, not one — so a "$550 challenge" is a ~$1,571 decision. Firms advertise the per-attempt price because it is the smaller number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Improving the pass rate is worth more than shopping for a cheaper firm.&lt;/strong&gt; Moving 35% to 50% adds roughly $470 of expected value; cutting the fee from $550 to $450 adds roughly $130. Optimising the input you actually control dominates optimising the marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The split compounds, the fee does not.&lt;/strong&gt; The fee is paid once per attempt; the split applies to every payout, forever. Two firms with the same target and a 10-point split difference are not close, and a single-challenge EV view hides that completely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two inputs people get wrong
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;p&lt;/code&gt; is the hard one, and it is hard because of memory, not dishonesty: traders benchmark against the attempt they remember passing, not the ones they quietly failed. If you are unsure, start at 30-40% for a self-traded challenge and see whether the number still works. If it does not survive a conservative pass rate, it was never a good bet — it was a good feeling.&lt;/p&gt;

&lt;p&gt;Split is the other. Enter the share &lt;strong&gt;you&lt;/strong&gt; keep, applied to net profit, not the target. Reading an 80% split as though the payout equals the target is the single most common arithmetic error in this category.&lt;/p&gt;

&lt;p&gt;Two things this model deliberately does not include: consistency rules (they change &lt;em&gt;when&lt;/em&gt; you can withdraw, not the total — but a blocked payout is worth less than an available one) and taxes, platform fees and transfer costs (small individually, not always small together).&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on what I do
&lt;/h2&gt;

&lt;p&gt;I run a &lt;a href="https://elitepropx.com/services/passing-prop-firm-services.html" rel="noopener noreferrer"&gt;flat-fee prop firm passing service&lt;/a&gt;, so read this with that in mind. The math above is the argument for it, and it is also the argument against it: a service makes sense exactly when it raises &lt;code&gt;p&lt;/code&gt; toward 1 and replaces a cost that scales with your failures with one that does not. Run your own numbers twice — once at your honest self-traded pass rate, once at a near-certain one — and compare the gap to the fee. If the gap is smaller than the fee, trade it yourself.&lt;/p&gt;

&lt;p&gt;If you just want the numbers without writing the script, I put the same model in a free browser calculator, no signup: &lt;a href="https://elitepropx.com/tools/prop-firm-profit-calculator.html" rel="noopener noreferrer"&gt;prop firm profit calculator&lt;/a&gt;. It returns expected attempts, expected fee outlay, expected value per attempt and the break-even pass rate. If you write about this, it is also &lt;a href="https://elitepropx.com/tools/prop-firm-calculator-embed.html" rel="noopener noreferrer"&gt;embeddable with one line of HTML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The formula is four lines of Python either way. The value is in running it before you buy, rather than after the third retry.&lt;/p&gt;

</description>
      <category>python</category>
      <category>playwright</category>
    </item>
  </channel>
</rss>
