The toolkit
The two previous sections describe the shape of the search and the shape of the validation. This one is the catalogue: what each tool actually is, how it works, and — the part that matters — which specific way of fooling yourself it exists to prevent.
Click any entry to open it, and the row it sits in opens with it. Nearly every one of these was built after a result turned out to be an illusion, which is why each carries a line naming what it guards against — and now a small set of facts: where it lives in the application, and which other tools it works with. The cross-references are links; a catalogue you can only read top to bottom is a list, and this is a system.
Candidates are not random byte soup. A grammar decides the shape of a tree — how many condition groups, how they combine, whether a regime gate is present — and then fills each slot by drawing an indicator, a comparison, an operand and a window from weighted tables.
The default draw tables are deliberately frozen. Absent an explicitly armed option, the generator takes its historical path byte for byte, so a stored seed reproduces the same population it produced when it was recorded.
The draw tables know about your own work too: custom indicators you have written are in the pool alongside the built-ins, so the search can explore around an idea you invented rather than only around the standard library.
Guards against: a search you cannot re-run. A result that cannot be reproduced is an anecdote, and quietly changing a draw weight invalidates every stored run without anyone noticing.
When a rule compares a fast average to a slow one, drawing both windows independently produces nonsense half the time — a "fast" 200 and a "slow" 20. Window groups draw them as an ordered set instead.
Like most of the search-quality machinery, this is armed per run rather than always on: the historical draw behaviour stays available byte for byte, so old seeds keep replaying exactly.
Guards against: burning most of a search budget evaluating incoherent candidates, which also distorts every population statistic computed over them.
A second grammar draws from every one of the 113 indicators and writes what a person can now write by hand — a condition negated on a cross, an at-least-K vote, an exit on the position's own state, a risk gate, an indicator read off a second instrument.
The classic grammar is frozen byte for byte, so every search stored on it still reproduces its population exactly. The extended grammar carries a revision number, and every noise floor measured under it is stamped with that revision — a floor is never read against a search it was not measured for.
Guards against: a vocabulary a person can use and a search cannot, which quietly biases every mined strategy toward the older grammar — and a grammar that changes under stored results, which makes them unrepeatable.
Evaluation runs across worker processes whose import surface is deliberately tiny — the engine and the indicator registry, and explicitly not the web application. A worker that had to load a web framework, a machine-learning stack and a large history file would cost a fraction of a second each, which across a large search is the difference between practical and not.
Workers are spawned, never forked. The main process is multithreaded and may be holding a live broker session; forking that produces a child in an undefined state.
Guards against: searches too slow to be worth running, which in practice means searches nobody runs long enough to be meaningful.
Thousands of candidates in one run reference the same indicators over the same data. The cache memoises those series per job and hands them out shared rather than copied.
That makes the read path strictly read-only by contract: a candidate that mutated a series in place would silently corrupt every later candidate that used it. The project treats this as load-bearing rather than an implementation detail.
Guards against: recomputing the same expensive series thousands of times — and, through the read-only rule, against one candidate's evaluation contaminating another's.
Candidates are scored, better ones become parents, and offspring inherit and mutate structure. Crossover swaps subtrees between two parents, so a good entry condition can meet a good exit condition that was discovered separately.
Because a strategy is a data tree rather than a script, mutation is precise: change one comparison, widen one window, drop one clause. The unit of inheritance is a piece of logic, not a blob of code.
Guards against: the combinatorial impossibility of enumeration. The space of expressible strategies is far too large to sweep, so it has to be explored by something that concentrates effort.
Rather than starting from nothing, a run can be rooted on an existing strategy and explore around it. Several lineages can run in one job, each tracking back to its own root, so the ancestry of any result is recoverable.
Guards against: losing the thread. Without lineage, an interesting variant arrives with no record of what it was a variant of, and the reasoning that produced it is gone.
A long run proceeds as cycles: search, prune what has been kept, search again from the survivors. The prune is applied against the freshly reloaded stored record rather than a copy held in memory, so a cycle cannot quietly grade yesterday's population. The filters for staying in the population and the filters for graduating out of it are deliberately separate questions with separate thresholds.
An extinction guard watches the arithmetic: if a prune would leave too little alive, the whole prune is skipped rather than applied partially. An empty population is not a rigorous population — it is the end of the experiment by accident.
Guards against: a multi-day search that needed a human to babysit every stage — and one over-strict filter silently ending the run while nobody was watching.
Optionally, a learned model can steer generation: trained on the candidates already evaluated in the run, it nudges the search toward regions that have been producing survivors. The descriptors it learns from travel with the run's configuration, so a steered search is as reproducible as an unsteered one.
What it is never allowed to do is score. Every candidate it points at is evaluated by the same causal engine, under the same held-out discipline and minimum-evidence thresholds as everything else. The model proposes; the backtest disposes.
Guards against: spending a search budget uniformly across a space that is mostly empty — without ever letting the guide become the judge of its own suggestions.
Instead of rules on one tape, it mines cross-sectional strategies: rank a universe of instruments through time, hold the leaders, charge the turnover. Every rank is computed from a prefix of history — the same arithmetic the screen uses at that moment — so it is causal by construction.
Guards against: a rotation rule that looked good because its ranks were computed with data from after the date they ranked.
A population left to breed converges. Periodically injecting entirely new random candidates keeps genuinely different material in circulation after the population has started to specialise.
Guards against: premature convergence — the search settling into one basin early and spending the rest of its budget polishing a local maximum it cannot see past.
A cap on how many structurally similar candidates may occupy the population at once, applied inside the selection loop rather than as a filter at the end.
Guards against: a leaderboard of one idea wearing a thousand hats. Filtering afterwards does not help — by then the search has already spent its whole budget breeding the same thing.
Structural difference is not behavioural difference. Two strategies built from entirely different indicators can produce nearly identical return streams. The cull compares candidates by the correlation of their returns, greedily keeping the best of each correlated group.
The same comparison drawn as a picture is the universe map on the Research page — every kept candidate against every other, shaded by how alike they behave. The cull is that heatmap acting instead of showing.
Guards against: a portfolio that looks diversified and is not. This is the failure that makes several "independent" strategies lose money in the same week.
An in-loop check on the shape of the equity curve itself — not its final value. A curve that is a single vertical step, or flat with one enormous trade, is rejected regardless of how well it scores.
Guards against: a score dominated by one lucky event. Summary statistics are perfectly happy to describe a single trade as an excellent strategy.
Parents are chosen along a Pareto frontier over several objectives at once — return, robustness, drawdown, trade count — rather than by one blended score.
Blending into a single number is what lets a candidate buy a superb return with terrible robustness and still rank first, because the weights you chose decided the answer before the search began.
Guards against: optimising a weighted sum you made up, and mistaking the result for a discovery about markets.
A candidate can be scored not on its own record but on what it contributes to the basket of candidates already being kept. The two rankings agree until a newcomer duplicates something the basket already holds — which is exactly the case a solo score cannot see.
It also reaches across data: a candidate can be scored on several tapes at once rather than only the one it was mined from, so something that works purely on its home series shows up as exactly that.
Guards against: a kept set that is five copies of the best idea. The best addition is usually not the best individual, and selecting on individual merit alone guarantees redundancy.
Costs and slippage can be varied while the search runs, so a candidate is scored under a range of assumptions rather than one. Fragility to cost is selected against rather than discovered afterwards.
Guards against: breeding a population of high-frequency candidates that only work at zero cost, then finding out at the validation stage that the entire run was wasted.
The fitness candidates are bred on is computed on training data only. Between the training window and the held-out one sits an embargo — a gap wide enough that an indicator with a long window cannot see across the boundary.
The embargo is the part people skip. Without it, an indicator with a 200-bar window evaluated on the first held-out day is partly computed from training data, and the separation you believe you have is partial.
Guards against: leakage — the search optimising against the very data you were saving to check it with.
Which candidates become parents is decided on the training span only. The validation span is where a candidate is judged; it is never where one is bred, because a search that selects parents on a slice slowly learns that slice.
A companion setting rotates the held-out slice between passes, keyed to the first pass's seed, so no single stretch of history does all the judging — and the overfitting estimate reads the training span it was meant to.
Guards against: an out-of-sample slice that became in-sample one generation at a time, and a single fixed holdout — one crash, say — deciding every candidate's fate.
Ranking a population by a single score forces every trade-off to be decided in advance by whoever chose the weights. The front does not: it keeps the candidates that nothing else beats on every objective at once — return against drawdown, say, or consistency against turnover — and cuts from that set rather than from a sorted column.
Selecting this way is measurably not free, and the number is on the record: taking the front rather than the best single score gave up about a third of the validation-period return for roughly half the drawdown. That is a trade you might want or might refuse, which is exactly why it is stated rather than folded into a formula.
Guards against: a weighting nobody chose deciding what survives. A blended objective always has an implicit exchange rate between risk and return buried in it, and the search will find whatever that rate rewards — including corners you would reject on sight if you saw them separately.
A strategy sitting on a knife-edge of its own parameters is a fitted artefact wearing a result's clothes. After each wave of candidates, this stage perturbs the survivors — jitters their windows and thresholds, builds near-twins — and scores those too, so a candidate is judged on the neighbourhood it sits in rather than on its single luckiest point.
The measurements are deliberately not counted as trials: they are stamped over the training span only, and they never enter the tally that the honesty arithmetic divides by. A neighbourhood that comes back perfectly flat — every jitter scoring exactly what the original did — is marked as such and treated as no evidence, because it means the knob being jittered was one the strategy never reads.
Guards against: the fitted peak. The single best parameter set in a search is, by construction, the one that got the most help from noise; its neighbours are the honest estimate.
Every extra condition is another place to fit noise, so fitness can be charged per condition. And an ablation verb removes a candidate's conditions one at a time and re-runs it, to see which were doing any work — at the scale of a whole bank of survivors, not one strategy.
Guards against: rewarding the candidate that fits the most noise because it has the most places to fit it.
Run enough trials against a fixed stretch of history and the best one will look good whether or not anything is there. How good is not a mystery — it follows from the number of trials and the length of the tape, and it can be computed before the search starts.
So it is. At the moment a run is armed, the app states the score a purely lucky best would be expected to reach given the tape you have pointed it at and the number of candidates you are about to ask for. A result under that line is not a weak result; it is not a result. The figure is also what showed that one early unattended run had been asking for ten times more trials than its history could carry.
Guards against: mining a short tape hard. The number of trials is the thing everyone wants to increase and the thing that most directly inflates the winner, and without this the penalty is invisible.
A signal computed from a bar's close and filled at that same close is a strategy that trades at a price it learned about after the fact. It is a small assumption and it flatters enormously, particularly on the fast, high-turnover shapes a search likes to find.
Candidates are scored on the fill the live path can actually deliver — the next session's open — so the number a search is optimising is the number the product could produce. The excess over the market is computed at the level of each individual fold rather than once over the whole run, so a strategy that beat the market in one era and lost in three cannot report the average as a win.
Guards against: optimising a fill you cannot have. The gap between a close fill and a next-open fill is exactly the size of the edge many mined strategies appear to have.
Every candidate is minted with its own conditions' statistics: how often each clause fired and which never fired at all. The cut can floor on it. The rate of dead clauses turned out to track how many conditions a candidate carries — the complexity a search is prone to reward.
Guards against: a clause that never fired sitting inside a candidate and making it look more considered than it is.
Per condition, per candidate: how often it fired, and what happened when it did. A condition present in every trade is contributing nothing; one that never fires is dead weight the search has not noticed.
The same attribution follows a strategy out of the lab: the logic view on a finished backtest and the records a live deployment keeps are the same question asked later — which clause is actually earning its place?
Guards against: accepting a complicated strategy whose entire result rests on one lucky gate, with four decorative conditions attached.
How much each condition adds on its own, and how much two conditions say the same thing, are measured as a candidate is minted. Both were built as filters and measured before either was trusted — and the first one's sign flipped inside its own standard error.
So both stay reports. A gate built on a number that noisy would select on luck while looking rigorous, which is the one kind of filter worse than none.
Guards against: a rigorous-looking gate that is really a coin toss.
A finished search saves as a universe: the complete logic trees, the statistics, the run configuration that produced them and the seed that reproduces them. Universes can be filtered, re-scored, compared, mapped and mined further.
Guards against: a result you cannot interrogate later. A row in a table tells you a number; it does not tell you what was run, under which assumptions, on which data.
A mining run's leaderboard is ordered by the thing the run was optimising, which is the one ordering guaranteed to be flattered by the search. The bank re-orders what survived by how those strategies did on data the search never touched, then by their worst held-out window, and only then by anything else.
Turning that ranked list into a combined book weights the members by inverse volatility, and refuses by name any curve that does not sit on the same time axis as the rest — two curves of equal length over different dates are not comparable, and silently averaging them is the kind of error that produces a beautiful, meaningless equity line. Ranking on the in-sample score is still possible and takes a confirmation, because occasionally it is what you actually want.
Guards against: reading a leaderboard as a ranking. The order a search produces is a statement about the search, not about the strategies.
Mining produces far more strategies than any store should keep, and the caps that stop the stores growing without bound will eventually evict something you wanted. The vault is the archive underneath: every distinct piece of strategy logic the system has ever generated, kept whether or not the run that made it still exists.
Entries are deduplicated by what a strategy is rather than what it is called, so renaming one or re-mining the identical logic produces a single entry — while a change to the capital or the cost assumptions, which does not change the logic, deliberately does not fork it. What you marked comes first: anything saved or starred is archived ahead of the rest, and the cap names what it dropped rather than dropping it silently.
Guards against: losing the one you meant to keep. The first version of this ranked by recency alone and was holding 1,899 mined rows while seven strategies that had been saved by hand had already been evicted.
Indicator series are computed over a prefix of history — the slice that existed at the moment being decided — so a rule cannot see its own outcome. Costs, slippage, execution delay and warm-up are modelled rather than assumed away, and the result is the full trade list and equity curve rather than a summary.
Because the ranking a screen shows and the ranking a backtest uses are the same implementation given different amounts of data, they cannot drift apart into two versions that agree until they do not.
Guards against: lookahead — the single most common way a backtest lies, and the one that produces the most beautiful curves.
A held-out period the search never saw, tested only after a candidate has been selected. With the same embargo the in-loop fitness uses, so the boundary is real rather than nominal.
A universe remembers every out-of-sample window it has been run against, each in its own card — a later gauntlet leg never erases the one before it, so a candidate that thrived in one window and collapsed in another is visible as exactly that.
Guards against: in-sample overfitting — a strategy that describes one specific history perfectly and nothing else.
Repeatedly fit on a window, test on the window that follows, advance, repeat. Fold statistics stay confined to their own fold — a fold's result is never computed with knowledge from another.
This answers a different question from a single hold-out. Not "did it work on data I did not look at" but "would it have kept working, being re-derived as you went, all the way along?"
Guards against: a strategy that worked for one era and has been dead for years, which a single split can easily hide.
Every number an unattended search produces has been selected on — fitted on the training span, selected on validation, selected on again at the out-of-sample tail. So the final months of the tape are sealed before the search begins: no pass, no gate and no Ordeal may read them. The seal is spent once, when the search is over, and the verdict is a live stamp on each survivor.
Guards against: an out-of-sample result that has quietly become in-sample through being looked at a hundred times.
The oldest months of a tape can be held out of the search as a third window with its own question, so out-of-sample evidence is not only ever the most recent stretch. And a bootstrapped continuation — the tape's own returns resampled in blocks — joins the parametric synthetic futures a survivor is judged against.
Guards against: out-of-sample evidence that all comes from one end of history, and synthetic futures that all come from one model of how markets move.
A structured battery of trials across pillars — different windows, different instruments, degraded assumptions, transferred symbols — with each pillar scored and the whole reported together. There is nothing to configure, deliberately: the same ordeal is applied every time, so two strategies' grades mean the same thing.
Coverage is always reported next to the score. A partial run can score higher than a complete one: if half the trials failed to run and the half that ran happened to be favourable, the average improves. Coverage is the only guard against that, so it is never a footnote.
Guards against: a result that depends on the exact conditions it was found in — and against a broken trial silently flattering the score it was supposed to test.
A candidate that cleared the search cleared it on one arrangement of history. The gauntlet takes the survivors and runs them again across the remaining held-out windows one at a time — including, where it is armed, a synthetic leg on invented continuations — and records each leg separately rather than averaging them.
Separately is the point. A strategy with a strong average and one catastrophic window is a different object from one that is unremarkable everywhere, and an average hides exactly that difference. The synthetic legs are graded only over the invented span, never the real run-in that precedes it, which is a correction that made those numbers drop toward honesty when it was applied.
Guards against: a single lucky era. Most strategies that survive one out-of-sample window do not survive four.
Rather than asking whether a strategy survives a crash, this asks how little has to change before it does not. Eleven named worlds run in order from calm to crash, each stated in units calibrated against the strategy's own measured behaviour — so "one and a half times the usual tail volatility" means that, and not a number someone picked.
It is a fixed ladder and deliberately not a search. An optimiser turned loose on this problem wins by discovering a degenerate corner of the world that nobody can interpret, and the deliverable here is a sentence you can act on. The control rung runs first and defines calibrated reality; if it fails to calibrate, the whole run fails rather than letting the other rungs' labels lie. Death is the rung's median drawdown breaching the floor — median, so one unlucky path cannot condemn a strategy.
Guards against: a robustness claim with no scale on it. "It survived a stress test" is meaningless without knowing how hard the test pushed, and this reports the answer as a position on a ladder.
Every bar is nudged by a draw scaled to its own true range — so quiet days wobble less than violent ones — highs and lows re-bracket the result, and the strategy runs again. The close is deliberately not re-chained: this is a wobble around the path history actually took, never a drift away into a different history.
It answers a question none of the neighbouring tools do. Perturbing the strategy asks whether the parameters are on a knife-edge; destroying the structure entirely asks what luck scores. This perturbs the tape, and asks whether the result depended on prices landing exactly where they did. A nudge of zero is an exact no-op, which is what makes the whole thing checkable.
Guards against: a result that rests on precise price coincidences — a stop grazed by a fraction, an entry that needed one particular tick.
Costs, slippage, execution delay, volatility shocks and price jumps swept across ranges rather than checked at one value. The question is not "does it survive my assumption" but "at what assumption does it stop surviving, and is that anywhere near reality?"
Guards against: a strategy whose edge is entirely inside the margin of error of your cost model.
Finished sweeps are saved whole, with the objective they were graded against stamped on them. Re-grading against a different threshold is a client-side operation on stored results rather than a re-run.
Guards against: moving the goalposts without noticing. If the threshold is stamped, a later comparison cannot quietly use a friendlier one.
Price paths generated beyond the end of real history, carrying the statistical character of the real series but none of its specific sequence. A strategy tested on these provably cannot have been fitted to them.
Synthetic results are held in memory and never written into stored history as though they were real runs. Evidence about robustness is not a track record, and the two must not be confusable later.
Guards against: the limits of having one history. There is only one actual past, and every test on it shares its idiosyncrasies.
The same search, at the same size, run against deliberately meaningless data. Whatever it returns is what a good result looks like when there is definitively nothing to find.
This is the most important number in the whole system and the one most often missing elsewhere. A Sharpe ratio means nothing without knowing what a search of that size produces from noise.
Guards against: multiple-comparison self-deception — the mathematical certainty that a large enough search returns something spectacular from pure noise.
Any result can be read as the difference against simply holding the same instrument for the same span — the same window, never a different one, because a baseline computed over a friendlier period is not a baseline, it is a thumb on the scale.
The difference is expressed in percentage points against that matched span. It is a deliberately humbling view: in a long rising market, most strategies are revealed to be an expensive way of owning the market.
Guards against: crediting a strategy for a bull market it merely sat in — the most common illusion in backtesting after lookahead, and the more flattering of the two.
A candidate is compared with simply holding the tape in six-month calendar blocks, and the share of blocks it beat is its own column. One block reads as a number, never as a share; a tape too short for two blocks gets no verdict rather than a flattering one.
Guards against: one good year carrying a whole comparison, so that a strategy which lost to the market in most of its history reads as having beaten it.
The comparison with holding is also made regime by regime. A strategy that beats the market only while it is rising is identified as a leveraged opinion about the market rather than an edge, however good its total looks.
Guards against: a bull-market strategy presented as an all-weather one.
Two published statistics, run against a search's own results. The first splits the trial record combinatorially and asks how often the configuration that looked best in one half failed to stay above median in the other — an estimate of the probability that the selection procedure itself is overfitting, rather than that any single strategy is.
The second asks whether the best result in a population is better than the best you would expect from that many attempts at nothing — the multiple-testing correction that a per-strategy significance test cannot make, because by the time you are looking at one strategy the selection has already happened. It is read as a floor and ties count against the candidate.
Guards against: testing the winner instead of the procedure. A search over ten thousand candidates produces a wonderful best one from pure noise, and no amount of testing that best one in isolation reveals it.
The same strategy, re-run from a range of start dates, to measure how much of the result depends on when you happened to begin.
This is deliberately distinct from slicing an existing curve. Slicing shows a segment of one run; re-running produces a different run, with different compounding and different warm-up. The gap between those two is exactly the effect being measured.
Guards against: start-date luck, which silently flatters or ruins a result and is invisible in a single run.
Behaviour restricted to a chosen period — a crash, a squeeze, a long grind — computed server-side on the full-resolution equity rather than on the sampled curve the browser draws, because the statistics of a drawdown are not preserved by sampling.
Guards against: a strategy that is fine on average and catastrophic in exactly the conditions you care about surviving.
This tool was asked for as an optimiser — mine the best stops, apply them, make mined strategies beat the market — and the measurement taken before building it said that could not be done honestly. A stop's effect on return did not transfer out of sample by any method tried: per-row, pooled, on a risk-adjusted basis, at the plateau rather than the peak, on the worst fold, and walk-forward on the parameter itself. All empty, with the relationship between in-sample and out-of-sample gain running firmly negative.
Its effect on drawdown transfers reliably — in 33 of 40 cases by one measure and 40 of 40 by another, and it correctly declines to claim a benefit where there is none. So the tool ships as a price list: every candidate exit is shown as an insurance line — what it costs in return, what it buys in drawdown, how many more trades it causes, and how often it actually fired — and the recommended pick is a constrained one, minimising cost subject to a protection requirement. It refuses to choose at all below a floor on how many times the stop was genuinely tested.
Guards against: optimising a knob whose gains are not portable. The first version stated both its budgets in risk-adjusted terms, which let a take-profit that cost 140 points of return win because it bought a fraction of a point of drawdown — a constraint stated on the wrong axis is not a constraint.
The lab prices exits for the rows a search produced. The bench is its inverse: it takes a strategy you saved yourself and re-runs it into the same comparison, so a hand-built strategy can be measured against the same insurance lines rather than only against itself.
It re-runs rather than copies, because a stored result carries the assumptions of the run that produced it. An import is deliberately not counted as a trial — it did not come out of a search, so it must not inflate the arithmetic that divides by how many things were tried. The bench needs a held-out span to report against; without one every premium it quoted would be measured over the same window it was chosen on.
Guards against: comparing a mined exit against a hand-built one on different terms.
The same search configuration is re-mined under a different seed and the two top-K lists are compared. A search that reproduces less than half of its best candidates was describing its seed, not the tape.
Guards against: treating a result as a property of the market when it is a property of the random number generator.
Minimum trade counts and minimum coverage ride on every run rather than being applied as an afterthought. A candidate with nine trades is not a strategy; it is a coincidence with a chart.
Guards against: statistics computed on samples too small to support them, which is where the most confident wrong numbers come from.
A set of diagnostics that ask where a result actually came from: how many positions contributed versus how many were carried, what the sizing scheme contributed as opposed to the signal, and how sensitive the whole thing is to acting a day later than assumed.
The lag question deserves its own sentence, because it is the one that catches real deployments: a strategy whose entire result evaporates when you act one day later than the model assumed was never a strategy you could have run.
Guards against: attributing to a clever signal what was actually produced by position sizing, by holding through, or by an unrealistic assumption about how fast you can act.
Blending survivors into a book is itself a test: correlated legs reveal themselves, turnover costs become visible, and a strategy that looked additive turns out to be a duplicate. The lab is modelling only and cannot place an order or alter a deployment.
Guards against: assuming that several individually-validated strategies combine into something better. Often they combine into the same strategy, three times, at three times the cost.
Day of the week, month of the year, and position within the month — the seasonal patterns the strategy grammar has been able to trade for a hundred rounds, finally measured rather than assumed. Every cell reports how many observations it rests on, always, next to the number itself.
Below a floor set from real measurements, the verdict fields are simply absent and the cell reads as a hint rather than evidence. That is the whole design: a two-year tape genuinely does not have enough turn-of-month observations to say anything, and a calendar tool that prints a confident number for a cell holding twenty-six samples is worse than no calendar tool.
Guards against: seasonal folklore. Calendar effects are the easiest thing in finance to find by accident, because the number of ways to slice a year is large and the number of years is small.
Every test on this page is a statement about a strategy at a moment. Once it is running, the useful question changes: not "was it real" but "is it still behaving like the thing that was tested". The monitor compares live behaviour against the distribution the strategy produced under test — trade frequency, holding period, the shape of its returns — and reports the divergence.
It reports and never acts. Nothing here closes a position or disarms a rule; the deviation is evidence for a decision that stays yours, which is the same rule every safeguard in this project follows.
Guards against: a strategy that quietly stopped being the strategy you tested — a regime it never saw, a data change, or a broker filling it differently than modelled.
On a running deployment, the replay splits the delay from signal to fill into the application's leg and the broker's, measures price drift on a named basis, matches round trips first-in-first-out on the size actually executed, and flags a trip opened by an exit order as a trade nobody meant.
Guards against: blaming the market or the broker for a delay the machine caused, and a position nobody intended hiding inside a book that looks fine in total.
Nothing on this page is investment advice or a performance claim. No figures, returns or results appear here and none are implied. Passing any or all of these tests is not evidence that a strategy will work in future — robustness testing reduces the chance of self-deception, it does not establish that a pattern will persist. Trading involves risk of loss.
A personal project. Not advice. Nothing for sale.
This site describes a personal engineering project, written and run by one person in their own time and published under the name Mithraeum Agora. There is no company behind it, no team and no other contributor. It is not a product and not a business. Nothing here is for sale — there is no account to open, nothing to buy, no subscription, no waiting list, and no service is being offered or solicited. Sending a message through the note form creates no customer, client or contractual relationship of any kind. The note form on the contact page is the way to reach me, and it is the only one.
Nothing on this site is investment advice, financial advice, tax advice, or a recommendation, solicitation or offer to buy or sell any security or financial instrument. I am not a financial adviser, a broker, an investment manager or a regulated firm, and nothing here should be relied on as though I were. If you are making decisions about money, take advice from someone qualified and regulated to give it.
Figures do appear on this site, inside screenshots, and none of them is a performance claim. Every one is a demonstration instance's own arithmetic over price series the application generated itself — synthetic data, with no real market behind it — shown to illustrate what the tools display. They are hypothetical and simulated: no capital was at risk, no orders were placed, and a result computed over history with the benefit of hindsight carries limitations that live trading does not forgive. Hypothetical results are not indicative of future returns, and past performance — real or simulated — predicts nothing.
No brokerage, market-data vendor or other company is named anywhere on this site, and where a name appeared inside a screenshot it has been redacted out of the image. Nothing here states or implies that any company is associated with this project, endorses it, sponsors it, supplies it or has reviewed it. None is, and none has.
What this site collects. Nothing, unless you write to me. There is no analytics, no tracking, no advertising, and nothing at all is loaded from another domain. If you use the note form it takes the name, address and message you type, stores them privately where only I can read them, and keeps them for up to a year before they are deleted — sooner if you ask, and you do not have to give a reason. Your IP address is not kept. One thing is stored on your own device: the colour theme you pick, remembered by your browser so the site does not change appearance every time you arrive. It is written only when you choose a theme, and it identifies nothing and nobody. The preference itself never leaves your browser, but the screenshots follow it, so the pictures your browser fetches from this site are the ones drawn in that palette. The contact page answers all of this in more detail.
Terms of use. This site is provided as is and as available, with no warranty of any kind, express or implied. It describes software under active development: anything here may be incomplete, out of date or simply wrong, and it may change or disappear without notice. Nothing on it is a contract, a term of service for any product, or a promise that anything described will be built, released or kept running. To the fullest extent the law allows, I accept no liability for any loss or damage arising from use of this site or from reliance on anything it says. Nothing here excludes or limits any liability that cannot lawfully be excluded or limited.
Trading involves risk of loss.