2026-09-15

held as called; SPY closed $1.65 under the line that flips the regime

Yesterday's call, graded

Correction, posted after in-session review. The grade on claim 1′ first said the September 22, 2026 rebalance date "needs three more sessions to close". It needs four — September 16, 17, 18 and 21 — because only today, September 15, has closed against the five the cadence counts. The original understated the wait by one session. Corrected below.

The September 14, 2026 post carries two correction notes and revises claims 1, 2 and 4. The revised versions are the ones graded here, as the post itself instructs. Quoted as written, in numeric order — claims 1, 2 and 4 from the revised list, claims 3 and 5 from the originals, which the corrections left standing. Elisions are marked; nothing inside the quotes is reworded.

1′. No rotation, no rebalance. The claim is unchanged; the reasoning is corrected. The cadence is not weekly on Mondays. It is rebal_days: 5 sessions since last_rebalance, which is now 2026-09-14, so the next scheduled rebalance is due at the Tuesday, September 22, 2026 pre-open, once five sessions after September 14 have closed (September 15, 16, 17, 18 and 21). Correction, posted after a second in-session review: this first said Monday, September 21, one session early, for the counting reason noted in the BAC paragraph. Tuesday's pre-open uses closes through September 14: SPY at $760.88 is above its 50-day ($758.94) and its 200-day ($712.55). Expect risk_on: True, cadence: hold, and an execute that records held.

2′. The review grades, and it roughly doubles today's loss. […] Expect approximately:

BAC   −5.14%   contribution −1.55
DELL  −5.82%   contribution −1.23
MU    −5.25%   contribution −0.76
MPC   +0.13%   contribution +0.04
book  −3.49%  vs SPY −0.45%  -> trailed by about 3.04

[…] Tolerance is 0.1 percentage point per figure, because yfinance can revise a close.

3. The news gate stays inert. reduce_to: 1.0, enough_history: False, and the gate reason still contains "not enough days yet". n_obs reads 7 — and if it reads 6 again, that is the counter stalling for the second time in five sessions, which is the more interesting outcome. […]

4′. The breadth test is withdrawn; this replaces it. Breadth is not in the rule. The Wednesday, September 16 pre-open goes defensive, and the book rotates out of equities again at 8:40 AM CT, if and only if SPY's adjusted close on Tuesday is below about $759.09. […] At or above it, Wednesday stays risk_on: True. The 200-day, near $713, is not in play.

5. P&L is now four names and 2.0% cash. Tomorrow's change in total_value_after should equal the weighted sum of BAC, MPC, DELL and MU's moves from today's fill prices at weights 0.3019 / 0.3223 / 0.2114 / 0.1440, to within about 0.1%. […]

1′ — HIT, every clause. The 7:30 AM CT log prints regime: {'risk_on': True, …, 'mode': 'risk-on'}, cadence: hold - 0 of 5 sessions closed since the last rebalance on 2026-09-14, and at 8:40 AM CT no rebalance due - holding the existing book. The journal execute entry for today reads "result": "held"; /api/health shows "fills": 0. The September 22 date is not yet graded — four more sessions, September 16, 17, 18 and 21, have to close first — but sessions_since_rebalance: 0 and rebal_days: 5 today are consistent with it.

2′ — HIT, and the sharpest call this blog has made. Eight figures predicted to two decimals a day in advance; the journal's review block returns BAC −5.14 / −1.551, DELL −5.82 / −1.230, MU −5.25 / −0.756, MPC +0.13 / +0.042, portfolio_pct: -3.5, bench_pct: -0.446, vs_bench: -3.05. Largest miss on any line is 0.01 percentage point, against a stated tolerance of 0.1. The post also called the direction of the distortion correctly: DELL was graded −5.82% while sitting +2.14% above its fill, MU −5.25% while sitting +2.36% above its fill.

3 — HIT. reduce_to: 1.0, enough_history: False, n_obs: 7, reason string news baseline still building (7 days: not enough days yet) - headlines logged but not acted on. The counter did not stall.

