Mithraeum · Agora

Safeguards and monitoring

What watches the system

The failures that cost the most in trading software are the quiet ones — a feed that stopped updating, a record that was half-written, a limit that was switched off months ago, a number that reads as zero because nobody could measure it. Most of this project's machinery exists to make those failures loud.

This page is the inventory: what the system refuses to do on a guess, how it keeps what it writes intact, where every action is recorded, how it diagnoses itself, what watches it while it runs, and how it tells you the truth when the truth is inconvenient. The order-level controls — the gates, limits and stops around anything that can place a trade — have their own inventory on the Live page, and are not repeated here.

ProgramWhat it watches
The MithraeumIts own data, its own orders, every job it runs, and the honesty of every search — and it diagnoses itself daily.
The AgoraSign-in events, sessions, device links and support conversations. It has no market data to watch, by construction.
The Control PlaneIts own operator trail, chained so an edit is detectable, and every request its gate refused, counted by reason.
The workbenchThe other three: whether they are running, what their history looks like at three in the morning, what should not be running at all, and whether the backups would actually restore.
The rule underneath all of it: "cannot tell" is never zero. A monitor that cannot reach its source records an absence, not a zero, and draws the gap as a break in the line rather than joining across it. An estimate that cannot be made prints nothing rather than a comfortable number. "There were none" and "we could not see" are different facts, and the second one is the one that hides an outage.

Refusing rather than guessing

6 refusals

Every default here fails closed. When the system does not know, it does not act — and it says which thing it did not know.

One data source and no fallback to anotherrefusal

Every market-data request goes to the source you selected and to no other. A source the application does not recognise requests nothing at all rather than quietly routing to whichever vendor happens to be configured.

Guards against: data arriving from somewhere you did not choose, under terms you did not agree to, and a backtest that silently changed source halfway through its history.

An unverified update surfaces nothingrefusal

The release feed is signed, and the application verifies it against a key it pinned earlier. A feed that fails verification shows no version, no link and no checksum — and a new signing key can only arrive through a different channel from the one serving the feed, so an update host can never vouch for itself.

Guards against: a tampered feed steering you to a download, which works precisely because it looks like a routine notification.

An unclassified service door is closedrefusal

The Control Plane's routes are sorted into public, service and operator scopes by one explicit map, and anything the map does not name defaults to the most restricted scope. Adding a new door never makes it public by omission.

Guards against: the most common way a backend leaks — a new endpoint shipped before anyone decided who may call it.

A protective order it cannot price is not sentrefusal

A stop with no price reference of any kind is refused rather than placed at a guess. A safeguard that places an order on an assumption is not a safeguard — and every order the system places on its own traces back to something the user configured.

Guards against: an automatic protection creating the very loss it was meant to prevent.

A stale input holds the orders it feedsrefusal

A deployment whose logic reads a second series pauses its orders the moment that series is stale or missing at the current bar, and says which series and why. It resumes when the data does.

Guards against: trading on an unknown input — a condition evaluated against a price that stopped arriving, which reads exactly like a quiet market.

An estimate it cannot make prints nothingrefusal

A preflight that cannot count what a job will cost shows no number rather than zero; a noise floor that was never measured is labelled unfloored rather than omitted; a figure computed from too few observations carries its sample size beside it.

Guards against: "this is free" and "this is fine" being read off a measurement that never happened.

Integrity of what is written

4 mechanisms
Every store write is atomic, per writerintegrity

Each write goes to its own temporary file and replaces the store in one step, and every read-modify-write holds the store's lock for the whole operation. This was learned the expensive way: two concurrent writes once shared one fixed temporary name, spliced a store together, and forty saved strategies were gone by the afternoon.

Guards against: a store that is half one write and half another, which is worse than either — it parses, so nothing notices.

A file that will not parse is kept, not replacedintegrity

A corrupt store is set aside under a timestamped name and reported, never overwritten with an empty one. Corrupt and missing are different facts, and treating them as the same is how a recoverable accident becomes a permanent one.

Guards against: the recovery path destroying the only evidence of what was there.

A record's number is never reusedintegrity

