The problem with morning research
Before market open, I used to spend 45–60 minutes reading news, checking charts, reviewing positions. Most of it was noise. I was making decisions based on whatever I happened to read last, not a systematic view.
Now I run a 9-wave Claude Code pipeline that takes 90 seconds and covers everything.
Here's the full architecture.
The 9-wave pipeline
Each "wave" is a separate Claude API call with a specific role. Running them sequentially means each wave can reference the previous ones.
Wave 1: Macro Context
Inputs: S&P 500, Nasdaq, VIX, 10Y yield, DXY, oil, recent Fed statements
Output: Macro regime classification (risk-on / risk-off / transitional)
Key levels to watch today
Probability-weighted scenario (bull/base/bear)
Wave 2: Sector Rotation
Inputs: All 11 S&P sectors (XLK, XLF, XLE, XLV, XLI, ...)
Output: Leaders vs laggards this week
Rotation signal (defensive → growth or vice versa)
Sectors with anomalous volume
Wave 3: Technical Scanner
For each holding:
- RSI(14): overbought/oversold flag
- Price vs SMA20, SMA50, SMA200
- MACD crossover status
- Key support/resistance levels
Wave 4: News Sweep
For each ticker in portfolio:
- 48h earnings / guidance / upgrades / downgrades
- Insider activity (buy/sell, size)
- Short interest changes
- Options flow anomalies (from Wave 4b — see below)
Wave 4b: Options Flow (sub-wave)
// This runs as part of Wave 4 for tickers with options activity
const realPCRatio = calculateRealPC(chain, stockPrice);
const lotteryPct = chain.calls.filter(isLottery).length / chain.calls.length;
// Only surface if real P/C ratio shows conviction
if (Math.abs(realPCRatio - 1.0) > 0.3) flagAnomaly(ticker, realPCRatio);
The real/lottery separation (explained in this post) is critical here.
Wave 5: Opportunity Finder
Scan watchlist (not current holdings) for:
- RSI < 35 with volume spike (potential reversal)
- Earnings within 5 days (catalyst)
- Sector alignment with Wave 2 rotation signal
Output: Ranked list of new swing trade candidates
Wave 6: Critic Review
Adversarial role. Rules:
- Challenge every bullish signal from Waves 1-5
- Require 2+ source confirmation for any claim
- Find the counter-evidence first
- What would make this thesis wrong?
This is the most important wave. Without it, the pipeline just confirms whatever I already believe.
Wave 7: Portfolio Simulation
For current holdings:
- Bull scenario (prob: X%): portfolio value = $Y
- Base scenario (prob: X%): portfolio value = $Y
- Bear scenario (prob: X%): portfolio value = $Y
Key risk: position concentration, sector overlap
Wave 8: Deep Connections
Cross-asset analysis:
- What is DXY doing to commodity plays?
- Is yield curve signaling growth/recession risk?
- Hidden correlations in current portfolio
- What smart money rotation implies for individual names
Wave 9: Meta-Critic + Action Plan
Final synthesis:
1. One thing I must act on today
2. One thing I should watch but not trade yet
3. One thing I was wrong about yesterday
4. Positions to reduce / add / hold with conviction levels
The anti-narrative harness
The hardest engineering problem was preventing the system from telling me what I wanted to hear.
Every wave runs under these rules:
1. Numbers required — "P/C 0.55, real call 28%" not "bullish sentiment"
2. Cross-verification — 2+ sources for any price or claim
3. Counter-evidence first — find the bear case before the bull
4. No sell on emotion — check if at bottom, verify with Wave 6 critic before any sell
5. No narrative repetition — each run uses fresh analysis, not yesterday's story
Rule 4 has saved me from panic-selling bottoms twice.
Implementation: TypeScript + Claude SDK
async function runBriefingWave(
wave: number,
prompt: string,
previousWaves: string[]
): Promise<string> {
const context = previousWaves
.map((w, i) => `=== Wave ${i + 1} Output ===\n${w}`)
.join('\n\n');
const response = await claude.messages.create({
model: 'claude-opus-4-5',
max_tokens: 2048,
messages: [{
role: 'user',
content: previousWaves.length > 0
? `${context}\n\n=== Wave ${wave} Task ===\n${prompt}`
: prompt
}]
});
return response.content[0].type === 'text' ? response.content[0].text : '';
}
Total cost per run: ~$0.08–0.12 with Claude Opus (9 waves × ~1500 tokens avg).
At daily runs: ~$2.50/month.
Output format
The final briefing goes to Telegram at 06:00 KST:
📊 MORNING BRIEFING — 2026-05-14
MACRO: Risk-off. VIX 18.4 (+12%). 10Y at 4.52%.
REGIME: Transitional. Watch CPI Thursday.
TOP SIGNAL: XLI P/C 5.32 (outlier). Institutional
hedge on industrials. Not actionable yet — needs
sector confirmation.
PORTFOLIO TODAY:
✓ AAPL: Hold. SMA50 support holding.
⚠ NVDA: RSI 72. Trim 20% if opens above $145.
✗ TEM: Stop-loss at $47.44 — DO NOT lower.
NEW OPPORTUNITIES: CELH (RSI 31, earnings May 18)
CRITIC NOTE: Bull thesis for AAPL depends on
China reopening. That narrative is 60 days stale.
Every field is a number or an action. No vibes.
The skill bundle
All 9 waves + the anti-narrative harness + the options flow scanner are packaged in one Claude Code skill bundle:
AI Investment Skills — $29 one-time on Gumroad →
Free tier: Waves 1-2 (Macro + Sector). Full bundle: All 9 waves.
This is production tooling I run every morning. Not a demo.
What surprised me
The Wave 6 Critic is the most valuable wave and the one I almost skipped. Without adversarial review, the pipeline just produces confident-sounding analysis that matches whatever the macro environment already implies.
The meta-critic output "what was I wrong about yesterday" is where the real learning happens. It forces me to track my own errors rather than just moving on.
Running since March 2026. ~60 morning briefings completed. The portfolio is up, but more importantly, the decision process is systematic.
Top comments (0)