Install
openclaw skills install @thesentitrader/stock-market-dashboardBuild a stock market dashboard as a single self-contained HTML file you can open in a browser. Generates a morning market briefing from live data: a fear-to-greed market mood gauge with its component signals, sentiment breadth, sector heat, the biggest 7-day attention shifts, an options radar, a watchlist with sentiment scores and analyst consensus, insider cluster buys, congressional trades, institutional flows, overnight story clusters, and the week's earnings calendar. No backend, no build step, no dependencies, one file. Use for "build me a stock market dashboard", "make a stock dashboard html", "morning market briefing", "watchlist dashboard", "daily market report". Read-only. No trading, no purchases, no write operations, no wallet access.
openclaw skills install @thesentitrader/stock-market-dashboardTurn live market data into a morning desk note you can open in a browser. One self-contained HTML file: no backend, no build step, no dependencies, no deploy. Fear-to-greed market mood and its component signals, sentiment breadth, sector tone, the biggest attention shifts, an options radar ranked against each name's own history, your watchlist, insider and congressional and institutional position changes, overnight stories ranked by impact, Street rating moves, and the week's earnings. Read-only API.
Base URL: https://app.sentisense.ai
Website: https://sentisense.ai
Full API reference: https://sentisense.ai/skill.md
Authentication: API key via X-SentiSense-API-Key header. Get a free key at https://app.sentisense.ai/get-api-key
A recipe, not a template. You fetch real data and write the HTML yourself, fresh each time. Nothing here ships a prebuilt app the user has to clone, configure or maintain, and that is the point: the file is disposable because regenerating it is cheaper than updating it.
The output contract, which is the part that matters:
<style> block, any JS in a <script> block, no CDN
links, no external fonts, no image URLs. It must render correctly with no network access.npm install, no build.If the user asks for something live and interactive that updates on its own, this is the wrong shape and you should say so rather than quietly producing a stale-by-design file.
Fetch everything first, then write the file once. Do not interleave writing and fetching, or you will end up hand-patching a half-written document.
| Section | Endpoint |
|---|---|
| Market mood + signals | GET /api/v2/market-mood?days=30 |
| Sector tone vs market | GET /api/v1/sentiment/sectors |
| Sentiment breadth | GET /api/v1/sentiment/breadth |
| Attention shifts, 7d sentiment movers | GET /api/v1/trackers/sentiment-movers |
| Options radar | GET /api/v1/options/overview |
| Insider cluster buys | GET /api/v1/insider/cluster-buys |
| Congressional trades | GET /api/v1/politicians/activity |
| Institutional net flows | GET /api/v1/institutional/flows |
| Overnight stories | GET /api/v1/documents/stories |
| Street rating changes | GET /api/v1/analyst/activity?actionTypes=UPGRADE,DOWNGRADE,INITIATE |
| Earnings this week | GET /api/v1/calendar/earnings |
| Latest price (15-minute delayed), per ticker | GET /api/v1/stocks/{ticker}/quote |
| SentiSense Score, per ticker | GET /api/v2/metrics/entity/{ticker}/metric/sentisense?startTime={epochMs30dAgo} |
| Sentiment polarity, per ticker | GET /api/v2/metrics/entity/{ticker}/metric/sentiment |
| Analyst consensus, per ticker | GET /api/v1/analyst/{ticker}/consensus |
A five-ticker watchlist plus the market-wide sections is about twenty-five calls. Run them concurrently.
Four parameter details that are not optional, each of which silently degrades the page if you drop it:
sentisense and sentiment are different metrics on different scales. sentisense is the
SentiSense Score, which currently runs roughly -30 to +45 across the tracked universe and is
centred on 0. sentiment is polarity, bounded to
[-1, 1]. Every threshold in this skill (the diverging bar, the strong-regime band, the absent
test) is on the Score scale. Feed it polarity and every one of them is wrong by two orders of
magnitude: nothing ever clears them, and the page silently renders every name as unremarkable.
Fetch both if you render both columns.startTime as epoch millis 30 days back, or you are averaging a
week and calling it a month.days=30 on market mood, not days=7. Below roughly two weeks of history the API returns
weeklyChange: null and a null change on every one of the six signals, so the trend arrows
the layout depends on all disappear.actionTypes on analyst activity. The bare call is mostly reiterations, which are not rating
changes. Without the filter the "Street moves" section is padding. Size the panel for what the
filter actually leaves: about 83% of all actions are reiterations, so of the roughly 70 to 110
actions on an active market day, only about 10 to 15 market-wide are real rating changes.
A "Street moves" panel built to hold twenty rows will look empty most days and that is the data,
not a broken call. Ask for a multi-day window (lookbackDays=3 or more) if you want the panel
full, and label the window you used.actionType comes from the research
provider and is not cross-checked against fromGrade and toGrade, so a few rows a week arrive
as an UPGRADE with identical grades, or an INITIATE that still carries a fromGrade. In a
dense dashboard row that renders as "UPGRADE Buy to Buy", which reads as a bug in your dashboard.
Filter to rows where fromGrade != toGrade before rendering the transition, and keep the
unfiltered count if you also show a total.Several v1 endpoints wrap the payload as { isPreview, previewReason, data }; read data. The
movers, options, insider, politicians, flows, analyst and earnings calls all do. Market mood,
sectors, breadth, stories, quote and the metrics endpoints return their payload directly.
Identify your client. Send a User-Agent naming your agent runtime and this skill, for
example OpenClaw/1.4 (stock-market-dashboard) or ClaudeCode/2.1 (stock-market-dashboard). Substitute your own runtime and
version if neither matches. You can also volunteer what your agent is called by adding an
agent/<your-agent-name> token inside the same parentheses, as in
OpenClaw/1.4 (stock-market-dashboard; agent/research-desk). All of it is optional, and it is what tells
us this skill has real integrations behind it, so it gets prioritized and you get notice before it
changes.
curl -s -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
"https://app.sentisense.ai/api/v2/market-mood?days=30"
Ask for the watchlist if the user did not give one. Do not invent tickers. If they want a default, say you are picking one and name the tickers.
Top to bottom. The order is the argument: market state frames everything below it, the user's own names come next, and the calendar is context rather than headline.
impactScore yourself or the
heading is a lie and the lead story is merely the most recent one.
A morning read with no narrative is a spreadsheet.The inclusion bar for any section: would a professional change their behaviour because of it? A price the reader can get anywhere fails. A divergence, an anomaly, a position change or an unusual filing passes.
Convergence is worth calling out and worth wording carefully. When independent sources line up on one name (an insider cluster buy, a congressional purchase, and a positive score), say so as an observation and explicitly not as a signal. That framing is not decoration, it is the line between research and advice.
One surface, restrained ink, color only where it carries meaning. Note there is no "raised" step: the page sits directly on the validated chart surface and nothing is boxed on top of it.
--bg:#0d1117 --track:#1b2330
--line:rgba(255,255,255,.06) --line2:rgba(255,255,255,.13)
--ink:#e8edf4 --ink2:#9daaba --ink3:#66738a
--bull:#2e9d75 --bear:#e05c4a --flat:#6b7280 --data:#3182ce
--gold:#D4A843 (brand chrome only, never a data series)
Hairline borders as translucent white rather than a solid grey step: they recede correctly at any surface lightness and never read as a box edge.
That bull/bear/data trio is validated for colorblind separation against this dark surface, so substitute at your own risk. The usual finance red-green pairing is one of the worst possible choices for deuteranopia; the green here is pushed toward teal specifically to survive it.
Calm and dense are not opposites, but you have to earn both. What makes a dense page read calm is mechanical, not a matter of taste:
Rules that keep it readable:
font-variant-numeric:tabular-nums) on every numeric column, or the digits
jitter between rows and the table looks broken.min-width of about 4px. A genuine reading of 0.9 on a 100-point scale renders
as nothing at all and is indistinguishable from missing data. A visible stub is honest; an empty
track is not.1. Label freshness per field, because it varies inside one row. Prices are 15-minute delayed,
not live: annotate them with priceAsOf where the payload carries it. Scores, sentiment and
signals come from the latest analytical batch and are older still. A 13F quarter that is still
filing shows early filers only, so positions will grow. Earnings dates are curated and unconfirmed
ones shift. Putting a price next to a batch score with no note invites the reader to diff them and
conclude something is broken.
2. A zero is not a missing value, and this one has bitten us twice in opposite directions. The
SentiSense Score (metric/sentisense, not metric/sentiment) is centered on zero, so 0.0
means genuinely neutral. When a same-day value comes back as exactly 0.0, you have to decide
whether it is a reading or a hole, and "non-zero 30-day average" is not a good enough test. Use
a magnitude threshold, on the Score scale:
same-day == 0.0 AND |30-day average| >= 5 -> ABSENT, render "no reading"
same-day == 0.0 AND |30-day average| < 5 -> REAL, render 0.0
Both halves are load-bearing, and each corresponds to a real row:
30d 25.4 reporting today 0.0 is a data hole. Rendering it prints the
self-contradicting line "Strong Bullish, today 0.0".30d -0.5 reporting today 0.0 is a true neutral. Suppressing it
as "no reading" invents a gap that is not there, which is the same error in the other direction.Rendering an absent value as zero on a zero-centered scale is unfalsifiable by the reader: they cannot tell a real neutral from a gap. Inventing a gap is equally unfalsifiable. Pick with the threshold, not by eye.
3. The score is a nowcast, not a forecast. It reads how bullish or bearish the market currently is on a stock, weighted by how actively it is discussed. It does not predict price. Never label it a buy signal, a target, or a prediction, and do not build a "top picks" section out of it.
4. Do not narrate a partial sample. The 13F flows endpoint returns isPending plus a
filerCount / baselineFilerCount pair while the quarter is inside the 45-day filing window. At
that point you are looking at a fraction of filers, and early filers are not a random sample of
late ones. Report the numbers, state the coverage as a percentage, and stop. Do not write the
sentence explaining what the pattern means.
The tell that you have crossed the line is a clause like "X are net sellers of Y", "the smart money is rotating out of Z", or any sentence where a partial dataset acquires a motive. Direction is reportable from a partial sample. Magnitude and intent are not. This is the single easiest way to turn a correct dashboard into a wrong one, because the numbers stay right while the sentence underneath them goes wrong.
Same discipline applies anywhere coverage is incomplete: a still-filing quarter, a curated calendar with unconfirmed dates, an options radar built from one session's chains.
5. Every dashboard carries a disclaimer. Not optional and not a footnote in 9px grey:
Not investment advice. Generated from public and licensed market data for research and educational purposes only. Not a recommendation to buy or sell any security, and it does not account for your circumstances, objectives or risk tolerance.
Natural additions once the base page works, each one more call and one more section: options positioning and IV rank, congressional and insider trades on the watchlist names, news stories per ticker, a sentiment leaderboard of the most bullish and bearish names. Add them as sections in the same file rather than splitting into multiple pages.
For "show the broader market", hand off to the market-heatmap skill when available. Pass the desired scope, metric, and watchlist context. Return a market treemap with coverage and as-of labels. Hand off only when the user changes the question; do not automatically route back. If the sibling is unavailable, answer the supported part here using a connected tool or the inline REST workflow, state any remaining gap, and never require an install.
Keep it one file. The moment it needs a bundler it stops being the thing that makes this useful, which is that anyone can generate one, email it, and have it open on the other end.
The file lands on the machine the agent runs on, which is not always the machine the user is looking at. Before presenting a path as if it were clickable, say where the file lives and how to open it: on a local desktop surface, the absolute path plus "open it in your browser" is enough; on a hosted or chat surface (a web chat talking to a remote host), a bare local path is not retrievable by the user, so offer a real delivery route instead: the host's file/attachment mechanism if it has one, serving the file briefly over a local port you name explicitly (state which machine "localhost" refers to), or pasting the HTML for the user to save. If the host offers a render surface for HTML documents (a canvas or render-only preview panel), presenting the dashboard there is a good fit, because this file is a self-contained static snapshot by design; check that the capability is actually connected before promising it. Treat such a surface as display, not interaction: a panel that renders HTML may not run scripts or accept input, and this dashboard is built to be read either way.
For example, OpenClaw's canvas node is such a surface: it renders the file well, and on some
surfaces it is render-only, which this snapshot is designed for. Since OpenClaw 2026.8.1 the
same host offers a better route: the show_widget tool takes the finished page as
widget_code with a short title, renders it inline in the chat, and with pin: true plus a
stable name (use market-dashboard) places it on the session dashboard, where it survives
/new and /reset. A later call with the same name replaces it in place, which is how the
next morning's note supersedes today's without another file. Pick a large size (xl or
full) and keep the page under the 262,144-character limit inline clients enforce. Inline
widgets are sandboxed (inline style and script allowed, no external loads, no network), which
this no-network file already satisfies. Do not declare capabilities.netOrigins for it: the
agent fetches the data with the key in its own environment and renders a snapshot, so the
widget never needs the API origin or the key, and it works under every session permission
mode. Check that the tool is present before promising it; when it is not, the canvas or the
file route above still applies.