Records are addressed by number from several places at once — the current selection, portfolio legs, starred conditions, stress history. The counter never rewinds, so deleting a record can never hand its number to an unrelated one.

Guards against: a pointer that silently re-binds to a different strategy after a delete, which looks like the right record with the wrong contents.

Backups that are checked, not just takenintegrity

Snapshots are scheduled by the age of the newest archive rather than a clock, each carries a checksum, and an archive without one is reported as unverifiable. The backup set is audited against the list of stores that must never be lost — an audit that has found whole directories missing from it before. Restoring is deliberately a command, not a button, and it refuses to write over a live tree.

Guards against: discovering that the backup was incomplete on the day you need it.

Trails — where every action is written down

5 trails
The audit trail is append-only and hash-chainedtrail

Every order, connection, deployment, risk event and configuration change is written to an append-only trail in which each record carries a hash of the one before it. The logging window shows the chain's integrity on every read — any edit, deletion or reordering breaks it and says where — with category filters, text search, a live poll and a CSV export of the filtered view.

It is local and never transmitted. The legal terms name it as something the operator of the online services never holds.

Guards against: a history that can be quietly corrected after the fact, which is no history at all.

The Control Plane's own trail is chained tootrail

Every operator act — conferring a tier, rotating a key, publishing a release — is recorded in the same chained form and verified every time it is read. A request its gate refused is counted, not recorded: an unauthenticated caller must never be able to grow the operator's own record.

Guards against: the commercial authority's history being editable by the people it records, and a stranger filling it with noise.

Every request, in one trailtrail

Brokerage and market data together: what was asked for, what actually crossed the wire, and what came back — a single fetch shown beside the individual requests it became. A summary of each can be mirrored into the audit trail so it survives beside the orders it fed.

Guards against: traffic nobody can account for, and "the data was wrong" with no record of what was asked.

Decision ledgers for everything that acts on its owntrail

Every standing rule keeps a fire ledger — including the rules in shadow mode, which record exactly what they would have done. Every research bot keeps a ledger of every decision it took and the reason, including every coercion of its configuration and every advisory it was given at deployment.

Guards against: automation whose behaviour can only be inferred from its results.

The end-of-day digest is one immutable recordtrail

A day's summary can be written into the trail as a single record, so a day that has been reviewed stays reviewed — the digest cannot be regenerated later into something different.

Guards against: a summary that changes each time it is recomputed from data that has since moved.

The Mithraeum — logs, audit trail and diagnostics
The Mithraeum's logging window on its audit-trail tab: a hash-chain integrity chip reading 180 records, counts of matches, criticals and warnings, severity and category filters and a search box, and a table of chained records — the application starting, sign-ins acknowledging the terms, the support form opened with diagnostics attached, and two critical self-diagnosis entries, one run by hand and one on the daily schedule — above a field for adding an immutable operator note.
The audit trail, with its chain checked. The logging window's first tab reads the append-only trail and verifies its hash chain on every open — 180 records, intact — with severity filters, a search box and a live switch; the second tab is the request trail, the third the self-diagnosis reports. Every record here was written by the demonstration instance on the day these pictures were taken: the application starting, with a note that sessions stay disconnected until the user reconnects; sign-ins acknowledging the terms; the support form opened with a diagnostics bundle attached; and two criticals — the application's own self-diagnosis, reporting errors in the demonstration's deployments, once run by hand and once on its daily schedule. A note can be added to the trail, and it is as immutable as everything else in it.

Diagnostics — the system examining itself

4 diagnostics
A daily self-diagnosis, in two formsdiagnostic

The application diagnoses itself: one engine feeds both the warning panel you see while working and a daily report written in two forms — one for a person to read and one for a program to consume. Severity is honest in both directions: an empty data store is not "all clear", and a session that is closed at midnight is not an incident.

Guards against: two diagnoses of the same system disagreeing, because they were computed by two different engines.

The data-quality sentinel reads every stored seriesdiagnostic

It scans every dataset for ordering, price, split, volume, staleness and interior-gap defects and writes a dated report you can open from the logging window, or run on demand.

