smithery/faisalanjum

news-impact

Identify what drives stock price moves with drivers, confidence, and returns

Installation

$ npx skills add smithery/faisalanjum --skill news-impact

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/faisalanjum · top by installs.

npx skills add smithery/faisalanjum

Browse all from smithery/faisalanjum

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsSkill, mcp__neo4j-cypher__read_neo4j_cypher, WebSearch, mcp__perplexity__perplexity_ask, mcp__perplexity__perplexity_search, mcp__perplexity__perplexity_reason, mcp__perplexity__perplexity_research

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,706 B
  • docs SUMMARY.md 95 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

News Impact

Identify what drives stock price moves with maximum accuracy, comprehensiveness, and confidence.

Arguments

Received: $ARGUMENTS

Parse as: TICKER STARTDATE ENDDATE [THRESHOLD] [--no-perplexity]

  • THRESHOLD: 3s (default), 1.5s, 2s, or fixed percent
  • --no-perplexity: Skip Perplexity for gap days (faster)

If no arguments received, ask user for TICKER, STARTDATE, ENDDATE.

Flow

Step 0: Validate Data Availability (REQUIRED FIRST)

CRITICAL: Run this query BEFORE any other step. STOP if validation fails.

MATCH (c:Company {ticker: $ticker})
OPTIONAL MATCH (d:Date)-[r:HAS_PRICE]->(c)
WITH c, max(d.date) AS latest_date, min(d.date) AS earliest_date, count(r) AS price_count
RETURN c.name AS company_name,
       latest_date,
       earliest_date,
       price_count,
       CASE WHEN latest_date >= date($start) THEN true ELSE false END AS has_start_data,
       CASE WHEN latest_date >= date($end) THEN true ELSE false END AS has_end_data

Validation Rules:

  1. If company_name is null → STOP: ERROR: Ticker {ticker} not found in database
  2. If price_count = 0 → STOP: ERROR: No price data for {ticker}
  3. If hasstartdata = false → STOP: ERROR: No price data for {ticker} in requested range. Latest available: {latest_date}
  4. If hasenddata = false → WARN but continue: WARNING: Data only available through {latest_date}, analysis will end there

DO NOT proceed to Step 1 if validation fails. DO NOT fall back to web search for missing price data.

Step 1: Get Benzinga News

Call /get-bz-news $ARGUMENTS

Returns news where |daily_adj| >= threshold (default 1.5σ) with:

  • volatility: trailing adjusted volatility used
  • z_score: how many sigmas this move was

If INSUFFICIENT_HISTORY returned, fall back to fixed 3% threshold.

Step 2: Analyze Each News Item

For each news item from Step 1:

  1. Read title AND body - titles can be vague
  2. Check market_session for timing context:

- premarket: News likely CAUSED the day's move → HIGH confidence - inmarket: News aligns with intraday action → MEDIUM-HIGH confidence - post_market: News EXPLAINS today's move, but impacts NEXT trading day → MEDIUM confidence (reactive)

Note: Post-market news (earnings, guidance) will move the stock at next market open. Associate post_market news with the NEXT day's return.

  1. Generate driver phrase (5-15 words explaining why stock moved)
  2. Assess confidence (0-100%) based on:

- How clearly news explains the move direction - Timing alignment (pre-market earnings → high; post-market commentary → lower) - Z-score magnitude (higher z-score + clear news = higher confidence)

Step 3: Find Gap Days

Query daily returns to find big moves without news coverage.

First, get the volatility (or use the one from Step 1):

MATCH (d:Date)-[r:HAS_PRICE]->(c:Company {ticker: $ticker})
WHERE d.date >= date($start) - duration('P365D') AND d.date < date($start)
MATCH (d)-[m:HAS_PRICE]->(idx:MarketIndex {ticker: 'SPY'})
WHERE r.daily_return IS NOT NULL AND m.daily_return IS NOT NULL
WITH stdev(r.daily_return - m.daily_return) AS adj_vol
RETURN adj_vol

Then find all significant move days:

