The Minerva Tester
Signals, parameters, strategies, backtests, and optimizations
A signal is a rule derived from historical data that indicates which direction to trade: go long, go short, or stay flat. "Buy when the price has risen for three days, sell when it falls for two" is an example of a trading signal: three consecutive up days generate a long signal and two consecutive down days generate a short signal.
A parameter is an adjustable value used to govern how a signal trades. In the example above, there are two parameters: the number of consecutive up days required to go long and the number of consecutive down days required to go short. Setting those values to 3 and 2 gives one parameter configuration, which can be written as (3, 2).
A strategy is a set of rules that specifies how and when to trade based on a signal, including rules for position sizing and, where applicable, risk controls. A strategy is what makes or loses money. While a signal indicates a trading direction, it is a strategy that defines the full trade that produces a profit-and-loss result.
A backtest applies a single strategy, using one specified parameter configuration, to a specified historical time series, one bar (i.e., time increment) at a time, sizing each position and applying the relevant trading costs. It produces a simulated account value over that period (also known as an equity curve). A backtest evaluates a single parameter configuration; it is not graded or certified.
An optimization tests multiple parameter configurations to determine which version of a strategy performs best. In the example above, an optimization might vary the number of consecutive up and down days required to generate each signal, testing combinations such as (2, 2), (2, 3), (3, 2), and (3, 3). Each configuration produces its own backtest. The configurations are compared using a performance criterion, and one configuration is ultimately selected as the winner. In the framework used at Minerva, the criterion is the Sharpe ratio, and that selection is based on held-back validation performance, after which the winner is submitted for certification. It may pass or fail one or more mathematical gates, while a separate evidence-floor warning indicates whether the historical record is broad enough to interpret comfortably. The Optimizations section below walks through the full pipeline, and Sections 6 and 7 cover the certification machinery: the five-gate Seal, the evidence diagnostic, and the score.
With these definitions in place, it is important to recognize that profitable historical performance does not necessarily identify a robust strategy. There are two distinct problems. First, the backtest itself may be unrealistic—for example, by allowing a signal to use prices that would not yet have been known or by ignoring trading costs. Second, even a properly constructed backtest may show strong historical performance simply because a favorable strategy was found by chance, particularly when many alternatives were tested. A backtest therefore tells us how a particular strategy performed on a particular historical sample; additional evidence is needed to determine whether that performance is credible and robust.
01Optimizations
A step-by-step description of what happens between pressing Run and receiving your result.
01What an optimization does
An optimization takes a trading signal — a rule that decides, bar by bar, whether to be long, short, or flat — and searches for the parameter settings that make it trade best. A parameter variation is one complete set of values for the settings the signal exposes: for example, a 20-bar lookback with a 2% entry threshold and a 5% stop is one variation; a 30-bar lookback with the same threshold and stop is another. You choose the signal, a ticker or a universe of tickers, a date range, trading costs, and a position-sizing method. Minerva then tests tens of thousands of variations — each one a full simulated trading run with real costs — and selects one winning variation for each ticker.
Throughout the run, a variation's performance is measured by its Sharpe ratio: the strategy's average return divided by how much its returns fluctuate, annualized. It is a risk-adjusted measure — steady profits score higher than the same profits earned with wild swings. When this page says a variation is "scored" or "graded," it means: the variation was run as a simulated strategy over a specific stretch of history, its trades were placed and its costs charged, and the Sharpe ratio of the resulting account returns was computed.
One problem shapes the whole design. When tens of thousands of variations are scored on the same history, the best score is inflated by chance: even if every variation were worthless, one would still come out on top and look impressive. Measuring the winner on the same data used to pick it would measure the luck of the search, not the strategy. So the run is split in two. All searching and selecting happens in the development window, the earlier part of your date range. The reported numbers come from the final holdout, the reserved last part, which is examined once, at the end, after the winner is already fixed.
The whole run, in order
- Preflight. Minerva checks that the request can actually run — enough history for the signal, price data available for every ticker — and quotes the price. Nothing is charged if it cannot run. Each accepted submission starts an independent job, even when its settings match a prior run.
- Reserve the final holdout. The date range is cut into thirteen equal blocks, and the last three are locked away before any backtest runs. The first ten become the development window.
- The CPCV search — the main search, run inside the development window only:
- The development window is cut into ten equal time periods.
- Minerva forms every possible combination of three periods to hold back for scoring. Each combination is called an arrangement; ten periods give 120 of them.
- Protective gaps — the purge and the embargo, explained in the CPCV section below — are cut wherever tuning data meets scoring data, so information cannot leak between the two.
- Inside each arrangement, Minerva scores an initial group of 128 parameter variations, keeps the best of them, builds new variations by mixing the settings of the good ones, and repeats that cycle three times.
- The best-scoring variation found in each arrangement is kept as that arrangement's winner — up to 120 winners in total.
- Walk-forward evaluation. Each distinct winner is scored again in strict time order: run on a stretch of history, scored on the stretch immediately after it, slid forward, and repeated across the development window. This is one separate pass; it does not happen inside the arrangements.
- Plateau screen. Each top winner is re-scored alongside near-copies of itself — the same settings nudged slightly up and down. A winner whose near-copies also score well beats a winner that only works at its exact settings.
- Freeze the winners. One winning variation per ticker is permanently recorded, before the reserved holdout data is touched.
- Grade on the holdout. Each frozen winner is run once across the reserved final months; that single run produces the performance you see.
- Final report. Five statistical checks decide the Robustness Seal, the MinervaScore summarizes the margin, and you receive one results row and one full P&L report per ticker.
02Preflight: checking and pricing the request
Preflight verifies that your request can produce a valid result before anything is accepted or charged: the date range must contain enough history for the signal's warmup (the bars an indicator needs before it can produce its first value), the validation windows described below must fit, and price data must exist for each ticker over those dates. When a longer date range would fix a problem, the message includes a specific recommended range you can apply with one click. When nothing can fix it — the required history would begin before Minerva's earliest available data, say — the request is refused with the reason.
The same stage prices the run, from the exact number of individual backtests the request will execute. Each accepted submission is priced and run as an independent job; matching settings from an earlier run do not reopen or reuse that result.
k+1 validation groups could remain scoreable after warmup; it is one-sided and refuses only requests that provably cannot work. The committed budget counts the inner search (128 × 3 + 1 = 385 evaluations per arrangement at defaults), the overfitting-probability fold matrix, the walk-forward evaluations, the plateau screen, and the holdout runs, per ticker.03Reserving the final holdout
Minerva divides your date range into thirteen equal blocks and reserves the last three as the final holdout, before any backtest executes. The boundary never moves afterward. That timing is the point: a test period chosen after seeing results could be chosen — deliberately or not — to flatter them. Fixed in advance, the holdout works like an exam printed and sealed before the course begins. Every stage that follows runs on the earlier ten blocks; the reserved data is read exactly once, during the holdout grading stage.
floor(total_days / 13) calendar days; the holdout is the final three blocks — about 168 days on the default two-year range. The holdout's exact dates and protocol version are recorded when the run is created, and a registry logs the first time it is consumed.04The CPCV search
The search stage is named Combinatorial Purged Cross-Validation, and each word describes part of what it does.
Cross-validation means the data is split into two roles that are kept apart: tuning data, which the search uses to try out and refine parameter variations, and grading data, which is held back and used only to score them. A variation that scores well on the data it was tuned on proves little — the tuning may simply have fit that data's random noise. A good score on held-back data the variation never influenced is much better evidence of a real edge. The roles then rotate, so every part of the data takes a turn at grading.
Combinatorial means every rotation is used. Minerva cuts the development window into ten equal periods and forms every way of holding three of them back for grading: 120 distinct arrangements. Using all combinations, rather than one split, prevents the verdict from depending on where a single dividing line happened to fall — one grading stretch might have been an unusually easy or unusually hard piece of market history.
Purged refers to two gaps cut at every boundary between tuning and grading data, because information can leak across a boundary in two ways. A trade opened near the end of a tuning period can still be open when the grading period starts; its profit or loss then depends on grading-period prices, so counting it in tuning would leak grading information backward. The purge deletes those straddling trades. And because prices on consecutive days are correlated, the bars just after a grading period still echo it; the embargo drops a slice of those bars too. Without the gaps, tuning would get partial credit for data it was supposed to never see.
What happens inside one arrangement
Within each of the 120 arrangements, Minerva runs a genetic search — a procedure that improves a pool of parameter variations the way selective breeding improves a herd, keeping what works and recombining it:
- An initial population of 128 parameter variations is generated at random within the ranges you declared for each parameter.
- Every variation is scored: it is run as a complete simulated strategy — trades placed, costs charged — over the arrangement's tuning periods, and its Sharpe ratio is computed from the grading periods only.
- A new population of 128 is built for the next round. The highest-scoring variations survive into it unchanged. The rest of the slots are filled with new variations, each created by taking two high-scoring variations (the "parents"), building a child that inherits each parameter value from one parent or the other at random, and then nudging some of the child's values by a small random amount. The first mechanism (crossover) combines settings that worked; the second (mutation) keeps the search exploring values no current variation has.
- Scoring and rebuilding repeat for three rounds ("generations").
- The variation with the best grading-period Sharpe ratio seen at any point in the search is recorded as that arrangement's winner. The contest is within the arrangement: 128 variations × 3 generations competing on that arrangement's grading periods.
Two scoring rules apply everywhere. First, a Sharpe ratio computed from one or two trades is statistically meaningless no matter how large it is, so the ranking always prefers a solid score built on many trades: a Sharpe of 2 from fifty trades beats a Sharpe of 99 from one trade. Second, when your run covers more than one ticker, each variation is scored separately on every ticker, and those scores are then reduced to a single number: the middle one, the median. Ranking on the middle score means a variation has to trade well on most of your tickers to rank highly. A variation that does brilliantly on one ticker and poorly on the rest still ranks by its middle result, so it loses to a variation that is merely good everywhere.
05The walk-forward evaluation
The CPCV search leaves up to 120 arrangement winners — usually fewer once duplicates are removed, because the same variation often wins several arrangements. Each unique winner is now scored once more, in strict chronological order. This walk-forward pass runs the variation on a training window of history, grades it (by Sharpe ratio, as always) on the period immediately after, slides both windows forward, and repeats across the development window.
This is a single, separate pass per variation — it does not run inside the 120 arrangements, and it is not repeated later. It exists because CPCV deliberately shuffles time so that no single era dominates the grading, while live trading experiences the market strictly in order. The walk-forward measures each winner the way an actual deployment would have experienced it, era by era, and its per-variation (and, for universes, per-ticker) results become the quality evidence the next two stages consume.
06The plateau screen: testing the winners for parameter stability
Minerva does not simply crown the highest scorer among the surviving winners — the maximum of many noisy scores is itself inflated by chance, the same selection effect described in the first section at a smaller scale. Instead, the leading winners are tested for parameter stability.
The reasoning: if a strategy captures something real about how a market behaves, small changes to its parameters should degrade its performance gradually. A moving-average rule that genuinely works with a 20-bar window should still work reasonably well at 18 or 22 bars. If performance collapses the moment a parameter moves one step, the original result was almost certainly fitted to noise — the "edge" existed at one exact coordinate rather than in the market. A region of parameter space where performance stays consistently good is a plateau; a single isolated high point is a peak.
To measure this, each leading winner becomes the center of a small neighborhood: every numeric parameter is stepped slightly down and slightly up, producing a set of variations that are nearly identical to the winner. Each neighbor is scored across a balanced subset of the 120 arrangements, and each also receives the walk-forward evaluation from the previous section. Neighborhoods where the center and its neighbors score well rank ahead of isolated spikes. Within the winning neighborhood, the final choice is the member whose worst ten percent of arrangements is least bad — a deliberately pessimistic criterion, because an average can conceal a variation that fails badly in particular market conditions. The published winner is therefore the most stable strong variation, which is not always the one with the single highest score.
07Freezing the winners
Selection ends with the freeze: for each ticker, one winning variation — the plateau screen's choice, backed by its walk-forward evidence — is written to durable storage. A ticker is excluded only for structural defects in its evidence, such as incomplete validation coverage — never for merely trading thinly or scoring poorly. A thin result is published honestly and remains uncertified rather than hidden.
What this means when you run several tickers at once is worth stating plainly, because it is not what most people assume. Minerva does not run a separate, independent optimization for each ticker. It runs one search for the whole list, ranked on the middle ticker's score, and that search ends by picking a single stable neighborhood of settings — one small region of the parameter space where performance holds up when the settings are nudged. Only then does each ticker choose, and it chooses from inside that one neighborhood. So your tickers end up with settings that differ from each other, but only slightly: they are neighbors, drawn from the same region, not independent answers to separate questions. A ticker cannot go off and use settings from somewhere else in the parameter space just because those settings happened to suit it.
In order, a multi-ticker run does this:
- Search settings that are tried against the whole list at once, ranked on the middle ticker's score.
- Settle on one winning neighborhood of settings for the entire list.
- Give each ticker the option inside that neighborhood with its highest Sharpe.
- Lock every ticker's assignment before the holdout is opened.
The neighborhood is smaller than it may sound. It is one set of settings at the center, plus — for each numeric setting being optimized — one variant nudged down and one nudged up, with nothing else changed. Optimize four numeric settings and the neighborhood holds at most nine options: the center and eight single-setting variants. Usually fewer, because a nudge that would run past a setting's allowed range, or break a rule such as a fast period having to stay below a slow one, is dropped. Settings that are on/off or pick-from-a-list contribute no variants at all. That is the entire menu each ticker chooses from.
Two consequences follow. A setting that would have been ideal for one ticker alone will usually not be chosen, because it has to survive the whole list first. And the tickers you include change the result for every other ticker, since they all influence which neighborhood wins. If you want a ticker judged entirely on its own merits, run it on its own.
Whether the run covers one ticker or fifty, the frozen record is checked and only then is the holdout opened. Nothing measured on the holdout can change which settings were chosen, reverse an exclusion, or swap in a different variation that happened to score better there.
One more thing happens at the freeze when a run covers several tickers. Your results table needs a single row to stand for the run as a whole — the one whose numbers appear on the run's summary card and prefill the settings if you launch another run from it. Minerva marks that row Frozen run headline. It is simply the ticker with the strongest development score, picked before the holdout is opened. It is one ticker's result, not an average or a summary of the others: the remaining tickers each keep their own row, their own settings, and their own numbers, and are marked Optimization result. Read the headline row as "this was the best of the list on the evidence available before the final test," not as "this is what the run achieved."
08Grading the winner on the holdout
Each frozen ticker-and-winner pair is replayed across the final holdout in a single continuous simulation: a fresh account, full commissions and slippage, and the signal's indicators warmed from prior history exactly as they would be at a live launch. The outcome of this replay is the result, favorable or not. No rule substitutes a different variation that happened to do better on the holdout, no losing ticker is dropped, and there is no second attempt — any of those would turn the holdout into one more thing the search had optimized, and its grade would stop being independent.
The headline Sharpe ratio is computed from this replay's daily account returns. Daily returns are correlated from one day to the next; that correlation makes a naive volatility estimate too small, which would overstate the Sharpe. The reported figure applies a Newey–West adjustment, a standard statistical correction for exactly that problem. If the holdout produces too little activity to support the calculation, the field reports no value along with the reason, rather than substituting a number that looks precise but is not.
√252, and adjusted with Newey–West (Bartlett weights, lag ⌊S^1/3⌋ for S sessions). A degenerate series yields a null Sharpe with an explicit reason code; there is no fallback to the unadjusted estimator. The per-bar Sharpe is retained as a separate field for the validation mathematics. Holdout evaluations of non-selected sibling variations exist only as internal family diagnostics and can never be published as results.09The final report
The finished result passes through five statistical gates, each asking a different version of "could this be luck?": a Sharpe ratio deflated by the size of the search that produced it; the measured probability that the search overfit; a bootstrap test of skill against pure chance; a check that the track record is long enough to support the Sharpe it claims; and a check that performance held up across different market periods, including the worst one. A result must pass all five to receive the Robustness Seal. The MinervaScore, from 0 to 100, expresses how far the result sits from those thresholds — 80 or above always means the Seal passed. A separate evidence note flags a record too thin to judge confidently; it informs your reading but does not change the verdict. The score ranks robustness evidence; it is not a prediction or a guarantee of future performance.
Your report contains one results row and one complete P&L report per ticker, each bound to that ticker's frozen winner, with the same figures appearing consistently in the results table, the report, and the trial ledger used by the Portfolio Generator. All of it is downloadable. Submitting the same settings again starts a separate job, and Minerva does not regenerate an unavailable report artifact through a recovery replay. A strategy that qualifies can then carry its exact tested configuration into paper trading, which executes with the same fills, costs, and trade lifecycle that produced the grade you just read.
Research software. Backtested and simulated results are hypothetical and not indicative of future returns. Nothing here is investment advice.
02The three signal types
A signal is a trading model's point-in-time opinion. It reads the data available at a bar and emits a forecast or target state: positive means long, negative means short, and zero means flat or no new position. The magnitude can carry signal strength. It is not the whole trade: position size, leverage, liquidity, commissions, slippage, stops, and circuit breakers are added by the strategy and simulator layers.
The signal contract also says what the opinion does to an open position. A long forecast can mean "be long now," "start a long trade that has a scheduled holding length," or "enter long and keep watching for an exit condition." Those are different promises. They change how Minerva grades the strategy, and they change how a user should read the paper-trader decision trace.
Every paper-trader trace separates signal opinion from paper execution. The decision badge shows what the signal wanted on that bar: BUY, SELL, HOLD, or a blocked decision. The reason text explains why. The forecast and strength numbers show conviction. The order line shows what the paper account actually did: no order, a filled quantity and price, or a blocked/skipped outcome. That distinction matters when you map the trace onto your own portfolio.
For a manual portfolio, read the trace in position terms: BUY means add or enter long exposure, or cover an existing short. SELL means reduce or exit long exposure, or open short exposure only if your rules allow shorts. HOLD means no new action from the signal at that bar. A strong forecast with "no order placed" means the signal opinion existed, but the paper account did not trade because the position, risk settings, cash, shorting permission, warmup state, or another gate prevented it.
Those BUY/SELL/HOLD meanings depend on which of three signal types the trading signal declares. Signal Type 1 treats the output as the position to hold now. Signal Type 2 treats the output as an entry event with a known holding or review horizon. Signal Type 3 treats the output as an entry event whose exit is managed by the signal as new bars arrive.
The number of shares is decided after the signal opinion. A paper trace takes the active risk profile, current equity and cash, existing position, signal price, shorting permission, minimum order value, leverage limit, and maximum position limit, then turns a BUY or SELL into an executable quantity. Fixed-dollar sizing uses dollars per trade / price. Fixed-percent sizing uses equity × percent / price. Risk-per-trade sizing uses (equity × risk percent) / (price × stop distance percent). Quantities are rounded down to whole shares unless fractional trading is enabled, in which case they are rounded down to two decimals.
Signal Type 1, target-state
The output is the position to hold right now. If the signal says long, the intended stance is long. If it says short, the intended stance is short. If it says flat, the intended stance is no position. There is no separate exit rule — the output changing is the exit.
In the decision trace, a target-state BUY means the desired state changed to long. If the paper account is flat, it may open a long; if it is short, it may buy to cover. A target-state SELL means the desired state changed to short or away from long; if the paper account is long, it may sell to close. A target-state HOLD means the current bar does not call for a new state change. If the account is already aligned with the signal, the trace can correctly show no order placed.
How much is bought, sold, or held. For Signal Type 1, quantity is the amount needed to move the paper account toward the target state, not a fresh bet every bar. A BUY while flat opens a risk-sized long. A BUY while short buys the open short quantity to cover it. A BUY while already long buys zero because the account is already aligned. A SELL while long sells the open long quantity. A SELL while flat can open a risk-sized short only when shorting is enabled. A SELL while already short sells zero because the account is already aligned. HOLD buys and sells zero; it preserves the current state until the signal changes.
Moving-average crossovers, trend-following rules, oscillators, statistical signals, and many fundamental screens work this way. The trace is useful because it tells you whether the signal changed its desired stance or simply stayed with the existing one.
Signal Type 2, deterministic horizon
The output is an entry event, and the trade has a known holding length or rebalance schedule. A breakout may enter and hold for a declared number of bars. A value signal may rebalance every set number of trading days. The key is that the trade's maximum reach is known when it opens.
In the decision trace, a deterministic-horizon BUY or SELL is an entry or rotation event. HOLD usually means no new entry event has fired on that bar, or the forecast was below the action threshold. If a paper order appears, the quantity and fill show how the paper account acted on the entry. If no order appears, the reason text tells you whether it was warmup, a weak forecast, a same-direction repeat, a risk cap, or another account-level condition.
How much is bought, sold, or held. For Signal Type 2, quantity is sized at the entry or rebalance event. A BUY entry while flat opens a long using the active risk-sizing rule and then clamps the order to cash, leverage, and max-position limits. A SELL entry while flat opens a short only when shorting is enabled and then applies the same notional limits. If an opposite position is already open, the trace sizes the order to close that inventory before a new entry can be considered. If the same direction is already open, the trace buys or sells zero rather than pyramiding. HOLD buys and sells zero because no new scheduled entry or rebalance action has fired. When the known horizon ends, the exit quantity is the open position quantity, because the trade is being closed rather than newly sized from forecast strength.
Use these traces as scheduled trade evidence: the signal is not merely saying "I like this stock"; it is saying "this is an entry point for a trade with a known review or expiry horizon." For your own portfolio, that means the trace should be paired with a calendar or holding-period rule, not treated as an open-ended opinion.
Signal Type 3, model-managed exit
The output is an entry event, but the exit is managed by the trading model rather than scheduled. The model enters because a setup appears, then checks each new bar for the condition that ends the trade: reversion to a mean, a pattern break, a failed spread, or another model-owned exit rule.
In the decision trace, a model-managed-exit BUY or SELL means the setup is active and strong enough to act. A later opposite-side trace can be the exit or reversal event, depending on the signal and the current paper position. HOLD means the model is still waiting: either no setup, not enough strength, warmup still in progress, or the exit condition has not appeared.
How much is bought, sold, or held. For Signal Type 3, the entry is risk-sized when the model-managed setup first fires. A BUY while flat opens a risk-sized long. A SELL while flat opens a risk-sized short only when shorting is enabled. While the model keeps managing the open trade, HOLD buys and sells zero; it means keep the current position and wait for the exit condition, not add more shares. If the exit condition produces the opposite side, the paper trace sizes the order to the currently open position so the trade can be closed. A new opposite entry is then sized by the same risk profile when the signal produces that new entry. If the account is already aligned with the signal, the trace buys or sells zero rather than adding to the position.
These traces are especially useful for discretionary review. You can watch the reason text and forecast strength to see whether the signal is still waiting, has fired an entry, or has moved to an exit. For your own portfolio, this is the place to compare the signal's exit logic with your actual stop, target, and risk plan.
Some signals change signal type by parameter — anchored VWAP is Signal Type 3 by default when confluence is required and Signal Type 1 when confluence is explicitly off. The contract is resolved from the actual parameters each run, never assumed.
The reason this matters is mechanical: the lifecycle determines how far a trade can reach into later prices during validation. Misclassifying it would either leak future data into the grade or remove more history than necessary.
03The data
A backtest is only as accurate as the prices behind it. Minerva validates price data, normalizes it, and records the transformations that affect a result.
Coverage
- Available US-listed securities. Minerva can use only symbols, resolutions, and date ranges for which production cloud bar objects exist. Availability varies by security, listing and delisting dates, and resolution; requested coverage is checked before a run.
- Supported window. Production availability begins on 2016-04-19 and the upper request bound advances conservatively behind the daily ingest; each symbol and resolution may cover a smaller interval.
- Granularity. Production bars are stored separately at 1-minute, 5-minute, 15-minute, 30-minute, 1-hour, and daily resolutions. Minerva does not construct every longer timeframe from a stored 1-minute base. When OHLCV aggregation is performed, open is first, high is the maximum, low is the minimum, close is last, and only volume is summed.
- Sessions. Historical extended-hours bars are present. When a session distinction matters, Minerva can classify a bar as pre-market, regular hours, or after-hours from its timestamp and the market-hours calendar; it does not need a separate stored session label to know that history exists.
What a bar is, and how it's stored
| prices | open, high, low, and close price during the slice |
| volume | shares traded during the slice |
| timestamp | universal time, to the second |
| dataset details | dataset identifier, normalized data marker, and bar length |
Bars are stored two ways: column-oriented files on disk for loading long histories quickly, and a database keyed by stock and timestamp for exact lookups. Timestamps from different market-data feeds come in different units (seconds, milliseconds, microseconds, nanoseconds); Minerva reads the unit from the size of the number rather than assuming, so a millisecond timestamp isn't read as seconds.
Each batch of bars is identified by five things together — stock, start date, end date, bar length, and dataset identifier — plus a flag for whether dividends have been applied. The lookup order is fixed and recorded. This identity keeps a dividend-adjusted series and a raw series for the same stock from being mixed up.
Corporate Actions
A corporate action is a company event that changes a stock's raw price without changing what a holder actually earned. Two affect backtests directly:
- A stock split divides each share — a $100 share becomes two $50 shares. The price halves overnight, but the holding is worth the same. Left uncorrected, a 2-for-1 split reads as a 50% crash.
- A dividend pays cash to shareholders. On the ex-dividend date — the first day the stock trades without the upcoming dividend attached — the price drops by about the dividend amount. The holder isn't worse off; they got the cash. The series shows a drop anyway.
A signal run on uncorrected prices treats both as real moves and trades them.
Why pre-adjusted prices are wrong for backtesting
Many market-data vendors offer "adjusted" prices with splits and dividends already removed. These aren't safe to backtest on. To remove an event from history, the vendor rewrites every earlier price in the series, so a price dated 2018 is calculated using a split that happened in 2023 — the adjusted 2018 value depends on the future. A signal trained on it is using information that didn't exist yet — look-ahead bias hidden in the data. López de Prado (2018) covers this.
What Minerva does
Prices are stored split-adjusted but not dividend-adjusted. Minerva never inherits a vendor's pre-baked adjusted series; every correction is computed by Minerva at load time from its own versioned record of the actual events, so the exact adjustment applied to any result is known and reproducible.
- Splits are applied when bars are built, so the stored series has no split jumps. A split is a known ratio on a known date, so applying it adds no future information.
- Dividends are applied only when a test requests total-return prices, using the backward-cumulative total-return adjustment of CRSP, the standard reference. Going through cash dividends earliest to latest, every price strictly before each ex-date is scaled by:
adj_t = raw_t × ∏ (C_d − D_d) / C_d over all ex-dates d later than t
where D_d is the dividend and C_d is the unadjusted close on the last bar before that ex-date. Two points keep this exact:
- Each dividend's factor uses the original prices, not prices already scaled by an earlier dividend, so multiple dividends don't compound incorrectly.
- Dividends with an ex-date after the last bar are skipped, so the most recent price isn't reduced by a payout that hasn't happened — the latest adjusted price equals the latest raw price. A test pins this.
The factor is applied to open, high, low, and close together so the bar's shape is unchanged. Volume is not scaled, because a dividend is cash, not a change in share count.
Why a backward factor is safe here, when a vendor's pre-adjusted series is not. The CRSP factor is a single constant applied to every price before an ex-date, so any two bars on the same side of that ex-date are scaled identically and the return between them is unchanged. The only return the adjustment alters is the one spanning the ex-date, which is exactly the artificial drop it exists to remove — no signal computed from returns can learn anything from a future dividend. That is different from a vendor's pre-adjusted series, where an unknown vintage of splits and dividends is baked into stored prices you cannot inspect, undo, or pin to a version. Minerva applies the adjustment only on request, only from a manifest-verified event record, and never for an ex-date after the last loaded bar.
How stale or wrong corporate-action data is caught
The split and dividend records and a manifest describing them are kept as one dataset tied together by SHA-256 hashes:
- The manifest stores a hash of the dividends file, a hash of the splits file, and a hash of which stocks and date range are covered. These combine into a short version string (16 hex characters) recorded on every result.
- Before using the data, a run checks coverage against the manifest. If a stock that needs adjusting isn't covered, the run stops instead of trading on uncorrected prices. A stock that never paid a dividend or split is covered — that's a recorded fact; a missing record is not.
- Because the version string is computed from the file bytes, changing the data without rebuilding the manifest is caught: the hashes no longer match and the data is rejected.
A missing or inconsistent record stops the test rather than producing a wrong number that looks right.
Survivorship: companies that no longer exist
Of the roughly 3,000 companies in the Russell 3000 index at the end of 1986, fewer than 500 still existed by 2014. The rest were acquired, went bankrupt, or were delisted.
Testing on today's index members leaves out every company that disappeared, so the test only trades the survivors. This is survivorship bias. It can change the answer, not just improve it: Brown, Goetzmann, Ibbotson & Ross (1992) showed a strategy that looks profitable on the survivors can lose money once the failed companies are included. Today's membership also adds future information, because a company is in today's index partly because it did well after the date being tested.
- Minerva reconstructs index membership as it was on each date. Each company's membership is stored as a start and end date, so the set of stocks on any given day matches what it actually was, including companies that have since disappeared.
- Companies that were later delisted keep their full price history up to their last trading day. Missing data is never a reason to drop a company.
- A "today's members" mode is available, but using it records a survivorship-bias warning on the result.
Bad and impossible prices
Market-data feeds occasionally carry a corrupt value, and one bad number can produce a large fake profit. (In a well-known case, a mistyped earnings figure of over $60,000 for a $20 stock distorted an entire index.)
- A share price must be positive and finite. While bars are built, any price that is zero, negative, infinite, or not a number is dropped and replaced with the good prices in the same bar, preferring close, then open, high, low. A zero low can't create a fake −100% bar.
- At scoring time, non-finite returns are removed before any statistic is computed, so one bad value can't distort a Sharpe ratio or a drawdown.
- This removes impossible values, not merely improbable ones. A price that is a valid number but far out of line isn't flagged statistically yet.
04Trading costs and execution realism
Every real trade costs money: a commission, and the fact that you rarely get the exact price you wanted — you pay slightly more buying and receive slightly less selling. A backtest that ignores costs favors strategies that trade frequently, the ones most likely to fail once costs are real. This is where a signal and a strategy differ: a signal that looks strong on paper can lose money once costs are charged.
Every fill charges the configured commission plus the selected slippage model, on entry and exit. The default Fixed mode applies flat basis-point slippage. Volatility mode scales slippage with observed volatility. Almgren–Chriss adds the volume-sensitive spread and temporary/permanent market-impact terms below.
Almgren–Chriss spread
When Almgren–Chriss is selected, the spread term starts at 3 basis points (0.03%), rises on low-volume bars, and is capped at 4×.
spread cost = price × (3 / 10,000) × √(reference_vol / current_vol) [capped 4×] × shares
Almgren–Chriss market impact
When Almgren–Chriss is selected, impact grows with the square root of the share of daily volume taken, split into a temporary part paid on the fill and a permanent part retained in the price.
participation = shares / average daily volume
impact (bps) = 0.1 × volatility × participation^0.5 × 10,000
temporary = shares × price × (impact / 10,000) × 0.6 (you pay)
permanent = shares × price × (impact / 10,000) × 0.4 (stays in the price)
Coefficient 0.1, exponent 0.5 (the square-root law), temporary/permanent split 60/40. Volatility is measured over a trailing window.
Commissions and fees
A tiered, broker-realistic schedule: $0.0035 per share at the lowest volume tier dropping to $0.0005 at the highest, a $0.35 minimum per order, and a 1%-of-value ceiling. On top: a CAT fee of $0.000022 per share on both sides, a FINRA TAF of $0.000166 per share on sells (capped $8.30 per order), and the SEC Section 31 fee on sells (currently 0.0, suspended May 2025).
A stress adjustment
The Almgren–Chriss spread/volume multiplier is capped at 4×. Separately, when regime cost scaling is active, the computed Almgren–Chriss slippage can be multiplied by the regime's cost multiplier. That multiplier does not alter commissions or the Fixed and Volatility slippage modes, and it is not the spread cap.
Limiting trade size to what actually traded
A backtest can record buying 100,000 shares of a stock that only traded 5,000 shares that day — an order that could not have been filled. Combined with position sizing, this produces large fake returns. Two limits prevent it, applied before any profit is counted:
- A volume limit. Each entry is capped at a share of the volume that was actually available —
20%by default, configurable from0.1%to100%; an exit closes the held position. "Available" is measured two ways and the smaller wins: a daily figure (that percentage of average daily volume) and a finer figure for the time of day (the same percentage of what usually trades in that part of the session). Both use earlier completed sessions only. A stock with no prior history gets no entry capacity — the trade is skipped rather than filled against invented volume. An order above the cap is reduced; below one share, it's skipped. Short orders keep their sign. - The volume limit applies once, at entry. A reduced order is not topped up on later bars — the position keeps the size it could fill on the bar it opened, for as long as it is held. So the limit bounds the whole position, not one slice of a multi-day execution. This matters when the requested position is large relative to the symbol's daily volume: the strategy then trades a smaller position than the sizing method asked for, and the reported return and drawdown describe that smaller position rather than the one you configured. The default was raised from
1%to20%because at1%a $100,000 account was capacity-limited on roughly three quarters of US listed symbols; at20%the ~3,000 most actively traded symbols are unconstrained at that account size. Outside that range, compare the filled quantity in the trades table against the position you intended. - A minimum stop distance. Some sizing rules take a larger position when the stop is closer. If the stop distance could round to near zero, the position would balloon. So the stop distance is held to at least the smallest real price increment —
$0.0001for sub-$1 stocks,$0.01otherwise — before sizing.
In thinly traded names, these limits prevent a backtest from turning unavailable volume or sub-tick stop distances into a position size that could not have been executed in the market.
Other execution controls
- Circuit breaker. When the day's loss crosses the configured limit, the position is exited at the next bar's open, like any other order, with full costs charged.
- Leverage cap. Position size is capped at the configured leverage limit times equity.
- Position bounds. A maximum position value and a minimum position size (default 1 share) are enforced; an order below the minimum is dropped.
- Three slippage models. Fixed, volatility-scaled, and the Almgren–Chriss model above. The participation and stop-distance limits apply to all three, because capacity is an execution fact, not a property of the cost formula.
A separate fragility check
After an optimization, Minerva can re-run the winning strategy under deliberately worse cost assumptions and report how much it degrades: zero cost as a control, 2× and 3× slippage, 2× commission, and a combined case with 2× slippage plus 1.5× commission. The fragility score is 1 − (worst-scenario Sharpe / base Sharpe), clamped to [0, 1]; a strategy whose edge survives only at the default cost level scores high. Advisory, computed after selection.
Comparison with another platform
The same public strategy was run on Minerva and on QuantConnect, an established backtesting platform, with identical settings (AMD, daily bars, 2021-05-19 to 2026-02-18, $0.005 per share, next-open fills). The results matched closely: 33 trades on each, every entry on the same date, and a final account value of $250,412 versus $250,427 — about $15 on $250,000, or 0.006%. The arithmetic agrees. The one intended difference is that Minerva never lets a signal see the current bar, which makes its numbers slightly more conservative.
05The result metrics
Minerva computes results from the equity curve, the account's value over time (equity = cash + shares × price). Three rules apply to every metric: bad values are removed first; a metric with no valid answer is reported as N/A, not a made-up number; and an unrecognized bar length stops with an error rather than a guess.
Most metrics are stated per year so signals run at different speeds compare fairly. The annualization factor is √(bars per year), exact per timeframe: 98,280 bars/year for 1-minute, 19,656 for 5-minute, 6,552 for 15-minute, 3,276 for 30-minute, 1,638 for hourly, 252 for daily. An unrecognized timeframe raises rather than defaulting.
- Total return and CAGR — how much the account grew, and that growth as a yearly rate.
- Sharpe ratio — for an ordinary backtest, mean per-bar excess return divided by per-bar return volatility and annualized for that timeframe. For a WF+CPCV optimization result, the displayed headline is instead computed from daily returns on the untouched final holdout, annualized with √252, with Newey–West adjustment for serial correlation. Risk-free return is subtracted only when that option is enabled. N/A if the applicable variance cannot be estimated. Higher is better.
- Sortino ratio — like Sharpe but the denominator counts only downward moves. N/A if there were no losing periods.
- Calmar ratio — yearly return divided by the largest peak-to-trough drop. N/A if there was no drop.
- Maximum drawdown — the largest peak-to-trough fall, as a percentage.
- Win rate, profit factor, average win and loss, expectancy — from completed round-trip trades (an entry paired with an exit; unpaired legs are logged, not counted). Profit factor is N/A, never infinity, when there were no losing trades.
On an optimization, development held-out periods determine the winning settings and supply the evidence used by the tests in §6. After that choice is frozen, Minerva evaluates it once on the untouched final holdout. The displayed headline Sharpe comes only from that final holdout's daily account returns and is Newey–West adjusted for serial correlation. This reporting Sharpe does not replace the development statistics used by the Seal or MinervaScore.
When a run covers several tickers, every ticker gets its own row in the results table, its own settings, and its own full P&L report. Those settings are not the product of a separate search per ticker: one search covers the whole list and ends on a single small group of closely related settings, and each ticker takes its best option from inside that group. The choice is locked before the holdout is opened. Section 7 describes this in full. If a report fails to generate, its row stays visible and shows the error, but that report cannot be traded or downloaded.
06The Robustness Seal
On an optimization, the selected strategy is evaluated against five mathematical gates using held-back validation results. The Seal passes if and only if all five gates pass. A thin record is reported separately through the evidence floor; that advisory does not rewrite the Seal or the continuous score.
Test 1: Deflated Sharpe ratio ≥ 0.95
Takes the strategy's Sharpe ratio and subtracts what the luckiest of all the variations tried would be expected to score by chance, then asks how confident we can be that the edge clears that bar (Bailey & López de Prado, 2014). The chance bar rises with the search effort. The trial count is the number of variations the search actually evaluated: every genetic evaluation across all 120 arrangements, plus every distinct neighbor scored by the plateau screen. It is deliberately conservative — repeated elites and near-duplicate variations each count as another attempt, so the chance bar is never set too low.
DSR = Φ( (SR − SR0) × √(T−1) / √( 1 − γ₃·SR + ((γ₄+2)/4)·SR² ) )
N is that trial count, T the number of bars, γ₃ skew, γ₄ excess kurtosis. The stored Sharpe is annualized, but the variance term and (T−1) are per-bar, so Sharpe is divided by the annualization factor and variance by its square before entering the formula. When no usable family variance panel is supplied, Minerva uses Lo's null sampling variance: 1/years in annualized units, equivalently 1/T per bar. Call paths whose history units cannot be resolved retain the legacy constant. HAC-corrected Sharpe is an audit field, not the DSR gate input. Passing at 0.95 means the DSR is at least 0.95.
Test 2: overfitting probability ≤ 0.50
From the development evidence, Minerva builds a candidate-by-period performance matrix over the ten periods and computes the Probability of Backtest Overfitting (Bailey et al. 2017). For each balanced split of those periods into in-sample and out-of-sample halves — 252 combinations across the fixed ten periods — it takes the variation that ranked best in-sample, finds its rank out-of-sample, rescales to ω = rank / (N + 1), and takes the logit λ = ln(ω / (1 − ω)), which is negative when the in-sample best lands below the out-of-sample median. PBO is the fraction of splits with λ < 0. Above 0.5, the search is selecting variations that do worse than average on new data — it is fitting noise.
Test 3: skill versus chance p ≤ 0.10
The gate tests each candidate against cash using 500 circular-block resamples of length n^(1/3), with the finite-sample p-value (1 + count) / (1 + B). Every candidate keeps its own scalar p-value regardless of family size. Global family evidence and candidate-level multiplicity decisions are stored separately and never substituted for that gate value. The following family-wise procedures are companion audit or screening outputs where available:
- White's Reality Check — the maximum excess return across the family, every candidate recentered to zero, using 1,000 reshuffles.
- Hansen's SPA — the same but each candidate's score is divided by its own volatility, and clearly inferior candidates are not recentered, which keeps a pile of bad candidates from hiding a good one. It uses 1,000 reshuffles and the threshold
A_k = −ω_k·√(2·ln ln n / n). - Romano–Wolf StepM — a stepwise version that rejects the clear winners, removes them, and repeats, finding more true positives than a single pass.
A Model Confidence Set and Benjamini–Hochberg false-discovery control are also available for screening across many surviving candidates, bounding the share that are false positives.
Test 4: track length ≥ minimum required
A thin Sharpe on a short record cannot be told apart from zero. This computes the minimum track-record length the observed Sharpe needs to be statistically significant, adjusted for skew and fat tails (Bailey & López de Prado 2012), and fails a result with too little history to support the Sharpe it claims. Note this is the single-trial significance length; the penalty for the size of the search is Test 1's job, not this one:
γ₃ skew, γ₄ excess kurtosis, as in Test 1. Like Test 1, this is a per-bar formula and de-annualizes the Sharpe first, so the two agree on units. The gate passes when the actual bar count is at least MinTRL.
Test 5: consistency across eras ≥ 0.60
The same strategy can look good or bad depending on which two-year window is shown. This grades steadiness across periods and checks the worst period specifically, not just the average:
p+ is the share of windows with positive Sharpe, sSR is the standard deviation of window Sharpe values, and SRmin is the worst-window Sharpe. The worst window is also reported on its own.
07The MinervaScore
MinervaScore is a 0–100, verdict-consistent ranking of how far a validated result sits from five robustness thresholds. The paper demonstrates strong ranking performance in synthetic ground truth. The score is set so that 80 or above always means all five Seal gates passed; below 80 means at least one Seal gate failed. The separate evidence-floor warning does not change the Seal or its display band.
- Per-test transformed margin. DSR uses its pre-
Φstatisticu:zDSR = (u − Φ⁻¹(0.95)) / 1.128. PBO and SPA use clamped log-odds:zPBO = (logit(0.50) − logit(PBO)) / 10.028andzSPA = (logit(0.10) − logit(SPA)) / 6.013. Regime useszregime = (logit(ρ) − logit(0.60)) / 1.161. Track length useszMinTRL = tanh((T − MinTRL) / max(0.2 × MinTRL, 50)). Probabilities are clamped to[10⁻⁶, 1−10⁻⁶]before the logit. A passed threshold contributes a positive margin; a miss contributes a negative margin. - Weighted combination. The five margins use weights
0.35 / 0.25 / 0.20 / 0.10 / 0.10(DSR / PBO / SPA / track length / regime). The combined statistic isS = (w·z) / √(wᵀ Σeff w).Σeffis a frozen cross-sectional correlation matrix estimated once from the calibration population and shared by every strategy. It normalizes the ranking scale; it is not covariance estimated from the current run's folds and carries no combined-test inferential claim. - A conservative offset. The raw score is
r = Φ(S − 0.5). The fixed0.5is a tunable conservative offset, not a López de Prado bias correction. - Verdict-consistent display mapping. A sealed result maps to 80–100. An uncertified result maps to 0–79.9 using the percentile of its raw score among 355,214 uncertified optimizer candidates in the frozen calibration reference population. For an uncertified result only, MinervaScore ÷ 0.8 is approximately that reference percentile. This interpretation does not apply to the sealed band, and absolute scores are comparable only within a calibration vintage. The guarantee by construction is that a displayed score of 80 or higher means the Seal passed.
08Robustness checks beyond the seal
The seal asks whether a result is statistically real. These additional checks ask whether it is stable — whether it survives small changes to its own parameters, depends on one lucky market regime, or sits on an isolated peak. They run on an optimization and are reported alongside the result.
- Plateau stability. The leading parameter sets are re-scored alongside close neighbors — each numeric parameter nudged one step down and one step up within
±5%of its declared range — across a balanced subset of the validation splits. A candidate sitting on a plateau of similar performance is preferred to an isolated spike, and at the fixed validation shape this preference participates in winner selection: the published winner is the most stable strong candidate, judged on its worst decile of splits, not necessarily the single highest scorer. The full mechanism is described in the Optimizations section. - Ranking on the middle ticker. When a run covers several tickers, each variation is scored on every one of them and ranked by its middle score, the median. Having to work across the list is itself a test: settings that fit one ticker's noise cannot win, because that one strong score is not what the ranking reads. Each ticker still ends up with its own settings, chosen from within the single group of settings the search settled on.
- Monotonicity. The shape of each parameter's response curve is checked. A smooth curve is expected; a U-shaped or multi-peaked response suggests the tuned value sits on a spike rather than a stable region.
- Neighborhood profitability. For the top results, Minerva looks at nearby parameter sets — within ±10% of each parameter's range, widening to ±25% and ±50% if too few neighbors exist — and reports the fraction that are profitable. An isolated profitable point surrounded by losers is a warning; a dense profitable neighborhood is evidence of a real region.
- Regime attribution. Performance is broken out by market regime, so a strategy that made all its money in one regime and lost in the rest is visible rather than hidden in the average. Per-bar metrics are attributed to the active regime; trade-level metrics to the regime at entry.
- Rolling Sharpe. An exponentially weighted rolling Sharpe over daily returns shows whether performance was steady or came from a few months, weighting recent periods rather than treating the whole history as one number.
09The settings you can change
On an optimization, these are the settings you control. For each, the question is whether raising it mainly improves the result, improves speed, or trades one for the other. Defaults are what the app uses unless changed. The CPCV validation geometry is intentionally fixed and is identified separately below.
The search
Minerva's optimizer explores parameter variations with a genetic (evolution-style) search: a population of variations is scored, the strongest are recombined and mutated, and the cycle repeats for a set number of generations.
| setting | what it controls | default | raising it |
|---|---|---|---|
| population | variations per round | 128 | more thorough slower |
| generations | rounds of evolution | 3 | more thorough slower |
| mutation / crossover rate | how much variations are shuffled each round | 0.05 / 0.6 | more exploration; too high disrupts good variations |
Total work is roughly population × generations × the number of train/grade combinations, plus the plateau-stability screen around the leading candidates and the walk-forward and final-holdout evaluations of the survivors.
The grading
Minerva fixes CPCV at ten development periods with three held back per arrangement: C(10,3) = 120 arrangements. The disabled CPCV fields in the app show that enforced geometry for auditability; they are not request inputs. Walk-forward window sizes remain configurable.
| setting | what it controls | default | raising it |
|---|---|---|---|
| walk-forward train window | days of history each sequential training window covers | 3 test blocks (one block = the date range ÷ 13) | steadier training estimates, fewer windows |
| walk-forward test window | days each survivor is graded on per window | 1 test block | longer per-window evidence, fewer windows |
| walk-forward step | how far the window slides each time | 1 test block | larger steps mean fewer, more independent windows |
| gaps (purge / embargo) | the leak-prevention gaps | automatic | more accurate purge from holding length, embargo 1% of range |
The fixed CPCV geometry produces 120 train/grade combinations per variation.
Fixed engine internals
The statistical machinery is not configurable. The predictive-ability gate uses 500 bootstrap reshuffles and the companion family-wise audits use 1,000; the validation geometry, purge multiplier, and embargo fraction follow the rules in the Optimizations section. The cost settings (§4) are on by default and change which strategies survive; starting capital and risk-per-trade set position size and don't affect speed.
Every accepted submission launches and is charged as its own computation, including one whose settings match a prior run.
10Accuracy mechanics reference
Minerva's accuracy contracts span data, signal replay, simulation, optimization, validation, and result storage. The point is not just to run fast; it is to make every reported number traceable to causal inputs and reproducible rules.
Bar identity, adjustment, and reproducibility
- Bar identity is explicit. A bar series is identified by
symbol + start + end + timeframe + dataset, plus whether dividends were applied and which corporate-action reference version was used. - Bar hashes are deterministic. Minerva hashes timestamp, open, high, low, close, and volume in order, with fixed numeric formatting, so local/cloud parity can compare exact loaded data rather than trusting labels.
- Timestamp units are detected by magnitude. Numeric bar timestamps are interpreted as seconds, milliseconds, microseconds, or nanoseconds by size and converted to UTC-aware datetimes.
- Minerva's price data is stored split-adjusted but not dividend-adjusted (§3). The dividend adjustment is applied at load time, and only when a test requests total-return prices. It is a CRSP-style backward adjustment: every bar before an ex-date is multiplied by
(previous close - cash) / previous close. The same factor is applied to O/H/L/C; share volume is not scaled. - Corporate-action reference data is manifest-verified. Dividends, splits, symbol coverage, window bounds, and file hashes are tied to an immutable reference version. Missing coverage or mismatched hashes stop the run with structured details.
- Future dividends are not applied. The adjustment routine skips ex-dates after the last bar in the loaded series so the most recent price remains the total-return anchor.
- Fundamental/filing data is point-in-time. Financial statement rows are filtered by filing availability date before model-context construction, so a signal cannot see a filing before it was available.
- Loaded bars are normalized before simulation. The loader maps price, volume, and timestamp fields; filters to the requested window; sorts; deduplicates by timestamp; validates required price fields; attaches dataset metadata; then hashes the final series.
Causality in the simulator
- Signals never see the current bar. Model context is built from prior bars only: from max(0, i − context window) through i, exclusive. Prediction caching is disabled inside the accuracy path so stale contexts cannot leak into new bars.
- Orders execute one bar later. A signal generated on bar
iqueues a pending order; it can execute only at bari+1's open. A signal on the final bar is recorded as non-executable. - Stops are tested before a new prediction. Fixed and trailing stops are evaluated first. The trailing stop is updated after the stop check, which means a new trailing level becomes actionable on a later bar, not retroactively on the same bar.
- Exit semantics are part of the signal contract. Target-state signals, deterministic-horizon signals, and model-managed-exit signals declare their lifecycle. Certification uses that explicit lifecycle to size purge and embargo geometry.
- Daily circuit-breaker state is causal. The daily peak, circuit-breaker active flag, and participation budget reset at trading-day boundaries. A circuit-breaker trigger queues an exit for the next open and clears any pending entry.
- Insolvency is terminal. If equity becomes non-positive, Minerva force-closes the position, writes the terminal equity state, and freezes the remaining equity curve at the non-negative terminal cash value.
- Secondary data is sliced per bar. Economic and regime data may be prepared ahead of time for speed, but the per-bar model context receives only the data available at that bar.
- A direct leakage check is available. The same backtest can be rerun with signals delayed by one extra bar; a Sharpe drop of more than 20% (
(normal − delayed) / |normal| > 0.2) flags a signal relying on information it should not have. - Metrics exclude warmup observations. Return metrics operate on post-warmup equity changes, finite values only, with a scale-aware epsilon for near-flat curves.
Execution feasibility, costs, and sizing
- Cost configuration is canonical. Slippage model names, commission settings, stress settings, and participation bounds are validated once and recorded in a normalized form with the result.
- Execution capacity is causal and model-independent. Entry shares are capped by
max participation × min(ADV remaining for session, expected volume for this bar), where both the daily and time-of-day estimates use prior completed sessions only. - Participation applies across slippage models. Fixed bps, volatility slippage, and Almgren–Chriss slippage all receive already-clipped entry quantities. The slippage model prices execution; it does not grant extra capacity.
- Session participation is budgeted. Minerva tracks entry shares already opened during the current trading day, subtracts them from the causal ADV cap, and resets that budget only on a new trading day.
- Stop-derived risk is tick-floored. Stop distance is floored to the conservative equity minimum tick:
$0.0001below one dollar and$0.01at or above one dollar. The stop price is rounded consistently with the effective risk. - Sizing uses the same risk floor. Fixed-risk, Kelly, ATR, volatility-targeted, and signal-proportional sizing all route through the shared sizing helper and cannot turn a sub-tick stop distance into huge leverage.
- Kelly statistics are causal. Kelly sizing is based only on closed trades observed so far, using net P&L after entry and exit costs.
- Post-sizing caps are ordered. Minerva applies maximum position value, long cash capacity, leverage, minimum order size, then integer non-negative share normalization.
- Commissions are explicit. The IBKR-style fee calculator includes per-share commission tiers, minimum commission, percentage cap, CAT, SEC, and FINRA TAF components where applicable.
- Slippage inputs are causal. Volatility and Almgren–Chriss calculations use trailing context, current bar volume, causal ADV, reference volume, and optional regime cost multipliers, all passed through the same resolver.
Walk-forward, CPCV, and multiple-testing controls
- CPCV is contract-aware. Purge geometry comes from the model-owned lifecycle horizon, not from observed winning trades. Target-state models need no lifecycle purge; deterministic-horizon and model-managed-exit models must declare bars or days.
- Feature warmup is not treated as label horizon. Warmup is past-looking and recorded as a diagnostic. Purge covers forward event overlap; embargo covers serial correlation after a test fold.
- Embargo is computed from bar geometry. The default is the AFML 1% bar-count rule converted to calendar days for the active timeframe. Unknown timeframes or invalid ranges raise instead of inventing an annualization or gap size.
- CPCV split evaluations are preflighted. Minerva validates split counts, date ranges, purge/embargo geometry, and feasible train/test windows before launching certification work. The
C(N,k)split-evaluation count remains distinct from theC(N−1,k−1)path count. - PBO carries a method label. When a candidate-by-fold matrix is available, Minerva computes true CSCV PBO from in-sample winner ranks against out-of-sample ranks and records that method with the result.
- Deflated Sharpe is family-aware. Candidate IDs are content-addressed from normalized parameters. Runtime execution keys are stripped from signal identity, while cost model, dataset, timeframe, universe, and date range stay in the trial family used for deflation. The trial count fed to deflation is the run's actual evaluation total — every inner genetic evaluation plus the distinct plateau-screen neighbors, counted without deduplication.
- Units are kept consistent. Stored Sharpe is annualized, but DSR and MinTRL use per-bar variance formulas. Minerva de-annualizes before those formulas and uses the active timeframe's annualization factor.
- The predictive-ability gate uses circular block bootstrap. Each candidate is tested against cash with block length
n^(1/3), 500 resamples, and finite-sample p-value correction. Its scalar p-value remains its gate input at every family size; family-max and stepwise results are separate fields. - Family validation uses aligned return panels. Family max, White Reality Check, Hansen SPA, StepM, Model Confidence Set, and FDR procedures operate on a common candidate-by-bar matrix so cross-candidate dependence is preserved.
- Benchmark length must match. Family-wise helpers raise on benchmark length mismatch rather than silently realigning or padding the benchmark.
- FDR q-values are monotone-corrected. Benjamini-Hochberg and Benjamini-Yekutieli restore q-values to input order after reverse cumulative minimum correction.
- HAC Sharpe and MinTRL are separate diagnostics. Lo-style Newey-West HAC Sharpe uses Bartlett weights and
floor(T^(1/3))lag selection; it is an audit field, not the DSR gate input. The Bailey & López de Prado MinTRL reports the required bar count and pass/fail state. - The Robustness Seal is a five-way AND gate. DSR, PBO, the predictive-ability bootstrap p-value, minimum track-record length, and regime stability all have to pass. The evidence floor is a separate sample-breadth warning and does not rewrite the Seal or MinervaScore.
Optimizer, signal, and ledger audit trail
- The optimization request requires timeframe. Annualization comes from the explicit timeframe or bar interval, and unknown values raise.
- Cost settings are normalized before search. Optimizer startup validates cost parameters, records the canonical model ID, and injects run-level position sizing into model parameters before trials execute.
- Regime search knobs are separated from model parameters. Regime settings are removed from the model parameter search surface and, when applicable, the regime count is pre-fit by BIC before candidates are scored.
- Bars are preloaded once for the run. The optimizer loads requested bars through the shared bar loader, stores diagnostics and the bar hash, and reuses the identity-keyed cache for trial execution.
- Signal replay is segment-audited. Signal outputs are stored per symbol and keyed by timestamp, model ID, parameter hash, timeframe, and dataset. Coverage segments store request bounds, bar bounds, emitted counts, bar hashes, and canonical parameters.
- Trial rows preserve validation context. Trial rows store the transaction cost model, data version, dataset, timeframe, WF/CPCV metrics, PBO and method, DSR, SPA, family-wise method and p-value, MCS, FDR, HAC Sharpe, MinTRL, symbol consistency, and equity-curve JSON.
- Batch ledger writes are transactional. Optimizer finalize writes trial rows in a single transaction and memoizes family curve reads within the batch so the DSR family scope is consistent across rows.
- Results preserve audit fields. Returned results include validation fields, run-level family statistics, model confidence set, false-discovery controls, PBO method, position sizing, regime policy, and per-symbol summaries.
- Post-selection diagnostics are labeled advisory. Execution stress reruns the finalist under cost mutations; parameter robustness scores the top candidates by the profitability of nearby evaluated neighbors and reports whether neighbor coverage is sufficient.
11Position sizing
Minerva signals decide whether a strategy wants to be long, short, or flat. A separate position-sizing method converts each accepted long or short signal into a dollar position and a whole number of shares. This explainer compares 100% of Equity with Fixed Risk, Kelly, Volatility Targeting, Signal Proportional, and ATR-Based sizing. The legacy names fixed_fractional and fixed are aliases for Fixed Risk, not separate methods.
Plain-English overview
The signal decides what direction to trade; the sizing method decides how much of the strategy’s current equity to put into the trade. 100% of Equity targets position notional equal to current equity whenever a signal qualifies. Fixed Risk chooses a position intended to lose a specified percentage of current equity if the initial stop is reached. Kelly adjusts that risk percentage using the strategy’s completed-trade history. Volatility Targeting changes the position according to the instrument’s volatility and the forecast magnitude. Signal Proportional starts with a Fixed Risk position and deliberately scales it by signal strength. ATR-Based uses an ATR-derived price movement instead of the actual stop distance to calculate shares.
The calculated position is only the requested position. Minerva can still reduce an entry because of cash, leverage, maximum-position, minimum-size, whole-share, or market-participation constraints. Once a position is open, Minerva does not continually resize it as the price, stop, volatility, ATR, or signal strength changes.
Visual: what consecutive same-direction signals actually do
Because a position is sized only when it opens, firing the same-direction signal again while the trade is live does nothing. The size is recomputed only at the next entry, after an exit returns the strategy to flat, or on a reversal. This behavior holds for every one of the six methods.
Three long signals in a row don't buy three times. The first opens the trade; the next two do nothing. Exposure changes only when a new trade opens — and it is recomputed from whatever the equity is then.
Shorts are the mirror image. A short signal opens a position of −q shares with the stop placed above entry; consecutive short signals while already short are ignored the same way. Everything below applies to both sides — only the sign flips.
Technical overview
Minerva separates signal generation from execution sizing. A signal produces a direction and strength. The execution layer converts that output to a signed forecast, applies the entry threshold and any regime adjustment, and sizes an accepted order at the next eligible bar open. Each sizing method calculates a raw absolute integer quantity q0 from current equity E, entry price P, and its method-specific inputs. The common execution layer then applies, in order, the maximum-position-value cap, the long-cash cap, the maximum-leverage cap, the minimum-position-size rule, and entry participation limits to produce executed quantity q.
Fixed Risk, Kelly, and Signal Proportional use the initial fixed or trailing stop distance when calculating quantity. ATR-Based substitutes ATR × multiple as its sizing distance. Volatility Targeting uses estimated daily percentage volatility instead of a stop distance. 100% of Equity uses only current equity and entry price. Stops, gaps, commissions, slippage, and the daily circuit breaker operate after sizing, so realized losses can differ from a method’s modeled risk.
Numerical examples
Example 1: The same accepted signal under every method
Assume:
- Current equity: $100,000
- Entry price: $100
- Initial stop distance: 5%, or $5 per share
- Risk per trade: 0.5%, or $500
- Final forecast: 10 out of 20
- Signal Proportional scale range: 0.2 to 1.0
- Daily percentage volatility: 2%
- Target annual volatility: 20%
- Forecast scalar: 10
- Instrument diversification multiplier: 1.0
- Regime volatility multiplier: 1.0
- ATR: $2
- ATR multiple: 2
- Kelly example: applied Kelly risk fraction of 1%
- No cash, leverage, maximum-position, minimum-size, liquidity, or rounding constraint binds
| Method | Numerical calculation | Requested shares | Requested position |
|---|---|---|---|
| 100% of Equity | $100,000 ÷ $100 |
1,000 | $100,000 |
| Fixed Risk | ($100,000 × 0.5%) ÷ $5 |
100 | $10,000 |
| Kelly | ($100,000 × 1%) ÷ $5 |
200 | $20,000 |
| Volatility Targeting | (10 ÷ 10) × (($100,000 × 20% ÷ 16) ÷ ($100 × 2%)) |
625 | $62,500 |
| Signal Proportional | Fixed Risk base 100 × scale [0.2 + (10 ÷ 20) × (1.0 − 0.2)] = 0.6 |
60 | $6,000 |
| ATR-Based | ($100,000 × 0.5%) ÷ ($2 × 2) |
125 | $12,500 |
Visual: Example 1 as a share of equity
The same accepted signal, sized by each method, drawn as a fraction of the $100,000 account. This is the “how much am I putting in” answer at the moment of entry.
Show the numbers
| Method | Requested shares | Requested position | % of equity | Modeled stop-loss |
|---|---|---|---|---|
| 100% of Equity | 1,000 | $100,000 | 100% | 5% ($5,000) |
| Volatility Targeting | 625 | $62,500 | 62.5% | 3.1% ($3,125) |
| Kelly | 200 | $20,000 | 20% | 1% ($1,000) |
| ATR-Based | 125 | $12,500 | 12.5% | 0.6% ($625) |
| Fixed Risk | 100 | $10,000 | 10% | 0.5% ($500) |
| Signal Proportional | 60 | $6,000 | 6% | 0.3% ($300) |
Reading ATR-Based: it budgets a 0.5% loss against its ATR sizing distance (ATR × 2 = $4), but the shared 5% execution stop ($5) is wider, so its modeled stop-loss is $625 — 0.625% of equity, slightly above the budget. The other five methods' modeled stop-loss equals their target because they size on the 5% stop itself (or, for 100% of Equity, take the full stop on full exposure).
Example 2: Why Fixed Risk does not imply a fixed dollar position
With $100,000 of equity and 0.5% risk per trade, the risk budget is always $500. The requested position changes when the initial stop distance changes:
| Initial stop distance | Risk per share at a $100 entry | Requested shares | Requested position |
|---|---|---|---|
| 0.5% | $0.50 | 1,000 | $100,000, capped at 1× leverage |
| 1% | $1 | 500 | $50,000 |
| 2% | $2 | 250 | $25,000 |
| 5% | $5 | 100 | $10,000 |
| 10% | $10 | 50 | $5,000 |
| No stop | $100 sizing distance, but no protective stop | 5 | $500 |
At a constant 5% stop, Fixed Risk at 0.5% requests approximately 10% of current equity on every new entry. At a constant 1% stop, it requests approximately 50%.
Example 3: How gains and losses change the next order
Assume a $100 entry price, 0.5% Fixed Risk, a 5% stop, and no binding caps:
| Equity when the next trade opens | 100% of Equity | Fixed Risk |
|---|---|---|
| $100,000 | 1,000 shares = $100,000 | 100 shares = $10,000 |
| $110,000 after accumulated gains | 1,100 shares = $110,000 | 110 shares = $11,000 |
| $90,000 after accumulated losses | 900 shares = $90,000 | 90 shares = $9,000 |
These quantities are recalculated only when a new position is opened. Neither method rebalances an existing position while it remains open.
Visual: how the position tracks equity over six consecutive trades
Run six trades in a row, each a fresh entry after the previous one closes. The colored bars are the dollars deployed at each entry; the grey line is total equity. Because every entry resizes from current equity, the bars rise and fall with the line while the fraction stays fixed. Switch scenarios to see growth versus drawdown, and note how each method's per-trade loss in the losing run is exactly its exposure × the 5% stop.
Six winning exits (+5% to +10% each). Watch every method's bars climb as equity compounds — 100% of Equity balloons, Signal Proportional inches up, but each stays the same fraction of its own (now larger) equity.
Buys ~100% of current equity on every entry.
Scales with forecast strength and how calm the instrument is.
Risk fraction K is re-estimated from completed trades.
Sizes off an ATR distance instead of the stop.
Risks 0.5% to a 5% stop → ~10% of equity.
Fixed-risk size dialed by confidence (m = 0.6 here).
Show the numbers for this run
| Method | Exposure | Stop-loss / trade | Position, trade 1 | Position, trade 6 | Final equity | Total return |
|---|---|---|---|---|---|---|
| 100% of Equity | 100% | 5% | $100,000 | $141,480 | $154,213 | +54.2% |
| Volatility Targeting | 62.5% | 3.1% | $62,500 | $77,866 | $131,593 | +31.6% |
| Kelly | 20% | 1% | $20,000 | $21,481 | $109,341 | +9.3% |
| ATR-Based | 12.5% | 0.6% | $12,500 | $13,073 | $105,757 | +5.8% |
| Fixed Risk | 10% | 0.5% | $10,000 | $10,365 | $104,584 | +4.6% |
| Signal Proportional | 6% | 0.3% | $6,000 | $6,131 | $102,730 | +2.7% |
Wins and stop-outs alternate. Equity drifts sideways and the deployed dollars breathe with it. The higher-exposure methods swing hardest between entries.
Buys ~100% of current equity on every entry.
Scales with forecast strength and how calm the instrument is.
Risk fraction K is re-estimated from completed trades.
Sizes off an ATR distance instead of the stop.
Risks 0.5% to a 5% stop → ~10% of equity.
Fixed-risk size dialed by confidence (m = 0.6 here).
Show the numbers for this run
| Method | Exposure | Stop-loss / trade | Position, trade 1 | Position, trade 6 | Final equity | Total return |
|---|---|---|---|---|---|---|
| 100% of Equity | 100% | 5% | $100,000 | $110,550 | $105,023 | +5% |
| Volatility Targeting | 62.5% | 3.1% | $62,500 | $66,693 | $103,373 | +3.4% |
| Kelly | 20% | 1% | $20,000 | $20,437 | $101,162 | +1.2% |
| ATR-Based | 12.5% | 0.6% | $12,500 | $12,671 | $100,735 | +0.7% |
| Fixed Risk | 10% | 0.5% | $10,000 | $10,110 | $100,591 | +0.6% |
| Signal Proportional | 6% | 0.3% | $6,000 | $6,040 | $100,357 | +0.4% |
Six stop-outs (−5% each). Every position shrinks with equity. Notice how small each per-trade loss is: it is exactly the exposure fraction × the 5% stop — 5.0% for 100% of Equity, but only 0.5% for Fixed Risk.
Buys ~100% of current equity on every entry.
Scales with forecast strength and how calm the instrument is.
Risk fraction K is re-estimated from completed trades.
Sizes off an ATR distance instead of the stop.
Risks 0.5% to a 5% stop → ~10% of equity.
Fixed-risk size dialed by confidence (m = 0.6 here).
Show the numbers for this run
| Method | Exposure | Stop-loss / trade | Position, trade 1 | Position, trade 6 | Final equity | Total return |
|---|---|---|---|---|---|---|
| 100% of Equity | 100% | 5% | $100,000 | $77,378 | $73,509 | -26.5% |
| Volatility Targeting | 62.5% | 3.1% | $62,500 | $53,326 | $82,655 | -17.3% |
| Kelly | 20% | 1% | $20,000 | $19,020 | $94,148 | -5.9% |
| ATR-Based | 12.5% | 0.6% | $12,500 | $12,114 | $96,308 | -3.7% |
| Fixed Risk | 10% | 0.5% | $10,000 | $9,752 | $97,037 | -3% |
| Signal Proportional | 6% | 0.3% | $6,000 | $5,911 | $98,213 | -1.8% |
Simplification: the exposure fraction is held constant per method so it tracks equity cleanly. In practice it also moves with each method's inputs — the stop distance (Fixed Risk), completed-trade statistics (Kelly), forecast, volatility and regime (Volatility Targeting), signal strength (Signal Proportional), and ATR and price (ATR-Based). Entry price is held at $100 and commissions, slippage and gaps are excluded so the focus stays on sizing.
Example 4: How portfolio weighting changes the capital sleeve
Assume a $400,000 portfolio account assigns a 25% weight to one Minerva strategy:
| Calculation | 100% of Equity | Fixed Risk at 0.5% with a 5% stop |
|---|---|---|
| Strategy sleeve | $400,000 × 25% = $100,000 |
$400,000 × 25% = $100,000 |
| Requested strategy position | $100,000 | $100,000 × (0.5% ÷ 5%) = $10,000 |
| Gross exposure as a percentage of the whole account | 25% | 2.5% |
| Modeled loss at the initial stop | $5,000, or 1.25% of the account | $500, or 0.125% of the account |
How portfolio sleeves are formed
A portfolio sleeve is the portion of a larger portfolio account allocated to one strategy holding. “Sleeve” is appropriate here because the strategy is one component of a multi-strategy portfolio; it is not the preferred term for the capital in a standalone backtest.
Let:
Eaccount,0be the portfolio account’s starting equity.wibe holdingi’s portfolio weight.Esleeve,ibe holdingi’s initial allocated capital.
Portfolio weights are positive and together exhaust the portfolio:
sum(wi) = 1
At portfolio launch, each holding’s initial sleeve is:
Esleeve,i = Eaccount,0 × wi
The launch weights and allocated-capital amounts are then frozen for the launched book. Each holding replays its tested strategy execution configuration inside its own allocated capital rather than sizing from the portfolio’s entire shared cash balance. As that holding makes or loses money, its strategy equity changes, and its next position is sized from that updated strategy equity.
How Minerva calculates portfolio weights
Except for Equal Weight, the methods begin with timestamp-aligned per-bar return histories for the strategy holdings. Correlation-aware methods use a denoised covariance matrix. A volatility floor prevents an unusually sparse strategy from appearing nearly riskless merely because most of its returns are zero, and a maximum-weight cap prevents one holding from dominating the book.
| Portfolio weighting method | Plain-English description | Technical definition |
|---|---|---|
| Equal Weight | Give every holding the same share of portfolio capital. | wi = 1 ÷ N |
| Inverse Volatility | Give calmer strategies more capital and more volatile strategies less. | wi = (1 ÷ σi) ÷ sum(1 ÷ σj), using volatility-floored aligned returns |
| DSR-Weighted / Bayesian Model Averaging | Give more capital to strategies with stronger deflated-Sharpe evidence. | wi = exp(DSRi − max(DSR)) ÷ sum(exp(DSRj − max(DSR))) |
| Minimum Variance | Choose long-only weights intended to minimize total portfolio variance. | Minimize wᵀΣw, subject to sum(wi) = 1, wi ≥ 0, and the maximum-weight cap |
| Full Risk Parity | Choose weights so that each holding contributes approximately the same fraction of portfolio volatility. | Equalize RCi = wi × (Σw)i ÷ sqrt(wᵀΣw) across holdings |
| Nested Clustered Optimization | Group correlated strategies, diversify within each group, and then diversify across the groups. | Cluster the correlation matrix; calculate minimum-variance weights within clusters and minimum-variance weights across cluster portfolios; multiply the two levels |
For three or more holdings, the default maximum holding weight is:
max_weight = min(100%, max(2 ÷ N, 40%))
The default volatility floor used for portfolio weighting is:
σfloor = 25% × median cross-sectional strategy volatility
These controls modify the raw portfolio-weighting solution before allocated capital is assigned.
How portfolio weighting and strategy sizing interact
Portfolio weighting and strategy sizing answer different questions:
- Portfolio weighting: What fraction of the portfolio account belongs to each strategy?
- Strategy sizing: What fraction of that strategy’s current equity should be deployed on this trade?
They operate sequentially and therefore multiply at portfolio launch:
initial holding position notional = portfolio starting equity × launch weight × strategy exposure fraction
Equivalently:
Ni,0 = Eaccount,0 × wi × xi,0
where xi is the position exposure produced by the strategy sizing method before shared caps.
Strategy sizing method inside holding i |
Strategy exposure fraction xi |
Approximate launch exposure as a fraction of the whole portfolio |
|---|---|---|
| 100% of Equity | xi ≈ 1 |
wi |
| Fixed Risk | xi ≈ r ÷ s |
wi × r ÷ s |
| Kelly | xi ≈ K ÷ s |
wi × K ÷ s |
| Volatility Targeting | xi ≈ (F ÷ Fs) × (τ × Mregime × IDM ÷ 16) ÷ σd |
wi × xi |
| Signal Proportional | xi ≈ m × r ÷ s |
wi × m × r ÷ s |
| ATR-Based | xi ≈ r × P ÷ (kATR × A) |
wi × r × P ÷ (kATR × A) |
At launch, the same multiplication determines modeled stop risk at the portfolio-account level:
- With 100% of Equity and a stop fraction
s, modeled account risk from holdingiis approximatelywi × s. - With Fixed Risk, modeled account risk from holding
iis approximatelywi × r. - With Kelly, it is approximately
wi × K. - With Signal Proportional, it is approximately
wi × m × r. - With ATR-Based, actual stop risk depends on how the execution-stop distance compares with
kATR × A. - With Volatility Targeting, stop risk is an output of the chosen exposure and stop distance rather than the sizing target.
After launch, each holding compounds independently:
Esleeve,i,t = Esleeve,i,0 + cumulative net P&Li,t
Ni,t = Esleeve,i,t × xi,t
Because holdings earn different returns, their effective weights can drift away from the frozen launch weights:
weffective,i,t = Esleeve,i,t ÷ Eaccount,t
Portfolio weighting therefore does not replace strategy sizing, and strategy sizing does not replace portfolio weighting. The launch weight establishes the strategy’s initial capital boundary. The strategy sizing method determines how much of its current strategy equity is used for each accepted trade.
Portfolio interplay example
Consider a $300,000 portfolio containing three equally weighted strategies:
w1 = w2 = w3 = 1 ÷ 3
Each strategy receives:
$300,000 × 1 ÷ 3 = $100,000
| Strategy sizing inside each $100,000 sleeve | Position per active strategy | Maximum combined gross position if all three are active | Combined modeled initial stop risk |
|---|---|---|---|
| 100% of Equity | $100,000 | $300,000, or 100% of the account | With a 5% stop: $15,000, or 5% of the account |
| Fixed Risk at 0.5% with a 5% stop | $10,000 | $30,000, or 10% of the account | $1,500, or 0.5% of the account |
The portfolio weights are identical in both rows. The difference comes entirely from the strategy sizing method used inside each allocated sleeve.
Formula notation
E= current strategy equity when a new position is sized.P= entry price at the next eligible bar open.q0= raw absolute shares before shared caps;q= final executed absolute shares.r= configuredrisk_per_tradefraction.D= initial stop-derived risk per share;Dexec= actual entry-to-execution-stop distance.s= initial stop-distance fraction, soD = P × swhen a percentage stop controls sizing.F= absolute final adjusted forecast on Minerva’s 0–20 scale;Fs= volatility-targeting forecast scalar.p= causal win rate;b= average win divided by average loss.fK= fractional-Kelly multiplier;Kmax= maximum Kelly risk fraction;K= applied Kelly risk fraction.τ= target annual volatility;Mregime= regime volatility multiplier;IDM= instrument diversification multiplier.σd= estimated daily percentage volatility.A= ATR;kATR= ATR multiple.mminandmmax= minimum and maximum Signal Proportional scales.L= maximum leverage;C= available cash;MPV= maximum position value.w= portfolio weight;Eaccount= total portfolio account equity.floor(x)= round down to a whole number of shares.
Complete comparison
The numerical rows in the detailed table use the assumptions from Example 1.
| Behavior | 100% of Equity | Fixed Risk | Kelly | Volatility Targeting | Signal Proportional | ATR-Based |
|---|---|---|---|---|---|---|
| What it controls | Standardized capital exposure | Loss budget relative to the initial stop distance | Dynamically estimated loss budget | Target portfolio volatility | Fixed-risk size multiplied by signal strength | Loss budget relative to ATR |
| Core share formula | floor(equity ÷ price) |
floor((equity × risk%) ÷ stop distance) |
floor((equity × Kelly risk%) ÷ stop distance) |
Forecast-scaled volatility-target quantity | floor(fixed-risk shares × signal scale) |
floor((equity × risk%) ÷ (ATR × multiple)) |
| Formal raw-quantity formula | q0 = floor(E ÷ P) |
q0 = floor((E × r) ÷ D) |
q0 = floor((E × K) ÷ D) when Kelly applies |
q0 = floor((F ÷ Fs) × ((E × τ × Mregime × IDM ÷ 16) ÷ (P × σd))) |
qbase = floor((E × r) ÷ D); q0 = floor(qbase × m) |
q0 = floor((E × r) ÷ (kATR × A)) |
| Risk-budget formula | No configured risk budget. Derived initial stop risk is q × Dexec. |
R = E × r |
R = E × K; fallback uses E × r |
Rvol,daily = E × τ × Mregime × IDM ÷ 16; this is a daily cash-volatility target, not stop-loss risk |
Reported base budget is R = E × r; effective sizing risk is approximately m × R before rounding and caps |
R = E × r, applied against kATR × A rather than the execution stop |
| Sizing-distance formula | Price determines shares: P. A stop distance does not determine size. |
D = max(minimum tick, abs(P − S0)); if no stop exists, D = P |
Same D as Fixed Risk when Kelly applies |
Volatility denominator is P × σd; stop distance is not used |
Same D as Fixed Risk for the base quantity |
DATR = max(minimum tick, kATR × A) |
| Method-specific scaling formula | No method-specific scale: m = 1 |
No method-specific scale: m = 1 |
b = average win ÷ average loss; Kfull = ((b × p) − (1 − p)) ÷ b; K = clamp(Kfull × fK, 0, Kmax) |
Forecast scale is F ÷ Fs; volatility scale is (τ × Mregime × IDM ÷ 16) ÷ σd |
n = min(F ÷ 20, 1); m = mmin + n × (mmax − mmin) |
Quantity varies inversely with kATR × A; there is no forecast-strength scale |
| Raw position-notional formula | N0 = q0 × P ≈ E |
N0 = q0 × P ≈ E × r × P ÷ D; when D = P × s, N0 ≈ E × r ÷ s |
N0 = q0 × P ≈ E × K × P ÷ D; when D = P × s, N0 ≈ E × K ÷ s |
N0 = q0 × P ≈ E × (F ÷ Fs) × (τ × Mregime × IDM ÷ 16) ÷ σd |
N0 = q0 × P ≈ m × E × r × P ÷ D; when D = P × s, N0 ≈ m × E × r ÷ s |
N0 = q0 × P ≈ E × r × P ÷ (kATR × A) |
| Raw initial-exposure formula | X0 = N0 ÷ E ≈ 1 |
X0 ≈ r × P ÷ D; with a percentage stop, X0 ≈ r ÷ s |
X0 ≈ K × P ÷ D; with a percentage stop, X0 ≈ K ÷ s |
X0 ≈ (F ÷ Fs) × (τ × Mregime × IDM ÷ 16) ÷ σd |
X0 ≈ m × r × P ÷ D; with a percentage stop, X0 ≈ m × r ÷ s |
X0 ≈ r × P ÷ (kATR × A) |
| Modeled initial stop-risk formula | Rstop = q × Dexec; at 1× exposure and a percentage stop, approximately E × s |
Rstop = q × D; before costs and gaps, Rstop ≤ E × r |
Rstop = q × D; when Kelly applies and before costs and gaps, Rstop ≤ E × K |
Rstop = q × Dexec; it is an output, not the sizing target |
Rstop = q × D; before costs and gaps, approximately m × E × r or less |
Rstop = q × Dexec; it equals the ATR budget only when Dexec = kATR × A |
| Shared capped-quantity formula | qcap = min(q0, floor(MPV ÷ P), floor(E × L ÷ P), floor(C ÷ P) for longs); below minimum size becomes zero; participation clipping then produces q |
Same shared formula | Same shared formula | Same shared formula | Same shared formula | Same shared formula |
| Signed-order and executed-notional formulas | Long shares Q = +q; short shares Q = −q; executed notional N = abs(Q) × P |
Same | Same | Same | Same | Same |
| Meaning of “0.5% risk” | Not an input | Target loss from entry to initial stop is approximately 0.5% of equity | Used only as fallback; Kelly normally calculates its own risk fraction | Not used | Base fixed-risk budget before strength scaling | Target loss against the ATR sizing distance, not necessarily the actual stop |
| Example requested shares | 1,000 | 100 | Depends on trade history; 200 if applied Kelly risk is 1% | 625 under the assumptions above | 60 using Minerva’s Optimizer defaults | 125 |
| Example requested dollars | $100,000 | $10,000 | $20,000 if applied Kelly risk is 1% | $62,500 | $6,000 | $12,500 |
| Is the requested amount constant? | Approximately 100% of current equity at every new entry | Approximately risk% ÷ stop% of current equity when stop percentage is constant |
No; calculated Kelly risk changes as completed-trade statistics change | No; changes with forecast, volatility, regime multiplier and equity | No; changes with forecast strength as well as stop distance and equity | No; changes with ATR, price and equity |
| Can the signal strength request a partial position? | No. A qualified signal is full-or-zero | No. A qualified signal receives the complete calculated fixed-risk size | No. Strength does not set Kelly size | Yes. Forecast magnitude directly scales quantity | Yes, explicitly. This method exists precisely to do that | No. Strength does not set size |
| Can actual risk be below the configured percentage? | No configured risk target | Yes—integer rounding, caps and liquidity can reduce it | Yes—Kelly can calculate less than its maximum; caps can reduce it further | Not applicable; it targets volatility, not stop loss | Yes—the strength scale intentionally reduces the fixed-risk position | Yes—caps can reduce ATR-budgeted risk; actual stop risk may also differ from ATR risk |
| Can actual loss exceed the risk percentage? | Yes | Yes | Yes | Yes | Yes | Yes |
| Why can loss exceed it? | Stops, if present, are separate; gaps, costs and slippage remain | Gap through stop, commission and slippage are not included in the risk budget | Same | Same | Same | Same, plus the ATR sizing distance can differ from the actual stop distance |
| Fixed-stop price formula | Long: S0 = P × (1 − s); short: S0 = P × (1 + s) |
Same | Same | Same | Same | Same |
| Fixed stop’s role in sizing | None | Directly determines shares | Directly determines shares once Kelly risk is known | None | Determines the underlying fixed-risk shares | None; ATR replaces stop distance for sizing |
| Fixed stop’s role in execution | Exits the full position if hit | Same | Same | Same | Same | Same |
| Initial trailing-stop formula | Long: S0 = P × (1 − t); short: S0 = P × (1 + t) |
Same | Same | Same | Same | Same |
| Subsequent trailing-stop formula | Long: Ht = max(previous H, completed close) and St = Ht × (1 − t); short: Lt = min(previous L, completed close) and St = Lt × (1 + t) |
Same | Same | Same | Same | Same |
| Trailing stop’s role in sizing | None | Its initial distance replaces the fixed stop distance | Same as Fixed Risk | None | Same as Fixed Risk | None |
| Trailing stop after entry | Ratchets, but does not resize shares | Same | Same | Same | Same | Same |
| When fixed and trailing stops are both enabled | Trailing stop governs execution; size remains 100% of Equity | Trailing-stop distance takes precedence in sizing | Same | Sizing remains volatility-based | Trailing distance determines the base fixed-risk size | Sizing remains ATR-based |
| No-stop sizing behavior | Still requests approximately 100% exposure | Uses the entire share price as the sizing distance: 0.5% risk produces approximately 0.5% notional exposure, but no actual stop exists | Kelly fraction becomes approximately the notional fraction, but no actual stop exists | Unchanged; still volatility-sized | Scaled fraction of the small no-stop fixed-risk position | Unchanged; still ATR-sized |
| Initial gross exposure formula | Approximately 100% | Approximately risk% ÷ stop% |
Approximately Kelly risk% ÷ stop% |
Approximately forecast ratio × target daily vol ÷ instrument daily vol |
Fixed-risk exposure × signal scale | Approximately risk% × price ÷ (ATR × multiple) |
| Equity and next-entry formula | Mark-to-market equity is E = cash + Q × current price; after exit and costs, the next entry recomputes q0 using the new E |
Same | Same, plus Kelly statistics update after each closed trade | Same, plus volatility and forecast inputs refresh | Same, plus forecast strength refreshes | Same, plus ATR refreshes |
| Effect of gains and losses | Next entry uses the new equity: $110,000 after a rise to $110,000; $90,000 after a fall to $90,000 | At a constant 5% stop, next position is approximately 10% of new equity: $11,000 or $9,000 | Recalculates from new equity and updated trade statistics | Recalculates from new equity and current volatility/forecast | Recalculates from new equity, stop distance and strength | Recalculates from new equity and current ATR |
| Rebalanced while holding? | No | No | No | No | No | No |
| Effect of same-direction strength changes while holding | None | None | None | None until a future entry—the existing position is not resized | None until a future entry—the existing position is not resized | None |
| Target-state signals | 100% of Equity on entry or reversal; same-direction signals do not resize | Calculated size on entry or reversal | Same | Same | Same | Same |
| Deterministic-horizon signals | 100% of Equity on an eligible event while flat; repeated events while holding are ignored | Calculated size on the eligible event | Same | Same | Same | Same |
| Model-managed-exit models | 100% of Equity on an eligible event while flat; held until model/safety exit | Calculated size on the eligible event | Same | Same | Same | Same |
| Leverage-cap formula | qleverage = floor(E × L ÷ P); 100% of Equity requests 1× even if L is higher |
Same cap | Same cap | Same cap | Same cap | Same cap |
| Leverage behavior | Requests 1×; leverage is a ceiling, not a target | May request more than 1× when the stop is narrow, then gets capped | Same | May request more than the cap | Base and scaled quantity are capped | May request more than the cap when ATR is small |
| Long cash-cap formula | qcash = floor(C ÷ P) |
Same | Same | Same | Same | Same |
| Long cash constraint | May reduce shares below the requested 100% of Equity position | Applies | Applies | Applies | Applies | Applies |
| Maximum-position cap formula | qposition = floor(MPV ÷ P) when MPV is configured |
Same | Same | Same | Same | Same |
| Maximum-position cap | Can reduce below 100% | Can reduce calculated size | Same | Same | Same | Same |
| Liquidity/participation-cap formula | Final entry shares satisfy both the configured fraction of causal ADV and the configured fraction of execution-bar volume, after subtracting shares already entered that session | Same | Same | Same | Same | Same |
| Liquidity/participation cap | Can reduce the entry below the 100% of Equity target | Can reduce the entry | Same | Same | Same | Same |
| Integer shares | Can leave a small amount uninvested | Causes actual risk to be at or below the target before costs | Same | Causes small deviations | Same | Same |
| Entry cash-update formula | cashafter = cashbefore − (Q × P + commission + slippage); for a short, negative Q × P increases cash before costs |
Same | Same | Same | Same | Same |
| Commissions and slippage | Applied after quantity is calculated; not reserved during sizing | Same | Same | Same | Same | Same |
| Circuit-breaker formula | DailyPeak = max(previous DailyPeak, E); DDdaily = (E − DailyPeak) ÷ DailyPeak; trigger when DDdaily < −threshold |
Same | Same | Same | Same | Same |
| Circuit breaker calculation | Same daily drawdown rule, but larger exposure makes triggering more likely | Same rule; likelihood depends on calculated exposure | Same | Same | Same | Same |
| Portfolio-sleeve formula | At launch, Esleeve,0 = Eaccount,0 × w; 100% of Equity subsequently sizes from current strategy equity |
Fixed Risk uses current Esleeve as E |
Kelly uses current Esleeve as E |
Volatility Targeting uses current Esleeve as E |
Signal Proportional uses current Esleeve as E |
ATR-Based uses current Esleeve as E |
| Portfolio construction | Uses 100% of the holding’s allocated sleeve—not 100% of the entire portfolio | Risk-sizes within the allocated sleeve | Same | Same | Same | Same |
| Carver relationship | None directly | Not Carver-style forecast sizing | Not directly | This is Minerva’s explicitly “Carver-style” implementation | Uses Minerva forecast strength but is not Carver’s volatility-target formula | Volatility-sensitive through ATR, but not Carver’s portfolio framework |
| Research question answered | “Does the signal make good directional decisions under standardized exposure?” | “How does it perform under this stop-linked risk budget?” | “How does adaptive trade-history sizing perform?” | “How does forecast- and volatility-scaled exposure perform?” | “How does confidence-scaled fixed-risk exposure perform?” | “How does volatility-distance risk sizing perform?” |
12References
| Luo et al. — Seven Sins of Quantitative Investing, Deutsche Bank (2014). | The one-day reversal look-ahead example behind the next-bar fill rule (Optimizations). |
| Bailey & López de Prado — The Deflated Sharpe Ratio, JPM 40(5) (2014). | Test 1 and the chance benchmark in the MinervaScore. |
| Bailey, Borwein, López de Prado & Zhu — The Probability of Backtest Overfitting, JCF 20(4) (2017). | Test 2 (PBO/CSCV); with the AMS paper, Test 4. |
| Bailey, Borwein, López de Prado & Zhu — Pseudo-Mathematics and Financial Charlatanism, Notices AMS 61(5) (2014). | Why large searches produce winners by chance. |
| López de Prado — Advances in Financial Machine Learning, Wiley (2018), ch. 7 & 12. | The held-back-data method and the purge/embargo gaps (Optimizations); future data in adjusted prices (§3). |
| Bailey & López de Prado — The Sharpe Ratio Efficient Frontier, J. Risk 15(2) (2012). | The MinTRL formula in Test 4. |
| Hansen — A Test for Superior Predictive Ability, JBES 23(4) (2005). | The full Hansen SPA companion audit in Test 3. |
| White — A Reality Check for Data Snooping, Econometrica 68(5) (2000). | White's Reality Check in Test 3. |
| Romano & Wolf — Stepwise Multiple Testing, Econometrica 73(4) (2005). | StepM in Test 3. |
| Hansen, Lunde & Nason — The Model Confidence Set, Econometrica 79(2) (2011). | The model confidence set screen in Test 3. |
| Benjamini & Hochberg — Controlling the False Discovery Rate, JRSS B 57(1) (1995). | The FDR screen in Test 3. |
| Politis & Romano — A Circular Block-Resampling Procedure for Stationary Data (1992). | The circular block bootstrap used by the predictive-ability gate. |
| Lipták — On the Combination of Independent Tests, MTA Mat. Kut. Int. Közleményei 3 (1958). | The algebraic form of the weighted inverse-normal combination in §7. |
| Hartung — A Note on Combining Dependent Tests of Significance, Biom. J. 41(7) (1999). | The lineage of the dependent-case denominator form in §7; Minerva uses it as a frozen population normalization, not as a combined hypothesis test. |
| Whitlock — Combining Probability from Independent Tests: Why Weighting?, J. Evol. Biol. 18(5) (2005). | The rationale for the weighted inverse-normal combination in §7. |
| Harvey & Liu — Backtesting, JPM 42(1) (2015). | Adjusting borderline results for search size. |
| Brown, Goetzmann, Ibbotson & Ross — Survivorship Bias in Performance Studies, RFS 5(4) (1992). | §3. |
| Almgren & Chriss — Optimal Execution of Portfolio Transactions, J. Risk 3(2) (2001). | The market-impact model (§4). |
| Kato — An Optimal Execution Problem with a Volume-Dependent Market Impact. | The volume-dependent extension behind the participation cap (§4). |
| Lo — The Statistics of Sharpe Ratios, FAJ 58(4) (2002). | The null sampling variance for DSR and the HAC Sharpe audit. |