Guards against: an unadjusted split or a run of fabricated bars that flatters every backtest run over it.

The support bundle is built through an allowlistdiagnostic

When you ask for help, the diagnostic bundle is assembled field by field from a declared list — build identity, platform, configuration flags, counts and error types — and a field nobody declared is dropped, never sanitised. Exception messages are discarded outright, because a language runtime interpolates values into them. The whole bundle is shown to you as text before anything is sent.

Guards against: a help request that carries a position, a symbol or an account number off your machine by accident.

The workbench's sweep reads the verdict, never re-derives itdiagnostic

The workbench adds only the facts it owns — whether the application is reachable, how things are trending — to the application's own verdict, and keeps a ticket for each finding: critical when it is new or has come back, standing when it is known, resolved automatically when it has been absent for a day.

Guards against: a second opinion computed a different way that slowly drifts from the first, until the two disagree about whether anything is wrong.

The Mithraeum — the data-quality report
The logging window's diagnostics tab: a dated self-diagnosis report for the demonstration instance with its totals and an overall verdict of critical; a table of the shared data store's datasets with their spans, staleness and findings; and a table of strategy and deployment findings — an error for a deployment with no protective stop, warnings for fill drift and implementation shortfall.
The application, diagnosing itself. One report, run on demand here, over the whole instance: the shared data store — three demonstration tapes flagged because their last bar is 245 business days old, five synthetic ones clean — and the strategies and deployments, where it raises an error for a deployment with no protective stop anywhere in its strategy and warns about the demonstration's mock fills drifting from what the engine expected. Severity is honest: the report calls itself critical because it found an error, and says how many of its sections it could not read — none.

Monitoring — what watches it while it runs

6 monitors
Alerts come from the trail, not beside itmonitor

Fills, rejects, disconnects, risk events and data events are derived from the audit trail rather than kept as a second record, so the alert you were shown and the record of what happened can never disagree. The badge turns red on an unseen error.

Guards against: a notification system with its own idea of what happened.

The headless monitor is a second screen that cannot trademonitor

The live book, the connections, the alerts and the emergency controls — nothing else — on a page that does not depend on the full application being responsive.

Guards against: losing sight of a running book because the main window is busy with something else.

Saying what is working, and what is only latchedmonitor

A slow action shows a turning ring and the present participle rather than a disabled button. A request that only sets a flag — finish the current cycle, stop at the next boundary — is drawn from the state the worker actually obeys, so "stopping" is never shown for a stop that was refused. The clock in the top bar becomes a ring while work runs.

Guards against: a button that looks pressed when nothing happened, and one that looks idle while something is still running.

One admission control for every heavy jobmonitor

Mining, stress sweeps, walk-forwards and every other heavy job pass through one broker that knows what is running and what it may still admit. A person's job pre-empts a research bot's in hundredths of a second, and the server can say at any moment exactly what is running.

Guards against: an unattended search slowing the interactive work of the person it works for.

Background sampling answers "what happened at 3 a.m."monitor

The workbench samples the health of the suite on a cadence, keeps a bounded history and raises threshold alerts. The application appears in it as exactly one fact — whether the process is up — because its stores are not the workbench's to read. A monitoring write may never fail a request.

Guards against: every screen showing the present while nothing remembers the night.

Strays, dependencies and drift are reported, never acted onmonitor

Processes nobody launched are found by where they run, not by their name, and reported rather than killed — an unrecorded process is not provably abandoned. Dependencies are checked against what the interpreter can actually install, not merely against the newest release. And the version of record is derived from the engineering log and compared with what shipped, so a disagreement is shown rather than assumed away.

Guards against: a sixteen-day-old process nobody knew about, an "upgrade available" that can never be performed, and a release number nobody remembered to update.

