From manual chart-staring to a fully autonomous pipeline that scans 8,000+ tickers nightly, scores setups across 6 dimensions, and delivers only A++ trade recommendations to your Discord. You do nothing except follow the alerts.
Every evening at 23:00, while you are asleep, an autonomous AI agent wakes up. It connects to live market data feeds, scans over 8,000 tickers across US, European, and Asia-Pacific exchanges, runs multi-strategy screening algorithms, scores every candidate through a 6-dimensional quality filter, and delivers 3 meticulously researched trade recommendations to your Discord channel. By the time you check your phone in the morning, the work is done. All you need to do is decide whether to execute.
This is not a fantasy. This is what we have been running in production at DailyTickers since January 2026. The system has generated over 200 scanner reports, each containing 10 A+ setups, with a documented hit rate tracked through weekly retrospectives. And it is built entirely on tools that are available to any retail investor today: Claude Code, the Model Context Protocol (MCP), and a handful of well-configured servers.
Over 6 parts, you will build the exact same pipeline we use. Not a simplified version. Not a toy demo. The real thing. By the end, you will have a fully operational automated trading research system that runs on your own machine, uses your own analysis criteria, and delivers results wherever you want them.
If you are a retail trader doing your own research, your workflow probably looks something like this: you open TradingView, flip through a watchlist of 30-50 tickers, check RSI and MACD on each, maybe read some news, glance at earnings dates, and then try to synthesize all of that into a trade decision. On a good day, this takes 2-3 hours. On a busy day, you skip it entirely.
The problems with this approach are structural, not personal:
Let us be precise about terminology, because "automated trading" means different things to different people:
This distinction matters enormously. Our system is a research automation pipeline, not a trading bot. It replaces the analyst, not the trader. You retain full control over execution, sizing, and risk management. The AI handles the tedious, high-volume, multi-dimensional screening work that no human can do consistently at scale.
Nothing in this series constitutes financial advice. The system we describe is a research tool. Every trade recommendation it produces must be independently validated before execution. Past scanner performance (tracked in our retrospectives) does not guarantee future results. You are solely responsible for your own trading decisions.
When you finish all 6 parts of this series, here is what your daily life as a trader will look like:
The entire pipeline takes less than 30 minutes and requires zero human intervention. Let us build it.
The system follows a classic ETL pattern — Extract, Transform, Load — with an AI agent at the center acting as the orchestrator. But unlike traditional ETL where each step is a discrete service, our entire pipeline is a single Claude Code session that makes tool calls through the Model Context Protocol.
There are four major subsystems, each exposed to Claude Code as an MCP server:
Let us trace a single execution from trigger to delivery. Understanding this flow is essential before we start building, because every architectural decision serves a specific purpose in this chain.
A Discord bot (or cron job) executes claude -p "scan du jour" inside a tmux session. The -p flag runs Claude Code in non-interactive (pipe) mode, meaning it reads the prompt, executes, and exits. The working directory is the articles repository, so Claude Code automatically loads CLAUDE.md as its system prompt.
Claude Code's first MCP call is RunAutoScreener. This is not a simple stock screener — it first analyzes the current market regime by examining VIX levels, yield curves, sector rotation patterns, and breadth indicators. The regime (Risk-On, Risk-Off, Neutral, Transition, Early Risk-On, Early Risk-Off) determines which screening strategies to prioritize. In a Risk-Off regime, for example, the system increases allocation to short setups and hedges (GLD, TLT, SH, SQQQ).
Three RunScreener calls execute in sequence, each with a different DSL (Domain-Specific Language) strategy: oversold reversals, momentum continuation, and breakout setups. Additional screeners target EU equities (VGK, EWG, EWQ, SAP, ASML), APAC names (EWJ, EWY, FXI), and thematic ETFs (XLF, XLE, GLD, ARKK). The combined candidate pool typically contains 100-200 names.
For every candidate that passes initial screening, Claude Code calls QueryData with types including quote, insider_transactions, sentiment_overall, trading_signals, support_resistance, and volume_profile. This enrichment step is where most of the API calls happen — easily 50+ calls per scan. The MCP Gateway handles batching and rate limiting internally.
Each enriched candidate is scored across six dimensions (detailed in Section 4). Claude Code computes a composite score using weights that adapt to the current regime. Only candidates scoring above 85/100 survive this filter. Typically, 20-30 out of 150+ candidates make the cut.
The survivors are passed to LLMAnalysis (DeepSeek) for a second-opinion AI analysis. This catches edge cases that the scoring system might miss — for example, a ticker with great technicals but a pending SEC investigation, or a setup that looks like a value trap. The AI re-ranking reduces the list to the final 10 A+ setups.
Three outputs are generated simultaneously: (1) a full HTML report committed to GitHub Pages via git add/commit/push, (2) Discord alerts for the top 3 A++ setups via the Discord MCP server, and (3) price-level alerts via the Market Alerts MCP server that will fire when entry zones are hit.
The Model Context Protocol is what makes this entire architecture possible. Before MCP, connecting an LLM to external data sources required custom API wrappers, prompt engineering for tool calling, and fragile output parsing. MCP standardizes the interface: every data source, every action, every delivery mechanism exposes the same JSON-RPC protocol. Claude Code does not know (or care) whether it is talking to a market data API, a Discord webhook, or a Git repository. It just makes tool calls.
This has three profound implications for our architecture:
The Model Context Protocol (MCP) is an open standard created by Anthropic for connecting AI models to external tools and data. Think of it like USB for AI: a universal connector that lets any AI model talk to any data source. An MCP server exposes "tools" (functions the AI can call) and "resources" (data the AI can read). Claude Code is an MCP client that can connect to multiple servers simultaneously, composing their capabilities into a single workflow.
Before we move on, it is important to document the deliberate constraints in this architecture, because they prevent common mistakes:
scanner/YYYYMMDD/). We never overwrite historical reports. This creates an immutable audit trail.Let us break down every component in the stack, what it does, and why we chose it. This is an opinionated stack — there are alternatives for every layer — but these components work together exceptionally well.
The central orchestrator. Claude Code is Anthropic's official CLI for the Claude model family. Unlike the web interface or API, Claude Code can execute shell commands, read and write files, and — critically — connect to MCP servers. When invoked with claude -p "prompt", it runs in non-interactive pipe mode: it reads the prompt, processes it using the system instructions from CLAUDE.md, makes whatever tool calls are necessary, and exits. This makes it perfect for scheduled automation.
Claude Code also maintains a CLAUDE.md file in the project root that acts as persistent memory. Our CLAUDE.md is over 400 lines of instructions that define the scanning methodology, scoring criteria, output format, and delivery mechanism. The AI follows these instructions deterministically on every run.
The communication layer. MCP is a JSON-RPC-based protocol that standardizes how AI models interact with external tools. Each MCP server exposes a set of "tools" (callable functions) that the AI can invoke. The protocol handles serialization, transport (stdio or HTTP/SSE), and error propagation. Our pipeline uses three MCP servers simultaneously, and Claude Code manages the connections automatically.
Key MCP concepts: Tools are functions the AI calls (e.g., GetMarketOverview). Resources are data the AI reads (e.g., a JSON dataset). Prompts are templates that structure AI interactions. We primarily use tools.
The data layer. This is our custom MCP server that provides access to 58 types of market data via a unified interface. Under the hood, it aggregates data from multiple providers (Yahoo Finance, Alpha Vantage, Polygon, Finnhub, social sentiment APIs) into a consistent schema. The key tools are:
GetMarketOverview — Full market snapshot: indices, commodities, crypto, rates, VIX, sentiment, regime classification, and top news stories.QueryData — Flexible data query supporting 58 types: quotes, OHLCV bars, technicals, financials, earnings, insider transactions, options chains, analyst actions, support/resistance levels, volume profiles, sentiment scores, and more.RunAutoScreener — Intelligent screener that first detects the market regime, then runs regime-appropriate screening strategies.RunScreener — Custom screener using a DSL (Domain-Specific Language) for defining screening criteria.GetInstruments — Deep analysis of specific symbols, returning comprehensive data across all 58 types.LLMAnalysis — Secondary AI analysis via DeepSeek for cross-validation.The notification layer. A lightweight MCP server that exposes Discord API operations as tools. Claude Code can send messages, embeds, and attachments to specified channels. For our pipeline, the Discord server is configured to post to a #scanner-alerts channel with rich embeds that include the ticker, setup type, entry/stop/TP levels, the score breakdown, and a link to the full report on GitHub Pages.
The Discord server also serves as the trigger mechanism: a Discord bot listens for scheduled commands (e.g., every weekday at 23:00 articles scan du jour) and invokes Claude Code via claude -p in a tmux session.
The monitoring layer. This server manages persistent price alerts that fire when specific conditions are met. When the scanner identifies an A++ setup with an entry zone at $45.20-$45.80, it creates an alert that monitors the price in real-time. When the price enters the zone, a Discord notification fires immediately, giving you a heads-up that the setup is actionable. Alerts support multiple condition types: price above/below, percentage change, volume spike, and custom expressions.
The trigger layer. Rather than using system cron (which has limited error handling and no easy way to inspect logs), we use a custom Discord bot that manages schedules via a JSON configuration file. The bot runs Claude Code inside tmux sessions, which means: (1) sessions persist even if the bot restarts, (2) you can attach to a running session to inspect progress in real-time, and (3) output is captured for debugging. The bot supports day-of-week filters, time zones, and manual trigger commands (run #1 to execute a schedule immediately).
The archive layer. Every scanner report, every analysis, every weekly briefing is a static HTML file committed to a Git repository and served via GitHub Pages. This gives us: (1) an immutable audit trail of every recommendation, (2) free hosting with global CDN, (3) version history via Git, and (4) easy integration with the pipeline (Claude Code can git add, git commit, and git push as part of its normal tool calls). The report site serves as both the public-facing archive and the internal dashboard for tracking scanner performance.
Before someone says "you could just use a Python script with yfinance" — yes, you could. Here is why we do not:
| Approach | Coverage | Analysis Depth | Adaptability | Maintenance |
|---|---|---|---|---|
| Python script + yfinance | US only | Technicals only | Hardcoded rules | High (code changes for every strategy tweak) |
| TradingView alerts | Broad | Technicals only | Pine Script | Medium (visual but limited logic) |
| Commercial screener (Finviz, TC2000) | US mostly | Tech + some fundamental | Preset filters | Low (but no AI layer) |
| Claude Code + MCP | Global (US/EU/APAC/Crypto) | 6 dimensions | Natural language | Zero (update CLAUDE.md) |
The fundamental advantage of the Claude Code approach is that strategy changes are prompt changes, not code changes. When you want to add a new scoring dimension (say, options flow analysis), you add a paragraph to CLAUDE.md. You do not write new code, you do not deploy a new service, you do not update a database schema. The AI reads the new instructions and adapts its behavior on the next run.
This is a paradigm shift. Traditional quantitative systems require engineering effort proportional to the complexity of the strategy. AI-orchestrated systems require engineering effort proportional to the complexity of the data plumbing — and MCP already handles that.
For reproducibility, here are the exact versions we run in production:
Claude Code CLI : 1.0.17 (claude --version)
Claude Model : claude-opus-4-6
Node.js : v22.x LTS
MCP SDK : @modelcontextprotocol/sdk 1.12.x
Discord.js : 14.x
GitHub CLI (gh) : 2.x
OS : macOS Sequoia 15.x / Ubuntu 24.04 LTS
Shell : zsh (macOS) / bash (Linux)
Git : 2.43+
This is the heart of the system. Everything else — the MCP plumbing, the scheduling, the Discord delivery — is infrastructure. The scoring system is the actual edge. It determines what gets recommended and what gets filtered out. Getting this right is the difference between a system that produces noise and one that produces alpha.
Our scoring model evaluates every candidate across 6 independent dimensions. Each dimension produces a score from 0 to 100. The composite score is a weighted average, with weights that shift based on the current market regime. A candidate must score above 85 on the composite AND above the individual threshold on EVERY dimension to qualify as A+. The top 3 candidates by composite score are labeled A++.
Single-dimension screening is how you blow up your account. A stock with a perfect RSI oversold signal means nothing if the company is going bankrupt (fundamentals), the sector is rotating out (sector), the overall market is crashing (macro), social media is screaming about fraud (social), and the AI detects an earnings trap (conviction). Every dimension is a veto gate. All 6 must pass. This is what makes A++ setups so rare — and so reliable.
We require at least 4 independent technical signals to confirm the setup. This is not "RSI is oversold, buy." This is multi-timeframe confluence:
The system checks all 8 signals and requires at least 4 to be present and aligned in the same direction. Conflicting signals (e.g., bullish RSI divergence but bearish EMA alignment) reduce the technical score.
Fundamental analysis prevents us from buying cheap garbage. The fundamental score aggregates:
For ETFs and crypto, the fundamental score adapts: ETFs are scored on tracking error, expense ratio, and AUM. Crypto is scored on network activity, TVL, and developer activity.
Swimming against the sector tide is a losing strategy. We want our picks in sectors that are gaining relative strength:
A setup in a sector that is underperforming SPY by more than 2% over 20 days gets an automatic downgrade, regardless of how good the individual stock looks.
The macro layer ensures we are not fighting the market. The regime detection algorithm classifies the current environment into one of six states:
A long-only momentum setup in a Risk-Off regime fails the macro check automatically. The system will not even score it further — it is immediately rejected.
The final layer is the AI's own judgment, applied after all quantitative scores are computed. Claude Code synthesizes all available information and assigns a conviction percentage:
The AI conviction layer is deliberately subjective. It captures the holistic reasoning that quantitative scores cannot — the "this just does not look right" instinct that experienced traders develop over decades.
The composite score is a weighted average that adapts to market regime. Here are the weight profiles:
{
"Risk-On": {
"technical": 0.25,
"fundamental": 0.15,
"social": 0.10,
"sector": 0.20,
"macro": 0.10,
"ai_conviction": 0.20
},
"Risk-Off": {
"technical": 0.30,
"fundamental": 0.10,
"social": 0.05,
"sector": 0.15,
"macro": 0.25,
"ai_conviction": 0.15
},
"Neutral": {
"technical": 0.25,
"fundamental": 0.20,
"social": 0.10,
"sector": 0.15,
"macro": 0.15,
"ai_conviction": 0.15
},
"Transition": {
"technical": 0.20,
"fundamental": 0.15,
"social": 0.05,
"sector": 0.15,
"macro": 0.30,
"ai_conviction": 0.15
}
}
Notice how the weights shift: in Risk-Off, macro weight jumps to 0.30 because fighting the macro trend is suicidal. In Risk-On, sector weight rises to 0.20 because riding the right sector wave amplifies returns. Social sentiment weight drops in Risk-Off because social media becomes unreliable in panics (too much noise).
The scoring system produces A+ setups (composite >= 85, all dimensions pass). But we go one step further to identify A++ — the absolute cream. The A++ designation requires:
On any given night, the scanner might produce 10 A+ setups but only 2-3 A++ setups. Some nights produce zero A++. That is fine — we would rather miss a mediocre opportunity than recommend one. A++ is about precision, not recall.
One critical filter that is easy to overlook: the system maintains a "recently recommended" list. Any ticker that appeared in the last 3 scanner reports is automatically deprioritized unless it has a materially different setup type (e.g., it was a momentum play last week but is now an oversold reversal). This prevents the scanner from falling in love with the same names and ensures at least 70% fresh tickers per scan.
To make this concrete, here is how a real A++ setup might score:
| Dimension | Score | Detail |
|---|---|---|
| Technical | 92 | 5/8 signals aligned: RSI bullish divergence (daily+weekly), MACD histogram reversal, price at Fib 0.618, volume spike 2.3x average. EMA alignment pending (8 below 21 but crossing). |
| Fundamental | 88 | 4 consecutive EPS beats, revenue growing 18% YoY, forward P/E 15x (sector median 22x), 3 insider buys in last 30 days totaling $2.1M. |
| Social | 78 | StockTwits bullish ratio 68% (up from 52% last week), Reddit mentions +40% but below hype threshold. News sentiment neutral-positive. |
| Sector | 85 | XLK outperforming SPY by 1.8% over 20 days. Tech earnings reporters beating at 72% rate. Fund flows positive. |
| Macro | 90 | Regime: Risk-On (VIX 14.2, breadth 68%, yield curve +42bps). All conditions favorable for long momentum. |
| AI Conviction | 91 | Strong asymmetric R:R (2.8:1), no binary events within 2 weeks, DeepSeek confirms "high conviction — clean pullback to rising support with institutional accumulation signals." |
Composite Score: 0.25(92) + 0.15(88) + 0.10(78) + 0.20(85) + 0.10(90) + 0.20(91) = 23.0 + 13.2 + 7.8 + 17.0 + 9.0 + 18.2 = 88.2 (A+)
With all dimensions above 75 and R:R at 2.8:1, this qualifies as A++.
Now let us trace the entire pipeline in chronological order, from the moment the cron fires to the moment Discord alerts land on your phone. This is the operational blueprint that Parts 2-6 will implement in detail.
The Discord bot reads schedules.json, matches the current time to the "Scanner Quotidien" schedule (weekdays 23:00), and spawns a new tmux session:
tmux new-session -d -s scanner-20260305 \
"cd /Users/marketwatchxyz/GolandProjects/articles && \
claude -p 'scan du jour' \
--model claude-opus-4-6 \
2>&1 | tee /tmp/scanner-20260305.log"
The -p flag puts Claude Code in pipe mode. The tee captures output for debugging. The session name includes the date for easy identification.
Claude Code boots up, reads CLAUDE.md from the project root (400+ lines of instructions), and identifies the "Scanner" command section. This section specifies the complete scanning methodology, including:
The AI has everything it needs to execute autonomously. No human input required from this point forward.
Before scanning anything, Claude Code reads every file in scanner/retrospective/*/index.html. These are weekly performance reviews that grade the scanner. From each retrospective, the AI extracts:
This is the feedback loop that makes the system improve over time. A strategy that underperforms in 2+ consecutive retrospectives gets its weight reduced automatically.
Claude Code reads the most recent scanner/YYYYMMDD/index.html to extract the 10 tickers from the last scan. These go into the anti-doublon filter: the new scan must contain at least 70% fresh tickers. This prevents the scanner from recommending the same names night after night.
previous_tickers = extract_tickers(last_scan) # e.g., [AAPL, NVDA, GLD, ...]
new_candidates = score_and_rank(all_candidates)
# Enforce 70% freshness
fresh_count = 0
for candidate in new_candidates:
if candidate.ticker in previous_tickers:
candidate.score *= 0.7 # 30% penalty for repeat
else:
fresh_count += 1
# If fresh_count < 7, expand screening to find more unique names
The first MCP call fires:
Tool: mcp__dailytickers__RunAutoScreener
Parameters: {}
RunAutoScreener returns a comprehensive regime analysis including:
{
"regime": {
"current": "Risk-On",
"confidence": 0.82,
"vix": 14.2,
"vix_trend": "declining",
"breadth": {
"above_200sma": 0.68,
"advance_decline": 1.85,
"new_highs_lows": 3.2
},
"yield_curve": {
"2y10y_spread": 0.42,
"trend": "steepening"
},
"sector_rotation": {
"leading": ["XLK", "XLY", "XLC"],
"lagging": ["XLU", "XLP", "XLRE"]
}
},
"recommended_strategies": [
"momentum_continuation",
"breakout_volume",
"oversold_quality"
],
"candidates": [
// ... initial candidate list
]
}
Based on the regime, Claude Code selects weight profiles and strategy allocation. In Risk-On with 82% confidence, the system allocates 40% to momentum, 35% to breakout, and 25% to oversold quality names.
Three RunScreener calls execute with different DSL strategies:
Tool: mcp__dailytickers__RunScreener
Parameters: {
"dsl": "RSI(14) < 35 AND SMA(50) > SMA(200) AND Volume > SMA_Volume(20) * 1.5 AND MarketCap > 1B",
"universe": "US_LARGE_MID"
}
Tool: mcp__dailytickers__RunScreener
Parameters: {
"dsl": "Close > SMA(20) AND SMA(20) > SMA(50) AND RSI(14) BETWEEN 55 AND 75 AND ADX(14) > 25 AND Volume > SMA_Volume(20) * 1.2",
"universe": "US_ALL"
}
Tool: mcp__dailytickers__RunScreener
Parameters: {
"dsl": "Close > BB_Upper(20,2) AND Volume > SMA_Volume(20) * 2 AND ATR(14)/Close < 0.05",
"universe": "US_ALL"
}
Additional screeners target international markets:
// European equities
Tool: mcp__dailytickers__RunScreener
Parameters: {
"symbols": ["VGK","EWG","EWQ","EWU","SAP","ASML","BBVA","TTE","SIE","LVMHF"],
"dsl": "RSI(14) < 40 OR (Close > SMA(20) AND ADX(14) > 20)"
}
// Asia-Pacific
Tool: mcp__dailytickers__RunScreener
Parameters: {
"symbols": ["EWJ","EWY","EWH","FXI","MCHI"],
"dsl": "RSI(14) < 40 OR (Close > SMA(20) AND ADX(14) > 20)"
}
// Thematic ETFs
Tool: mcp__dailytickers__RunScreener
Parameters: {
"symbols": ["XLF","XLE","XLK","XLV","XLI","GLD","SLV","TLT","ARKK","ICLN"],
"dsl": "RSI(14) < 35 OR (Close > SMA(20) AND Volume > SMA_Volume(20) * 1.3)"
}
The combined output from all screeners typically yields 100-200 candidates. These are deduplicated and passed to the enrichment step.
For the top 30 candidates (ranked by raw screening score), Claude Code calls QueryData with comprehensive data types:
Tool: mcp__dailytickers__QueryData
Parameters: {
"symbols": ["AAPL", "NVDA", "TSLA", ...], // top 30 candidates
"types": [
"quote", // Current price, volume, change
"bars_daily", // 90 days OHLCV
"insider_transactions", // Last 90 days insider buys/sells
"sentiment_overall", // Aggregated sentiment score
"trading_signals", // Technical signal summary
"support_resistance", // Key S/R levels
"volume_profile", // Volume at price distribution
"stats", // Beta, avg volume, 52w range
"analyst_actions", // Recent upgrades/downgrades
"financials", // Latest quarterly financials
"earnings_quarterly" // EPS history and surprises
]
}
This is the most API-intensive step. Each ticker requires data from multiple providers, aggregated by the MCP Gateway. The Gateway handles caching (60-second TTL for quotes, 24-hour for financials) and rate limiting internally.
Claude Code now has all the data needed to score each candidate. It computes the 6 dimension scores, applies the regime-adjusted weights, and calculates the composite score. This is where the AI's reasoning ability matters — it is not just running formulas, it is interpreting the data contextually:
For each candidate:
1. Technical Score
- Count aligned signals from trading_signals + support_resistance
- Check multi-timeframe confirmation (daily vs weekly)
- Score: (aligned_signals / 8) * 100, with bonuses for rare confluences
2. Fundamental Score
- Extract EPS trend from earnings_quarterly
- Check insider_transactions for net buying
- Compare valuation metrics to sector medians from financials
- Score: weighted aggregate of sub-scores
3. Social Score
- Parse sentiment_overall for bullish/bearish ratio
- Check if sentiment is rising but below "euphoria" threshold
- Score: alignment * magnitude * freshness
4. Sector Score
- Compare sector ETF performance vs SPY (5d, 20d)
- Check if sector is in the "leading" list from regime analysis
- Score: relative_strength * 100, capped at 100
5. Macro Score
- Is the setup type compatible with current regime?
- Long momentum in Risk-On? Score = 95
- Long momentum in Risk-Off? Score = 20 (auto-fail)
- Score: compatibility * regime_confidence * 100
6. AI Conviction
- Synthesize all data points holistically
- Check for red flags: upcoming earnings, FDA, FOMC
- Estimate R:R from entry to S/R levels
- Score: subjective assessment 0-100
Composite = sum(weight_i * score_i) for i in dimensions
Pass = composite >= 85 AND all individual scores >= threshold
The top 20 candidates (by composite score) are passed to the LLMAnalysis tool for a second-opinion from DeepSeek:
Tool: mcp__dailytickers__LLMAnalysis
Parameters: {
"query": "Rank these 20 setups by conviction. For each, provide:
1. Conviction level (high/medium/low)
2. Primary risk factor
3. Optimal entry strategy (limit at support vs market)
4. Position sizing suggestion (% of portfolio)
Setups: [detailed data for each candidate]"
}
DeepSeek's independent analysis serves as a cross-validation layer. If Claude scores a setup as 92/100 but DeepSeek flags a risk that Claude missed (e.g., "this company has a patent trial verdict next Tuesday"), the setup gets downgraded. Conversely, if both AIs agree on high conviction, the setup's A++ status is confirmed.
Before finalizing the selection, a critical sanity check runs: for every selected ticker, Claude Code calls QueryData with types: quote to get the real-time spot price. If the calculated entry price differs by more than 10% from the current market price, the setup is rejected. This catches stale data issues, stock splits, and ticker symbol errors:
for each selected_setup:
spot_price = QueryData(symbols=[setup.ticker], types=["quote"]).price
entry_price = setup.entry_zone_midpoint
deviation = abs(spot_price - entry_price) / spot_price
if deviation > 0.10:
REJECT setup # Entry price too far from reality
log("P0 FAIL: {ticker} spot={spot_price} entry={entry_price} dev={deviation}")
The final 10 setups must meet geographic diversification requirements:
If the scoring naturally produces 10 US names, Claude Code replaces the lowest-scoring US names with the highest-scoring EU, APAC, and ETF candidates — even if their absolute scores are lower. This prevents home bias and ensures global coverage.
Additionally, in Risk-Off or Early Risk-Off regimes, at least 20% of setups (2 out of 10) must be defensive: short positions, inverse ETFs (SH, SQQQ), or safe havens (GLD, TLT).
Claude Code generates a full HTML report at scanner/YYYYMMDD/index.html using the project's CSS framework (report.css). The report includes:
The report is written directly to the filesystem via Claude Code's file writing capability.
Three sequential commands execute:
# Index the new report
node tools/add_card.js scanner/20260305/index.html
# Commit and push
git add scanner/20260305/ data/scanner.json data/search_data.js
git commit -m "feat: scanner 20260305 — Risk-On, 10 setups A+"
git push origin main
The add_card.js script parses the HTML report, extracts metadata (title, date, tags, tickers), creates a card object, injects it into data/scanner.json, and regenerates the global search index. The git push triggers a GitHub Actions deployment that publishes the report to GitHub Pages within 60 seconds.
For the top 3 A++ setups, Claude Code sends rich Discord embeds:
{
"embeds": [{
"title": "A++ SETUP: NVDA — Momentum Continuation",
"color": 1089337, // #10a569 (green)
"fields": [
{ "name": "Entry Zone", "value": "$875 - $882", "inline": true },
{ "name": "Stop Loss", "value": "$848 (-3.5%)", "inline": true },
{ "name": "TP1 / TP2", "value": "$920 / $965", "inline": true },
{ "name": "R:R", "value": "2.4 : 1", "inline": true },
{ "name": "Score", "value": "91/100 (A++)", "inline": true },
{ "name": "Regime", "value": "Risk-On (82%)", "inline": true },
{ "name": "Thesis", "value": "Pullback to rising 21 EMA with volume contraction. 5 of 8 technical signals aligned. Insider buying $4.2M in last 30 days. AI datacenter capex cycle intact." },
{ "name": "Confirmations", "value": "1. Hold above $870 on daily close\n2. Volume expansion on next green day\n3. SOX index holds 5,200\n4. No VIX spike above 18" },
{ "name": "Invalidations", "value": "1. Daily close below $848 (stop)\n2. Sector rotation out of XLK\n3. Macro regime shift to Risk-Off\n4. Earnings pre-announcement" }
],
"footer": {
"text": "Full report: articles.dailytickers.com/scanner/20260305/"
}
}]
}
For each A++ setup, a persistent price alert is created via the Market Alerts MCP:
Tool: mcp__market-alerts__create_alert
Parameters: {
"symbol": "NVDA",
"condition": "price_between",
"value": [875, 882],
"message": "NVDA entering A++ entry zone ($875-$882). Scanner score: 91/100.",
"channel": "#scanner-alerts",
"expires": "2026-03-12T23:59:59Z" // 7 day expiry
}
The alert fires if/when the price enters the entry zone during market hours. This solves the timing problem: the scanner runs at 23:00, but the optimal entry might be during the next trading session when the price pulls back to the entry zone.
Claude Code exits. The tmux session closes. The Discord bot logs the completion status and duration. Total elapsed time: approximately 27 minutes. The complete pipeline log is saved at /tmp/scanner-YYYYMMDD.log for debugging if needed.
The next morning at 07:00, a separate pipeline runs the "Daily Briefing" which includes a section summarizing last night's scanner highlights.
Let us get your environment set up. By the end of this section, you will have Claude Code installed, all three MCP servers configured, and you will run your first test scan. We will build the full pipeline in subsequent parts, but this foundation must be solid.
You need the following installed before proceeding:
nvm install 22 or from nodejs.org.brew install gh (macOS) or apt install gh (Linux).brew install tmux (macOS) or apt install tmux (Linux).# Install Claude Code globally
npm install -g @anthropic-ai/claude-code
# Verify installation
claude --version
# Expected: claude-code 1.0.x
# Authenticate (interactive — follow browser prompts)
claude auth login
# Test basic functionality
claude -p "What is 2 + 2?"
# Expected: "4" (or a more verbose response ending with 4)
Claude Code stores its configuration in ~/.claude/. The key files are:
~/.claude/config.json — Global settings (model, theme, permissions)~/.claude/CLAUDE.md — Global system instructions (applied to all projects)~/.claude/projects/ — Per-project memory filesMCP servers are configured in ~/.claude/claude_desktop_config.json. This file tells Claude Code which MCP servers to connect to and how to start them. Here is the full configuration for our 3-server setup:
{
"mcpServers": {
"dailytickers": {
"command": "node",
"args": [
"/path/to/dailytickers-mcp/dist/index.js"
],
"env": {
"MW_API_KEY": "your-dailytickers-api-key",
"MW_BASE_URL": "https://api.dailytickers.com",
"MW_CACHE_TTL": "60",
"MW_MAX_CONCURRENT": "10",
"MW_TIMEOUT": "30000"
},
"disabled": false
},
"market-alerts": {
"command": "node",
"args": [
"/path/to/market-alerts-mcp/dist/index.js"
],
"env": {
"ALERTS_DB_PATH": "/path/to/alerts.db",
"ALERTS_CHECK_INTERVAL": "60000",
"DISCORD_WEBHOOK_URL": "https://discord.com/api/webhooks/xxx/yyy"
},
"disabled": false
},
"discord": {
"command": "node",
"args": [
"/path/to/discord-mcp/dist/index.js"
],
"env": {
"DISCORD_TOKEN": "your-discord-bot-token",
"DISCORD_DEFAULT_CHANNEL": "scanner-alerts",
"DISCORD_GUILD_ID": "your-guild-id"
},
"disabled": false
}
}
}
The claude_desktop_config.json file contains API keys and tokens. Never commit this file to version control. Add it to your global .gitignore. Consider using a secrets manager or environment variable references instead of hardcoded values.
The DailyTickers MCP server is the data backbone of the pipeline. It exposes 58 data types through a unified QueryData interface. Here is how to set it up:
# Clone the MCP server
git clone https://github.com/dailytickers-xyz/dailytickers-mcp.git
cd dailytickers-mcp
# Install dependencies
npm install
# Build
npm run build
# Test the server locally (stdio mode)
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js
# Expected: JSON response listing all available tools
# - GetMarketOverview
# - QueryData
# - RunAutoScreener
# - RunScreener
# - GetInstruments
# - LLMAnalysis
# - CalculateOptionsGreeks
# - AnalyzeOptionsStrategy
# - ... (20+ tools total)
The server configuration is controlled via environment variables. Here are the key ones:
| Variable | Default | Description |
|---|---|---|
MW_API_KEY |
(required) | API authentication key |
MW_BASE_URL |
https://api.dailytickers.com |
Gateway API endpoint |
MW_CACHE_TTL |
60 |
Cache TTL in seconds (quotes) |
MW_CACHE_TTL_FINANCIALS |
86400 |
Cache TTL for financials (24h) |
MW_MAX_CONCURRENT |
10 |
Max concurrent API requests |
MW_TIMEOUT |
30000 |
Request timeout in milliseconds |
MW_RETRY_COUNT |
3 |
Number of retries on failure |
MW_LOG_LEVEL |
info |
Logging verbosity (debug, info, warn, error) |
Create the directory structure for your automated trading reports:
# Create the project
mkdir -p automated-trading-reports
cd automated-trading-reports
git init
# Create the directory structure
mkdir -p scanner/{retrospective}
mkdir -p daily
mkdir -p weekly
mkdir -p analyses
mkdir -p data
mkdir -p assets
mkdir -p tools
# Create the CNAME for GitHub Pages
echo "your-domain.xyz" > CNAME
# Initialize the data files
echo "[]" > data/scanner.json
echo "[]" > data/daily.json
echo "[]" > data/weekly.json
echo "[]" > data/analyses.json
echo "var searchData = [];" > data/search_data.js
The CLAUDE.md file is the brain of the operation. It contains all the instructions that Claude Code follows during automated runs. Here is a minimal skeleton to get started — the full version we use in production is 400+ lines:
# CLAUDE.md - Automated Trading Pipeline
## Project Overview
Automated trading research pipeline using Claude Code + MCP.
Publishes scanner reports, daily briefings, and ticker analyses.
## MCP Gateway
Available tools:
- `mcp__dailytickers__GetMarketOverview` — Full market snapshot
- `mcp__dailytickers__QueryData` — 58 data types
- `mcp__dailytickers__RunAutoScreener` — Regime-aware screening
- `mcp__dailytickers__RunScreener` — Custom DSL screening
- `mcp__dailytickers__GetInstruments` — Deep symbol analysis
- `mcp__dailytickers__LLMAnalysis` — DeepSeek second opinion
## Scanner Command ("scan du jour")
### Step 1: Read Retrospectives
Read ALL files in `scanner/retrospective/*/index.html`.
Extract: hit rates, flop tickers, strategy adjustments.
### Step 2: Read Previous Scan
Read the most recent `scanner/YYYYMMDD/index.html`.
Extract the 10 tickers for anti-doublon filter (70% new minimum).
### Step 3: Regime Detection
Call `RunAutoScreener` to detect market regime.
Regimes: Risk-On, Early Risk-On, Neutral, Transition,
Early Risk-Off, Risk-Off.
### Step 4: Multi-Strategy Screening
Run 3 DSL strategies:
1. Oversold: RSI(14) < 35 AND SMA(50) > SMA(200) AND Volume spike
2. Momentum: Close > SMA(20) > SMA(50) AND RSI 55-75 AND ADX > 25
3. Breakout: Close > BB_Upper AND Volume > 2x average
Additional screens: EU (VGK, SAP, ASML...), APAC (EWJ, FXI...),
ETFs (XLF, GLD, TLT, ARKK...).
### Step 5: Scoring (6 Layers)
For top 30 candidates, score across:
1. Technical confluence (>= 4 signals)
2. Fundamental quality (>= 80/100)
3. Social sentiment (aligned with direction)
4. Sector trend (outperforming SPY)
5. Macro regime (compatible)
6. AI conviction (>= 85%)
Composite >= 85 = A+. Top 3 with >= 90 = A++.
### Step 6: Output
- Create `scanner/YYYYMMDD/index.html` (> 40KB)
- Run `node tools/add_card.js scanner/YYYYMMDD/index.html`
- Git add, commit, push
- Send top 3 A++ to Discord
### Constraints
- Geographic diversity: min 5 US + 2 EU + 1 APAC + 2 ETF
- Risk-Off: min 20% defensive setups
- Anti-doublon: min 70% new tickers vs previous scan
- P0 control: reject if entry price > 10% from spot
This file IS the trading strategy. When you want to add a new scoring dimension, change the geographic allocation, adjust the A++ threshold, or modify the output format, you edit this file. No code changes, no deployments, no compilation. Claude Code reads it fresh on every invocation. This is why AI-orchestrated systems are fundamentally different from traditional automation: the strategy lives in natural language, not in compiled code.
With everything configured, let us run a minimal test to verify the pipeline works end-to-end:
# Navigate to your project directory
cd /path/to/automated-trading-reports
# Run a simple market overview query
claude -p "Call GetMarketOverview and summarize the current market regime in 3 sentences."
# Expected output: Something like:
# "The current market regime is Risk-On with 78% confidence.
# VIX is at 15.3 and declining, with market breadth at 65%
# above the 200-day SMA. Leading sectors are Technology and
# Consumer Discretionary."
If this works, your MCP Gateway is correctly configured. Now test a more complex query:
# Test QueryData with multiple data types
claude -p "Query the following data for AAPL and NVDA: quote, trading_signals, support_resistance. \
For each ticker, tell me: current price, RSI(14), nearest support level, nearest resistance level, \
and whether you would consider it a buy, sell, or hold based purely on technicals."
If both tests pass, your data layer is operational. The next test is the full scanner — but we will build that properly in Parts 2-5 of this series.
For automated scheduling, you need a Discord bot that can invoke Claude Code on a timer. Here is the minimal setup:
# Clone the Discord bot
git clone https://github.com/dailytickers-xyz/claude-discord-bot.git
cd claude-discord-bot
# Install dependencies
npm install
# Configure
cp .env.example .env
# Edit .env with your Discord bot token and channel IDs
{
"schedules": [
{
"id": 1,
"name": "Scanner Quotidien",
"cron": "0 23 * * 1-5",
"command": "cd /path/to/automated-trading-reports && claude -p 'scan du jour'",
"channel": "scanner-alerts",
"enabled": true,
"description": "Nightly scanner — weekdays at 23:00"
},
{
"id": 2,
"name": "Daily Briefing",
"cron": "0 7 * * *",
"command": "cd /path/to/automated-trading-reports && claude -p 'analyse daily'",
"channel": "daily-briefing",
"enabled": true,
"description": "Morning briefing — every day at 07:00"
},
{
"id": 3,
"name": "Weekly Report",
"cron": "0 18 * * 0",
"command": "cd /path/to/automated-trading-reports && claude -p 'nouvelle analyse weekly'",
"channel": "weekly-reports",
"enabled": true,
"description": "Weekly market report — Sundays at 18:00"
},
{
"id": 4,
"name": "Scanner Retrospective",
"cron": "0 23 * * 5",
"command": "cd /path/to/automated-trading-reports && claude -p 'rétrospective scanner'",
"channel": "scanner-alerts",
"enabled": true,
"description": "Weekly scanner review — Fridays at 23:00"
}
]
}
# Start the Discord bot
npm start
# Or in a tmux session for persistence
tmux new-session -d -s discord-bot "cd /path/to/claude-discord-bot && npm start"
# Test: In Discord, type:
# > run #1
# This will manually trigger the Scanner task
| Issue | Symptom | Fix |
|---|---|---|
| MCP server not found | Error: Tool mcp__dailytickers__* not available |
Check claude_desktop_config.json path. Run node /path/to/dist/index.js manually to verify the server starts. |
| API key invalid | 401 Unauthorized in server logs |
Verify MW_API_KEY in the config. Check the key has not expired. |
| CLAUDE.md not loaded | Claude Code does not follow scanning instructions | Ensure you are running claude -p from the project root where CLAUDE.md lives. Use pwd to verify. |
| Git push fails | Permission denied (publickey) |
Set up SSH key: ssh-keygen -t ed25519 and add to GitHub. Or use gh auth login for HTTPS. |
| Discord bot offline | Schedules do not fire | Check tmux session: tmux attach -t discord-bot. Look for crash logs. Restart if needed. |
| Scanner report too small | HTML file < 10KB | Claude Code may have been truncated. Increase the max_tokens setting or split the generation into multiple write operations. |
| Rate limiting | 429 Too Many Requests |
Reduce MW_MAX_CONCURRENT to 5. Increase MW_CACHE_TTL to reduce API calls. |
Run through this checklist before proceeding to Part 2:
# 1. Claude Code installed and authenticated
claude --version # Should show 1.0.x
claude -p "hello" # Should respond
# 2. MCP servers configured
claude -p "List all available MCP tools that contain 'market'"
# Should list: GetMarketOverview, QueryData, RunScreener, etc.
# 3. Market data accessible
claude -p "Call GetMarketOverview and tell me the current VIX level"
# Should return a VIX value (e.g., "VIX is at 14.8")
# 4. Git configured
git status # Should show clean working tree
git remote -v # Should show your GitHub remote
# 5. GitHub Pages deployed
gh api repos/{owner}/{repo}/pages
# Should show: "status": "built"
# 6. Directory structure correct
ls scanner/ daily/ weekly/ analyses/ data/ assets/ tools/
# All directories should exist
# 7. CLAUDE.md present
wc -l CLAUDE.md
# Should show 100+ lines (ideally 400+)
If all 7 checks pass, your environment is ready. You have the foundation for a fully automated trading research pipeline.
In this first part, we established the vision, architecture, and foundation of the automated trading pipeline. You now understand:
| Part | Title | What You Will Build |
|---|---|---|
| 1 (this) | The Automated Trading Stack | Architecture overview, environment setup, first MCP test |
| 2 | Real-Time Market Intelligence | Deep dive into the MCP Gateway: all 58 data types, QueryData mastery, caching strategies, rate limiting. Build a market regime detector from scratch. |
| 3 | The AI Analysis Engine | Implement the 6-layer scoring model in CLAUDE.md. Build the full screener pipeline: DSL strategies, multi-strategy screening, data enrichment, composite scoring, AI re-ranking. |
| 4 | The Alert DSL | Build the Market Alerts MCP server. Design the alert condition language. Implement persistent price monitoring with expiry, snooze, and escalation logic. |
| 5 | Discord Pipeline | Build the Discord delivery system: rich embeds, formatted alerts, channel routing, error notifications. Set up the Discord bot scheduler with tmux integration. |
| 6 | Feedback Loop | Build the retrospective system that grades scanner performance weekly. Implement adaptive weight adjustment based on cumulative retrospective data. Close the feedback loop. |
Make sure you have completed the following before starting Part 2:
claude --version works)GetMarketOverview test passes)CLAUDE.md in the project rootPart 2 will be deeply technical — we will explore every one of the 58 data types available through the MCP Gateway, learn how to compose complex queries, build real-time market regime detection, and understand the caching architecture that makes 50+ API calls per scan feasible. It is the data plumbing that makes everything else possible.
Before Part 2, try this exercise: Using only the tools you have now, run the following Claude Code prompt and examine the output:
claude -p "Call RunAutoScreener to detect the current market regime. \
Then call RunScreener with this DSL: \
'RSI(14) < 35 AND SMA(50) > SMA(200) AND Volume > SMA_Volume(20) * 1.5' \
For the top 5 results, call QueryData with types quote,trading_signals. \
For each ticker, provide: name, price, RSI, and whether you think it is \
a genuine oversold reversal or a falling knife. Explain your reasoning."
This is a simplified version of what the full scanner does. If you can get this working, you already understand the core concept: Claude Code as an autonomous research analyst that chains MCP tool calls into a coherent analysis workflow.