Repository navigation
0.22.0 - 2026-09-11
Release Notes
- Portfolio valuations include premarket and after-hours prices whenever
the source reports them, independently of the extended-candle toggle.
The portfolio, holding columns, quote rail and JSON use the same price;
Lastmarks an extended price with*, and JSON exposes it as
position.price. PremarketDayis measured from the latest regular
close; after hours it includes the regular session's move as well. - A Portfolio view,
8, for what you actually hold: quantity, average
price, value, the day's move in money, the profit or loss since you
bought and the share of the portfolio each ticker carries, with a total
underneath. It was the one thing the widely used tools here are built
around and this one had no answer to. psets the holding for the ticker under the cursor, from any view: a
quantity and an average price on one line, prefilled with what is held,
an empty line clearing it. Unlike every other runtime change, it is
written to the config file straight away, because a quantity and a price
are your data rather than a display preference.- Holdings can be written by hand as
[[positions]]entries with
symbol,qtyandavg_price. A fractional quantity is fine, and a
negative one is a short, which profits when the price falls. - A held ticker that is not on the watchlist is polled all the same, so
every row can be valued; the startup warning about a source's request
budget counts those tickers too. A row whose first price has not arrived
says so instead of being summed in as zero, and the total states how
many rows it covers. - The watchlist table grows
ValueandP&Lcolumns, and the quote rail
a zone with the same numbers, but only for tickers you hold. Totals that
span several currencies are labelledmixed currencies: there is no
conversion here, and a sum across currencies should not look exact. --jsoncarries apositionobject for a held ticker, with the cost,
the value, the profit or loss and its percentage, so a status bar can
show the money instead of the price.- The color presets moved from
pandPto}and{, which is
what freedp. The old keys are two lines away in the config:
[keybindings] next_theme = "p"andprev_theme = "P". - The config file is now written to a temporary file and renamed into
place. It holds API keys, and it is written on every position edit, so a
half-finished write should never be able to replace it. - Prices that survive a source fallback are labelled with their real age
instead of passing as live: a quote carries the source it came from, and
a row inherited from the abandoned one keeps the time it was fetched.
Adding credentials in the settings screen also makes a fallback search
that had run out of options worth trying again. - The quote cache is written out when the app exits, so a session shorter
than its flush interval still leaves its prices behind for the next
start, and a failed write backs off like a successful one. - News marks respect the length of a candle: a mark lands on the bar whose
interval actually contains its publish time, so an overnight gap or a
missing recent bar no longer pins unrelated news to the last candle.
Also in this build
0.21.0 was never tagged on its own, so everything in it ships here too:
- The price chart marks the ticker's news on the candles it was published
in:▲or▼for the AI sentiment call,◆when it is neutral, dimmer
or brighter with the relevance score, and the freshest of them named on
the chart's bottom border. The scored news was the one thing here no
other terminal stock tool has, and it lived in a view of its own, so a
chart-first reader never saw it; now the move and its reason share a
column.ntoggles the marks,[chart] news_markers = falsestarts
without them, and the action is rebindable asnews_markers. - The marks cost no API request. They are drawn from the news bundle the
Split and News views already keep fresh for the selected ticker, which
also means they are absent until one of those views has loaded it. - Rows older than the first candle on screen are dropped rather than
pinned to the left edge, and a candle that carried several stories keeps
the highest-scoring one, so a busy day stays readable. - The Split view's footer drops its
s settingshint to stay inside 110
columns, the way the News footer already does.?still lists it. - A blocked or throttled price source no longer means an empty screen. The
last good quotes and candles are kept in the platform cache directory and
drawn while the first poll is in flight, labelledcached 2h agoon the
quote rail until live data lands. Entries older than a week, or taken
with a different range and interval, are ignored. - Yahoo's
429now says what it is: an IP block that lasts tens of minutes
(measured: 19 minutes after about ten requests, over an hour for the
second one that day), with the advice to switch source. It is also no
longer retried, since another request only feeds the counter that holds
the block open. Alpaca's 429, which is a genuine transient refusal, keeps
its retries. - When every ticker has been failing for 45 seconds, the app switches to
another source that has its credentials, keeps the rows already on
screen, and says so in the footer. It never switches back on its own and
never returns to a source that failed this session;source_fallback = falsein the config turns it off. --jsonprints the one-shot quote run as a JSON array instead of a text
table, for status bars and cron jobs: price, the move from the previous
close, the extended print with its own move from the regular close, the
day and 52 week ranges, volume and the source. It implies--once.
Absent figures are left out rather than sent as null, a symbol that
failed gets a row carrying its error, and warnings stay on stderr so
stdout is a valid document.