event-watch
Skill8 starsChanged 4 months agoApache-2.0View on GitHub
Covers a high-volatility economic event calendar — FOMC, CPI, NFP, EIA, and OPEC. Also covers earnings-season awareness and session-boundary context — globex open, NY cash open, settlement, and EIA release windows. Reports upcoming events and filters them by the user's current positions. Explains a move after it happens (for example, "ES +24pts in 8min matches the hot CPI print"). Computes historical reaction-size magnitudes from prior releases. Proposes reaction-window bracket alerts via alerts-composer. It is strictly reactive, with no timer-based push. Use when the user asks "what's coming up", "economic calendar", "why did it move", "NY cash open", or "session open". Also use when the user names a specific event — CPI, FOMC, NFP, EIA, OPEC, or earnings.
In this repository13 other files it gives its agents.
- AGENTS.mdAGENTS.md
- alerts-composerSkill
- chart-renderSkill
- contract-intelSkill
- correlation-hedgeSkill
- market-contextSkill
- position-watchdogSkill
- pretrade-riskSkill
- risk-coachSkill
- scale-managerSkill
- trade-debriefSkill
- trade-journalSkill
- trade-replaySkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 2 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 41
Every event you report must appear in the economic_calendar payload (after importance_filter.py).
- Distinctive: line 44
Never invent numbers: Do not add any consensus, prior, actual, or rate level that is not in the payload.
- Very specific: line 45
Day placement is mechanical: Place each event on the day its own date timestamp shows.
- Very specific: line 66
If the response has hasMore: true, page with offset and run the filter over each page before you answer.
- Very specific: line 110
All values are in raw points.
- Distinctive: line 120
When the user's question falls near a high-vol boundary (NY cash open, EIA release, FOMC statement, etc.), surface the context:
- Very specific: line 129
When the user holds a position exposed to a known-risk event, propose a reaction-window bracket alert.
- Very specific: line 135
Use mean_abs_move from reaction_size.py as the per-side magnitude, or bump it by 1.5× for a "meaningful surprise" threshold.
- Very specific: line 165
No third-party calendar scraping: Only the internal economic_calendar / earnings_calendar tools.
≈ “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
event-watch
Purpose
Give the user volatility-event context on demand. Three things:
- Pre-event awareness on ask ("what's on the calendar tomorrow?")
- Historical reaction-size context ("how much does ES usually move on CPI?")
- Post-event attribution on ask ("why did it just spike?")
It also recognizes session boundaries: NY cash open, EIA release window, FOMC press conference. Those drive volatility even without an explicit event.
Environment routing
Calendars and event data only — no account binding. A sibling skill's account resolution might already pin the session to demo (simulation) or live. If so, stay on that same MCP server.
MCP tools used
Tool names below are bare. The NinjaTrader MCP server provides them. Your client adds its own prefix. See AGENTS.md at the repo root.
economic_calendar— upcoming releases withdate,eventName,importance(1–5),actual,consensus,prior. These field names come from an external, unversioned passthrough API. Verify them against a live call — the MCP server's own schema does not guarantee them.earnings_calendar— equity-index contextmarket_history— bar windows around past releases for reaction-size mathmy_portfolio— dollar exposure in current positions. Prune withfields=["positions[].symbol","positions[].netPos","positions[].openPnL"].market_snapshot— gives the current price when you propose bracket alerts. Prune withfields=["snapshots[].symbol","snapshots[].lastPrice","snapshots[].tickSize"].
Explicitly not allowed: third-party commercial calendar sites (investing.com, forexfactory, tradingeconomics) — TOS-restricted and redundant with data the server already exposes.
Design constraint — strictly reactive
Phrase outputs as "you asked near X", never "X is about to happen" (that would imply a timer this skill does not have). Proactive pushes belong on the MCP's SSE channel, not in a skill.
Grounding rules — the calendar is the tool output, nothing else
Every event you report must appear in the economic_calendar payload (after importance_filter.py). These rules are absolute:
- Never add an event from memory, even one that "should" happen this week. If it is not in the tool output, it does not go in the answer.
- Never invent numbers. Do not add any consensus, prior, actual, or rate level that is not in the payload. If a field does not appear in the payload, leave it out. Never estimate it.
- Day placement is mechanical. Place each event on the day its own
datetimestamp shows. When you convert time zones, convert each event and re-bucket its day from the converted time. Never group events by the day the market "usually" releases them. - Disclose partial data. Say so if you only see or page through part of the payload. The list may be incomplete. An honest gap beats a filled one.
Workflow
1. Pre-event on ask — "what's coming up?" / "what's on the calendar?"
economic_calendar(fromDate=<today ISO-8601>, toDate=<today+3d ISO-8601>)
my_portfolio(fields=["positions[].symbol","positions[].netPos","positions[].openPnL"])Call my_portfolio once for each account name you already know from an earlier tool call in this session. The tool requires an account argument — a call without one fails. If you do not know an account name yet, ask the user for one before you call my_portfolio. Never pass a guessed account name, like Sim101. The server rejects it.
Expect an oversized result. A multi-day calendar window often exceeds the inline tool-result cap. When that happens, your client saves the JSON to a file and returns the path instead of the payload. That file is the input to importance_filter.py — pass the saved path with --file. Do not explore the file with ad-hoc jq queries or reassemble the calendar yourself. The filter script is the only sanctioned reader. Never re-type or inline a large JSON payload into the command.
python3 scripts/importance_filter.py --file <saved-tool-result-path> \
--products ES MNQ CL --min-importance 3If the response has hasMore: true, page with offset and run the filter over each page before you answer. Otherwise, say the list covers only the first page.
importance_filter.py drops:
- events with
importance < --min-importance(default 3) - events whose name does not match a product-group keyword for the user's products (see the script's canonical map)
Output fields: kept, dropped_by_importance, dropped_by_relevance, events[] (each with matched_product_groups).
2. Reaction-size context — "how much does ES usually move on CPI?"
Gather the last N releases from economic_calendar. Use a fromDate far enough back for about 6 releases of the same type. CPI is monthly, so that is about 180 days. Then, for each release, fetch a bar window around the release time via market_history:
market_history(
symbol="ESU6",
barType="Minute",
barSize=5,
from=<release - 5min, ISO-8601>,
to=<release + 30min, ISO-8601>
)Structure each release + its bars into the input format:
{"events": [
{"timestamp": "2026-01-15T13:30:00Z", "bars": [...]},
{"timestamp": "2026-02-13T13:30:00Z", "bars": [...]},
...
]}Save that as events.json and run reaction_size.py:
python3 scripts/reaction_size.py --file events.json --offset-minutes 5Output fields:
samples— events that had enough bar datamean_abs_move— avg |close(t+offset) − close(t0)|mean_max_move_up/mean_max_move_down— directional maxrange_mean/range_max/range_stdev— window range stats
All values are in raw points. Multiply by valuePerPoint × |netPos| for the dollar exposure.
Input fixture for shape reference: scripts/fixtures/cpi_reactions_synthetic.json.
3. Post-event attribution on ask — "why did it spike?"
Two inputs: recent price action (from market-context or market_history) + the nearest release from economic_calendar. Narrate the causal link where the timestamps line up. If no release falls within 10min, do not invent one — say "no scheduled release near the spike; could be headline-driven."
4. Session-boundary on ask
When the user's question falls near a high-vol boundary (NY cash open, EIA release, FOMC statement, etc.), surface the context:
"You asked 3 min before NY cash open — expect a vol spike and spread-widening in the first 10 min."
The boundary table lives in references/session-schedules.md — load that file and pick the nearest boundary.
5. Alert-proposal handoff
When the user holds a position exposed to a known-risk event, propose a reaction-window bracket alert. Then hand it to the user to submit via alerts-composer:
Propose: lastPrice(ESU6) > <entry + reaction_size> OR lastPrice(ESU6) < <entry - reaction_size>Use mean_abs_move from reaction_size.py as the per-side magnitude, or bump it by 1.5× for a "meaningful surprise" threshold. Pass this expression to alerts-composer — this skill does not submit alerts.
Subjects must be unquoted. The DSL parser rejects lastPrice("ESU6"). The subject regex [\$@]?[\w\s\-\+/|]+ excludes double-quotes: the server's rule parser accepts only unquoted subject strings. alerts-composer/scripts/validate.py catches this offline before submission.
Output idioms
- Pre-event: "CPI in 18 min (08:30 ET, consensus 0.3% m/m, prior 0.2%).
Recent CPI releases moved ES by double-digit points within
minutes. You're long 2 ES — run
reaction_size.pyfor today's actual reaction range before you size a hedge or a stop. Options: flatten, hedge with MES short, or widen stops to 1.5× normal." - Reaction-size report: "Recent CPI releases moved ES by
double-digit points in the first 5 minutes, with occasional larger
outliers. Run
reaction_size.pyover the last N releases for the exact average, max, and spread before you size a bracket." - Post-event: "ES +24pts in 8min is consistent with the hotter-than- expected CPI (0.5% vs 0.3% consensus) released at 08:30 ET."
- Session-boundary: "NY cash open in 3 min. Expect wider spreads and a vol burst in the first 10 min."
Disambiguation
- vs
market-context: market-context is intra-day analytics on one symbol (VWAP, ATR, profile). event-watch is cross-event history ("how does ES usually move on CPI?") + calendar surfacing. - vs
position-watchdog: watchdog monitors one live position. If a known-risk event threatens that position, narrate with event-watch and propose a reaction-window alert. - vs
pretrade-risk: pretrade-risk sizes an entry. If the entry sits near a known event, flag the event-derived volatility. Do not hard-gate the trade — the user decides. - vs
alerts-composer: event-watch proposes an alert expression; alerts-composer constructs + submits it. One-way handoff.
Explicit non-goals
- No proactive warnings. This skill has no timer. If the user does not ask, the skill does not act.
- No third-party calendar scraping. Only the internal
economic_calendar/earnings_calendartools. - No price prediction. Reaction-size reports are historical magnitudes, not directional forecasts.
- Not a strategy. Whether to hedge, flatten, or hold through an event is the user's decision. This skill shows magnitude and precedent.
Resource layout
scripts/importance_filter.py— filters theeconomic_calendarpayload by min importance + product-group relevance. Input via stdin.scripts/reaction_size.py— historical reaction-size math for a list of {event, bars} pairs. Input via stdin.scripts/fixtures/— synthetic samples for smoke-testing:econ_calendar_synthetic.json— 8-event calendar for the filtercpi_reactions_synthetic.json— 3 CPI releases with 5-min bars
references/session-schedules.md— US futures market hours + a high-vol boundary table (08:30, 09:30, 10:00, 10:30, 14:00, 14:30, 16:00 ET). Load it when a question falls near a session boundary.references/event-playbooks.md— per-event narrative context (FOMC, CPI, NFP, PCE, PPI, ISM, EIA, OPEC, ECB, BOJ, earnings). Load it when you narrate the story behind one named event.
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.