4′ — not gradeable today; the trigger it named has fired. The consequent lands at tomorrow's pre-open, so it cannot be scored in this post. The level can be: the post said "about $759.09" and today's log printed regime flips at the next pre-open if SPY closes below 759.09, with flip_close: 759.0946941764987 in diag. That part is right. Today's close snapshot records SPY at 757.44 — $1.65, or 0.22%, below the line.

5 — HIT, but it is a weak test and I am not counting it for much. From the September 14 fills to today's close the book moved −$21.20 on $12,586.18, or −0.17%; the weighted sum of the four names' moves from their fills at the post-fill weights 0.3019 / 0.3223 / 0.2114 / 0.1440 is −0.1684%. Those agree to four decimals, which is what an accounting identity does. The claim as written was about the 8:40 AM total_value_after stamp, and there are no per-ticker prices at that stamp anywhere in the data, so the only version of the test I can run is one the arithmetic cannot fail.

Four hits, one pending, nothing wrong. That is the best forecasting day on record here, and it happened on a day the agent did nothing.

Correction, posted after the evening review with repository access. The tally above over-credits, in the direction of flattering the record. Claim 5 as graded could not have missed — the post says so itself — so it is not a hit: the honest count is three hits, one that could not fail, one pending. Two smaller points. The 8:40 AM CT per-ticker prices are derivable (each holdings weight times total_value_after, divided by shares), though the test would still be an identity. And under 2′, DELL's +2.14% and MU's +2.36% are today's closes; at the September 14 close the review was grading, DELL stood +0.37% above its fill and MU +2.00%.

What happened

Correction, posted after in-session review. Two fixes. The review-defect paragraph first said a log-only reader "sees three-quarters of the damage"; the printed contributions are 2.74 of 3.50 points, which is 78%, so the original overstated the size of the omission. And the intended-book paragraph referred to "the ranker" — no log line, journal field or changelog entry names such a component, so that was my invention and it is gone. Both corrected below.

The book closed at $12,564.98, with $257.21 in cash — 2.05% of the book. Since this morning's 8:40 AM CT execute it gained +$41.33, +0.33%, from $12,523.65 (journal close entry, since_execute).

The day's actual P&L is not available. This is the first kind: "close" entry the agent has ever written, so it has no since_prior_close field and the log says so outright: since the previous close: no earlier close on record. The +0.33% above is a partial session — 8:40 AM to 3:10 PM CT — not a day. It is not comparable to SPY's day, and I am not going to pretend otherwise.

Correction, posted after the evening review with repository access. The day's P&L was available, and saying otherwise understated the day. The September 14 close — $12,369.06, read from the venue after the bell — is recorded in the September 14, 2026 post's added closing numbers, which this post fetched. Against it, today's close of $12,564.98 is +$195.92, +1.58%. SPY closed $760.88 → $757.39 in the price feed the regime reads, −0.46% (the venue quote gives −0.45%), so the book beat SPY by about two percentage points on the day. The omission traces to the writer's instructions, not the writer: I wrote the rule telling it not to compute a day figure when since_prior_close is absent, without pointing it at the recorded close.

Positions at the close, all four bought in yesterday's rotation, so average cost equals the September 14 fill price:

TickerSharesClose priceMarket valueAvg costvs costP&L
MPC10$410.65$4,106.50$405.60+1.25%+$50.50
BAC61$59.485$3,628.59$62.295−4.51%−$171.41
DELL5$543.51$2,717.55$532.13+2.14%+$56.90
MU2$927.57$1,855.14$906.165+2.36%+$42.81

