Commit graph

51 commits

Author SHA1 Message Date
fced18528b Backfill the history missed while the live stream was down.
History was only fetched by the startup seed, so a Schwab outage stayed a
hole until the next deploy — Sept 9 to 24 after a refresh token expired.
A reconnect more than two minutes past the last bar now fetches the gap
from Yahoo, fills empty buckets only, refolds the live forming buckets,
rebuilds levels without alerting, and resyncs every socket.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 18:48:54 -05:00
234b57e8b6 Stamp drawings and alerts with symbol; snap from the instrument profile.
Missing JSON still loads as /ES. No switcher and no second stream.
2026-09-07 04:01:08 -05:00
d0a0f9f6d6 Document End trendline here: cutoff clips, last_t does not move.
The menu hid the item unless the click was past the second anchor.
2026-09-04 03:34:58 -05:00
2fbb5957f3 Revert "Drop HTF source times that sit inside a compressed 1m halt."
This reverts commit e6fa6beaf0.
2026-08-31 03:45:43 -05:00
e6fa6beaf0 Drop HTF source times that sit inside a compressed 1m halt.
Yahoo 30m/1h can print through Saturday; those opens added index steps
while 1m display is one slot, kinking the line at 17:00. Short holes
and settlement compression are unchanged.
2026-08-31 03:29:40 -05:00
c784f9ed12 Pulse a frame around the live price label, not the whole plot.
Opacity on a ~50x20 box can use the compositor. The old full-width
gradient could not.
2026-08-26 03:26:26 -05:00
111d367224 Animate the live-price cue with transform only.
background-position on a full-width gradient was ~15% CPU. The dash
stays put; only a small shine translates.
2026-08-26 03:25:30 -05:00
f7fbee1187 Coalesce forming 1m ticks to one candle update per frame.
Schwab can print many times a frame; only the last OHLC is visible.
2026-08-26 03:22:22 -05:00
fe4e6b1ae8 Send only the live candle on a forming 1m tick.
Future calendars and HTF geometry wait until that timeframe advances.
The quote paints the header directly so Vue does not rerender the page
at 4 Hz.
2026-08-26 03:19:26 -05:00
60ffaf4657 Stop rebuilding the 1m time scale on every forming tick.
Identical future_times are now a no-op, and HTF ticks only resync lines
when a source bar is actually appended. Document the slotted-hole kink.
2026-08-26 03:12:00 -05:00
f5ba154c98 Count short tape holes in source index so 1m lines stay straight.
Prod already owned the empty 1m slots; source index still treated the
bars on either side as adjacent. Also post a geometry SNAPDBG on ?diag=1.
2026-08-26 03:04:52 -05:00
becbc0e0b4 Sample trendlines on their own timeframe and hit-test the painted line.
1m was putting a point on every bar for 30m/1d lines, which kinked at
tape holes and made hover/select miss. Clicks that were eaten by the
vertical pan gesture now select on pointer-up.
2026-08-26 01:55:47 -05:00
5468bbec60 fix future drawing interactions 2026-08-25 05:41:55 -05:00
90fc77df92 fix canonical future geometry 2026-08-25 05:03:42 -05:00
cb81672a37 trendline fix and just 2026-08-25 04:00:52 -05:00
693d0873f8 diag delay so we can solve trendline slope problem 2026-08-24 01:43:35 -05:00
01acdce045 slope calc fix 2026-08-24 01:02:51 -05:00
18585e42cd trendline selection issue 2026-08-23 23:25:55 -05:00
eaf118ef8b drawings from higher timeframes to lower fixes 2026-08-23 21:37:19 -05:00
913eec34ea lower time frame trendlines blocked from dma chart 2026-08-23 21:10:09 -05:00
7c5f0a7627 large timeframes dashed 2026-08-23 18:27:08 -05:00
1c3a852a03 better fib left start 2026-08-19 09:29:48 +00:00
58a64c1eeb fib levels 2026-08-19 09:09:47 +00:00
08cff3ce53 enable symbols and comments in the future whitespace 2026-08-19 08:36:31 +00:00
44cec38750 slope in tooltip 2026-08-19 05:30:16 +00:00
cc25871032 Keep the Schwab token alive, and reconnect from the header
The live socket never made a REST call, so the seven-day refresh
token expired while the chart still looked fine. A deploy then
could not log in. Ping user preferences every six hours, and when
the grant is already dead offer a one-click reconnect that writes
the token on the existing callback.
2026-08-18 10:11:02 +00:00
d9a272760b Add a Drawings layer toggle that hides lines and comments 2026-08-18 09:53:33 +00:00
1ee2a96fc0 more performance 2026-08-17 01:03:28 -05:00
90f8a1b567 performance fixes 2026-08-17 00:50:20 -05:00
fc09da7053 final pan fix 2026-08-16 23:25:36 -05:00
dfe5224e35 docs 2026-08-16 22:44:01 -05:00
5ee32b327c transmite full 1m data 2026-08-15 04:22:40 -05:00
0c7e81d222 2nd fix 2026-08-15 03:50:38 -05:00
73570d2904 line fix 2026-08-15 03:40:34 -05:00
796e6cdeb8 superior extended trendlines 2026-08-15 00:58:19 -05:00
d523dad1be improved diag screen capture 2026-08-14 23:40:49 -05:00
edcfd3977e trendline wrinkle 2026-08-14 23:28:44 -05:00
333ca4c111 trendline extension slope fix 2026-08-14 23:15:00 -05:00
aae47b6681 autoscroll optional 2026-08-14 13:58:44 -05:00
a921db4610 horizontal line to start of trendline problem 2026-08-14 06:06:16 -05:00
8ab054cf67 timeframe trendline interactions 2026-08-14 04:58:08 -05:00
087d9d9d2a changed ntfy string 2026-08-14 02:44:10 -05:00
f9e02fc3e4 fixed del key bug 2026-08-14 01:12:20 -05:00
54f4871757 key nudge for all drawing types 2026-08-13 19:02:49 -05:00
0a56d56261 reposition price level lines 2026-08-13 06:44:01 -05:00
0e2d5fa2cb Expand drawing widths and quarantine live-feed test 2026-08-13 03:54:28 -05:00
22a638cf73 Label the axis past the last bar, and fix the Yahoo bars that exposed
Trendlines project into the whitespace beyond the newest candle, but the time
axis stopped there, so a converging pair could be seen without knowing when it
converges. Lightweight Charts only labels times present on its scale, so the
chart now carries whitespace points past the last bar: no value, nothing drawn,
but the axis has something to label and timeToCoordinate answers out there.

