| name | financial-researcher |
| description | Professional-grade autonomous financial analyst leveraging 9 legendary investor perspectives (Buffett, Graham, Lynch, Wood, Soros, Dalio, Burry, Simons, Shiller). Features Python processing layer for institutional-grade composite scores (Piotroski, Altman, Beneish). Guided by DRIVER methodology. For internal use - provides bold, forward-looking analysis. |
| version | 2.0.0 |
Financial Researcher Skill
Quick Reference
/financial-researcher AAPL # Analyze Apple (prompts for mode)
/financial-researcher NVDA --full # Force full analysis
/financial-researcher TSLA --quick # Force quick lookup
ORCHESTRATION OVERVIEW
This skill operates in two modes and follows the DRIVER methodology:
┌─────────────────────────────────────────────────────────────┐
│ USER: /financial-researcher {TICKER} │
├─────────────────────────────────────────────────────────────┤
│ 1. MODE SELECTION │
│ └─> Quick lookup OR Full 9-guru analysis │
├─────────────────────────────────────────────────────────────┤
│ 2. [DISCOVER] - Data Fetching │
│ ├─> Calculate data union based on mode │
│ ├─> Fetch from financialdatasets-mcp │
│ ├─> Fetch from tavily-mcp │
│ └─> Fetch 13-F holdings for relevant gurus │
├─────────────────────────────────────────────────────────────┤
│ 3. [PROCESS] - Python Metrics Calculation ⭐ NEW │
│ ├─> Run processing.run_analysis() on raw data │
│ ├─> Calculate composite scores (Piotroski, Altman, etc) │
│ ├─> Generate quality flags and warnings │
│ └─> Format LLM-ready context for each expert │
├─────────────────────────────────────────────────────────────┤
│ 4. [REPRESENT] - Planning │
│ ├─> Map pre-calculated metrics to each expert │
│ └─> Prepare dispatch parameters │
├─────────────────────────────────────────────────────────────┤
│ 5. [IMPLEMENT] - Expert Dispatch (Full mode only) │
│ └─> Spawn 9 Task subagents IN PARALLEL │
├─────────────────────────────────────────────────────────────┤
│ 6. [VALIDATE] - Cross-Check │
│ └─> Verify all expert outputs, log failures │
├─────────────────────────────────────────────────────────────┤
│ 7. [EVOLVE] - Consolidation │
│ ├─> Tally signals │
│ ├─> Build agreement matrix │
│ └─> Aggregate risks │
├─────────────────────────────────────────────────────────────┤
│ 8. [REFLECT] - Output │
│ ├─> Generate markdown report │
│ └─> Save JSON to ./reports/{ticker}_{date}.json │
└─────────────────────────────────────────────────────────────┘
STEP 1: MODE SELECTION
1.1 Mode Detection
First, check if the user specified a mode flag:
--quick or --fast → Quick Mode
--full or --deep → Full Mode
- No flag → Ask User
1.2 Ask User (if no flag)
Use the AskUserQuestion tool:
question: "Quick lookup or Full analysis for {TICKER}?"
header: "Analysis Mode"
options:
- label: "Quick lookup"
description: "Key metrics and fundamentals only (~30 seconds)"
- label: "Full analysis"
description: "All 9 guru perspectives + consolidation (~3-5 minutes)"
1.3 Mode Comparison
| Aspect | Quick Mode | Full Mode |
|---|
| Data Fetched | Metrics, prices, company_facts | ALL data for all experts |
| Expert Analyses | None | All 9 gurus in parallel |
| 13-F Holdings | None | 6 investors |
| News/Search | Basic context | Finance + news + risk searches |
| Output | Simple metrics table | Full report with all analyses |
| Approximate Time | 30 seconds | 3-5 minutes |
STEP 2: DATA ROUTING LOGIC
2.1 Expert Data Requirements Matrix
Each expert needs specific data. Fetch the UNION once, then route SUBSETS to each expert.
┌──────────────────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ Data Type │ WB │ BG │ PL │ CW │ GS │ RD │ MB │ JS │ RS │
├──────────────────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤
│ income_statements│ ✓ │ ✓ │ ✓ │ ✓ │ │ │ ✓ │ │ ✓ │
│ balance_sheets │ ✓ │ ✓ │ ✓ │ ✓ │ │ ✓ │ ✓ │ │ │
│ cash_flows │ ✓ │ ✓ │ ✓ │ ✓ │ │ ✓ │ ✓ │ │ │
│ financial_metrics│ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │
│ company_facts │ ✓ │ │ ✓ │ ✓ │ │ │ ✓ │ ✓ │ ✓ │
│ prices (stock) │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │
│ prices (SPY) │ │ │ │ │ │ │ │ ✓ │ │
│ prices (sector) │ │ │ │ │ │ │ │ ✓ │ │
│ prices (VIX) │ │ │ │ │ │ │ │ ✓ │ │
│ insider_trades │ ✓ │ │ ✓ │ │ │ │ ✓ │ │ │
│ sec_filings │ ✓ │ ✓ │ ✓ │ ✓ │ │ ✓ │ ✓ │ │ │
│ 13f_berkshire │ ✓ │ │ │ │ │ │ │ │ │
│ 13f_ark │ │ │ │ ✓ │ │ │ │ │ │
│ 13f_soros │ │ │ │ │ ✓ │ │ │ │ │
│ 13f_bridgewater │ │ │ │ │ │ ✓ │ │ │ │
│ 13f_scion │ │ │ │ │ │ │ ✓ │ │ │
│ 13f_renaissance │ │ │ │ │ │ │ │ ✓ │ │
│ news_finance │ ✓ │ │ ✓ │ ✓ │ ✓ │ │ ✓ │ │ ✓ │
│ news_recent │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ │ ✓ │
│ news_risks │ │ │ │ │ │ ✓ │ ✓ │ │ │
│ analyst_estimates│ │ │ │ │ │ │ │ │ ✓ │
└──────────────────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
Legend: WB=Buffett, BG=Graham, PL=Lynch, CW=Wood, GS=Soros, RD=Dalio, MB=Burry, JS=Simons, RS=Shiller
2.2 Data Windows (Extended)
Extended data windows for full business cycle coverage:
| Data Type | Window | Rationale |
|---|
| Income Statements (Annual) | 15 years | Full business cycle + multiple recessions |
| Income Statements (Quarterly) | 20 quarters | Seasonal patterns + recent trend analysis |
| Balance Sheets (Annual) | 15 years | Long-term capital structure evolution |
| Cash Flow Statements (Annual) | 15 years | Cash generation consistency |
| Price History | 5 years | Medium-term technical context |
| 13-F Holdings | 3 years (12 quarters) | Position building/reduction patterns |
| Insider Trades | 100 records | Recent management sentiment |
2.3 Data Fetch Sequence (Full Mode)
Execute these MCP tool calls to gather the full data union:
get_income_statements(ticker="{TICKER}", period="annual", limit=15)
get_income_statements(ticker="{TICKER}", period="quarterly", limit=20)
get_balance_sheets(ticker="{TICKER}", period="annual", limit=15)
get_cash_flows(ticker="{TICKER}", period="annual", limit=15)
get_financial_metrics(ticker="{TICKER}", period="ttm", limit=8)
get_company_facts(ticker="{TICKER}")
get_prices(ticker="{TICKER}", start_date="{FIVE_YEARS_AGO}", end_date="{TODAY}", interval="day")
get_prices(ticker="SPY", start_date="{FIVE_YEARS_AGO}", end_date="{TODAY}", interval="day")
get_prices(ticker="{SECTOR_ETF}", start_date="{FIVE_YEARS_AGO}", end_date="{TODAY}", interval="day")
get_prices(ticker=, start_date=, end_date=, interval=)
get_insider_trades(ticker=, limit=)
get_sec_filings(ticker=, limit=)
report_period_gte =
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(
investor=,
limit=,
report_period_gte=report_period_gte
)
get_institutional_ownership(ticker=, limit=)
search_finance(query=, ticker=, max_results=)
search_news(query=, ticker=, max_age_days=, max_results=)
search_news(query=, ticker=, max_age_days=, max_results=, use_trusted_domains=)
STEP 2B: PYTHON PROCESSING LAYER
After fetching raw data, run the Python processing layer to pre-calculate professional metrics.
2B.1 Processing Layer Location
/processing/
├── __init__.py # Main exports
├── orchestrator.py # Entry point: run_analysis()
├── data_extractor.py # Maps API responses to Python objects
├── metrics_calculator.py # All composite score calculations
└── financial_metrics.py # Legacy calculations (backwards compat)
2B.2 Processing Layer Usage
from processing import run_analysis, format_for_expert
result = run_analysis(
ticker="{TICKER}",
income_statements=income_statements_response,
balance_sheets=balance_sheets_response,
cash_flows=cash_flows_response,
metrics=metrics_response,
price_data=price_response,
holdings_by_investor={
"BERKSHIRE_HATHAWAY_INC": berkshire_holdings,
"ARK_INVESTMENT_MANAGEMENT_LLC": ark_holdings,
"SOROS_FUND_MANAGEMENT_LLC": soros_holdings,
"BRIDGEWATER_ASSOCIATES_LP": bridgewater_holdings,
"SCION_ASSET_MANAGEMENT_LLC": scion_holdings,
"RENAISSANCE_TECHNOLOGIES_LLC": renaissance_holdings,
},
insider_trades=insider_trades_response,
company_facts=company_facts_response,
wacc=0.10,
)
llm_context = result.to_llm_context()
buffett_context = format_for_expert(result, "buffett")
burry_context = format_for_expert(result, "burry")
simons_context = format_for_expert(result, "simons")
shiller_context = format_for_expert(result, "shiller")
2B.3 Metrics Calculated (NOT from API)
The processing layer calculates metrics that financialdatasets.ai does NOT provide:
| Category | Metrics | Primary Users |
|---|
| Composite Scores | | |
| Piotroski F-Score | 9-point financial strength (0-9) | Graham, Buffett, Dalio, Burry |
| Altman Z-Score | Bankruptcy prediction (zones) | Graham, Dalio, Burry |
| Ohlson O-Score | Bankruptcy probability (0-1) | Dalio, Burry |
| Beneish M-Score | Earnings manipulation (-2.22 threshold) | Burry |
| Magic Formula | Greenblatt ROIC + Earnings Yield | Buffett |
| Quality Metrics | | |
| Sloan Accrual Ratio | Earnings quality (-10% to +10% safe) | Burry |
| Gross Profitability | Novy-Marx GP/Assets | Wood |
| FCF Conversion | FCF/EBITDA (>80% healthy) | Buffett |
| Value Creation | | |
| Owner Earnings | Buffett's true cash to owners | Buffett |
| EVA | NOPAT - (IC × WACC) | Dalio |
| Decomposition | | |
| DuPont 5-Factor | ROE breakdown (tax, interest, margin, turnover, leverage) | All |
| Growth | | |
| Sustainable Growth Rate | ROE × Retention Ratio | Lynch, Wood |
| Trend Analysis | Accelerating/Decelerating patterns | Lynch, Wood |
| Shareholder Returns | | |
| Total Shareholder Yield | Dividend + Buyback + Debt Paydown | Buffett |
2B.4 Metrics FROM API (Don't Recalculate)
financialdatasets.ai already provides these 48+ metrics - use directly:
- Valuation: P/E, P/B, P/S, EV/EBITDA, EV/Revenue, PEG
- Profitability: ROE, ROA, ROIC, Gross Margin, Operating Margin, Net Margin
- Liquidity: Current Ratio, Quick Ratio, Cash Ratio
- Leverage: Debt/Equity, Debt/Assets, Interest Coverage
- Efficiency: Asset Turnover, Inventory Turnover, DSO
- Growth: Revenue Growth, EPS Growth, FCF Growth
- Per Share: EPS, Book Value, FCF, Dividends
2B.5 Processing Layer Output Structure
@dataclass
class AnalysisResult:
ticker: str
company_name: str
analysis_date: str
company_data: CompanyData
comprehensive_analysis: ComprehensiveAnalysis
summary: Dict[str, Any]
data_quality_notes: List[str]
def to_llm_context(self) -> str:
"""Format all metrics as LLM-ready text context."""
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary for JSON serialization."""
@dataclass
class ComprehensiveAnalysis:
ticker: str
piotroski: MetricResult
altman_z: MetricResult
ohlson_o: MetricResult
beneish_m: MetricResult
magic_formula: MetricResult
sloan_accrual: MetricResult
gross_profitability: MetricResult
fcf_conversion: MetricResult
shareholder_yield: MetricResult
eva: MetricResult
owner_earnings: MetricResult
dupont: MetricResult
sustainable_growth: MetricResult
revenue_trend: MetricResult
earnings_trend: MetricResult
red_flags: []
green_flags: []
overall_quality_score:
:
value:
interpretation:
components: [, ]
flags: []
data_quality:
2B.6 Example LLM Context Output
# Pre-Calculated Metrics for AAPL
Company: Apple Inc
Analysis Date: 2026-01-23
## Composite Scores
### Piotroski F-Score: 8/9
Interpretation: Very Strong - High quality, consider buying
Components: ROA+, CFO+, ΔROA+, Accruals+, ΔLeverage+, ΔLiquidity+, NoDilution+, ΔMargin+, ΔTurnover-
### Altman Z-Score: 4.52
Interpretation: Safe Zone - Low bankruptcy risk
### Beneish M-Score: -2.85
Interpretation: Unlikely Manipulator (M=-2.85)
## Quality Metrics
### Sloan Accrual Ratio: -3.2%
Interpretation: Safe Zone - Quality earnings backed by cash
### FCF Conversion: 95.2%
Interpretation: Healthy - Strong cash conversion
### Gross Profitability (GP/Assets): 38.5%
Interpretation: Excellent gross profitability
## Value Creation
### Owner Earnings: $98.5B
Per Share: $6.42
Interpretation: Owner earnings exceed net income - high quality
### Economic Value Added (EVA): $72.3B
Interpretation: Creating value: $72.3B above cost of capital
## Shareholder Returns
### Total Shareholder Yield: 4.8%
- Dividend Yield: 0.5%
- Buyback Yield: 4.1%
- Debt Paydown Yield: 0.2%
## ROE Decomposition (DuPont 5-Factor)
ROE: 147.2%
- Tax Burden: 0.84
- Interest Burden: 0.99
- EBIT Margin: 30.1%
- Asset Turnover: 1.15
- Leverage: 5.12x
Analysis: ROE driven by strong margins, efficient asset use, leverage
## Sustainable Growth
Sustainable Growth Rate: 143.2%
Interpretation: High sustainable growth - can grow rapidly internally
## ✓ GREEN FLAGS
- Very strong Piotroski F-Score (8/9)
- Safe Altman Z-Score zone
- Low manipulation risk (Beneish < -2.22)
- Excellent FCF conversion (>80%)
- Positive EVA - creating shareholder value
## Overall Quality Score: 87/100
2.3 Data Fetch Sequence (Quick Mode)
Minimal data for quick lookup:
get_financial_metrics(ticker="{TICKER}", period="ttm", limit=1)
get_company_facts(ticker="{TICKER}")
get_prices(ticker="{TICKER}", start_date="{90_DAYS_AGO}", end_date="{TODAY}", interval="day")
search_finance(query="{TICKER} stock", ticker="{TICKER}", max_results=3)
2.5 Data Subset Routing
After fetching raw data and running Python processing, route pre-calculated metrics to each expert:
const calculated = {
piotroski: calculate_piotroski(financials),
altman: calculate_altman_z(financials, market_data),
beneish: calculate_beneish_m(financials),
owner_earnings: calculate_owner_earnings(financials),
roic: calculate_roic(financials),
graham: calculate_graham_valuation(financials, price),
valuation: calculate_valuation_metrics(financials, market_data),
growth: calculate_growth_analysis(financials)
};
const dataSubsets = {
warren_buffett: {
owner_earnings: calculated.owner_earnings,
roic: calculated.roic,
piotroski: calculated.piotroski,
valuation: calculated.valuation,
growth: calculated.growth,
current_price: latest_price,
market_cap: company_facts.market_cap,
filings_content: sec_filings,
: [...news_finance, ...news_recent],
: berkshire_holdings.( h. === ticker)
},
: {
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: sec_filings,
: news_recent
},
: {
: calculated.,
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: sec_filings,
: [...news_finance, ...news_recent],
: insider_trades
},
: {
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: sec_filings,
: [...news_finance, ...news_recent],
: ark_holdings.( h. === ticker)
},
: {
: calculated.,
: latest_price,
: company_facts.,
: prices,
: ,
: [...news_finance, ...news_recent],
: soros_holdings.( h. === ticker)
},
: {
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: sec_filings,
: [...news_recent, ...news_risks],
: bridgewater_holdings.( h. === ticker)
},
: {
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: sec_filings,
: [...news_finance, ...news_recent, ...news_risks],
: insider_trades,
: scion_holdings.( h. === ticker)
},
: {
: calculated.,
: latest_price,
: company_facts.,
: prices,
: spy_prices,
: sector_prices,
: vix_data,
: ,
: ,
: renaissance_holdings.( h. === ticker)
},
: {
: calculated.,
: calculated.,
: latest_price,
: company_facts.,
: prices,
: ,
: [...news_finance, ...news_recent],
: analyst_estimates,
:
}
};
STEP 3: SUBAGENT DISPATCH SYSTEM
3.1 Dispatch Pattern
CRITICAL: Spawn ALL 9 experts in a SINGLE message with multiple Task tool calls for true parallelism.
Use Task tool with:
subagent_type: "general-purpose"
description: "{Guru Name} analysis of {TICKER}"
prompt: [Constructed from expert template + injected data]
3.2 Expert Prompt Construction
For each expert, construct the prompt by:
-
Load the expert template from experts/{guru_id}.md
-
Replace template variables with pre-calculated data:
{TICKER} → actual ticker symbol
{COMPANY_NAME} → from company_facts
{current_price} → latest price
{market_cap} → formatted market cap
Pre-calculated Metrics (from Python processing layer):
{piotroski_json} → Piotroski F-Score with component breakdown
{altman_json} → Altman Z-Score with zone classification
{beneish_json} → Beneish M-Score with red flags
{owner_earnings_json} → Owner Earnings calculation
{roic_json} → ROIC with interpretation
{graham_json} → Graham Number and NCAV
{valuation_json} → PEG, EV/EBITDA, FCF yield, etc.
{growth_json} → CAGR, trends, acceleration
Context Data:
{filings_content} → formatted SEC filings
{news_items} → formatted news items
{holdings_json} → 13-F holdings for this guru (with 3-year history)
3.3 Parallel Dispatch Call
Execute this SINGLE message with 9 Task tool invocations:
// DISPATCH ALL 9 EXPERTS IN PARALLEL - SINGLE MESSAGE
Task({
subagent_type: "general-purpose",
description: "Warren Buffett analysis of {TICKER}",
prompt: constructedBuffettPrompt
})
Task({
subagent_type: "general-purpose",
description: "Ben Graham analysis of {TICKER}",
prompt: constructedGrahamPrompt
})
Task({
subagent_type: "general-purpose",
description: "Peter Lynch analysis of {TICKER}",
prompt: constructedLynchPrompt
})
Task({
subagent_type: "general-purpose",
description: "Cathie Wood analysis of {TICKER}",
prompt: constructedWoodPrompt
})
Task({
subagent_type: "general-purpose",
description: "George Soros analysis of {TICKER}",
prompt: constructedSorosPrompt
})
Task({
subagent_type: "general-purpose",
description: "Ray Dalio analysis of {TICKER}",
prompt: constructedDalioPrompt
})
Task({
subagent_type: "general-purpose",
description: "Michael Burry analysis of {TICKER}",
prompt: constructedBurryPrompt
})
Task({
subagent_type: "general-purpose",
description: "Jim Simons analysis of {TICKER}",
prompt: constructedSimonsPrompt
})
Task({
subagent_type: "general-purpose",
description: "Robert Shiller analysis of {TICKER}",
prompt: constructedShillerPrompt
})
3.4 Response Collection
After parallel dispatch:
- Collect all 9 responses
- Parse JSON from each expert's response
- Validate schema compliance
- Handle any failures gracefully (continue with N-1 experts)
STEP 4: DRIVER WORKFLOW EXECUTION
4.1 [DISCOVER] Phase
Output to user:
═══════════════════════════════════════════════════════════
[DISCOVER] Starting analysis for {TICKER}
═══════════════════════════════════════════════════════════
[DISCOVER] Fetching financial statements (15 years)...
[DISCOVER] Fetching metrics and market data...
[DISCOVER] Fetching SEC filings...
[DISCOVER] Fetching 13-F institutional holdings (3 years)...
[DISCOVER] Fetching news and market context...
[DISCOVER] Data collection complete.
Data Summary:
- Financial Statements: {N} annual + {N} quarterly periods
- Metrics: {N} metrics available
- Price History: {N} days (5 years)
- SEC Filings: {N} filings
- 13-F Holdings: {N} relevant positions found
- News Articles: {N} items
Actions:
- Execute data fetch sequence based on mode
- Store all data in structured format
- Log any missing data points
- Calculate data quality score
4.2 [PROCESS] Phase ⭐ NEW
Output to user:
═══════════════════════════════════════════════════════════
[PROCESS] Calculating professional metrics
═══════════════════════════════════════════════════════════
[PROCESS] Running Python processing layer...
[PROCESS] Calculating composite scores:
├─ Piotroski F-Score: {X}/9 ({interpretation})
├─ Altman Z-Score: {X} ({zone})
├─ Beneish M-Score: {X} ({interpretation})
└─ Ohlson O-Score: {X}% probability
[PROCESS] Calculating quality metrics:
├─ Sloan Accrual: {X}%
├─ FCF Conversion: {X}%
└─ Gross Profitability: {X}%
[PROCESS] Value creation analysis:
├─ Owner Earnings: ${X}
└─ EVA: ${X}
[PROCESS] Generating expert contexts...
[PROCESS] Pre-calculation complete.
Quality Summary:
- Overall Quality Score: {X}/100
- Red Flags: {N}
- Green Flags: {N}
Actions:
- Call
run_analysis() from processing layer
- Extract composite scores and quality metrics
- Identify red/green flags
- Generate expert-specific contexts using
format_for_expert()
- Log any calculation warnings
Python Code:
from processing import run_analysis, format_for_expert
result = run_analysis(
ticker=ticker,
income_statements=income_statements,
balance_sheets=balance_sheets,
cash_flows=cash_flows,
metrics=metrics,
price_data=price_data,
holdings_by_investor=holdings_by_investor,
insider_trades=insider_trades,
company_facts=company_facts,
)
analysis = result.comprehensive_analysis
print(f"Piotroski F-Score: {analysis.piotroski.value}/9")
print(f"Altman Z-Score: {analysis.altman_z.value}")
print(f"Overall Quality: {analysis.overall_quality_score}/100")
expert_contexts = {
"buffett": format_for_expert(result, "buffett"),
"graham": format_for_expert(result, "graham"),
"lynch": format_for_expert(result, "lynch"),
"wood": format_for_expert(result, "wood"),
"soros": format_for_expert(result, "soros"),
"dalio": format_for_expert(result, "dalio"),
"burry": format_for_expert(result, "burry"),
"simons": format_for_expert(result, "simons"),
"shiller": format_for_expert(result, "shiller"),
}
4.4 [REPRESENT] Phase
Output to user:
═══════════════════════════════════════════════════════════
[REPRESENT] Planning analysis approach
═══════════════════════════════════════════════════════════
[REPRESENT] Mode: {FULL|QUICK}
[REPRESENT] Company: {COMPANY_NAME} ({TICKER})
[REPRESENT] Market Cap: ${MARKET_CAP}
[REPRESENT] Current Price: ${CURRENT_PRICE}
Pre-Calculated Metrics Summary:
├─ Piotroski F-Score: {X}/9 ({interpretation})
├─ Altman Z-Score: {X} ({zone})
├─ Quality Score: {X}/100
└─ Red Flags: {N} | Green Flags: {N}
Experts to dispatch:
├─ Warren Buffett (moat, owner earnings, FCF conversion)
├─ Ben Graham (margin of safety, Z-Score, NCAV)
├─ Peter Lynch (PEG, sustainable growth, trends)
├─ Cathie Wood (disruption, gross profitability)
├─ George Soros (reflexivity, sentiment)
├─ Ray Dalio (cycles, stress testing, EVA)
├─ Michael Burry (M-Score, accruals, forensics)
├─ Jim Simons (quant factors, statistical patterns)
└─ Robert Shiller (CAPE, behavioral economics)
[REPRESENT] Expert contexts prepared from processing layer.
Actions:
- Validate ticker and data availability
- Use
format_for_expert() to prepare expert-specific contexts
- Build the expert prompts with pre-calculated metrics
- Log the analysis plan
4.5 [IMPLEMENT] Phase (Full Mode Only)
Output to user:
═══════════════════════════════════════════════════════════
[IMPLEMENT] Dispatching expert analysts (parallel execution)
═══════════════════════════════════════════════════════════
[IMPLEMENT] → Spawning Warren Buffett analysis...
[IMPLEMENT] → Spawning Ben Graham analysis...
[IMPLEMENT] → Spawning Peter Lynch analysis...
[IMPLEMENT] → Spawning Cathie Wood analysis...
[IMPLEMENT] → Spawning George Soros analysis...
[IMPLEMENT] → Spawning Ray Dalio analysis...
[IMPLEMENT] → Spawning Michael Burry analysis...
[IMPLEMENT] → Spawning Jim Simons analysis...
[IMPLEMENT] → Spawning Robert Shiller analysis...
[IMPLEMENT] All 9 experts dispatched. Awaiting results...
Actions:
- Send single message with 9 parallel Task calls
- Wait for all responses
- Log progress as each completes
Post-dispatch output:
[IMPLEMENT] ✓ Warren Buffett complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Ben Graham complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Peter Lynch complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Cathie Wood complete (signal: {SIGNAL})
[IMPLEMENT] ✓ George Soros complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Ray Dalio complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Michael Burry complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Jim Simons complete (signal: {SIGNAL})
[IMPLEMENT] ✓ Robert Shiller complete (signal: {SIGNAL})
[IMPLEMENT] All expert analyses received.
4.6 [VALIDATE] Phase
Output to user:
═══════════════════════════════════════════════════════════
[VALIDATE] Cross-checking expert outputs
═══════════════════════════════════════════════════════════
[VALIDATE] Checking JSON schema compliance... {N}/9 valid
[VALIDATE] Checking for missing required fields... OK
[VALIDATE] Identifying contradictory assumptions...
Assumption Check:
- Growth rate assumptions: Range {X%} to {Y%}
- Valuation method disagreements: {N} found
- Risk assessment divergence: {HIGH|MEDIUM|LOW}
[VALIDATE] Consensus strength: {STRONG|MODERATE|WEAK|DIVIDED}
Actions:
- Validate each expert's JSON output
- Check for required fields
- Identify contradictory assumptions
- Flag if consensus is suspiciously uniform (potential groupthink)
4.7 [EVOLVE] Phase
Output to user:
═══════════════════════════════════════════════════════════
[EVOLVE] Consolidating insights
═══════════════════════════════════════════════════════════
[EVOLVE] Signal distribution:
Bullish: {N} experts ({X}%)
Neutral: {N} experts ({X}%)
Bearish: {N} experts ({X}%)
[EVOLVE] Computing confidence-weighted consensus...
[EVOLVE] Building agreement matrix...
[EVOLVE] Aggregating risk factors...
[EVOLVE] Extracting common themes...
[EVOLVE] Computing price target consensus...
[EVOLVE] Consolidation complete.
Actions:
Step 1: Tally Signals
const signalTally = {
bullish: experts.filter(e => e.signal === "bullish").length,
neutral: experts.filter(e => e.signal === "neutral").length,
bearish: experts.filter(e => e.signal === "bearish").length
};
const bullishExperts = experts.filter(e => e.signal === "bullish").map(e => e.expert);
const neutralExperts = experts.filter(e => e.signal === "neutral").map(e => e.expert);
const bearishExperts = experts.filter(e => e.signal === "bearish").map(e => e.expert);
Step 2: Compute Confidence-Weighted Signal
const weightedScore = experts.reduce((sum, e) => {
const signalValue = { bullish: 1, neutral: 0, bearish: -1 }[e.signal];
return sum + (signalValue * e.confidence);
}, 0) / experts.reduce((sum, e) => sum + e.confidence, 0);
const confidenceWeightedScore = Math.round((weightedScore + 1) * 50);
const confidenceWeightedSignal =
confidenceWeightedScore > 60 ? "bullish" :
confidenceWeightedScore < 40 ? "bearish" : "neutral";
Step 3: Build Agreement Matrix
Track which experts mentioned which themes and whether positively or negatively.
const TRACKED_THEMES = [
"Strong moat / Competitive advantage",
"Management quality",
"Valuation attractive",
"Growth potential",
"Balance sheet strength",
"Cash flow quality",
"Accounting concerns",
"Macro/cycle headwinds",
"Disruption risk",
"Insider activity signal"
];
const agreementMatrix = {};
for (const theme of TRACKED_THEMES) {
agreementMatrix[theme] = {};
for (const expert of experts) {
const sentiment = analyzeThemeSentiment(expert, theme);
agreementMatrix[theme][expert.expert] = sentiment;
}
}
const agreementThemes = TRACKED_THEMES.filter(theme =>
Object.values(agreementMatrix[theme]).filter(s => s === "positive").length >= 3
).map(theme => ({
theme,
: .(agreementMatrix[theme])
.( s === )
.( e),
: .(agreementMatrix[theme]).( s === ).
}));
divergenceThemes = .( {
sentiments = .(agreementMatrix[theme]);
sentiments.() && sentiments.();
}).( ({
theme,
: (experts, theme),
: (experts, theme),
: {
: .(agreementMatrix[theme])
.( s === ).( e),
: .(agreementMatrix[theme])
.( s === ).( e)
}
}));
Step 4: Aggregate Risks
Union all key_risks arrays, deduplicate similar risks, track attribution.
const allRisksRaw = experts.flatMap(e =>
e.key_risks.map(risk => ({ risk, expert: e.expert }))
);
const allRisks = deduplicateRisks(allRisksRaw);
allRisks.sort((a, b) => b.flagged_by.length - a.flagged_by.length);
allRisks.forEach(r => {
r.severity = r.flagged_by.length >= 4 ? "high" :
r.flagged_by.length >= 2 ? "medium" : "low";
});
function deduplicateRisks(risks) {
const deduplicated = [];
for (const { risk, expert } of risks) {
const existing = deduplicated.find(r =>
similarityScore(r., risk) >
);
(existing) {
(!existing..(expert)) {
existing..(expert);
}
} {
deduplicated.({ risk, : [expert] });
}
}
deduplicated;
}
Step 5: Compute Price Target Consensus
const priceTargets = experts.map(e => ({
expert: e.expert,
buy_at: parsePriceString(e.would_buy_at),
target: parsePriceFromOutlook(e.forward_outlook.price_target),
sell_at: parsePriceString(e.would_sell_at)
})).filter(p => p.target !== null);
const consensusPriceTargets = {
consensus_buy_below: median(priceTargets.map(p => p.buy_at).filter(Boolean)),
consensus_target: median(priceTargets.map(p => p.target).filter(Boolean)),
consensus_sell_above: median(priceTargets.map(p => p.sell_at).filter(Boolean)),
range_low: Math.min(...priceTargets.( p.).()),
: .(...priceTargets.( p.).())
};
Step 6: Synthesize Bull and Bear Cases
const bullCaseSummary = bullishExperts.length > 0 ?
synthesizeCaseFromExperts(
experts.filter(e => bullishExperts.includes(e.expert)),
"bullish"
) : "No experts are currently bullish on this stock.";
const bearCaseSummary = bearishExperts.length > 0 ?
synthesizeCaseFromExperts(
experts.filter(e => bearishExperts.includes(e.expert)),
"bearish"
) : "No experts are currently bearish on this stock.";
const neutralCaseSummary = neutralExperts.length > 0 ?
synthesizeCaseFromExperts(
experts.filter(e => neutralExperts.includes(e.expert)),
"neutral"
) : "No experts are currently neutral on this stock.";
Step 7: Final Consolidation Object
const consolidation = {
signal_tally: signalTally,
confidence_weighted_signal: confidenceWeightedSignal,
confidence_weighted_score: confidenceWeightedScore,
agreement_themes: agreementThemes,
divergence_themes: divergenceThemes,
all_risks: allRisks,
bull_case_summary: bullCaseSummary,
bear_case_summary: bearCaseSummary,
neutral_case_summary: neutralCaseSummary,
price_targets: consensusPriceTargets,
agreement_matrix: agreementMatrix
};
4.8 [REFLECT] Phase
Output to user:
═══════════════════════════════════════════════════════════
[REFLECT] Generating final report
═══════════════════════════════════════════════════════════
[REFLECT] Formatting markdown report...
[REFLECT] Populating executive summary...
[REFLECT] Formatting 9 expert analyses...
[REFLECT] Building agreement matrix visualization...
[REFLECT] Saving JSON to ./reports/{TICKER}_{DATE}.json
[REFLECT] Analysis complete.
═══════════════════════════════════════════════════════════
Actions:
Step 1: Format Expert Signal Table
const expertSignalTable = experts.map(e => {
const signalEmoji = { bullish: "🟢", neutral: "🟡", bearish: "🔴" }[e.signal];
const keyInsight = extractKeyInsight(e.thesis, 50);
return `| ${formatExpertName(e.expert)} | ${signalEmoji} ${e.signal} | ${e.confidence}% | ${keyInsight} |`;
}).join("\n");
experts.sort((a, b) => b.confidence - a.confidence);
Step 2: Format Agreement Matrix Visualization
const matrixHeaders = ["Theme", "WB", "BG", "PL", "CW", "GS", "RD", "MB", "JS", "RS"];
const matrixDivider = "|" + matrixHeaders.map(h => "---").join("|") + "|";
const matrixRows = Object.entries(agreementMatrix).map(([theme, experts]) => {
const cells = ["WB", "BG", "PL", "CW", "GS", "RD", "MB", "JS", "RS"].map(abbrev => {
const expertId = abbreviationToExpertId(abbrev);
const sentiment = experts[expertId];
return sentiment === "positive" ? "✓" :
sentiment === "negative" ? "✗" : "·";
});
return `| ${theme} | ${cells.join()} |`;
}).();
Step 3: Format Price Target Table
const priceTargetTable = experts.map(e => {
const buy = e.would_buy_at || "N/A";
const target = e.forward_outlook.price_target || "N/A";
const sell = e.would_sell_at || "N/A";
return `| ${formatExpertName(e.expert)} | ${buy} | ${target} | ${sell} |`;
}).join("\n");
Step 4: Generate Signal Distribution Bar
function generateSignalBar(count, total, char = "█") {
const barLength = Math.round((count / total) * 20);
return char.repeat(barLength);
}
const bullishBar = generateSignalBar(signalTally.bullish, 9);
const neutralBar = generateSignalBar(signalTally.neutral, 9);
const bearishBar = generateSignalBar(signalTally.bearish, 9);
Step 5: Format Each Expert Section
For each expert, format using this structure:
### {Expert Display Name}
**Signal:** {emoji} {signal} | **Confidence:** {confidence}%
> **Thesis:** {thesis}
#### Forward Outlook
| Aspect | Assessment |
|--------|------------|
| **Prediction** | {prediction} |
| **Timeline** | {timeline} |
| **Price Target** | {price_target} |
| **Catalyst** | {catalyst} |
#### Analysis Breakdown
{For each criterion in expert.analysis:}
**{Criterion Name}:** {summary with key data points}
- Score: {score}/10
- Key finding: {most important reasoning point}
#### Risk Assessment
**Key Risks Identified:**
1. {risk1}
2. {risk2}
3. {risk3}
**What Would Change This View:**
- {change1}
- {change2}
#### Holdings Context
| Metric | Value |
|--------|-------|
| **Current Position** | {current_position} |
| **Recent Changes** | {recent_changes} |
| **Signal from Actions** | {signal_from_actions} |
#### Entry/Exit Levels
- **Would buy aggressively at:** {would_buy_at}
- **Would start selling at:** {would_sell_at}
#### Private Assessment
> *{private_assessment}*
Step 6: Assemble Final Report
Use the template from templates/consolidated_report_template.md and replace all placeholders:
const finalReport = reportTemplate
.replace("{TICKER}", ticker)
.replace("{DATE}", formatDate(new Date()))
.replace("{MODE}", "Full")
.replace("{VERSION}", "1.0.0")
.replace("{BULLISH_COUNT}", signalTally.bullish)
.replace("{NEUTRAL_COUNT}", signalTally.neutral)
.replace("{BEARISH_COUNT}", signalTally.bearish)
.replace("{WEIGHTED_SIGNAL}", confidenceWeightedSignal)
.replace("{WEIGHTED_SCORE}", confidenceWeightedScore)
.replace("{AGREEMENT_SUMMARY}", agreementThemes[0]?.theme || "No strong agreement")
.replace("{DIVERGENCE_SUMMARY}", divergenceThemes[0]?.theme || "No major divergence")
.replace("{CURRENT_PRICE}", currentPrice)
.replace("{CONSENSUS_TARGET}", consensusPriceTargets.consensus_target)
.replace("{BULL_CASE_SUMMARY}", bullCaseSummary)
.replace("{BEAR_CASE_SUMMARY}", bearCaseSummary)
.(, neutralCaseSummary)
.(, bullishExperts.(formatExpertName).())
.(, bearishExperts.(formatExpertName).())
.(, neutralExperts.(formatExpertName).())
.(, expertSignalTable)
.(, matrixRows)
.(, priceTargetTable)
;
Step 7: Save JSON Output
const jsonReport = {
meta: {
ticker: ticker,
company_name: companyName,
generated_at: new Date().toISOString(),
mode: "full",
skill_version: "1.0.0",
current_price: currentPrice,
market_cap: marketCap
},
data_sources: {
financial_data: { source: "financialdatasets.ai", retrieved_at: dataFetchTime },
news: { source: "tavily", max_age_days: 14, article_count: newsCount },
sec_filings: secFilingsSummary,
thirteenf_holdings: holdingsSummary
},
experts: {
warren_buffett: expertOutputs.warren_buffett,
ben_graham: expertOutputs.ben_graham,
peter_lynch: expertOutputs.peter_lynch,
cathie_wood: expertOutputs.cathie_wood,
george_soros: expertOutputs.george_soros,
ray_dalio: expertOutputs.ray_dalio,
michael_burry: expertOutputs.michael_burry,
jim_simons: expertOutputs.jim_simons,
robert_shiller: expertOutputs.robert_shiller
},
consolidation: consolidation,
: quickMetrics
};
reportPath = ;
Step 8: Display Report to User
Output the formatted markdown report directly to the user. The report should:
- Start with the executive summary
- Show signal distribution visually
- Include all 9 expert analyses in full
- End with consolidation, risks, and methodology notes
STEP 5: OUTPUT GENERATION
5.1 Quick Mode Output
Quick mode still runs the Python processing layer but skips expert dispatch.
# {TICKER} Quick Lookup
**{COMPANY_NAME}** | ${CURRENT_PRICE} | Market Cap: ${MARKET_CAP}
## Composite Scores (Pre-Calculated)
| Score | Value | Interpretation |
|-------|-------|----------------|
| **Piotroski F-Score** | {X}/9 | {interpretation} |
| **Altman Z-Score** | {X} | {zone} |
| **Beneish M-Score** | {X} | {manipulation_risk} |
| **Overall Quality** | {X}/100 | {quality_interpretation} |
## Key Metrics (from API)
| Metric | Value | Assessment |
|--------|-------|------------|
| P/E Ratio | {PE} | {vs_sector} |
| P/B Ratio | {PB} | |
| PEG Ratio | {PEG} | |
| ROE | {ROE}% | |
| ROIC | {ROIC}% | |
| Debt/Equity | {DE} | |
| Revenue Growth | {RG}% | YoY |
| FCF Conversion | {FCF_CONV}% | |
| Free Cash Flow | ${FCF} | |
## Quality Indicators
### Green Flags ✓
{list of green_flags from processing layer}
### Red Flags ⚠️
{list of red_flags from processing layer}
## Price Context
- **Current:** ${CURRENT_PRICE}
- **52-week Range:** ${LOW} - ${HIGH}
- **Distance from High:** {X}%
## Quick Assessment
{2-3 sentence summary based on composite scores and flags}
---
*Quick lookup generated by financial-researcher v2.0.0*
*Processing layer: Piotroski, Altman, Beneish, Quality Score*
*For full 9-guru analysis, run with --full flag*
5.2 Full Mode Output
Use the template from templates/consolidated_report_template.md
Key sections:
- Executive Summary with signal tally
- Each of 9 expert analyses IN FULL
- Consolidation with agreement matrix
- All risks aggregated
- Price target summary
- Data sources and methodology
5.3 JSON Output Structure
Save to ./reports/{TICKER}_{YYYY-MM-DD}.json:
{
"meta": {
"ticker": "{TICKER}",
"company_name": "{COMPANY_NAME}",
"generated_at": "{ISO_DATETIME}",
"mode": "full",
"skill_version": "2.0.0",
"processing_version": "2.0.0",
"current_price": {PRICE},
"market_cap": {MARKET_CAP}
},
"data_sources": {
"financial_data": {
"source": "financialdatasets.ai",
"retrieved_at": "{ISO_DATETIME}",
"periods_annual": 15,
N
...
STEP 6: ERROR HANDLING
6.1 MCP Server Unavailable
[DISCOVER] ⚠️ financialdatasets-mcp not responding
[DISCOVER] Attempting WebFetch fallback...
Fallback: Use WebFetch to call API directly:
URL: https://api.financialdatasets.ai/{endpoint}
Headers: X-API-KEY: {from environment}
6.2 Expert Subagent Failure
[IMPLEMENT] ⚠️ {Guru Name} analysis failed: {error_message}
[IMPLEMENT] Continuing with remaining {N} experts...
Actions:
- Log the error
- Continue with remaining experts
- Note missing expert in final output
- Adjust consolidation to work with available data
6.3 Missing Data
[DISCOVER] ⚠️ 13-F data not available for SCION_ASSET_MANAGEMENT_LLC
[DISCOVER] Michael Burry will analyze without holdings context
Actions:
- Pass null/empty for missing data
- Experts should handle gracefully and note in their analysis
- Adjust confidence accordingly
6.4 Invalid Ticker
[DISCOVER] ❌ Ticker "{X}" not found
[DISCOVER] Suggestions: Did you mean {SIMILAR_TICKER}?
Actions:
- Inform user
- Suggest similar tickers if possible
- Ask user to confirm or provide correct ticker
6.5 Rate Limits
[DISCOVER] ⚠️ API rate limit reached for financialdatasets.ai
[DISCOVER] Waiting 60 seconds before retry...
Actions:
- Implement exponential backoff
- Inform user of delay
- Continue when rate limit resets
THE 9 GURUS
Value Investors
| Guru | Focus | Key Criteria | 13-F Source |
|---|
| Warren Buffett | Moat, intrinsic value, owner earnings | Circle of competence, moat durability, margin of safety | BERKSHIRE_HATHAWAY_INC |
| Ben Graham | Margin of safety, asset values | 7 defensive screens, NCAV, EPV | Historical reference |
Growth Investors
| Guru | Focus | Key Criteria | 13-F Source |
|---|
| Peter Lynch | GARP, business story | PEG ratio, stock classification, tenbagger potential | Historical reference |
| Cathie Wood | Disruption, TAM expansion | Wright's Law, 5-year model, innovation platforms | ARK_INVESTMENT_MANAGEMENT_LLC |
Macro/Cycles
| Guru | Focus | Key Criteria | 13-F Source |
|---|
| George Soros | Reflexivity, sentiment | Boom-bust stage, narrative momentum, feedback loops | SOROS_FUND_MANAGEMENT_LLC |
| Ray Dalio | Debt cycles, history | Cycle position, stress tests, historical templates | BRIDGEWATER_ASSOCIATES_LP |
Contrarian/Risk
| Guru | Focus | Key Criteria | 13-F Source |
|---|
| Michael Burry | Forensics, bear case | Revenue/earnings quality, hidden liabilities, contrarian signals | SCION_ASSET_MANAGEMENT_LLC |
Quant/Systematic
| Guru | Nickname | Horizon | Key Output | Focus | 13-F Source |
|---|
| Jim Simons | The Quant | Medium-term (1-6 months) | Probability of positive return | Quant factor analysis | RENAISSANCE_TECHNOLOGIES_LLC |
Academic/Behavioral
| Guru | Nickname | Horizon | Key Output | Focus | 13-F Source |
|---|
| Robert Shiller | The Behavioral Economist | Long-term (5-10 years) | CAPE-implied return forecast | Behavioral economics | (none - academic) |
KEY PRINCIPLES (NEVER DEVIATE)
-
Independent Analyses: Each guru forms their OWN thesis. No debate between them.
-
All Preserved: Consolidation ADDS synthesis, never REMOVES individual insights.
-
Bold Forward-Looking: Internal use only. Specific predictions, price targets, timelines.
-
Changes > Holdings: For 13-F data, recent changes matter more than static positions.
-
Visible DRIVER: Show all stage markers so user sees the methodology in action.
-
Parallel Dispatch: ALL 9 experts spawn in single message for true parallelism.
-
Expert-Driven Data: Each guru gets exactly what they need, fetched once as union.
-
Quality Over Speed: Flag missing data, don't hallucinate to fill gaps.
-
Graceful Degradation: If some experts fail, continue with available data.
-
Complete Output: Both markdown (displayed) and JSON (saved) for every analysis.
-
Pre-Calculate, Don't Duplicate: Use Python processing layer for composite scores. Don't recalculate what financialdatasets.ai provides.
-
Processing Layer First: ALWAYS run run_analysis() before expert dispatch. Experts receive pre-calculated metrics, not raw data.
END-TO-END TEST PROCEDURE
Test Command
/financial-researcher AAPL --full
Expected Flow
-
Mode Selection: Should detect --full flag and skip mode question
-
[DISCOVER] Phase (10-30 seconds):
- Fetch financial statements (15 years annual, 20 quarters)
- Fetch metrics and market data
- Fetch SEC filings
- Fetch 13-F holdings for 6 investors (3-year history)
- Fetch news and context from Tavily
Expected output:
[DISCOVER] Fetching financial statements (15 years)...
[DISCOVER] Fetching metrics and market data...
[DISCOVER] Fetching SEC filings...
[DISCOVER] Fetching 13-F institutional holdings (3 years)...
[DISCOVER] Fetching news and market context...
[DISCOVER] Data collection complete.
Data Summary:
- Financial Statements: 15 annual + 20 quarterly periods
- Metrics: 48+ metrics available
- Price History: 1250+ days (5 years)
- SEC Filings: 20+ filings
- 13-F Holdings: X relevant positions found
- News Articles: 20+ items
-
[PROCESS] Phase (2-5 seconds):
- Run Python processing layer
- Calculate composite scores
- Generate expert contexts
Expected output:
[PROCESS] Running Python processing layer...
[PROCESS] Calculating composite scores:
├─ Piotroski F-Score: 8/9 (Very Strong)
├─ Altman Z-Score: 4.52 (Safe Zone)
├─ Beneish M-Score: -2.85 (Unlikely Manipulator)
└─ Ohlson O-Score: 2% probability
[PROCESS] Calculating quality metrics:
├─ Sloan Accrual: -3.2%
├─ FCF Conversion: 95.2%
└─ Gross Profitability: 38.5%
[PROCESS] Value creation analysis:
├─ Owner Earnings: $98.5B
└─ EVA: $72.3B
Quality Summary:
- Overall Quality Score: 87/100
- Red Flags: 0
- Green Flags: 4
-
[REPRESENT] Phase (1-2 seconds):
- Validate ticker
- Prepare data subsets with pre-calculated metrics
- Build expert prompts using format_for_expert()
Expected output:
[REPRESENT] Mode: FULL
[REPRESENT] Company: Apple Inc (AAPL)
[REPRESENT] Market Cap: $X trillion
[REPRESENT] Current Price: $XXX.XX
Pre-Calculated Metrics Summary:
├─ Piotroski F-Score: 8/9 (Very Strong)
├─ Altman Z-Score: 4.52 (Safe Zone)
├─ Quality Score: 87/100
└─ Red Flags: 0 | Green Flags: 4
Experts to dispatch:
├─ Warren Buffett (moat, owner earnings, FCF conversion)
├─ Ben Graham (margin of safety, Z-Score, NCAV)
...
-
[IMPLEMENT] Phase (60-180 seconds):
Validation Checklist
After test completes, verify:
Processing Layer:
Expert Outputs:
Output Files:
Known AAPL Facts for Validation
Use these to verify expert analyses are using real data:
| Fact | Expected in Analysis |
|---|
| Berkshire ownership | Buffett should mention ~5-6% of Berkshire's portfolio |
| ~$100B+ cash | Graham/Dalio should note fortress balance sheet |
| Services growth | Lynch/Wood should discuss recurring revenue shift |
| China exposure | Burry/Dalio should flag as risk |
| Buybacks | Buffett should mention capital allocation |
| Moat | Buffett should rate ecosystem moat highly |
| P/E ratio | Graham should compare to historical averages |
Test Failure Modes
If test fails, check:
- MCP servers not running: Ensure both financialdatasets-mcp and tavily-mcp are configured
- API keys missing: Check .env for FINANCIAL_DATASETS_API_KEY and TAVILY_API_KEY
- Expert timeout: Increase Task tool timeout or check for infinite loops
- JSON parse error: Expert returned malformed JSON - check expert prompt
- Missing holdings data: 13-F data may not be available for current quarter
Performance Benchmarks
| Phase | Target Time | Notes |
|---|
| DISCOVER | < 30s | Parallel MCP calls |
| PROCESS | < 5s | Python processing layer |
| REPRESENT | < 2s | Data routing only |
| IMPLEMENT | < 180s | Parallel expert dispatch |
| VALIDATE | < 5s | Schema validation |
| EVOLVE | < 10s | Consolidation logic |
| REFLECT | < 10s | Report generation |
| Total | < 4 min | Full mode target |
Processing Layer Test
Run standalone processing layer test:
cd /mnt/d/github/FAskills/financial-researcher
python3 -m processing.test_pipeline
Expected output:
- All individual metric tests pass
- Full pipeline test passes
- Piotroski F-Score: 7/9 (test data)
- Altman Z-Score: 7.79 (test data)
- All calculations complete without errors