StockHours
Whether the stock market is trading, answered on Robinhood Chain by the feeds themselves
What it is
Robinhood Chain carries eighteen Chainlink price feeds for US stocks. Nothing on the chain says when the market behind them is trading, so every contract that cares has to guess with a timestamp, keep a calendar, or trust somebody to publish one
StockHours reads the feeds instead. Robinhood's stock tokens trade 24 hours a day on weekdays, and the feeds follow: they write rounds all week and stop dead from Saturday to Monday, and on the holidays the market takes. Thirty days of rounds were measured before the rule was chosen, and over that month the weekends and Labor Day carried zero rounds across all eighteen feeds. The reading is a view call, costs nothing, and cannot be changed after deployment
What it answers is the trading week, not the 13:30 to 20:00 regular session. The session leaves a density peak in the data, not an edge, so no rule over feed activity separates it: the measurements show the best attempt reaching 89% and calling the market open before the bell on one day in five. For that, use a calendar
The rule
Count the feeds whose last update falls inside the window. If that count reaches the quorum, the market is on
A feed with a price of zero or a timestamp in the future is skipped, so a broken feed cannot vote. Both numbers are immutable, and both are visible on the panel at all times
Both numbers came out of the measurement rather than a guess: a four hour window is the first one wide enough to ride through an overnight lull without blinking shut, and five of eighteen is the count that refuses to call the market on when only the two busiest feeds are awake
The log
The reading answers about this second. The log answers about last Tuesday. Anyone may call poke(); when the reading disagrees with the log, the contract opens or closes an entry, which in practice is one trading week
The stamps are not the time of the call. An open carries the tick that first carried the quorum, and a close carries the last tick seen while the session was running, so a session that is poked a few times through the day lines up with the real bell even when nobody rings at the close. Each entry also keeps the two poke times, so you can see how well it was attended
Reading it
One interface, all views except poke
function isOpen() view returns (bool);
function requireOpen() view; // reverts with MarketClosed()
function activity() view returns (uint8 active, uint64 newest);
function state() view returns (bool open, uint8 active, uint8 total, uint64 newest, uint64 sinceTick, uint64 pokeAge, uint256 sessions);
function feeds() view returns (string[] symbols, address[] addrs, int256[] answers, uint64[] updatedAts, bool[] active);
function sessions(uint256 from, uint256 count) view returns (Session[]);
function lastSession() view returns (Session);
function usualDay() view returns (uint32 open, uint32 close, uint256 counted);
function poke() returns (bool open);
A poke over the eighteen feeds cost 94,670 gas in the fork tests. usualDay averages the closed sessions in the log: it describes what has happened, not what will
How wrong it can be
The rule lags. The weekly open is caught within a minute, because the feeds come back in a burst. The close is slower: the week is held open for up to the window past the last tick, which measured five minutes on median and nineteen at worst
It can be fooled by a quiet market. Over the thirty days measured the deployed rule blinked shut thirteen times inside a trading week, for a median of two minutes and 79 at the longest, adding up to 143 minutes in a month. A gate that must never flicker should read activity() and apply its own hysteresis
It reads no calendar, so a holiday appears as a week that never opened and needs no maintenance. A half day has not been seen yet: thirty days contained none, so that behaviour is unverified
What was measured
Eight thousand seven hundred and eighty nine rounds, walked back one by one through each feed's round counter over thirty days. No read failed and no history was truncated, so the numbers are the feeds' own record rather than a sample of it
Every candidate rule was then replayed minute by minute against that record and scored. The calibration page has the table, the month in bars, and the five weekly opens to the second
The panel
The eighteen feeds the contract is deployed with, in order
$STOCKHOURS
A token on Pons. It is not a fee, not a key and not a share: the contract charges nothing and works the same whether or not you hold any