A backtest records what a system would have done under a historical data and execution model. The competition telemetry records what my process actually observed while dealing with changing quotes, execution modes, broker state and a deadline.
Those are different records.
The result figures in this article come from the project repository and recorded run outputs. I do not have a separate organizer certificate confirming them, so I treat them as project records rather than externally audited results.
That is the only evidence caveat I need to repeat. The rest of the article is about the run itself: how I built the live-only series, what changed in configuration, what I watched while the process was running and which records I should have preserved better.
Constructing the live telemetry record
The public telemetry source contains 1,045 rows with five main fields:
| Field | Meaning |
|---|---|
cycle_index |
The loop cycle associated with the observation |
timestamp |
The recorded UTC time |
mode |
live, paper-live or dry-run |
equity |
The account-equity snapshot recorded by the process |
margin_level |
The margin-level value available at that observation |
The mode column is not presentation metadata. It changes what the row means.
The source contains:
- live
- 893 observations
- paper-live
- 143 observations
- dry-run
- 9 observations
- total
- 1,045 observations
If I joined all 1,045 rows into one line, I would create a sequence that moved between different execution semantics and present it as one account path.
For the live-equity analysis, the definition is therefore explicit:
# scripts/writing/model_to_market/build_live_equity_dataset.py
live = (
telemetry.loc[telemetry["mode"].eq("live")]
.assign(timestamp=lambda frame: pd.to_datetime(frame["timestamp"], utc=True))
.sort_values("timestamp")
.reset_index(drop=True)
)
live["drawdown"] = live["equity"] / live["equity"].cummax() - 1.0
That transformation performs two separate jobs.
First, it limits the series to observations recorded as live.
Second, it derives drawdown from the running peak of that live-only equity series. It does not add the final settlement value as another telemetry row.
Building the live-only equity path
Filtering to mode == "live" leaves 893 observations.
The detailed chart below uses those rows only. It keeps the UTC timestamps, does not smooth the line and does not interpolate missing observations. The settlement value is shown separately because it came from a different record.
The annotations identify repository events, not causal explanations.
For example, Git history can show that I enabled OU on 23 June. It cannot prove that the subsequent rise in equity was caused by OU, or even identify the exact first live cycle that loaded the new file without the matching runtime hash.
I want the chart to show when the system changed without pretending that proximity proves attribution.
Competition timeline and changing risk
The first live observation records:
Equity: $1,000,000.00
Timestamp: 20 June 2026 12:52:06 UTC
The lowest live observation in the sanitised series records:
Equity: $996,627.61
Timestamp: 22 June 2026 13:17:39 UTC
That is a decline of about $3,372 from the first recorded live value.
It is not necessarily the account’s lowest intrabar equity. The telemetry only tells me what was observed at the recorded timestamps. It also is not the final settlement or a backtest drawdown.
The launch configuration at that point was the conservative two-sleeve baseline described in Parts 1 and 2:
- momentum at 0.60;
- Kalman gold/silver at 0.40;
- target volatility 0.03;
- maximum instrument weight 0.10;
- maximum leverage 2.0.
The low arrived before the later OU configuration and before the final-day risk settings. That chronology is useful. It still does not explain the low on its own.
22–25 June: from the low to the peak
From the 22 June low, the live series climbed to:
Equity: $1,070,700.36
Timestamp: 25 June 2026 14:04:34 UTC
That is the highest observation in the sanitised live dataset.
The configuration changed during that interval. Git history records OU being enabled on 23 June, with momentum and Kalman reweighted to make room for the new sleeve.
I can establish that sequence:
- the account recorded its lowest live observation on 22 June;
- the OU configuration was committed on 23 June;
- the series recorded its highest live observation on 25 June.
I cannot establish from those facts alone that the configuration change caused the move from the low to the peak.
That would require a cleaner runtime-activation record, position attribution and a counterfactual account path under the previous configuration. I do not have all three.
The operator view was therefore less satisfying than a retrospective chart. While the process was running, I was not looking at a labelled arc from “low” to “peak.” I was checking whether the loop was alive, which mode it was in, which configuration it had loaded and whether the broker positions still matched the targets.
Risk changed while the account was running
The competition did not run under one fixed risk configuration.
- 0120 June — launch baselineMomentum 0.60 and Kalman 0.40, with target_vol 0.03, max_weight 0.10 and max_leverage 2.0.
- 0223 June — OU configurationCommit b813b9d enables OU at 0.20, reweights momentum and Kalman to 0.55 and 0.25, and changes the permitted configuration state.
- 0325 June — alternative-crypto controlsRepository history records ETH, SOL, XRP and BAR disables and changes to the handling of existing disabled-symbol exposure.
- 0426 June — final-day configuration mergeMerge 6cd774b records target_vol 0.20, max_weight 0.75 and max_leverage 12.0 in the archived live configuration.
The launch and final-day values were materially different:
- Target volatility
- 0.03 → 0.20
- Maximum instrument weight
- 0.10 → 0.75
- Maximum leverage
- 2.0 → 12.0
- Enabled sleeves
- Momentum + Kalman → Momentum + Kalman + OU
That is why I no longer describe the whole competition as simply “too conservative.”
I launched conservatively. I tested more aggressive profiles offline. Those tested profiles failed their recorded gate at that stage. I later increased permitted exposure anyway as the competition and remaining window changed.
Those statements can all be true at once.
The unresolved question is whether a different schedule of risk increases would have produced a better final result. The surviving records do not answer it. A final-day increase that happened to precede a gain would not prove optimal timing, and one that preceded a loss would not prove the earlier conservative limits were correct.
Drawdown below the running peak
The headline low and peak do not show how long the account remained below its previous high.
For that, I derive a drawdown series from the same 893 live observations:
This chart answers a different question from the equity curve.
The equity chart shows the account level. The drawdown chart shows when the account was below its own previous live high and how far below it had moved.
It is still based on sampled telemetry rather than every intrabar account movement. I use it as a view of the recorded live path, not as a claim about an unobserved continuous equity process.
Live control, broker state and operational interventions
The monitor was useful because it brought together state that otherwise lived in different parts of the system.
I needed to see:
- the execution mode;
- the cycle number;
- the latest equity;
- the loaded configuration identity;
- current targets;
- broker-observed positions;
- skipped or quarantined symbols;
- recent order and reconciliation outcomes.
The live-control loop had two different feedback paths.
The first was mechanical: MT5 returned positions and order results, and reconciliation compared those with the internal state.
The second was operational: telemetry went to me. I could inspect it, decide that a configuration or symbol control needed to change, then apply that change explicitly.
The live strategy was not self-modifying. It did not inspect its own P&L and rewrite its weights. The operator-feedback arrow belongs outside the strategy loop.
Configuration identity was part of runtime state
A Git commit shows that a file changed. It does not prove which file a running process loaded.
That is why config_sha1 mattered in the heartbeat.
| Runtime field | Question it answered |
|---|---|
mode |
Was this cycle live, paper-live or dry-run? |
cycle |
Was the process still advancing? |
equity |
What account state did the process observe? |
config_sha1 |
Which exact configuration blob did the process load? |
| targets | What portfolio state did the engine want? |
| positions | What state did MT5 report? |
| skipped / quarantined symbols | Which instruments had been withheld from normal processing? |
The OU history exposes the weakness in the surviving archive.
I have the dated Git change that enabled OU. I do not have a clean public record of the first live heartbeat whose config_sha1 matches that configuration.
The safe statement is therefore that OU was promoted in configuration on 23 June. A precise first-live-cycle claim remains unsupported.
Broker state and reconciliation
The target portfolio was never the account of record.
MT5 was.
After order attempts, reconciliation compared internal and broker-observed positions. A mismatch meant that every later sizing decision risked using the wrong starting state.
Part 1 covers the implementation. During the run, the practical distinction was:
The monitor had to keep four claims separate: the target position, the submitted order, the accepted order, and the broker-observed position.
The monitor needed to make the final term visible.
I treated an unexplained position mismatch as an alarm condition rather than a harmless logging difference. Missing one trade could reduce the return. Sizing the next trade from an incorrect position could corrupt the portfolio.
That distinction is also why I do not reconstruct the competition solely from configuration files. The intended target and the actual broker state are different evidence categories.
Alternative-crypto controls during the finals
The finals-period history records changes to alternative-crypto controls.
Around 22 June, the repository accumulated quarantine-related work and progressive symbol restrictions. On 25 June, a later change disabled ETH, SOL, XRP and BAR and changed how existing exposure in disabled symbols should be handled. Another change adjusted that behavior after manual flattening.
Those commits establish that the operational control surface changed.
They do not give me enough public evidence to write a detailed incident narrative with exact positions, volumes, losses and broker responses.
I could write a more dramatic paragraph by inferring those details from the commit messages. It would also be less reliable than the rest of the article.
The supported conclusion is narrower: alternative-crypto exposure led me to change symbol eligibility and close-existing behavior during the competition window.
A future version of this postmortem should add the event sequence only when it can be backed by a redacted runtime extract rather than reconstructed from Git language alone.
Settlement and what the evidence can support
The last live observation in the sanitised CSV records:
Equity: $1,059,853.82
Timestamp: 26 June 2026 14:53:46 UTC
The repository also contains a different live-state snapshot in the README:
$1,061,173.81
The recorded settlement is:
$1,059,439
These are three separate records.
| Record | Value | Interpretation |
|---|---|---|
| Last sanitised live row | $1,059,853.82 | Final observation available in the public live-only CSV |
| README live-state snapshot | $1,061,173.81 | A different recorded account snapshot |
| Recorded settled equity | $1,059,439 | Final settlement figure preserved by the project |
The repository records the final placement as 19th out of 440, with a return of +5.94%, P&L of +$59,439 and a $1,000 prize.
I do not force the three equity endpoints to match. Their difference is a reason to preserve the source and timestamp, not a reason to choose whichever number looks best.
What live operation added to the research record
The backtests answered whether a candidate behaved acceptably under a particular panel and cost model.
The live process introduced other questions:
- Was the process in the expected execution mode?
- Had the intended configuration actually loaded?
- Did the broker accept the requested order?
- Did the observed position match the internal book?
- Had a symbol been disabled or quarantined?
- Had the risk limits changed since the earlier validation?
- Was a result coming from strategy behaviour, execution constraints or an operational decision?
Those questions do not invalidate the backtests. They describe the information the backtests did not contain.
The network and aggression tests in Part 2 also should not be mapped directly onto every section of the live curve. They were validation records from named panels. The telemetry was a different record produced by the running account.
What I would keep and redesign
Mode-separated telemetry
I would keep execution mode as an explicit field and require every chart or summary to filter it deliberately.
A paper-live observation may be useful. It is not interchangeable with a live one.
Configuration identity in every heartbeat
I would keep the configuration hash and make it mandatory for every persisted cycle record.
Without it, a Git timeline and an account timeline can only be aligned approximately.
Broker-authoritative reconciliation
I would keep broker positions as the source of truth after execution.
The internal target describes intent. It should never overwrite what the venue reports simply because the target is more convenient for the next calculation.
A simple operator kill switch
I would keep the STOP file or an equivalently simple external control.
The shutdown mechanism should not depend on the strategy that may be misbehaving.
Separate strategy statuses
I would keep the distinction between research-only, gated, rejected-by-validation, promoted and operationally disabled candidates.
Those states prevented code existence from being mistaken for live use.
What I would redesign
One immutable run bundle per live cycle
I would persist one compact, immutable public-safe record containing:
- timestamp;
- mode;
- cycle;
- source-data identity;
- configuration hash;
- target positions;
- broker positions;
- risk decisions;
- order outcomes;
- reconciliation result.
The competition system produced much of this information, but it was spread across logs, handoff files, Git history and later summaries.
A single run bundle would make the postmortem less dependent on reconstruction.
Explicit configuration-activation events
A configuration commit and a runtime activation should be separate records.
I would add an event such as:
configuration_loaded
timestamp_utc
config_sha1
source_commit
previous_config_sha1
restart_or_hot_reload
That would resolve the current OU ambiguity without relying on the first available heartbeat.
Redacted incident exports
I would create a deterministic redaction pipeline during the competition rather than after it.
The public-safe derivative could preserve:
- timestamp;
- anonymised order or event identifier;
- symbol;
- direction;
- requested and observed quantity;
- broker outcome;
- failed rule;
- reconciliation state.
Account IDs, ticket numbers, server names and local paths could remain private.
That would allow the alternative-crypto sequence to be discussed from the event record rather than from commit messages.
Risk changes on the same timeline as equity
I would make risk-configuration changes first-class chart annotations backed by activation events.
The operator view should answer:
- what limits were active;
- when they became active;
- what equity and drawdown were at that time;
- how much of the competition window remained.
That still would not prove the counterfactual, but it would make the decision timeline inspectable.
A defined post-event counterfactual
I would preserve the final market panel and replay the account under a small set of predeclared alternatives:
- launch risk settings throughout;
- actual recorded configuration timeline;
- selected earlier activation of later settings;
- no alternative-crypto exposure;
- unchanged strategy blend.
The purpose would not be to find the most flattering hindsight configuration. It would be to answer a limited set of decisions that were genuinely considered during the event.
Without that replay, calling a change “too late” remains an opinion.
Evidence gaps and connection to QuantSilico
Three evidence gaps remain material:
-
Organizer evidence I do not have an original organizer leaderboard export, certificate or prize notice separate from the repository-authored records.
-
The first OU-enabled live cycle Git dates the configuration change, but the matching first-cycle runtime hash has not been recovered in a public-safe form.
-
The alternative-crypto event sequence The control changes are commit-verified. The detailed positions, order results and reconciliation sequence have not been published as a redacted event record.
Those gaps limit specific claims. They do not require the rest of the telemetry and configuration record to be discarded.
Where this connects to QuantSilico
The competition system was one trading implementation built for one fixed window.
QuantSilico takes several recurring problems exposed by that run—dataset identity, validation lineage, configuration promotion, runtime evidence and deployment controls—and treats them as platform concerns.
The competition engine is not the QuantSilico product architecture. It is one of the reasons I started defining those concerns more explicitly.
Reproducibility
- Repository: PriestlyAdejo/quantsilico-model-to-market-competition
- Project page: /projects/model-to-market
- Series hub: /writing/series/model-to-market
- Part 1: /writing/model-to-market-system-design
- Part 2: /writing/model-to-market-research-and-validation