PRISM-INSIGHT
These are 13 specialized AI agents that analyze Korean and US stocks in real-time, and this is open source and free to use.
AI translation
Rates, risk, carry, commodities and the tape on one screen, with a daily read and a growth × inflation regime map.
FinanceJavaScript · CSSGitHub @EthosanOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Equarian Markets: live macro dashboard for futures traders, with a risk appetite index, regime map, option flow and AI explanations. Vite PWA on Cloudflare Pages. markets.ethantam.dev
Taken from the repository README
Loading the full README.
Read the full README ↗A live macro dashboard for futures traders. Rates, credit, carry, the options market and the tape on one screen, read through a rule-based daily read and four quantitative models: a Risk Appetite Index, a growth × inflation regime, the absorption ratio of systemic risk, and the NY Fed recession probability — plus a walk-forward market-bias forecast scored out of sample since 2000 and an SPX option-flow panel built from the live option board.
History: First built in July 2026 and deployed on Netlify. Moved to GitHub in October 2026, so the commit history starts there. Moved to GitLab (eatentam/eqmarkets) on 17 Oct 2026 after the GitHub account was suspended. Moved to Cloudflare Pages on 23 Oct 2026 (see
MIGRATION.md). Since 28 Oct 2026 GitLab mirrors every push back to GitHub, read-only.
| Live | https://markets.ethantam.dev |
| Hosting | Cloudflare Pages project eqmarkets, connected to this repository; every push to main deploys. Static Vite build, plus Pages Functions: the data proxies (functions/_middleware.js) and /api/explain |
| Data | Live public sources (Yahoo Finance, FRED, Treasury.gov, the BOJ, the Fed, the CFTC, CBOE) through same-origin proxies; the last good values are saved on the device |
| Run locally | npm install && npm run dev (see Develop) |
| Source | gitlab.com/eatentam/eqmarkets. Read-only mirror: github.com/Ethosan/eqmarkets, which GitLab updates on every push |
Settings (names only; values live in the Pages project's environment variables): MISTRAL_API_KEY (optional, enables AI explanations), EXPLAIN_MODEL (optional).
Markets and Oracular are separate tools, and new features should stay on their side of the line.
Planned (1 Nov 2026): Markets becomes Oracular's Macro tab during December 2026 and January 2027, and markets.ethantam.dev then points there; until the tab ships this repo takes fixes only. See docs/PLAN.md.
| Markets (this repo) | Oracular |
|---|---|
| Top-down and cross-asset: rates, credit, vol, FX, commodities, index futures | Bottom-up: one company or ticker at a time |
| Live market data | Live market data, one ticker at a time |
| Regimes, flows, premia and positioning (RAI, absorption, recession odds, CTA, VRP, stock–bond, SPX dealer gamma) | Investment memo, verdict badge and seven-factor scorecard |
| Calendar events that move index futures (turn of month, FOMC, expiry, rebalancing), tested as event studies | Per-ticker seasonality tables with t-statistics, lifecycle phase map |
| Testing whether a signal works (backtest lab, overfitting guards) | Options and derivatives analytics, research chat |
| Alt signals: fear-and-greed gauges, the Pentagon Pizza Index, the Stripper Index, distress searches, the Coinbase rank and the moon, each tested against the index (moved from Oracular, Oct 2026) |
The alt-signal feeds come from Oracular's data worker through the same-origin /odw proxy; the worker turns away browsers from other sites, and a same-origin rewrite sends no Origin header.
So Markets doesn't show single stocks, fundamentals, single-name option chains, buy/hold verdicts or month-of-year seasonality tables — index-level option positioning (dealer gamma, index put/call flow, the vol curve) is macro and lives here — and Oracular doesn't do macro regimes or cross-asset flows.
Every number on the page is a real reading. When a source is down, Treasury.gov stands in for the Treasury yields and the breakeven; anything else keeps its last real value, marked stale, or the device's saved copy. There are no typed-in fallback values.
| Data | Source | Series | How it's reached |
|---|---|---|---|
| Futures, FX, indices, ETFs, BTC | Yahoo Finance chart API | ES=F NQ=F GC=F CL=F JPY=X DX-Y.NYB HYG BTC-USD ^TNX ^VIX ^VIX3M ^MOVE | /yf/* proxy |
| Treasuries, real yields, breakevens | FRED (H.15, Fed Board); Treasury.gov daily par and real yield curves when FRED is down (breakeven = 10Y nominal − 10Y real, as FRED defines it) | DGS3MO DGS2 DGS10 DFII10 T10YIE | /fred/* proxy; /ust/* proxy |
| Term premium | FRED (Kim–Wright, Fed Board) | THREEFYTP10 | /fred/* |
| Credit spreads | FRED (ICE BofA; Moody's) | BAMLH0A0HYM2 BAMLC0A0CM BAA10Y | /fred/* |
| Labour, Fed balance sheet | FRED (DoL; Fed H.4.1; NY Fed) | ICSA (weekly), WALCL WTREGEN (weekly), RRPONTSYD | /fred/* |
| Financial conditions | FRED (Chicago Fed, St. Louis Fed) | NFCI STLFSI4 (weekly) | /fred/* |
| Fed funds | FRED (NY Fed) | DFF | /fred/* |
| BOJ policy rate | boj.or.jp homepage | scraped | /boj/* proxy; if the scrape fails, the last real reading stays up, marked stale |
| Yen speculative positioning | CFTC Legacy COT (Socrata 6dca-aqww) | non-commercial net, 3 years | /cftc/* proxy |
| Commodities | Yahoo Finance chart API | HG=F SI=F NG=F ZC=F ZW=F ZS=F DBC DBA | /yf/* proxy |
| FOMC meeting dates | federalreserve.gov FOMC calendar page | scheduled statement days | /fed/* proxy, built-in fallback in src/quant/calendar.js |
| SPX option board | CBOE delayed-quotes API | full chain: strike, expiry, IV, gamma, open interest, volume | /cboe/* proxy, cached 20 min () |
All of these are free and need no API key.
ES and NQ are roll-adjusted. Yahoo's ES=F and NQ=F switch to the next contract at each quarterly expiry, and the next contract trades at a premium, so the raw series jumps 1–3% on the third Friday and the session after. Checked against the cash indices over five years, those days were the only large gaps (25 days over 0.4% for ES, 31 for NQ). Every calculation uses a back-adjusted series instead (src/data/roll.js): from 8 sessions before each quarterly expiry to 1 after (NYSE calendar, so it also covers the CME roll date), each day takes the cash index's return (^GSPC, ^NDX) where the index has printed; every other day keeps the futures' own return, and the path is rebuilt back from today's price. Afterwards no daily gap to the index exceeds 0.4% and the typical one is 0.04%. Returns then roughly match what holding the futures earned: over five years 8.6% a year for ES instead of the raw series' 11.5% (the index did 11.3%; the difference is financing net of dividends). Using index returns on 10 sessions a quarter puts back a little carry on those days, so the adjusted series overstates futures returns by roughly 0.3–0.5% a year. GC and CL futures are not adjusted; the regime uses the rolled funds DBC and DBA instead.
Credit spreads start in October 2023. FRED only serves the ICE BofA high-yield and investment-grade spreads for the last three years, so the HY card's percentile, the Risk Appetite Index's credit input and anything else built on it can only say "wide for the last year or three", never "wide by history". That matters: on 16 Oct 2026 HY OAS was 3.23%, the 96th percentile of its past year after widening 58 bp in three weeks, yet that is well below the long-run norm of roughly 4.5–5% in ICE's full history (which peaked near 20% in 2008 and 11% in 2020). The Baa–10Y card (Moody's, daily since 1986, not licence-limited) is the long-run yardstick: its note gives its percentile since 1986, the HY card's note adds "long run tight / normal / wide" from it, and Today's read says whether a widening is a move from tight levels or real stress. In the long-history market-bias model and the lab, the Risk Appetite Index also lacks Bitcoin before 2014 and VIX3M before 2007, so for much of 2000–2023 it runs on 5 to 7 of its 8 inputs (it needs at least 4).
None of these send CORS headers, so the browser can't call them directly. On Cloudflare Pages, functions/_middleware.js proxies each path to its upstream host, which makes them same-origin (netlify.toml does the same on Netlify, and vite.config.js in development). Anywhere else the app falls back to public CORS proxies.
| Quantity | Definition |
|---|---|
| Returns | log returns for prices; first differences for rates (bp) and levels |
| Realized vol | sample std (n−1) of the last 21 steps × √252 (√365 BTC, √52 weekly) |
| EWMA vol | RiskMetrics σ²ₜ = λσ²ₜ₋₁ + (1−λ)r²ₜ₋₁, λ = 0.94, seeded with the first 20 obs |
| Percentile | mid-rank of today's value within the prior year |
| Robust z | (x − median) / (1.4826 · MAD) over the trailing year; classical z if MAD = 0 |
| RAI trend score | ln(Pₜ / Pₜ₋₂₁) / (σ_EWMA · √21), signed, clipped ±3 |
| RAI level score | robust z of the level over 252 days, signed, clipped ±3 |
| RAI | mean of available scores (≥ 4 of 8); label on the 3-day mean, thresholds ±0.25σ / ±0.75σ |
| Absorption ratio | Σ top-k eigenvalues / Σ all, k = round(N/5), correlation matrix of 63-day returns (Jacobi eigen-solver) |
| ΔAR | (15-day mean AR − 252-day mean AR) / 252-day std AR |
| Recession probability | Φ(−0.5333 − 0.6330 · S̄), S̄ = 21-day mean of DGS10 − DGS3MO in pp |
| Carry-to-vol | (EFFR − BOJ) / annualized EWMA vol of USD/JPY |
| Vol-scaled move | Δₕ / (σ_EWMA at window start · √h): log change for prices, point change for rates; clipped ±3 |
| Growth score | mean of ES, copper/gold, −HY OAS (≥ 2 of 3), each the average of its 63- and 126-day vol-scaled moves |
| Inflation score | mean of the 10Y breakeven, DBC, DBA (≥ 2 of 3), each the average of its 63- and 126-day vol-scaled moves |
| Regime | read weekly (last close of each week); switches only after the new quadrant holds 3 completed weeks in a row, with a ±0.15 dead band around each axis; dated to the first week of the run |
| Today's read | 19 rules on 21-day vol-scaled moves, VIX/MOVE level z-scores, VXN/VIX and VIX9D/VIX ratio z-scores and NDX/SPX, RSP/SPY relative moves; strength = weakest condition; top 4 shown |
| Momentum (12−1M) | ln(Pₜ/Pₜ₋₂₁) − ln(Pₜ₋₂₅₂/Pₜ₋₂₅₂)'s window form: (ln Pₜ − ln Pₜ₋₂₁) ÷ (σ_EWMA at the window start × √231), clipped ±3 |
| 5-day reversal | (ln Pₜ − ln Pₜ₋₅) ÷ (σ_EWMA at the window start × √5), clipped ±3; its regression slope is restricted to be negative (Jegadeesh 1990) |
| Weeks like this |
All of this lives in src/quant/ as pure functions, covered by tests/quant.test.js and tests/flows.test.js. The tests check them against closed-form cases: EWMA convergence to the true σ, eigenvalues of known matrices, an AR near 1 when one factor drives everything and near k/N for independent assets, the NY Fed probit formula, and bp units for rates.
One read per horizon (next 1, 5 and 21 sessions) for ES and NQ, built so that nothing is fitted to the period it is judged on (src/quant/composite.js, tests in tests/composite.test.js):
It runs in a Web Worker on full daily history from 2000 and is cached on the device for six hours. The scorecard is also split by market state, and the card says in plain words whether the model beats a plain average overall, in calm markets and in stressed ones.
Results and variants tried (out-of-sample R² for day / week / month, full history, every forecastable day counted, re-run 19 Oct 2026 with node scripts/bias-research.mjs; earlier runs differ slightly because the data window moved). Every variant run this round is disclosed:
| Variant | ES | NQ |
|---|---|---|
| v7 as shipped (5 signals, no abstention) | +0.06 / +0.07 / −0.34% | +0.22 / +1.06 / +3.23% |
| v7 + abstention (with the all-abstain fallback) | +0.11 / +0.02 / +0.68% | +0.29 / +1.12 / +1.24% |
| v8 live: v7 + abstention + 12−1 momentum + 5-day reversal (day/week only) | +0.11 / +0.12 / +0.66% | +0.23 / +0.98 / +2.81% |
| v8 with all 12 candidate signals (see below) | +0.04 / −0.13 / −0.46% | +0.21 / +1.09 / +2.92% |
The headline fix this round is the abstention rule: a signal whose sign-restricted slope comes out wrong-sided used to keep voting with its historical mean, and the error-weighted combination rewarded that fake accuracy with a large share. Zeroed signals now abstain. On its own that took ES monthly from −0.34% to +0.68%; adding momentum and reversal gives the live v8 — ES beats its long-run average at all three horizons for the first time (monthly +0.66%, Clark–West p 0.026), and NQ stays significant everywhere (p ≤ 0.006 daily, < 0.001 weekly and monthly). Against the abstention-only variant, momentum and reversal add the most exactly where the complaint was: NQ monthly +1.24% → +2.81%, and daily NQ bearish calls right 58% of the time versus 44% on other days. The honest costs: NQ weekly and monthly R² sit a touch under the no-abstention v7 over the full history (0.98% vs 1.06%, 2.81% vs 3.23%), because the abstaining days now count.
The all-abstain fallback. Abstention first shipped with a hole the size of 2023–26: over the recent window every signal's estimated slope points the wrong way at once (the meltup inverted the usual momentum, trend and risk-appetite relationships), so at the monthly horizon nothing voted and the model went silent for ~700 days — the card showed "Not enough history", which was wrong. Now, when every signal abstains on a day, the combination falls back to the abstaining signals and is set to the long-run average exactly — a neutral read, flagged in the card as "no working signal: recent moves contradict every signal's usual direction". That state is live right now on NQ week/month and ES month; ES week is genuinely bullish on the variance premium and the reversal signal.
21 Oct 2026 round: VIX term structure and credit momentum, rejected. Two more candidates with long free history were tested: VIX/VIX3M (Fassas & Hourvouliades 2019; backwardation has tended to precede rebounds) and credit momentum, the 63-day vol-scaled move of HYG against IEF in total return (Gilchrist & Zakrajšek 2012). The acceptance rule was fixed before the run: ship only if full-sample out-of-sample R² beats v8 at 2 of 3 horizons for both ES and NQ, without lowering the average post-2019 R². Neither passed (day / week / month, scripts/cache/run-2026-10-21.txt):
| Variant | ES | NQ |
|---|---|---|
| v8 live | +0.11 / +0.12 / +0.66% | +0.23 / +0.98 / +2.81% |
| v8 + VIX term structure | −0.04 / −0.11 / −1.23% | +0.17 / +0.88 / +1.50% |
| v8 + credit momentum | +0.09 / +0.02 / +0.42% | +0.22 / +0.94 / +2.75% |
| v8 + both | −0.05 / −0.18 / −1.25% | +0.16 / +0.83 / +1.32% |
Credit momentum did improve the post-2019 cut (NQ monthly −0.66% → −0.23%), but it lowered the full record everywhere, so it stays out. Both remain in the harness so the numbers are reproducible.
The last three years, on the card. The full record since 2002 hides how weak the model has been lately: since 2019 no horizon beats the plain average for ES or NQ. The card now shows a Last 3 years row alongside the full record, and a lean whose horizon hasn't beaten the plain average over those three years is graded Low confidence, whatever its long record says (src/model/bias.js). That rule was set before looking at which reads it would change.
Candidate signals tried and rejected (all estimated on the same walk-forward, all reproducible in the harness): NDX/SPX relative strength ("growth leadership"), RSP/SPY equal-weight breadth, VXN/VIX, VIX9D/VIX and VVIX level z-scores. NDX/SPX is a relative signal — it predicts Nasdaq outperforming the S&P, not the S&P itself, which is what the ES numbers showed. The vol-ratio signals helped NQ's 2019–2026 monthly cut but wrecked ES weekly bearish calls, so none shipped inside the model; VXN, VVIX and SKEW are still on the board as indicators and in the option-flow panel, and the divergence rules in Today's read quote them directly.
Scored on 2019–2026 only, nothing is significant for ES or NQ. Directionally, the skill sits in bearish calls: on full history the index fell short of its average after 43–58% of bearish calls versus 30–45% of other days, while bullish calls did no better than other days. The lab's Market bias model card shows the full scorecard, the Goyal–Welch cumulative error plot, weights over time and calibration.
NQ stays significant at every horizon (Clark–West p ≤ 0.009); ES at none, though monthly now clears p 0.05. Scored on 2019–2026 only, nothing is significant for ES or NQ. Directionally, the skill sits in bearish calls: on full history the index fell short of its average after 44–58% of bearish calls versus 30–44% of other days, while bullish calls did no better than other days. The lab's Market bias model card shows the full scorecard, the Goyal–Welch cumulative error plot, weights over time and calibration.
References for the bias model's new signals: Jegadeesh & Titman (1993), Returns to Buying Winners and Selling Losers, JF. Jegadeesh (1990), Evidence of Predictable Behavior of Security Returns, JF. Lehmann (1990), Fads, Martingales, and Market Efficiency, QJE. Ang, Hodrick, Xing & Zhang (2006), The Cross-Section of Volatility and Expected Returns, JF. Baltussen, van Bekkum & van der Grient (2018), Unknown Unknowns: Uncertainty About Uncertainty and Equity Returns, JFQA (all rejected for the live model; see the results table).
References for the bias model: Dangl & Halling (2012), Predictive Regressions with Time-Varying Coefficients, JFE. Henkel, Martin & Nardari (2011), Time-Varying Short-Horizon Predictability, JFE. Goyal & Welch (2008), A Comprehensive Look at the Empirical Performance of Equity Premium Prediction, RFS. Campbell & Thompson (2008), Predicting Excess Stock Returns Out of Sample, RFS. Rapach, Strauss & Zhou (2010), Out-of-Sample Equity Premium Prediction: Combination Forecasts and Links to the Real Economy, RFS. Stock & Watson (2004), Combination Forecasts of Output Growth in a Seven-Country Data Set, JoF. Harvey, Leybourne & Newbold (1998), Tests for Forecast Encompassing, JBES. Clark & West (2007), Approximately Normal Tests for Equal Predictive Accuracy in Nested Models, JoE. DeMiguel, Garlappi & Uppal (2009), Optimal Versus Naive Diversification, RFS.
References for flows and premia: Moskowitz, Ooi & Pedersen (2012), Time Series Momentum, JFE. Hurst, Ooi & Pedersen (2017), A Century of Evidence on Trend-Following Investing, JPM. Bollerslev, Tauchen & Zhou (2009), Expected Stock Returns and Variance Risk Premia, RFS. Carr & Wu (2009), Variance Risk Premiums, RFS. Campbell, Pflueger & Viceira (2020), Macroeconomic Drivers of Bond and Equity Risks, JPE. Lakonishok & Smidt (1988), Are Seasonal Anomalies Real?, RFS. McConnell & Xu (2008), Equity Returns at the Turn of the Month, FAJ. Lucca & Moench (2015), The Pre-FOMC Announcement Drift, JF. Ariel (1990), High Stock Returns before Holidays, JF.
References: Ilmanen, Maloney & Ross (2014), Exploring Macroeconomic Sensitivities: How Investments Respond to Different Economic Environments, JPM. Bridgewater Associates (2012), The All Weather Story. Moskowitz, Ooi & Pedersen (2012), Time Series Momentum, JFE. Erb & Harvey (2006), The Strategic and Tactical Value of Commodity Futures, FAJ. Gorton & Rouwenhorst (2006), Facts and Fantasies about Commodity Futures, FAJ. Kumar & Persaud (2002), Pure Contagion and Investors' Shifting Risk Appetite, IMF. Kritzman, Li, Page & Rigobon (2011), Principal Components as a Measure of Systemic Risk, JPM. Estrella & Mishkin (1996), The Yield Curve as a Predictor of U.S. Recessions, NY Fed. Estrella & Trubin (2006), The Yield Curve as a Leading Indicator, NY Fed. J.P. Morgan/Reuters (1996), RiskMetrics Technical Document. Gilchrist & Zakrajšek (2012), Credit Spreads and Business Cycle Fluctuations, AER. Kim & Wright (2005), An Arbitrage-Free Three-Factor Term Structure Model, Fed Board.
Caveat: the NY Fed fits its probit to monthly averages and the bond-equivalent 3M bill, so this daily version can differ from the published table by a point or two. Check NYFED_PROBIT in src/quant/models.js against the NY Fed's current release.
Today's read changes day to day now. The monthly rules can hold for weeks, so the same sentences used to lead every morning. Each pattern is tagged with how long it has held (New today, This week, 2+ weeks, from the same rules run on the data as it stood 1, 5 and 10 sessions back), patterns on for two weeks or more give up some rank to fresh news, and three daily rules lead when something happened: moves since the last close of more than twice a normal day, VIX jumps or drops (read together with VVIX), and new 52-week highs and lows. The daily rules use oil and gold ETFs (USO, GLD) and leave out the other unadjusted front-month futures: on 21 Oct 2026 CL=F "fell" 6.3% because the November contract expired, while USO and Brent moved under 1%.
Why the regime uses DBC and DBA instead of the grain and energy futures: Yahoo's continuous front-month contracts (ZC=F and so on) jump on each roll date, by the gap between the expiring and the next contract. Over a 3-month window that can be several percent of fake "move". The funds hold and roll the futures themselves, so their prices don't jump. The commodity cards still show the futures, and the guide warns that big monthly moves there can include roll.
A hidden Lab tab for testing the models as trading signals. Open the site with ?admin=1 to turn it on in that browser (?admin=0 turns it off). It only hides UI: there is no secret behind it, and the lab code loads as its own chunk the first time the tab opens.
ctx.p.a / ctx.p.b runs over a grid, shown as a heatmap scored on the in-sample period, with the best cell's out-of-sample Sharpe. A real edge is a broad plateau, not one bright cell.eqlab.test(ctx => ctx.raiS > 0 ? 1 : 0) prints a rule against buy and hold. eqlab.frame has the aligned data and eqlab.events the calendar study.A rule is the body of function (ctx), called once per bar. It returns a position (1 long, 0 flat, −1 short, clipped to ±3) or null to hold. ctx exposes only the current and past bars (ctx.price, ctx.raiS, ctx.dAR, ctx.rec, ctx.vrp, ctx.sbCorr, ctx.trend, ctx.sma(n), ctx.get(field, k)…), so a rule can't peek ahead. The one exception is ctx.cal(flag, ahead): calendar dates are known in advance, so a rule may ask whether the next bar is, say, a turn-of-month day. The engine is src/quant/backtest.js, tested in tests/backtest.test.js (lag, costs, holding on null, no look-ahead, vol targeting, ΔAR path).
Caveats: futures use Yahoo's continuous front-month series, so roll gaps count as returns. Flat earns nothing, and Sharpe uses a zero risk-free rate. A backtest over a few years of one market is a sanity check, not evidence of an edge.
The Explain in plain English button calls functions/api/explain.mjs (a Cloudflare Pages Function; netlify/functions/explain.mjs is the Netlify version), which asks Mistral (mistral-medium-latest, Mistral Medium 3.5) for a two-paragraph note.
eqmarkets → Settings → Variables and secrets → add MISTRAL_API_KEY as a secret, then redeploy. Create the key at console.mistral.ai → API Keys. Without it the button says it isn't set up.EXPLAIN_MODEL to use a different Mistral model, for example mistral-small-latest (cheaper and faster) or mistral-large-latest.src/ai/explain.js, and only then calls the API, so nothing typed by a visitor can reach the prompt.Two read-only endpoints expose the dashboard's own models, computed with the same code the site runs (functions/api/_macro.mjs), so the API and the dashboard always agree. Free for now; no key, no account.
GET /api/regime → the growth × inflation regime: { quadrant, label, confidence, growth, inflation, readingQuadrant, provisional, weeksIn, since, pending, switchesYear, trail: [{ date, growth, inflation }], asOf, updated, stale }. trail is the 13 finished weekly readings the regime map draws; growth and inflation are this week's reading.GET /api/risk → the Risk Appetite Index: { value, latest, label, inputs, total, contributions: [{ id, label, score }], history: [{ date, value }], asOf, updated, stale }. history is the daily index the dashboard charts (about a year); value is the mean of its last three days.stale: true means a refresh failed and the last good read is being served. asOf is the latest market session the numbers cover.
Call them from anywhere — no key, no signup, CORS-open:
curl https://markets.ethantam.dev/api/regime
curl https://markets.ethantam.dev/api/risk
const [regime, risk] = await Promise.all([
fetch("https://markets.ethantam.dev/api/regime").then(r => r.json()),
fetch("https://markets.ethantam.dev/api/risk").then(r => r.json()),
]);
Cache-Control: public, max-age=60.429 { error: "busy" } when rate-limited, 503 { error: "unavailable" } when no read exists yet. An error body is the only thing an error ever says.index.html page shell and static markup
src/
main.js boot, refresh loop
pwa.js service worker, install bar, update notice
config.js indicator list, refresh interval
state.js latest series per indicator
data/
transport.js proxy fallbacks and timeouts
sources.js Yahoo, FRED, BOJ and CFTC fetchers
fomc.js FOMC dates from federalreserve.gov, cached a week
roll.js quarterly roll adjustment for ES and NQ
snapshot.js last good data saved on the device for instant and offline launch
quant/
stats.js statistics: EWMA, robust z, percentiles, eigenvalues, alignment
models.js RAI, absorption ratio, recession probit, per-series stats
regime.js vol-scaled moves, growth × inflation regime
narrative.js rules behind Today's read
flows.js variance risk premium, stock–bond correlation, CTA trend positioning
optionflow.js SPX option board: dealer gamma, profile, flip level, walls, put/call, 0DTE
conditional.js "after a week like this": bucketed conditional forward-return history
calendar.js NYSE holidays, FOMC dates, turn of month, option expiry, event study
backtest.js backtest engine: simulate, metrics, vol target, rules, presets, bootstrap, deflated Sharpe
composite.js market bias: walk-forward forecast combination and its out-of-sample scorecard
lab/ admin backtest lab (separate chunk)
lab.js controls, strategies, results, custom rule editor
plot.js multi-series chart with shading and synced crosshairs
insights.js calendar event study and parameter-sweep heatmap
ai/
explain.js payload validation and prompt building (shared with the function)
model/
derived.js curve spreads, VIX term structure, carry-to-vol
models.js builds the models from fetched state
facts.js the numbers behind Today's read and the AI note
history.js long history, the point-in-time model frame and the momentum, reversal,
leadership and options-vol signal paths (lab and market bias)
bias.js market-bias build, cache and worker hand-off
bias.worker.js runs the market-bias build off the main thread
ui/
board.js indicator cards
detail.js detail sheet (dialog)
models-panel.js models section rendering
flows-panel.js CTA positioning, variance premium, stock–bond correlation, calendar
bias-panel.js market bias card
optionflow-panel.js SPX option-flow card (chain load, gamma profile chart, vol-curve gauges)
methods.js "How it's calculated" notes on each model card
read-panel.js Today's read and the AI button
regime-panel.js regime map
chrome.js clocks, session chips, tabs, progress bar
notes.js one-line reads per indicator
chart.js interactive chart: axes, crosshair, tooltip, keyboard
tour.js first-run spotlight tour with live values
guide.js "how to read this" guide sheet
sheet.js swipe-to-dismiss for bottom sheets
format.js number formatting and sparklines
styles/ base tokens, layout, components
public/ manifest, icons, service worker, _headers, _routes.json (copied as-is)
functions/ Cloudflare Pages Functions
_middleware.js same-origin data proxies (/yf, /fred, /ust, /boj, /fed, /cftc, /cboe, /odw)
api/explain.mjs POST /api/explain (Mistral)
netlify/functions/
explain.mjs the same endpoint for Netlify
scripts/
bias-research.mjs research harness: downloads history, runs the walk-forward offline, prints and saves the results table in the README
netlify.toml the Netlify build settings, data proxies and headers (kept so the site can go back)
Needs Node 20 or newer.
npm install
npm run dev # http://localhost:5173
vite.config.js mirrors the proxies in functions/_middleware.js, so npm run dev and npm run preview fetch data same-origin like the deployed site. Open http://localhost:5173/?admin=1&tab=lab for the lab.
| Script | What it does |
|---|---|
npm run dev | Vite dev server with hot reload |
npm run build | Production build into dist/ |
npm run preview | Serve the production build |
node scripts/bias-research.mjs | Re-run the walk-forward research offline (fetches full history, caches in scripts/cache/) |
npm run lint | ESLint |
npm test | Vitest unit tests for the quant library and backtest engine |
npm run audit:design | impeccable design anti-pattern scan (npx impeccable if not installed) |
The live site is the Cloudflare Pages project eqmarkets, connected to this repository: build command npm run build, output directory dist. Every push to main deploys. functions/ is picked up automatically, and public/_routes.json runs Functions only on the proxy paths and /api/*. Setup steps are in MIGRATION.md.
To go back to Netlify, import the repository there: it reads netlify.toml (build command npm run build, publish directory dist).
.gitlab-ci.yml runs lint, tests and the build on every merge request and every push to main.
After a BOJ rate decision, if the live scrape ever fails, update BOJ_RATE in src/config.js.
Found a security problem? See markets.ethantam.dev/.well-known/security.txt, or email [email protected].
?notour to the URL to skip the tour.kind. Prices use % changes and log-return vol; rates and spreads use bp changes and normal (bp) vol; indices use points. Cards show the 1M change and EWMA vol. The detail sheet adds 1W/1M/3M/YTD/1Y changes, 21-day and EWMA (λ = 0.94) vol, 1Y percentile, robust z, high/low and max drawdown.gmtoffset, so FX and futures share a calendar. Curve spreads use H.15 closes on both legs. Models use as-of joins with a 7-day staleness cap./?tab=rates). A notice offers a reload when a new version is deployed.src/data/sources.js| Vol indices, index ratios | Yahoo Finance chart API | ^VIX9D ^VIX1D ^VXN ^VVIX ^SKEW ^OVX ^GVZ ^NDX ^GSPC RSP SPY | /yf/* proxy |
| Oil and gold for day moves | Yahoo Finance chart API | USO GLD (no contract rolls) | /yf/* proxy |
| Today's 5-day move bucketed at ±1σ and ±2σ; the bucket's next-day and next-week up-rate and mean return since 2000, matched on calm/stressed regime and 12−1 momentum sign when ≥ 30 cases, relaxed to the plain bucket at ≥ 10, else no claim |
| Net dealer gamma | Σ (Γ_call × OI) − Σ (Γ_put × OI), × 100 × S² × 1%: dollars of S&P hedging per 1% index move, $bn. Naive positioning assumption: dealers long call gamma, short put gamma |
| Gamma profile | Black–Scholes Γ(S, K, T, σ_quoted, r = EFFR, q = 1.25%) recomputed on an index grid from −18% to +18%, options ≤ 126 days and within 30% of spot; flip = nearest zero crossing |
| Walls | Largest call OI, put OI and |
| 0DTE share | Volume of options expiring within 1 day ÷ total SPX volume; same-week share adds 2–7 days |
| Vol-curve gauges | VIX9D/VIX, VXN/VIX, VVIX, SKEW: level, 1-year mid-rank percentile |
| CTA position | mean over L ∈ {21, 63, 126, 252} of clip(zₗ / 2, ±1), zₗ = (xₜ − xₜ₋ₗ) / (σ_EWMA · √L), x = ln P (or −yield) |
| CTA flip level | the close tomorrow at which zₗ changes sign: xₜ₋ₗ₊₁ |
| CTA ±kσ week | position after xₜ + kσ√5 with every lookback rolled forward 5 days, minus today's |
| Variance risk premium | VIX − √(252 · mean r²) × 100 over ES's last 21 daily log returns, vol points |
| Stock–bond correlation | 63-day Pearson correlation of ES log returns with −Δ10Y yield |
| Month-end gap | ES month-to-date % − 10Y Treasury month-to-date % (≈ −8.5 × Δyield) |
| Turn of month | last NYSE trading day of the month and the first three of the next (holidays computed from the NYSE rules) |
| Option expiry | third Friday, or the Thursday before when Friday is a holiday; quad witching in Mar/Jun/Sep/Dec |
| FOMC dates | read from federalreserve.gov's calendar page at startup (cached a week) and merged over a built-in 2010–2027 list |