rsi-screener
Skill1 starsChanged 3 months agoMITView on GitHub
Builds a single-file HTML momentum board that ranks a watchlist by RSI-14 and shows where every name sits on the oscillator, powered by viaNexus CORE/STOCK_STATS_US. One batched API call at build time, no polling, no backend, no client-side math. Use whenever the user wants an RSI screen, momentum screener, overbought/oversold view, relative strength ranking, or a "which of my stocks are stretched" answer — even if they don't say RSI (e.g. "which names are oversold", "screen my watchlist for momentum", "what's overbought right now", "rank these by relative strength").
In this repository7 other files it gives its agents.
- earnings-calendarSkill
- election-market-dashboardSkill
- financial-researchSkill
- live-market-dashboardSkill
- mt-newswires-analystSkill
- portfolio-monitorSkill
- transcript-analysisSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 7 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
Read references/dataset.md before writing any fetch code.
- Distinctive: line 46
Ask for (or extract from the conversation) the tickers.
- Distinctive: line 51
Only exchange-listed US equities and ETFs are in this dataset.
- Distinctive: line 63
Do not loop per symbol. Sixty symbols in one request is ~28 KB and about a second.
- Very specific: line 73
One
datevalue: All rows should carry the same date. - Distinctive: line 158
Color never carries meaning alone: Every dot's value is also its x position.
- Distinctive: line 166
Render API values verbatim: No rounding beyond display, no interpolation, no filling a null.
- Distinctive: line 180
Do not end by handing over a file path.
- Distinctive: line 196
no horizontal scroll on the page body at 1200px wide.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
RSI Screener
Generate a single HTML file the user opens in any browser: a momentum board that ranks a watchlist by RSI-14 and plots the whole universe on one 0–100 oscillator axis.
This skill differs from live-market-dashboard in one important way: the page
is a snapshot, not a poller. You make one API call at build time and embed
the result. The finished page makes zero network requests, contains no token,
and can therefore be shipped as a hosted artifact, emailed, or committed — none
of which are safe for a polling dashboard.
The other core idea: RSI-14 is a stored field, not something the page
computes. rsi14 ships on the same STOCK_STATS_US record as the 50-day and
200-day moving averages. Never pull price history and never implement Wilder's
smoothing in the generated page. If you find yourself writing an RSI function,
you have taken the wrong path.
Read references/dataset.md before writing any fetch code. The finished reference implementation is assets/example-screener.html — this is the layout to reproduce, not merely a source of ideas.
Step 1 — Get the watchlist
Ask for (or extract from the conversation) the tickers. If the user has no list and just wants to see the thing work, use the default universe in references/dataset.md (60 US large caps) and say that is what you used.
Only exchange-listed US equities and ETFs are in this dataset. Mutual funds (5-letter tickers ending in X, e.g. FZROX) return nothing — name them to the user and offer ETF analogs rather than dropping them silently.
Step 2 — One call, then verify
A single request with all symbols comma-separated and filter= applied:
GET /v1/data/CORE/STOCK_STATS_US/{sym1,sym2,...}?token={pk_}&filter=symbol,issuerName,date,rsi14,day50MovingAverage,day200MovingAverageDo not loop per symbol. Sixty symbols in one request is ~28 KB and about a second; that measurement is the story the page tells, so keep it true.
Then check three things before you build:
- Missing symbols. Any ticker absent from the response did not resolve. Report those to the user by name.
- Null
rsi14. Legitimate for names with fewer than 15 trading days of history. Keep the row, render it as "insufficient history", and never substitute a number. - One
datevalue. All rows should carry the samedate. If they don't, say so in the page footer rather than implying a single as-of moment.
Record the payload size and elapsed time of that one call. They go in the masthead.
Step 3 — Build the page
One HTML file, no external dependencies. Inline all CSS and JS, no CDN scripts, no webfonts, no frameworks. Sections in this order, because the board is scanned, not read:
- Masthead — dataset identity (
viaNexus · CORE / STOCK_STATS_US), the headline, and a right-aligned provenance block: as-of date, symbol count, payload size, elapsed time. - Four tiles — universe size, oversold count, neutral count, overbought count. Each tile is a button that filters the rest of the page.
- The oscillator — the hero. All symbols as dots on one 0–100 axis (see Step 4). This is the view that makes the point in a screenshot.
- The table — every symbol, sorted weakest to strongest by default, with an inline RSI bar, both moving averages, and a trend chip. Sortable columns. This doubles as the accessible view of the chart.
- Provenance — the exact curl that produced the page, and one unedited record. Users trust a screen they can reproduce.
- Footer — how RSI is calculated, what nulls mean, and the not-advice line.
Step 4 — The oscillator, exactly
The hero is a dot plot stacked upward from the baseline, not a bar chart and not a gauge. Position on the x-axis carries the RSI value; the stack height where dots collide reveals the distribution for free.
Bands are fixed at the conventional thresholds. Do not invent your own:
| Band | Range | Meaning |
| Oversold | RSI < 30 | selling pressure exhausted |
| Neutral | 30 – 70 | no momentum signal |
| Overbought | RSI > 70 | extended after a run |
Shade 0–30 and 70–100, draw hairline rules at 30, 50 and 70, and label the 30 and 70 rules in the plot.
Layout algorithm — lanes, so dots never overlap:
const dot = 11, gapY = 2, minGapX = dot + 2;
const sorted = [...DATA].sort((a, b) => a.rsi14 - b.rsi14);
const lanes = []; // lanes[i] = rightmost x used in that lane
sorted.forEach(d => {
const x = (d.rsi14 / 100) * plotWidth;
let lane = 0;
while (lanes[lane] != null && x - lanes[lane] < minGapX) lane++;
lanes[lane] = x;
d._x = x; d._lane = lane; // bottom = 4 + lane * (dot + gapY)
});Direct-label only the two extremes (lowest and highest RSI) with value and ticker. Everything else gets a hover tooltip carrying symbol, company, RSI, and both moving averages. Never print a number on every dot.
Step 5 — Color, fixed
These hexes are validated (lightness band, chroma floor, colorblind separation, normal-vision separation, and contrast against their own surface, in both modes). Use them as given. If the user asks for their own brand colors, re-validate rather than swapping by eye.
| Role | Light | Dark |
| Oversold pole | #0d7fc4 | #2b96d6 |
| Overbought pole | #a35f00 | #c07d18 |
| Neutral midpoint | #6f7885 | #7d8794 |
| Page / surface | #eceff3 / #f7f9fb | #080d10 / #0c1317 |
| Primary / secondary ink | #0e1620 / #4b5a6c | #f2f6f8 / #a8b4c0 |
| Chrome accent (never on a data mark) | #0b7f70 | #12b39c |
The scale is diverging: a cool pole, a warm pole, and a neutral gray at the middle. Rules that follow from that:
- Never red/green. It reads as good/bad, and oversold is not "bad".
- The two pole hues encode the RSI band and nothing else. Trend chips, status, and links use ink and glyphs (▲ / ▼), never the pole colors, or blue starts meaning two different things on one page.
- Color never carries meaning alone. Every dot's value is also its x position; every row prints its number; every band is named in the legend.
- Define these as CSS custom properties and redefine them under both
@media (prefers-color-scheme: dark)and:root[data-theme="dark"]so a viewer's explicit toggle wins over the OS setting.
Step 6 — Integrity rules
- Render API values verbatim. No rounding beyond display, no interpolation, no filling a null.
- RSI is one reading on one day. The page states this. It never says buy, sell, cheap, expensive, or "due for a bounce".
- No signals. Crossing 30 is not a recommendation, and neither is a golden cross. Report the level and the trend relationship; stop there.
- Same-record claim must stay true. The page's whole argument is that momentum and trend arrive together. If you end up making a second call for anything on the board, either drop that element or correct the masthead.
- No token in the file. The page makes no requests, so it needs none. Grep
the output for
pk_andsk_before delivering.
Step 7 — Verify, then launch it
Do not end by handing over a file path. Open it:
- Browser pane / preview tool (Claude Code desktop, Cowork). Note that preview panes may render files outside the project folder as static snapshots with scripts disabled — if the tiles and dots come up empty, that is why; write the file inside the project folder and reopen.
- Desktop shell:
open(macOS),xdg-open(Linux),start(Windows). - No visible browser: present the file for download, and say which rung you used.
Then confirm, in the rendered page:
- tile counts sum to the symbol count;
- the dot count equals the number of symbols with a non-null
rsi14; - the lowest and highest RSI names are the ones direct-labeled;
- both themes render (toggle the OS/preview color scheme, don't assume);
- no horizontal scroll on the page body at 1200px wide.
For a LinkedIn or deck screenshot, a 1200×660 viewport in dark mode crops the masthead, tiles, and oscillator into one image.
Unlike live-market-dashboard, this page is safe to deliver as a hosted
artifact — it is a static snapshot with no outbound calls and no credential.
Example triggers
- "Which of my holdings are overbought? AAPL MSFT NVDA TSLA"
- "Build me an RSI screen for the S&P mega caps"
- "Show me what's oversold right now"
- "Rank these tickers by relative strength"
- "Momentum board for my watchlist"
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