Future times repeat the most recent bar interval, which is what timeAtIndex
already does for the projections themselves. That drifts across the daily halt
and the weekend; agreeing with the projected line matters more than abstract
accuracy, and session-accurate projection needs server-side session rules the
client does not have.

Two bugs surfaced while measuring it. Padding meant to be five bars measured as
sixty-seven, because the interval came from the gap between the final two bars;
barInterval now takes a median over recent bars and ignores a ragged tail.

And that gap was two seconds on a one-minute chart because Yahoo stamps its
in-progress candle with the time of the request, while the poller emitted
anything newer than the last thing it sent. Every poll therefore appended a new
"1m" bar seconds after the previous one, interleaved with the real ones — live
in production, which is still on Yahoo. Timestamps are bucketed on parse, and
the final candle is emitted unclosed so it revises the current minute rather
than entering the aggregator and adding its volume to every higher timeframe
again on each poll. Verified live: eight consecutive bars, all aligned, all
sixty seconds apart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:55:27 -05:00
07f7befc08 Keep the alert number out of the message and in the push body
Producing a real alert to check the wiring showed #47 twice in one Events row:
once as the badge the browser draws from the `number` field, and again at the
start of the message, because the number had been prefixed onto the shared
string.

ntfy carries plain text and has nowhere else to put a number or a timestamp, so
those belong in a push body built for it. The browser already receives `number`
and `at` as fields and formats its own local time, so its message stays clean.
Alert now carries both: `message` for a screen, `push` for a phone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:23:58 -05:00
32e25b84aa Number alerts, stamp them locally, and compact the zone list
Alerts get a number, assigned server-side and shown in both the push and the
Events list, so a notification on a phone can be matched to a row on a screen
when several fire together. It could not come from the browser: that counter
restarts on reload and differs between tabs. It is persisted next to the
cooldown state, because numbering restarting after a deploy would collide with a
phone's existing notification history — which changed that file from a list to
an object, with the loader still reading the old shape.

Pushes now carry a timestamp in the configured zone rather than the server's.
ALERT_TIMEZONE defaults to America/Chicago; containers run UTC, and a push
reading 02:14 to someone seeing 21:14 costs a translation every time. The
browser already formats its own times locally and is unchanged.

Confluence zones are one line each, ordered by price rather than by proximity,
so the list reads top to bottom the way the chart does and all of them fit on
screen — sixteen zones in 394px, about 25px each, where each previously took a
four-line block. Ordering is a display concern only: the server still returns
them nearest-first, which is what the alert path wants.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:44:57 -05:00
7590d53b13 Put diagnostic capture retrieval behind the same auth as everything else
Uploading a capture required a token; retrieving one did not. That was a
deliberate capability-URL design with a test asserting it, and the reasoning
held: it lets whoever is debugging fetch a capture without the chart password.

Changed because of what a capture contains. getDisplayMedia returns a picture of
someone's screen, and preferCurrentTab is a preference rather than a constraint,
so a mis-click shares a different window. An unguessable id stops guessing but
not leakage: capability URLs escape through proxy logs, browser history and
pasted links.

Retrieval now uses the dependency the rest of the API uses, which already
accepts the session cookie — so a logged-in browser needs nothing extra, which
was the condition for making this change at all. An agent on the server reads
the capture directory directly; one working over HTTP sends the API token.

Both handlers moved from meta.py to routes.py. meta.py is the deliberately open
router — health, version, login, logout — and a screenshot endpoint did not
belong there. The existing test now asserts 401 without credentials, and a new
one covers the browser path: log in, then retrieve with only the cookie.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 17:24:04 -05:00