An Engine with No Door

Posted by Michael S. on June 5, 2026

The Palantir chart was showing yesterday. Not a little stale. Yesterday's closing price, sitting flat, while the live quote a few pixels above it ticked along in real time. Same broker feeding both numbers. One was current, one was a full day behind, and they were on the same screen openly disagreeing.

That kind of bug is my favorite and my least favorite at the same time. Favorite because the cause is always something specific and learnable. Least favorite because the symptom points everywhere except the actual problem.

The chart that ended 18 hours ago

My terminal pulls candles from Schwab's price-history endpoint. You ask for a day of five-minute bars, you get them. What the docs don't say loudly: if you don't pass an explicit end date, Schwab anchors the window to the previous business day's close. So at 1:45 in the afternoon, market open, my quote feed printing live trades, the candles came back ending at yesterday's bell. The chart wasn't broken. It was faithfully drawing a window that closed eighteen hours ago.

One line fixed it. Pin the end date to "now." I tested it against the live API before touching code, the same request twice, the only difference an explicit now, and watched the newest bar jump from yesterday to a candle thirty seconds old.

I thought that was the whole bug. It was most of it.

The five-year view had a different lie

Every range landed on today after that fix. Except the five-year one, which stayed a day behind.

The five-year chart uses weekly candles, and weekly candles have their own personality. The current week's bar was there, and its open, high, and low were all live. The low was even tracking the day's intraday bottom. But the close was frozen at the previous day's close. Schwab updates a developing weekly bar's extremes as the week goes, then pins its close until the week actually rolls over. So the candle was honest in three of its four values and wrong in the fourth, which happens to be the one your eye goes straight to.

The fix was to stop asking for weekly bars on that range and ask for daily ones, which land cleanly on today. The chart wanted daily-resolution data for a five-year window anyway, so it was the right shape regardless of the bug.

Two problems, one surface, two different causes. The first one was hiding the second.

The overlay I kept moving

Since I was already in the chart code: the floating price readout. It's the little strip of open/high/low/close that updates as you move the crosshair. For a while it had been covering things. A week ago I'd dragged it from the top-left, where it sat on the indicator legend, down to the bottom-left, which only traded one collision for another. Now it lay across the volume bars and any oscillator panel down there. Every corner of a chart has something living under it.

So I stopped guessing and measured. Pulled the actual pixel rectangles of every floating element on the chart. The indicator legend had since moved up into the toolbar, above the canvas, which left the canvas's whole top-left corner empty. The thing I'd fled from a week ago wasn't there anymore. The readout went back to the top-left, over the empty headroom above the candles, and finally stopped covering anything. Measuring beats remembering.

The alerts had a split brain

Then the part I actually care about. My terminal can watch a stock and message my phone when it crosses a moving average, even with the app closed, because a small always-on process does the watching. Good. Except when the app was open, the browser evaluated the same rules the background process did, with subtly different firing logic, and the two coordinated through a single shared flag.

The result was occasionally absurd. The open app firing an alert would quietly flip that flag, which told the background watcher to stop watching the rule. Close the app, the watcher fired on its own and left the app's copy untouched, so the next time you opened the app it might fire again and then deactivate itself. Two engines, one rule, no clear owner.

I made the background process the single source of truth for those alerts. The app lists them now, shows a little "24/7" badge so you know where they actually fire, and stops trying to fire them itself.

While I was in there I found something worse. The alert rules had been living only in the browser's local storage, syncing one direction out to the watcher. Which means a cleared browser profile silently wipes every rule, and the watcher dutifully mirrors the wipe. So I made the durable side the backstop. Clear the browser now, the rules come back on the next load. It's the same lesson I keep paying tuition on: the boring thing you already run beats the convenient thing you'll forget you were depending on.

The actual new feature

The thing I set out to build was an alert on VWAP Boulevard. It's a set of anchored volume-weighted average lines, each one started from a recent high-volume bar, on the theory that price respects levels where a lot of size changed hands. I wanted to be paged when a stock dropped below the strongest of those lines plus a few dollars of cushion.

The work was getting the math to run inside the background watcher, which until now only knew how to compute plain moving averages off daily bars. VWAP Boulevard needs more history and a different calculation: pull a couple of years of bars, rank them by volume, anchor a running VWAP from the heaviest one, and compare price against that line every minute.

I seeded a rule for one of my names, restarted the watcher, and tailed the log. It pulled the history, computed the line at 300.16, saw the stock at 277.62, and fired. My phone buzzed a second later. There it was, a real alert, end to end, on a level that didn't exist in the system an hour earlier.

I also added a way to freeze one of those lines so it holds flat at the price it's at, instead of drifting as new bars arrive. Sometimes you want to mark a level and leave it exactly where it was.

Five copies of the same rule

A smaller fix, but a satisfying trace. My alert list had quietly grown five identical copies of one rule. Same symbol, same settings, different internal ids, created at intervals across the day. The culprit was the "import from TradingView" button. It ran with a force flag that bypassed the one-time "already imported" guard, so every press re-ran the whole import and minted the rule again. The creation routine had no concept of "this one already exists."

I made it refuse to create a duplicate, and added a pass that collapses identical rules on load, keeping the oldest so the original survives. The copies now heal themselves.

And then I went to use it

Here's where the day turned honest on me. With all of it built, the math running, the alert literally still buzzing on my phone, I went to add a VWAP Boulevard alert the normal way. Through the interface. Like a person.

There was no way to do it.

Not hidden behind a tab. Not one click too deep. Just absent. The alerts panel I actually use in my current layout lists existing price alerts in three tidy buckets and nothing else. It has no form to create anything. It doesn't even display indicator alerts. The composer that knows how to build a moving-average or a VWAP-Boulevard alert lives in an older panel my layout stopped mounting a while ago. The function that creates one of these alerts has zero callers anywhere in the interface I run. The only way to make the alert I'd just built was to hand-edit the file the watcher reads.

So I'd written an engine that computes anchored VWAP lines, wired it into a process that runs around the clock, fired a correct alert to my phone, and left no door for a human to walk through and create one.

That's the real shape of a lot of solo work, and it's worth saying plainly. The hard, interesting part gets built and tested and even works. The boring last mile, the form, the button, the place a person clicks, is the part that quietly decides whether the feature exists at all for the person using it. An engine with no door isn't a feature. It's a demo you keep giving yourself.

So that's the next thing on the list. A form. The least glamorous object in the whole program, and the only reason any of the rest of it counts.