The Mithraeum — alerts
The alerts menu open under the top bar: two critical self-diagnosis entries and two warnings that an entitlement lease failed its signature check while the cached lease stays in effect, then the delivery controls — desktop and browser notification, a link to the audit trail, a webhook with its address field, and checkboxes choosing which kinds of warning escalate.
Alerts, derived from the trail. The menu under the bell lists what the audit trail recorded — here the application's own self-diagnosis reporting a critical finding each time it was run, and the licensing check refusing a lease it could not verify. The demonstration instance runs with no licensing service behind it, so the lease it was handed at each start carried no key to verify against; the application refuses it, says so, and keeps the lease it already holds and its offline grace rather than locking anyone out. Beneath them, where an alert can go: a desktop notification, the browser, a webhook, and which kinds of warning escalate to those channels. Every channel is off in the demonstration instance.
The Mithraeum — the headless monitor
The headless monitor over the demonstration paper book: a risk line, the book's value and cash, five deployments each with its value and its own pause and stop, the emergency controls — routing on, automatic mode, flatten all — and an alert feed, above a footer explaining that closing the window stops nothing.
The headless monitor. A second screen with everything that matters when something goes wrong: the book, every deployment with its own pause and stop, the emergency controls and the alert feed — and a footer saying that closing it stops nothing, because the execution service is the application process itself.

Warnings that tell the truth

5 warnings
Hypothetical results are labelled where they appearwarning

Every surface that shows a backtest, a mined strategy, a stress run or a model output carries the standing hypothetical-results language in place, beside the numbers — not in a terms page nobody opens.

Guards against: a simulated figure being read as a track record.

A strategy with no stop is told so firstwarning

The strategy explainer leads with the exits no condition controls — stops, trails, take-profits, time limits — and states plainly when there are none. When it was first run against the saved strategies, more than half had no stop of any kind, and a handful could never trade at all.

Guards against: a logic tree that looks complete while describing a plan the engine does not run.

A search result without its noise floor says sowarning

A mined universe is read against an empirical null — the same search run on tapes with the signal destroyed. Until that floor exists, or once the search settings have moved away from the ones it was measured under, the result is labelled unfloored or stale, and the label says why.

Guards against: admiring the best of a thousand candidates without knowing what the best of a thousand looks like on pure noise.

Advisories and barren stages in the unattended funnelwarning

A research bot is advised at deployment when its configuration will never ask whether a survivor beats simply holding the market. And a funnel stage whose floor rejected every candidate is recorded as barren and refuses to promote anything out of that cycle — "nothing was deleted" is not the same fact as "everything passed".

Guards against: a survivor promoted because every alternative was worse, rather than because it was good.

Findings and gaps are kept separatewarning

The limits sweep reports two different facts: whether your configuration is inside every published limit, and whether something bounds every limit at all. A known gap is not a breach — folding the two together leaves a signal that is always red, and a signal that is always red is not a signal.

Guards against: alarm fatigue hiding the one alarm that mattered.

Limits you cannot switch off

4 limits

A data vendor publishes how fast it may be asked for history, and answers a breach by cutting the service off. Those numbers are treated as facts about the vendor rather than preferences of the user.

A vendor's number is a ceiling, not a defaultlimit

Each governed window has a ceiling — the vendor's last legal value — and a default set deliberately under it. The ceiling is enforced in the one place every settings write passes through, so an edited file cannot step over it either, and a zero on a governed window means the ceiling rather than "off". A limit you can switch off is not a limit.

Guards against: a backfill quietly running at forty times the published rate because a setting was left at zero.

Two published rules, counted separatelylimit

A budget per ten minutes, and a limit on repeated requests for the same instrument in a two-second window — the second one reachable by a single symbol's own history walk while the first is nowhere near its cap. Both are enforced, across every transport to the same account, and survive a restart.

Guards against: obeying one published rule while breaking another that nothing was counting.

Taking the slot instead of widening the marginlimit

Checking the window and recording the request used to be two steps, and every waiting thread could see the same free slot between them. They are one step under one lock now, measured at zero overshoot with thirty-two threads contending.

Guards against: a race that a comfortable safety margin was hiding, until the day it was not comfortable.

The market-data line cap refuses loudlylimit

Past the account's allocation of live quote lines, a vendor simply stops sending. The application states a cap, refuses the newcomers by name when it is reached, and never drops a symbol already streaming to make room — described in full on the Live page.

