Notebook 019 - The System Got Smaller
The cleanup was not housekeeping. It was risk management.
The most important Onyx change this weekend wasn't a new signal. It was subtraction.
That's a strange thing to write about a trading system, because trading software wants to grow. Add a model. Add a scan. Add a panel, a mode, a fallback, a helper script that seemed useful at midnight and then quietly survived into production. Onyx had reached that point. The desk had good ideas inside it, but too many old ideas were still living beside the current one: one-off backtests, retired plan helpers, split data roots, and code paths from versions of the system that no longer match how the desk operates.
None of those files were evil. Most of them taught us something. But a trading system is not a museum, and complexity is not sophistication if it makes authority harder to understand.
This is a build note from a paper-trading system, not trading advice. The lesson is architectural: a desk improves when its authority paths get fewer, stricter, and easier to explain.
Too Many Paths Is A Risk
Unused code isn't harmless clutter. It still shapes how people and agents reason about the system. A filename implies a workflow. A stale test implies a contract. An old plan path implies authority. An archived strategy implies the desk still supports a behavior it abandoned.
If the live rule is simple, but the repo still contains five old ways to think about the same action, the desk has to spend attention proving which one is real. If the agent reads old instructions, it can reason from the wrong model. If the user sees old labels, the UI can quietly train the wrong behavior.
So cleanup became a safety task, not housekeeping.
Concretely, we removed old one-off research and comparison scripts like scripts/backtest_daytrade_strategy.py, scripts/compare_watchlist_helium_vs_bh.py, and scripts/eval_no_rsi_exit.py. We also retired the old v3 decision-event helper, scripts/write_v3_decision_event.py, and removed the previous live-plan helper set under src/onyx/live/: plan_loader.py, entry_order_manager.py, and account_risk.py. Those files were useful while Onyx was finding its shape. They do not belong beside the current Onyx Next and Fast Rail workflow as if they are still active desk surfaces.
The Current Shape
Hermes thinks. Onyx watches, guards, executes, and remembers.
Hermes is the desk brain: it reads context, judges the setup, pushes back when the trade is a chase, and decides whether something deserves attention, preparation, rejection, or action. Onyx Next is the cockpit: account, positions, watchlist, news, alerts, plan posture, profit projection, and system health. It's the truth surface, not the approval authority.
MarketFeed is the nervous system. It wakes the desk when watchlist levels go material. Fast Rail is the guarded order rail: limit-only, previewable, duplicate-protected, size checked, cash checked, exposure checked, time-limited, receipt-backed, and journaled. Guard is the hard stop. It doesn't care how persuasive the story is if the evidence, authority, order shape, or risk limits don't pass. The journal is memory.
So the flow is one line: Hermes judges from the current packet, book, feed, watchlist, and plan evidence; Onyx turns that into a Fast Rail preview or a target-management action; Guard decides whether it's allowed; only then does a broker order produce a receipt, a state update, and a journal record.
The older intent and plan paths still exist as fallback and migration support. They're no longer the center of the desk. The cleanup was about making that difference visible. A rollback path can stay available without being the default.
The Watchlist Became The Workbench
Onyx stopped talking about a "universe" and started talking about the watchlist.
That was not only copy cleanup. The news helper changed from build_news_symbol_universe to build_news_watchlist_symbols, and the tests moved with it. A few older references to the "Onyx universe" were rewritten as watchlist references. The code still prioritizes holdings, plan rows, and macro proxies, but the name now matches the desk's actual behavior. Onyx is not pretending to trade or monitor an abstract universe during the day. It is working the names we deliberately put on the board.
"Universe" suggests coverage, every symbol part of the same field. That's fine for research, but wrong for how this desk runs a day. A watchlist is opinionated. It has memory. Names are on it for reasons: recovery positions, fresh-risk scouts, market-health tells, watch-only names because the level isn't ready.
That difference changes the daily question. The question is not simply what the system can trade. The better question is which few names from the watchlist are worth risking capital on today, at what price, for what target, under what tape conditions, and with what exit or rejection rule. That is a desk question.
It forces selectivity, and it makes the alert layer honest. An alert on a watchlist name isn't "go trade." It's "the question we wrote down may be live now." Attention, not authority.
The Dashboard Got More Honest
A trading dashboard can accidentally reward motion. A symbol is moving, a target is near, a row is green, and the screen makes activity feel important before the desk has asked whether the trade is worth the capital and the risk.
The watchlist now surfaces projected profit, which reframes the question. For a held position, if the target fills, what does that do relative to average entry? For a fresh scout, if we buy near the maximum allowed chase price and sell at target, is the upside still meaningful?
The implementation is deliberately plain. A position-target projection uses average entry as the basis. A fresh-scout projection uses the max chase price as the conservative basis. In the dashboard test fixture, a ten-share recovery row with a 255.40 average entry and a 263.00 target shows 76.00 of projected profit, or about 2.98%. A fresh scout capped at 25,000 notional, with a 205.50 max chase and 214.00 target, shows about 1,034.06 of projected profit, or about 4.14%. The point is not the symbols in the fixture. The point is that the row can be active and still fail the capital question if the chase cap eats too much of the opportunity.
It also enforces the no-loss rule in the way the desk actually needs to see it. The system never intentionally submits an automated sell below average entry, so the dashboard surfaces the above-entry recovery path instead of burying it in generic P/L. Less decoration, more decision truth.
Boring Architecture Matters
Storage got simpler. Onyx Next no longer needs a separate top-level data split. In code, DATA_ROOT moved from REPO_ROOT / "data_next" to REPO_ROOT / "data", and Onyx Next's cache and runtime paths now live under data/onyx_next/news_cache/ and data/onyx_next/runtime/. The old top-level data_next/ split is gone.
That's not a dramatic screenshot. But when a system has multiple roots for similar data, every future question gets harder: which folder is durable, which is runtime, which can Hermes read, which can be deleted, and which one is the real journal?
Those questions create hesitation, and hesitation shows up at the wrong time. Durable records get one home, runtime and cache get one namespace, journal evidence lives in the dated journal. Boring, and understandable.
Deletion With Memory
There are two bad ways to clean up a trading system. One is to keep everything forever until the current process is buried under old assumptions. The other is to delete aggressively enough that the desk loses the lessons it paid for.
The middle is deletion with memory. Remove code that no longer belongs in the active tree, preserve the reason, name what's still active versus rollback-only versus historical, and then run the tests that prove the current path still holds.
That's why the cleanup also produced a legacy/delete-later manifest. It names data/target_plan.json, plans/next/, src/onyx_next/, web/onyx_next/, Fast Rail, material alerts, watchlist helpers, and the intent executor as active. It names data/trade_plan.json, scripts/plan_trade_v3.py, and the old v3 runtime support as rollback or research only. That distinction is what keeps history from pretending to be authority.
The system did not get smaller by forgetting. It got smaller by deciding what still matters.
It’s smaller, not weaker. The desk doesn’t need ten competing ways to trade; it needs one current path for action, a clearly labeled rollback path, and a journal that remembers why things changed. Hermes owns judgment. Onyx Next shows the truth. MarketFeed rings the doorbell. Fast Rail and Guard constrain execution. The journal remembers. The doorbell still cannot trade, and that is the point: the system got smaller by making authority harder to misunderstand.