MATCH (d:Date)-[r:HAS_PRICE]->(c:Company {ticker: $ticker})
WHERE d.date >= date($start) - duration('P365D') AND d.date < date($start)
MATCH (d)-[m:HAS_PRICE]->(idx:MarketIndex {ticker: 'SPY'})
WHERE r.daily_return IS NOT NULL AND m.daily_return IS NOT NULL
WITH c, stdev(r.daily_return - m.daily_return) AS adj_vol

MATCH (d2:Date)-[r2:HAS_PRICE]->(c)
WHERE d2.date >= $start AND d2.date < $end
MATCH (d2)-[m2:HAS_PRICE]->(idx:MarketIndex {ticker: 'SPY'})
WITH d2.date AS date,
     r2.daily_return AS stock,
     m2.daily_return AS macro,
     (r2.daily_return - m2.daily_return) AS daily_adj,
     adj_vol
WHERE abs(daily_adj) >= $multiplier * adj_vol
RETURN date, stock, macro, daily_adj, adj_vol,
       abs(daily_adj) / adj_vol AS z_score
ORDER BY date

Compare with news dates from Step 1. Gap = date with big move but no news.

Step 4: Research Gaps (WebSearch → Perplexity)

Skip this step if --no-perplexity flag is set. Just list gaps as UNKNOWN with confidence=0.

Otherwise, for each gap day:

4a. WebSearch first (faster, multi-source validation):

  1. Search: "{ticker} stock news {date}" or "{company name} {date} move"
  2. Look for 2+ independent sources corroborating the same explanation
  3. If 2+ sources agree → accept with confidence based on source quality:

- 3+ sources: 70-85% confidence - 2 sources: 50-70% confidence

  1. If <2 sources found → escalate to Perplexity

4b. Perplexity fallback (if WebSearch insufficient):

  1. Spawn perplexity-search agent — "{ticker} stock news {date}"
  2. Spawn perplexity-research agent — only for major moves (>5%) with no results

Generate driver and confidence from research. Include z-score context.

Step 5: Merge and Return

Combine news (Step 2) + gaps (Step 4), sort by date ASC.

Output Format

Pipe-delimited, one per line:

date|news_id|driver|confidence|daily_stock|daily_adj|sector_adj|industry_adj|z_score|volatility|market_session|source
Field Description
date Event timestamp
news_id Neo4j ID or URL(s) for external research
driver Short phrase (5-15 words) explaining move
confidence 0-100% certainty
daily_stock Raw daily return
daily_adj dailystock - dailymacro (vs SPY)
sector_adj dailystock - dailysector (idiosyncratic vs sector)
industry_adj dailystock - dailyindustry (idiosyncratic vs industry)
z_score How many sigmas (e.g., 2.1)
volatility Trailing adjusted vol used
market_session premarket / inmarket / post_market (empty for perplexity)
source neo4j, websearch, or perplexity

Move Type Interpretation:

  • If |dailyadj| >> |sectoradj| → Sector-driven (not company-specific)
  • If |sectoradj| ≈ |industryadj| ≈ |daily_adj| → Idiosyncratic (company-specific)
  • If all small but daily_stock large → Market beta

Rules

  • All adjusted returns and volatility calculated in Cypher, NOT by LLM
  • WebSearch first for gap days — validate with 2+ sources before accepting
  • Perplexity fallback only if WebSearch finds <2 sources
  • Always read news body, not just title, for accurate driver extraction
  • Use market_session timing to assess causation vs explanation
  • Post-market news impacts NEXT trading day, not current day
  • If no explanation found, driver = "UNKNOWN", confidence = 0
  • Default threshold: 1.5σ of trailing adjusted returns
  • Minimum 60 days history required; fall back to 3% if insufficient

CRITICAL - Date Range Enforcement:

  • ONLY return results for dates within the requested STARTDATE to ENDDATE range
  • If no significant moves found in the range, return: NOSIGNIFICANTMOVES: No moves exceeding {threshold} found for {ticker} between {start} and {end}
  • NEVER substitute other dates - do not search for or return data from outside the requested range
  • NEVER compensate for empty results by finding "interesting" moves from other periods