Guards against: symbols that silently never tick.

The Mithraeum — data limits
The System settings window at its data-request limits: the strict-limits switch with its explanation, a lookback limit counted in bars per granularity with a paragraph on what it governs, a per-request limit with its own explanation, the heading of the logging section below, and the footer noting that every change is audited. Provider names are redacted.
The limits, stated in the unit they bind in. The lookback limit is counted in bars — one limit for every path, interactive and unattended alike, a thousand by default and clamped to what the source serves — and the panel says outright that it is a reach, not a request size. The per-request limit beneath it is the size, with the source's own ceiling derived and shown. The strict switch above halves both the reach and the rate, and every change is audited. Provider names are redacted out of the image, as they are everywhere on this site.

Performance, measured honestly

4 measures

Monitoring a running strategy is not only watching for errors — it is watching whether what happened is what was expected, and being careful about whose fault the difference is.

Execution delay in two legs, never one numberperformance

The time from a signal to a fill is split into the application's leg — from the signal to the order being placed — and the broker's leg, from placement to fill. They are shown stacked, never summed into one figure, because one figure blames the market for a delay the machine caused.

Guards against: tuning the wrong half of a delay.

Price drift on a named basisperformance

"Drift" is ambiguous: against the signal's price, the price when the order was placed, or the market on the bar it filled? The replay offers each as a named basis, defaults to execution — the fill against the market it executed into — and says that its two legs add up in money but not in basis points, rather than stacking two numbers that do not sum.

Guards against: charging a broker for time an order spent waiting inside the application.

The Vigil keeps watching after deploymentperformance

A promoted strategy can be deployed to forward paper evidence for a stated number of bars, and live evidence is refreshed on a cadence against one high-water mark — so a deterioration is a fact the system fires on, not a feeling somebody has.

Guards against: a strategy that stopped working while everyone was looking at the backtest that said it would.

Calibration and deviance measure the gap to the planperformance

Calibration compares what testing predicted with what happened; deviance reads the audit trail for every guard you overrode and measures, after the fact, whether overriding it helped. Neither writes anything, blocks anything or changes a deployment.

Guards against: learning nothing from the difference between the plan and the outcome.

The Mithraeum — execution quality
The replay's execution-quality section for a demonstration deployment on a synthetic series: a per-fill execution chart lying flat at zero, a per-fill lag chart split into the application's signal-to-placed leg and the broker's placed-to-filled leg, summary chips — a median placing delay of thousands of hours, a filling delay of zero seconds, none of 33 fills adverse — an hour-by-hour table, and the page's own paragraph defining what the drift is measured against.
Execution quality, from the replay. Each fill's delay split into the application's leg — signal to placed — and the broker's — placed to filled — beside its price drift on a basis the page defines in its own words. The deployment is a demonstration on a synthetic series, filled by the application's mock book, which placed a whole history's orders in a single moment when routing was switched on: so the application's leg reads as thousands of hours, the broker's as zero, and the execution drift as nothing at all. That lopsided split is the measurement doing its job — it puts the delay on the leg that caused it, not on the market.

Testing the tests

None of the above is worth much if the checks that guard it can pass for the wrong reason. The project runs 332 test suites, and the suite runner takes each one's exit code as its verdict — never its printed summary, which exists in six formats and would eventually be misread as a pass. The suites are themselves tested by mutation: a deliberate defect is written into the code a suite guards, and a suite that stays green is a suite that is not checking anything. And a surprising share of what is described on this page was found the same way — by rendering the page and looking at it while every check was green.

Why this is its own page. A trading tool is usually judged by what it can do. The better question is what it does when something is wrong — the data, the network, the configuration, the code, or the strategy — and whether you would find out. Everything above is an answer to that question, and each one exists because the failure it prevents was either observed or measured.

None of this makes trading safe. Every mechanism on this page reduces a specific, known failure mode; together they do not remove market risk, execution risk, data or connectivity failure, software defects, or the risk that a strategy which worked stops working — and no list of safeguards can. Nothing here is investment advice, a recommendation, a warranty, or a claim that these measures are sufficient for any purpose. 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.