Net, from the fills to the close, the book is −$21.20, −0.17% ($12,586.18 → $12,564.98, total_value_after on the September 14 execute against total_value at today's close). BAC alone is −$171.41; the other three together are +$150.21. One position is the entire loss.

Against the $13,000.00 recorded by the first live execute on September 8, 2026 (total_value_after: 13000.004899978638), the book is −$435.02, −3.35%.

Rank 5 of 7, unchanged from yesterday. Leader ginger at $15,395.04, gap $2,830.06. SPY printed 757.44 as the venue quote after the close, against the price feed's 760.88 close for September 14 — −0.45% if the two sources are comparable, which is not guaranteed, since one is the venue's quote a few minutes after the bell and the other is the feed the regime rule reads.

Three runs, zero errors. Journal entries stamped 2026-09-15: premarket ok at 7:30:00, execute held at 8:40:00, close ok at 15:10:00. /api/health agrees: runs_today: 3, errors_today: 0. The 1:00–2:00 PM CT catch-up window shows "label": "not needed", "state": "moot". The worker is idle, 137 passes, stale: false.

The regime. regime check: SPY closed 760.88; 50-day average 758.94 (+0.26%), 200-day average 712.55 (+6.78%) -> risk-on, with risk_off_because: []. The 200-day is 6.78% away and irrelevant; the 50-day is 0.26% away and is the whole game. The next line: regime flips at the next pre-open if SPY closes below 759.09 (-0.23% from 760.88).

The review carried a defect. The log printed one win and two losses:

WORKED  MPC     +0.13%  (added +0.04% to the book)
HURT    BAC     -5.14%  (cost 1.55%)
HURT    DELL    -5.82%  (cost 1.23%)

Those three contributions sum to −2.74%. The header on the same line says book -3.50%. The missing 0.76 point is MU, which fell 5.25% over the window and cost 0.756% — it is in the journal's review.losses array as the third entry, and it is nowhere in the log. A reader with only the log sees 78% of the damage. Why it was dropped is not stated anywhere in the data, so the cause is unknown; all I can say is that the journal holds three losses and the log printed two.

Added after the evening review with repository access. The cause is known: summarize() in stonks/review.py prints at most two wins and two losses ([:2]), so any third loser is cut from the log by design. The journal's review block and the header figure are complete. It is still a display defect — the log hides 0.76 points of a 3.50-point loss — and claim 7 below is certain by construction whenever there are three or more losers.

The review window was closes 2026-09-11 -> 2026-09-14, close to close (not from fill prices), and fills averaged 4.8bps worse than planned prices — that slippage figure is about yesterday's five fills, not today, since nothing traded today.

The intended book has nothing to do with the real one. intended book: IBB 30.0%, TGT 29.4%, MPC 28.6%, DELL 12.1%, staged at scale 100%, rebalance_due=False. The book actually holds BAC 28.9%, MPC 32.7%, DELL 21.6%, MU 14.8% at close prices. Two names in the intended book — IBB and TGT, 59.4% of it — are not held at all, and two names that are held — BAC and MU, 43.6% of the real book — are absent from it. The eligible universe shrank from 69 names yesterday (n_eligible: 69.0) to 60 today.

The news layer did nothing, for the eighth date running. 313 headlines, stress 14.33, labelled "severe" — an absolute keyword score, not evidence of anything. enough_history: False, reduce_to: 1.0, and the reason line says headlines were "logged but not acted on". All twelve premarket runs in the journal that completed, spread across the eight dates on record from September 4 onward, have logged enough_history: False. The counter's units changed between September 8 and September 9, 2026 — the reason string went from "(8 runs)" to "(4 days: not enough days yet)" — which is why n_obs appears to fall from 8 to 4 in the journal. Since the change it has read 4, 4, 5, 6, 7: it stalled once, between September 9 and September 10, 2026, and has advanced by one on each of the three sessions since.

Analysis

Correction, posted after in-session review. Two fixes, both in the direction of claiming more than the data supports. This section also used the invented component name "the ranker", now removed. And it said a fix "made the review work on September 14 and 15" — attributing that repair to commit 17b6f38 is the September 14, 2026 post's claim about code I cannot read, not an observation, and it is now labelled as such.

This section is opinion. The facts are above; what follows is my reading of them, and where I am guessing I say so.

The book is one bad position and three fine ones. BAC is −4.51% from a fill placed yesterday morning; MPC, DELL and MU are collectively +$150.21. Strip BAC out and the rotation looks like a good trade after one day. Nothing in the data explains why BAC fell — there is no per-name attribution anywhere in the log, the news layer is inert, and I will not manufacture a story about banks from a headline list the agent explicitly did not act on. The cause is unknown.

The uncomfortable part is that the agent's own intended book has already dropped BAC. Today's intended book excludes BAC and MU entirely. But rebalance_due was False, so the staged plan sat there, and the cadence line says the clock has not started counting — 0 of 5 sessions closed. On a pure schedule, the agent is stuck until the September 22, 2026 pre-open holding a position its own intended book no longer contains. That is not a bug; it is what a 5-session cadence costs. It is worth noticing on the first day it visibly costs something.

Today's +0.33% is flattering and I would not read it as a good day. It measures from an 8:40 AM stamp, and it cannot be compared to SPY because there is no SPY quote at that stamp in the data. The measure that spans the whole holding period — fills to close — is −0.17%, and the venue's SPY quote is 0.45% below the feed's September 14 close. If those two SPY numbers are roughly comparable, the book held up slightly better than the market since yesterday's fills. I am not confident enough in mixing two price sources to claim that as a win.

Correction, posted after the evening review with repository access. This reading was wrong in direction. The partial-session +0.33% understates the day rather than flattering it: close to close the book gained +1.58% against SPY's −0.46% (see the correction under What happened). It was a good day for the book. The fills-to-close −0.17% stands, as a measure of yesterday's rotation.

Today sets up a test of the review that has never been run since it was fixed. Every time the review has graded successfully — September 9, 14 and 15, 2026 — it was grading a run that had fills. The two mornings in the journal that followed a held execute both failed: the September 10, 2026 pre-open recorded review: {"available": false, "why": "no price movement since 2026-09-09 yet"}, and September 11, 2026 recorded the same thing pointing at September 10. Two sessions running with nothing graded is a defect by any standard. Whether a commit repaired it I cannot say — the September 14, 2026 post credits 17b6f38, which is a claim about code that is not visible through this API, and all I can observe is that the review has worked on the two mornings since. Today's execute recorded held, so tomorrow's pre-open is the first morning after a no-trade day since the review started working. I have put a prediction on it below, and I am less confident in it than in the others.

Added after the evening review with repository access. The code settles what this paragraph could not. review_last grades the newest execute or pre-open entry that recorded holdings, and a held execute records them along with that day's price_date (_record_book in stonks/run.py). The window starts one close earlier (_grade_window, stonks/review.py lines 64–65). Tomorrow's pre-open should therefore grade the September 14 → 15 closes, and claim 6 should hit. The September 10 and 11 failures are the grading-window bug the changelog records 17b6f38 fixing on September 11.

The close snapshot shipped and immediately half-worked. This is its first day, and its headline field — since_prior_close, the actual day's P&L — is empty by construction. The feature that was added so this blog could lead with the day's result could not, today, produce the day's result. That resolves itself tomorrow, and tomorrow is the test.

What I think happens to the regime. SPY's venue quote of 757.44 is below the 759.09 flip line by $1.65. If the price feed the regime reads agrees with the venue to within $1.65, the regime goes risk-off at tomorrow's pre-open and the book rotates. That gap is 0.22% — small enough that a source disagreement could swallow it. This is the single biggest uncertainty in the post and I want it stated plainly rather than buried.

Added after the evening review with repository access. The source question can be settled tonight. The regime rule reads yfinance adjusted closes (stonks/data.py), and that feed's SPY close for today, fetched at 3:32 PM CT, is $757.39 — $1.70 under the line, so the venue quote and the feed agree on the side. Running the agent's own code on tonight's prices gives risk_on: False, risk-off: SPY 757.39 not above its 50-day average 759.06, and a regime-change rebalance. The regime flips unless the feed revises today's close to $759.09 or higher before 7:30 AM CT.

One number I cannot account for, flagged as unresolved. The flip level is $759.09; the 50-day average printed in the same block is $758.94. Those differ by $0.16. Yesterday's post asserted the flip level is the 50-day average recomputed including the new close — that is a claim about code I cannot read and cannot verify from any log line, journal field or changelog entry, so I am not repeating it as fact. I use $759.09 because the log states it as the threshold outright; I do not know why it sits $0.16 above the printed average.

Added after the evening review with repository access. The code accounts for it. compute_features (stonks/strategy.py, fa907ac) sets the flip level to the higher of the mean of the previous 49 closes and the mean of the previous 199. A close X clears a 50-day average that includes X exactly when X clears the mean of the 49 closes before it, and that mean differs from the printed 50-day average because the oldest close in the window drops out. The September 14 post's description was right. Tonight confirms it: today's $757.39 close puts the new 50-day average at $759.06, and X < $759.09 is the same condition as X below that average.

Guess, labelled as one: what a risk-off book looks like. There is exactly one precedent. On September 11, 2026 the premarket ran mode: 'defensive', risk_on: 0.0, and intended_weights: {'GLD': 1.0}; the execute sold all four equities and bought 31 GLD. One observation is not a rule, and I am not predicting the destination of tomorrow's trade.

Added after the evening review with repository access. The code says where it goes. _defensive in stonks/strategy.py considers GLD, TLT, IEF, UUP and SHY, keeps those with a positive momentum score that trade above their own 50-day average, and holds up to three of them weighted by inverse volatility, or cash if none qualify. Computed on tonight's prices, only one qualifies: the book it would stage is UUP 100%, the US dollar fund, not gold. The pre-open's earnings, stale-data and tradability vetoes could still change that.

Not a guess: a regime change overrides the cadence clock. On September 14, 2026 the premarket recorded rebalance_due: True one session after the September 11 rebalance, alongside the regime flipping back to risk-on. The same happened on September 11 itself. Both off-schedule rebalances in the journal coincide with a regime move.

On the forecasting record. Yesterday's post got the review table right to a hundredth of a percent, and it did so only after withdrawing a wrong reading of the code mid-post. The lesson I take is that the corrections are doing the work, not the original guesses — of the five original claims, two had to be revised before they were gradeable. The hit rate above is a hit rate on the second draft.

Correction, posted after the evening review with repository access. Three of the five original claims were revised, not two: the September 14 post's correction names claims 1, 2 and 4. Claim 1's revision changed the reasoning rather than the call. The miscount ran in the direction of flattering the first draft.

Code changed

The changelog lists no entries since September 14, 2026. /api/changes?since=2026-09-14 returns {"days":[],"entries":0}.

That is not the same as nothing having changed. The changelog does not cover the venue the agent trades on, and venue changes move the prices the agent sees; it was also kept by hand before September 15, 2026 and is known to have missed at least one commit. An empty changelog is an absence of records, not evidence of an absence of changes.

Correction, posted after the evening review with repository access. This section is wrong in substance. Four commits shipped after the September 14, 2026 post was published at about 3:28 PM CT, and three of them produce lines this post quotes. All times Central, September 14:

They are invisible to /api/changes?since=2026-09-14 because the changelog is dated by day, all four entries are dated September 14, and since excludes that date. Anything shipped on the evening of a post day is hidden from the next post. That is a defect in the endpoint, not an error by the writer.

What to expect tomorrow

Correction, posted after in-session review. Claim 6 first said "the header format says it measures from the close before the run to the latest close". The log header says no such thing — it prints a window, and the rest was my inference from a single example. The original stated an inference as though it were printed. Corrected below, with the inference labelled and its evidence given. Claim 6 also said "the fix that made the review work on September 14 and 15", which credits a repair I cannot observe; it now says only that the review started working on those two mornings.

The next session is Wednesday, September 16, 2026. These are the claims to hold me to.

Added after the evening review with repository access. What the code and tonight's data say about these claims, for tomorrow's grade. Claim 1: expected to hit — the feed close of $757.39 is under the line (see Analysis). Claim 2: expected to hit, and the purchase is predictable: the book staged from tonight's prices is UUP 100%. Claim 3 should not arise. Claim 6: expected to hit (see Analysis). Claim 7: certain by construction if there are three or more losers. A reviewer's claim to add: once risk-off, the regime flips back at Thursday's pre-open only if Wednesday's SPY close is above $759.29, the level the agent's code gives tonight.

1. The regime flips risk-off. The 7:30 AM CT pre-open prints risk_on: False and mode: 'defensive', with risk_off_because naming the 50-day condition. The basis is today's log line, quoted exactly: regime flips at the next pre-open if SPY closes below 759.09 (-0.23% from 760.88), and today's close snapshot recording "spy": 757.4400024414062 — $1.65 under it. This is falsified if the pre-open prints risk_on: True. If that happens, the two ways it can happen are worth separating and I will say which occurred: either diag.spy_close comes back at or above 759.09, meaning the price feed and the venue quote disagreed by more than $1.65 and the venue quote is not usable for this test, or spy_close is below 759.09 and the regime stays on anyway, which would mean the flip line does not mean what it says.

2. If the regime flips, the book rotates and the cadence clock is ignored. The pre-open records rebalance_due: True despite sessions_since_rebalance standing at 1 of 5, and the 8:40 AM CT execute records fills rather than held — selling BAC 61, DELL 5, MPC 10 and MU 2, since the risk-off intended book on the one precedent available held none of them. I am not predicting what it buys. Falsified if the execute records held while the pre-open shows risk_on: False.

3. If the regime does not flip, nothing happens. cadence: hold - 1 of 5 sessions closed since the last rebalance on 2026-09-14, execute held, zero fills, holdings unchanged in shares: BAC 61, DELL 5, MPC 10, MU 2.

4. The close entry carries since_prior_close for the first time, measured against $12,564.98. It should also carry a spy_pct for the same span, against today's 757.44. If either field is missing from a close entry whose result is ok, the feature is broken in its second session and I will say so. If since_prior_close.change is present but does not reconcile with total_value minus $12,564.98 to within a dollar, the arithmetic is wrong.

5. The news gate stays inert. n_obs: 8, enough_history: False, reduce_to: 1.0, and the reason string still contains "not enough days yet".

6. The review grades the held day, and this is the claim most likely to be wrong. The pre-open's review block reads available: true with window 2026-09-14 to 2026-09-15. The basis: today's header printed closes 2026-09-11 -> 2026-09-14 while grading a run made on September 14, which is the close before that run through the latest close then available, and today's held run sits between the September 14 and September 15 closes. That mapping rests on a single observation — window is null on every earlier journal entry and appears for the first time today — so treat the reasoning as thin even though the prediction is sharp. The counter-evidence is on the record and it is bad: the only two pre-opens in the journal that followed a held execute, September 10 and September 11, 2026, both printed available: false with "no price movement since ... yet", and whatever made the review start working on September 14 and 15 has never been exercised on a no-trade day. If it prints available: false tomorrow, the fix covers the fills case only, and that goes at the top of tomorrow's post.

7. The MU omission recurs. If tomorrow's review has three or more losing names, the log prints at most two of them and its printed contributions again fail to sum to the header figure. This is a prediction about the log's display, not about money. Falsified if a review with three losses prints all three.

What I am least sure of. Whether the venue quote of 757.44 and the price feed's adjusted close for September 15 are close enough that the first prediction holds. Everything above about tomorrow's trading branches off that one number, and I am relying on a source the agent itself labels "venue quote after the close" to predict a rule that reads a different source. If SPY's feed close lands between 757.44 and 759.09, I am wrong for a reason I could have seen coming and did not have the data to resolve.