| Age | Commit message (Collapse) | Author |
|
This reverts commit 676ef596d16f39f5e101ea50ef025dd5415705ce.
|
|
Replaces the keyed-container sticky hack with a proper psm-top HTML bar
(st.markdown) matching the design system. Clock is updated via
components.html writing to window.parent.document. Fixes ancestor
overflow so position:sticky works. Moves the / shortcut listener to
window.parent.document so it fires regardless of iframe focus.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
Keys the market bar container (st-key-market_bar_sticky) so CSS can
target it reliably, then applies position:sticky top:0 z-index:200 with
the page background so content scrolling underneath is covered.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Ctrl+K conflicts with the browser address bar on Linux. / is the
conventional global search shortcut (GitHub, Linear) and is not
intercepted by browsers. Guard prevents firing while an input is focused.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
All four treasury yield symbols return values already in percent;
the old /10 and /100 divisors were displaying ~0.04–0.46% instead
of the correct 3–5% range. Also rename ambiguous `l` variable and
add a spinner for the cold-cache load.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Injects a zero-height components.html block after the market bar that
listens for Cmd/Ctrl+K and focuses the sidebar search input by matching
its placeholder text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Persists watchlist and active ticker to localStorage across page reloads
- Adds "← Watchlist" button in sidebar to return to landing page
- Fixes write-before-read race that destroyed stored data on fresh load
- Fixes click swallow caused by st.rerun() aborting render before click
receivers were registered
|
|
Two root causes:
1. The JS wrote empty session defaults to localStorage before reading
stored values back, destroying saved data on every fresh page load.
Fixed by gating on data-loaded: JS reads+restores only when loaded=0,
writes+saves only when loaded=1.
2. st.rerun() inside render_persistence_bridge() aborted the render
before qt_click_receiver/wl_click_receiver were registered. Streamlit
clears unrendered widget state, so pending click values (_qt_click,
_wl_click) were wiped before quotetable/watchlist could process them.
Fixed by removing st.rerun() — the bridge runs at the top of the
render cycle so restored session state propagates to components below
in the same pass; no extra rerun needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Three market-wide panels backed by yfinance (no new API keys). Macro tab
renders before the st.stop() ticker guard so it's always accessible regardless
of ticker state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Persists watchlist and active ticker across browser refreshes via a
localStorage bridge (components/persistence.py), and adds a sidebar
"← Watchlist" button to clear the active ticker and return to the
QuoteTable landing page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Rename "Positions" → "Quotes" (heading was misleading; implies holdings)
- Always clear _qt_click on read so stale values from removed tickers
don't persist across rerenders
- Replace serial get_latest_price + get_company_info calls with
parallel ThreadPoolExecutor fetch of get_company_info only;
regularMarketPrice/currentPrice from info is sufficient for the table
and halves the number of yfinance calls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
display:none removes elements from React's event processing, causing
JS-dispatched input events to be silently dropped. Switching to
visibility:hidden + height:0 keeps the inputs in the React tree so
programmatic value changes trigger reruns correctly.
Also covers the new qt_click_receiver for the quotetable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replaced inline onclick with escaped string literals with the same
data-sym / closest(tr[data-sym]) event delegation pattern used by the
working sidebar watchlist. Avoids JS string quoting issues in HTML
attribute context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Renders watchlist tickers as a styled psm-card data table (Symbol, Sector,
Last, Δ, % Day, Volume) when no ticker is selected. Falls back to the
existing placeholder when the watchlist is empty. Uses the same JS
hidden-input click pattern as the sidebar watchlist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- 5D period now uses '%a %H:%M' tick format so each day is labelled (Mon 09:30)
instead of bare times that repeat across five days
- default_period resolves to '1mo' when 1D series is empty (market closed,
weekend, holiday) so the chart isn't blank on first load
- JS activePeriod reads from OVERVIEW_META.default_period at boot instead of
hardcoded '1d', and bootOverview syncs the active button to match
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds get_intraday_history() to data_service.py (5m/30m bars, ttl=60s)
and wires it into the overview chart with HH:MM x-axis formatting,
market-hours filtering, intraday-only primary fetch, hidden comparison
buttons, and 1D as the default period on load.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace horizontal st.tabs() with session-state-driven vertical nav
buttons in the sidebar (Workspace section). Remove company snapshot
entirely — ticker info is covered by the persistent TickerHeader.
Add NYSE live clock between brand and search. Update brand sub-label
to "v 1.2".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replaces st.button rows with a components.html iframe that renders sym·price·Δ%
in a 3-column grid with hairline dividers, monospace fonts, and colored change
percentages. Adds hidden text_input click receiver so row clicks update
session state. Fixes toggle button to show toast when watchlist cap is hit and
removes now-redundant psm-watch-toggle CSS.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds a save/remove toggle below the company snapshot, a watchlist section
(capped at 10 tickers) that renders sym · price · Δ% rows above Top Movers,
and an empty-state placeholder. Clicking a watchlist row loads that ticker.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Injects a persistent header band between the market bar and st.tabs():
sector tag, italic symbol, company name, 52W range rail with price pin,
price, and Δ/% change chip; below that a 6-cell KPI strip (Market Cap,
P/E, EPS, Div Yield, Beta, Short % Float). All data from cached service
calls — free hits. Graceful "—" fallbacks for missing fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- overview: use json_for_script for inline payload/meta to prevent
</script> break-out from yfinance-sourced strings; raise iframe
height to cover responsive single-column collapse under 1100px
- news: treat naive ISO/strptime datetimes as UTC before converting
to local-naive, matching the int-timestamp branch from 75dbe29
- news: bump per-row iframe height to fit summary + metadata under
scrolling=False
- top_movers: drop name column in compact (sidebar) mode and tighten
grid so symbol/price/change fit a default-width Streamlit sidebar
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
|
|
|
|
Unix-int timestamps from Finnhub were returned as naive UTC, then
.timestamp() reinterpreted them as local time — shifting relative ages
and date filtering. Now normalize to local-naive like the other branches.
Also escape </ in the JSON embedded in <script>, so headlines containing
</script> cannot break out of the inline script.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
Replaces st.radio/st.tabs/st.expander/st.dataframe with a single
components.html() panel matching the Prism design system — same token
block, val-ctx bar, lede card, and CSS grid tables as the Valuation tabs.
Annual/Quarterly toggle and Income/Balance Sheet/Cash Flow tabs are
handled in-iframe via vanilla JS with no Streamlit re-renders.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
tabs
Switch scrolling=True → scrolling=False and increase height estimates so iframe
content never clips. Excess height is invisible whitespace matching page background.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
tab.
|
|
The sliders live inside the canvas iframe (keeping live JS behavior)
but are now in a narrow left rail column — the same visual layout as
before the live-DCF refactor. The canvas uses a 272px + 1fr grid:
left aside has the header, four range inputs, and the filings panel;
right div has all output sections unchanged.
Removes the horizontal va-controls bar added in the previous commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Move all four DCF assumptions (WACC, TG, horizon, FCF growth) from
st.slider widgets into the canvas iframe as native range inputs. A
JavaScript runDCF() engine recomputes the full projection in the browser
on every drag event, updating the verdict, bar chart (Plotly.react),
cash-flow table, bridge, recon strip, and cross-check cell in place
without a Streamlit round-trip.
Python still runs run_dcf() once on page load (using session-state
defaults) to populate dcf_intrinsic for the Multiples cross-check.
The Recompute button in the rail clears API caches and reruns when
fresh filing data is needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Collapse model picker from 4 tabs → 2: DCF and Multiples, persisted
in session_state["models_view"]
- New Multiples view: summary band, interactive comparison grid (8 math
rows × 3 methods), sensitivity strip, DCF cross-check, footer
- In-canvas sliders with sector marker + typical-band shading; JS
recomputes all derived values live without a Streamlit rerun
- Sector medians computed from peer ratios via FMP; falls back to
reasonable defaults when peer data is unavailable
- DCF intrinsic stored in session_state["dcf_intrinsic"] so the
cross-check on the Multiples tab reads the live DCF value
- P/Book applicability shows ◐ + warning color for asset-light
companies instead of the solid ● used for strong-fit methods
- Fix Recompute button text: target inner <p>/<span> with
color: var(--brass-ink) to override Streamlit's fg-2 default
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replaces the flat column layout with a two-column inspector design:
left rail holds four st.slider inputs + "From the filings" reference
panel + Reset/Recompute actions; right canvas renders verdict hero,
projection card (Plotly.js bar chart + cash-flow table), EV bridge,
per-share recon, and cross-check via a single components.v1.html block.
Also fixes primary button text color app-wide by targeting the modern
Streamlit selector (stBaseButton-primary) alongside the legacy one.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
typography
Implements the design kit: champagne brass accent (#C2AA7A), deep midnight
backgrounds, EB Garamond italic headings, IBM Plex Sans/Mono body and numbers,
terminal-density KPI cards, restyled sidebar brand mark, flat pill tabs, and a
global Plotly theme so all charts inherit the dark palette automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
- Add Top Movers section
- Note sidebar live price and company info display
- Rename DCF Model tab to Models; document all four valuation models
- Update project structure with top_movers.py and valuation_service.py description
- Expand valuation notes to cover EV/EBITDA, EV/Revenue, and P/B models
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|