Home/Reports/JPstock-agent: Thematic Equity Research Workflow

JPstock-agent: Thematic Equity Research Workflow

2026-04-22 19:16 · 28.7 KB

{#

================================================================================

ANALYSIS WORKFLOW TEMPLATE

This is NOT a prompt template — it documents the step-by-step methodology

for conducting thematic equity research using JPstock-agent.

Use this as a checklist for future analysis runs.

Last updated: 2026-04-14 (Claude-only analysis + J-Quants + site publishing)

================================================================================

#}

JPstock-agent: Thematic Equity Research Workflow

Overview

This template documents the end-to-end process for producing a validated

equity research report on a thematic investment idea (e.g., nuclear restart,

defense spending, AI/semiconductors).

Total time: ~30-60 minutes depending on stock count and LLM availability.

Analysis Architecture (Claude-only, J-Quants data)

StepWhatHow
0. DataFetch fundamentals from J-Quants (paid plan, 107 columns)Python function: fetch_jquants_with_valuation(ticker)
1. Full DD14-section DD + dimension scores + peer comparisonClaude writes, submits via PUT /api/stocks/{ticker}/deep-dd
2. Stock CardPer-stock WHY/RISK/TRIGGER with peer contextClaude writes, included in deep-dd submission
3. ResearchWeb search, macro, cross-validation, supply chainClaude performs web searches, validates metrics
4. PortfolioRank, weight, construct, write reportClaude builds final report with sourced evidence

No Qwen/LLM involved. Claude does all analysis. J-Quants provides the data.

Why no Qwen:

  • Claude has web search — validates metrics, finds macro context, sources evidence
  • Claude has judgment — conviction calls, weight decisions, risk assessment
  • Claude produces higher quality narratives than Qwen's JSON-constrained output
  • J-Quants provides official JPX data (107 columns) — no need for yfinance's unreliable ratios

Data sources (use the RIGHT source for each metric):

WhatPrimary SourceWhyAvoid
PE, PB, valuation ratiosStockAnalysis.comHandles splits correctly, split-adjustedJ-Quants (split bugs), yfinance (known errors)
Raw financials (revenue, NI, margins)J-QuantsOfficial JPX data, 107 columnsyfinance (unreliable for JP stocks)
Company forecasts (fwd EPS, guidance)J-QuantsDirect from company filingsStockAnalysis (analyst consensus, not company)
Cash flow (CFO, CFI, FCF)J-QuantsOfficial filing datayfinance (can be wrong, see Yamato Kogyo)
Cross-validationYahoo FinanceGood secondary check

J-Quants PE CAVEATS (verified from actual filings 2026-04-17):

J-Quants raw data (EPS, NI, shares from 決算短信) is ACCURATE. But the PE our code calculates has 2 issues:

1. SPLIT BUG: After a stock split, J-Quants filing EPS is pre-split but price is post-split.

Must divide EPS by split ratio. Known: KHI 5:1, IHI 7:1, SBI 2:1.

Fix: check ShOutFY changes between filings to detect splits.

2. TIMELINESS: J-Quants may have older filings than StockAnalysis (e.g., Nidec had 2Q

while StockAnalysis had 3Q data). This is a data lag, not a bug.

3. METHODOLOGY: J-Quants annualizes cumulative period EPS (e.g., 3Q×4/3). StockAnalysis

uses rolling TTM (sum of last 4 quarters). Both are valid but can differ 10-20%.

Best practice:

  • Use StockAnalysis PE as the display value (split-adjusted, rolling TTM, widely understood)
  • Use J-Quants raw EPS/NI for fundamental analysis (official filing data, most accurate)
  • If PE gap >20% between sources, investigate: is it a split? stale filing? different methodology?

J-Quants IS reliable for:

  • Financial summaries: revenue, OP, NI, EPS, BPS, total assets, equity, CFO/CFI/CFF
  • Company forecasts: forward revenue, forward EPS, forward OP (company guidance)
  • Prices: official TSE OHLCV
  • Universe: 3,800+ TSE stocks with sector/market classification
  • Derived metrics calculated locally: PE, PB, ROE, margins, D/E, FCF, dividend yield
  • Function: from src.data.jquants_fundamentals import fetch_jquants_with_valuation

Pipeline order: J-Quants data fetch → Claude research + analysis → Claude submits deep-dd → HTML report


PHASE 1: Theme Identification & Stock Universe (10 min)

1a. Identify core stocks

Two approaches — use BOTH, not just one:

Approach A: Direct search (good for Japan-specific themes)

Query existing stocks, search for Japanese companies in this sector.

Good for: Nuclear, Tourism, Governance, VTuber, Defense — themes where Japan IS the market.

Approach B: Global-first value chain tracing (the "T-glass method")

Use when the theme is driven by a GLOBAL industry (AI, EV, semiconductors, etc.):

1. Identify the global leaders (any country) — e.g., Nvidia, TSMC, Tesla, BYD

2. Trace their value chain backwards — from end product to raw materials

3. At each layer ask: "Who is the dominant supplier? Is it Japanese? Is the position irreplaceable?"

4. Search in English, Japanese (日本語), AND Chinese (中文) — Taiwan/China industry sources (DigiTimes, TrendForce) often have the best supply chain intelligence

Why this matters: The T-glass discovery proved that the most valuable Japanese companies are often INVISIBLE upstream suppliers — not the obvious names. Nittobo (90% T-glass monopoly) was missing from our AI coverage because we started by looking for "AI companies in Japan" instead of tracing "what does an Nvidia GPU need to be manufactured?"

1b. Value chain mapping

Every theme has a value chain — the number of layers varies by industry:

Theme TypeTypical LayersExample
Semiconductor/AI10-13 layersMaterials → Equipment → Fab → Packaging → Components → System
EV/Automotive5-8 layersMaterials → Battery → Drivetrain → Assembly → Infrastructure
Nuclear/Energy4-6 layersFuel → Equipment → Operator → Grid → Services
Consumer/Tourism3-5 layersInfrastructure → Services → Distribution → Experience

Map the value chain for YOUR theme, then check Japan's position at each layer.

1c. Moat rating

Rate each Japanese company's structural advantage:

RatingCriteriaExample
★★★★★ MONOPOLY>80% share, no alternative, impossible to replicate in <10yrTEL coater/developer, Nittobo T-glass
★★★★ DOMINANT>50% share or duopoly, very difficult to replicateShin-Etsu wafers, Hoya mask blanks
★★★ STRONG20-50% share, defensible but competitors existMurata MLCC, Ibiden substrates
★★ COMPETITIVE<20% share, multiple competitorsRenesas MCU, Hirose connectors
★ WEAKNo structural advantage vs global peersJapan PCB mfg vs Taiwan

Prioritize ★★★★★ and ★★★★ for investment. Include ★★★ for diversification. Skip ★★/★ unless valuation is extreme.

1d. Competitive context

For key positions, briefly compare Japan vs the closest global competitor.

This prevents overestimating Japan's edge (e.g., Asahi Kasei Q Glass looked like a monopoly until we found Glotech and Feilihua competing).

1e. Gap check

Read existing theme JSONs. Ask:

  • Which value chain layers have NO Japanese stock coverage?
  • Are we missing upstream material suppliers? (These are where monopolies hide)
  • Have we only covered the "obvious" names and missed the Nittobo-type hidden chokepoints?

1f. Select stocks for deep DD

Focus on 5-10 stocks:

  • At least 1 from each major value chain layer
  • Prioritize positions with structural moats (★★★+)
  • Mix of pure-plays and diversified exposure

PHASE 2: Data Gathering (10 min)

2a. Pull fundamentals from database

`sql

SELECT f.ticker, s.name, f.metric_name, f.metric_value, f.fiscal_date, f.fetched_at

FROM fundamentals f

JOIN stocks s ON f.ticker = s.ticker

WHERE f.ticker IN ({{ core_tickers | join(', ') }})

AND f.fiscal_date = (SELECT MAX(fiscal_date) FROM fundamentals WHERE ticker = f.ticker)

ORDER BY f.ticker, f.metric_name

`

Key metrics to extract:

  • Valuation: pe_ratio, forward_pe, pb_ratio, ev_ebitda, dividend_yield
  • Quality: roe, roa, operating_margin, net_margin, ebitda_margin
  • Growth: revenue_growth, earnings_growth
  • Health: debt_to_equity, current_ratio
  • Other: beta, market_cap, free_cashflow, payout_ratio

2b. Check data freshness

CRITICAL: Note the fetched_at timestamp. If data is >7 days old, consider

re-fetching fundamentals before analysis:

`

make fetch-fundamentals TICKER=XXXX.T

`

2c. Pull relationships and peer data

`sql

SELECT source_ticker, target_ticker, relationship_type, description, confidence

FROM company_relationships

WHERE source_ticker IN ({{ core_tickers }}) OR target_ticker IN ({{ core_tickers }})

AND confidence >= 0.6

`

2d. Gather macro context via web research

Search for:

1. Current policy/regulatory status for the theme

2. Recent government announcements or legislation

3. Demand drivers and catalysts (e.g., data center demand for nuclear)

4. Any recent corporate news for the core stocks

5. Consensus analyst views and target prices

Sources to check:

  • NRA Japan (nuclear), MOD Japan (defense), METI (energy policy)
  • Nikkei, Reuters Japan, Bloomberg
  • World Nuclear Association, EIA, IEA (for energy themes)
  • Kabutan, Yahoo Finance JP, Minkabu (for stock-specific)

PHASE 3: Build Comparison Table (10 min)

3a. Construct the peer comparison table

Organize all core stocks in a single table with these columns:

CategoryMetrics
IdentityTicker, name, role, nuclear/theme exposure description
ValuationPE (TTM), Forward PE, P/B, EV/EBITDA, dividend yield
QualityROE, operating margin, EBITDA margin
HealthD/E ratio, current ratio
GrowthRevenue growth, EPS growth
TechnicalBeta, 52-week range, distance from high
SizeMarket cap

3b. Normalize units

IMPORTANT — these are the normalized scales after our data pipeline fixes:

  • Ratios (ROE, margins, yields, D/E): stored as decimals (0.12 = 12%). Display as %.
  • Currency (market_cap, EV, FCF): stored in raw JPY. Display as ¥B (divide by 1e9).
  • Multiples (PE, PB, EV/EBITDA): stored as raw numbers. Display as-is with 'x'.

3c. Flag obvious data anomalies

Before proceeding, scan for:

  • [ ] Any dividend yield > 10% → likely data error
  • [ ] Any PE < 0 → loss-making, use forward PE instead
  • [ ] Forward PE wildly different from trailing → check for stock splits, one-time charges
  • [ ] D/E > 300% → flag as high leverage, verify it's real
  • [ ] ROE negative → flag as distressed
  • [ ] Any metric that seems 10x off from peers → investigate

LESSON LEARNED (IHI 7013.T, April 2026): yfinance can produce incorrect

forward EPS after stock splits. IHI did a 7-for-1 split in Oct 2025, and

yfinance mixed pre-split forward EPS (¥578) with post-split share count,

producing a fake forward PE of 6.1x (actual: ~26.7x). ALWAYS cross-check

forward PE against at least one web source when the gap vs trailing PE is >50%.


PHASE 4: Web Validation (15 min)

4a. Cross-check every number against independent sources

For each core stock, validate against at least ONE of:

Metrics to validate:

  • [ ] PE ratio (trailing and forward)
  • [ ] P/B ratio
  • [ ] ROE
  • [ ] Dividend yield
  • [ ] Market cap
  • [ ] Any metric used in a recommendation

4b. Validate macro claims

Every macro/policy claim must have a named source:

  • [ ] Government policy documents (cite specific plan/date)
  • [ ] Reactor count (cite NRA or World Nuclear Association)
  • [ ] Demand forecasts (cite research firm and report date)
  • [ ] Corporate events (cite press release or news article)

4c. Document discrepancies

Create an errata table:

Original ValueValidated ValueSourceImpact on Thesis

If a correction changes the ranking, update the ranking.


PHASE 5: Analysis & Ranking (10 min)

5a. Score each stock across dimensions

Use the Condensed Equity Peer Comparison framework:

CategoryWeightWhat to evaluate
Business quality & moat25%Market position, pricing power, barriers
Growth15%Revenue/EPS trajectory, capacity expansion
Profitability15%Margins, ROE vs TSE 8% target
Cash flow & balance sheet15%FCF, leverage, liquidity
Valuation15%Relative and absolute, premium/discount
Catalysts & timing10%Near-term (0-6M) and medium-term (6-24M)
Risk5%Downside scenarios, governance

Japan-specific factors to always consider:

  • Corporate governance reform (JPX 2023: PBR > 1.0 push)
  • BOJ monetary policy and yen dynamics
  • Sector policy tailwinds (nuclear, defense, semiconductors)
  • Shareholder return trends (payout ratio expansion)

5b. Produce ranking with conviction levels

ConvictionCriteria
HIGHValuation compelling + quality confirmed + clear catalyst + manageable risk
MEDIUMGood but missing one element (expensive, or catalyst uncertain)
LOWSpeculative or overvalued — only with position sizing caveat

5c. Generate Stock Cards (Layer 2 — Comparison)

For each core stock, generate a stock card that adds peer comparison context.

This bridges the gap between per-stock DD (Layer 1) and portfolio ranking (Layer 3).

`

GET /api/stocks/{ticker}/stock-card

`

Each stock card produces:

FieldContent
thesisWHY this stock — 2-3 sentences with specific catalysts
weight_pctSuggested weight (integer %)
weight_rationaleWHY this weight — comparison to peers
riskWhat could go wrong — 2-3 specific risks with metrics
monitoring_triggerWhen to add/trim — If [metric/event], then [action]
dimension_scoresQuality, growth, valuation, health, catalyst, moat (1-10)
vs_peersBest at, worst at, unique edge vs peer group
scenarioBull/base/bear with probabilities

5d. Write scenario analysis for top picks

For each HIGH conviction stock:

  • Bull case: What goes right + approximate upside % + key assumption
  • Base case: Status quo + expected return (yield + modest re-rating)
  • Bear case: What goes wrong + approximate downside % + key risk

5e. Construct recommended portfolio

Use stock card suggested weights as starting point, then adjust:

  • HIGH conviction: 15-30% each (stock card may suggest higher)
  • MEDIUM conviction: 5-15% each
  • LOW/speculative: 3-5% max
  • AVOID: 0% with explanation
  • Total must sum to 100%
  • Verify no single stock exceeds 35% (concentration limit)

PHASE 5.5: Claude Deep DD (All Analysis)

Claude performs ALL analysis. J-Quants provides the raw data.

No Qwen/LLM intermediary — Claude writes everything directly.

5.5a. Per-stock deep research (Claude)

For each stock, Claude performs ANALYST-LEVEL research (not just metric checking):

1. Financial filings & IR — the primary source of truth

- Search: '{company name} IR 決算 2026', '{company} investor relations presentation'

- Read: latest earnings presentation (決算説明資料), medium-term plans, segment data

- Extract: revenue by segment, margin trajectory, guidance revisions, capex plans, return policy

2. Press releases & corporate news

- Search: '{company name} press release 2026', '{会社名} プレスリリース 2026'

- Look for: new contracts, M&A, partnerships, product launches, management changes

- Grade each finding by materiality: HIGH (thesis-changing) / MEDIUM / LOW

3. Global/macro impact analysis

- Trade policy: tariffs, export controls affecting this company

- Commodity prices: steel, oil, copper, rare earth (if relevant to this stock)

- FX: yen strength/weakness impact on this company's earnings

- Industry regulation: new laws, standards, subsidies

- Competitor moves: global competitors entering/exiting Japan

4. Supply chain evidence — MANDATORY, every stock must have 2-3+ entries

- Grade: CONFIRMED (press release/filing) / PROBABLE (industry standard) / INFERRED (logical)

- Date every evidence link for freshness

- Check for supply chain CHANGES (new wins, losses, disruptions)

- Each entry: {customer, product, evidence, detail, source_url, date}

- source_url is REQUIRED for 'confirmed' evidence — link to actual press release, filing, or article

- date when the relationship was confirmed or last verified

- Search for: key customers, key suppliers, JV partners, government contracts

- NO stock should have empty supply_chain[] — if missing, fill during evolve/explore rounds

- Future validation: source_url enables re-checking if the relationship still holds

5. Key dates refresh — keep catalyst timeline current

- Remove past dates that have occurred

- Update earnings dates from company IR calendar

- Add NEW catalyst dates discovered during research

- Format: {date, type: earnings|catalyst|monitoring|rebalance, description}

6. Thesis validation — the most important step

- Does the original WHY still hold? What's strengthened/weakened?

- Are monitoring triggers being hit?

- Has conviction changed? (HOLD / UPGRADED / DOWNGRADED / EXIT)

- New risks discovered?

7. Per-stock deep card — Claude writes/updates the WHY/RISK/TRIGGER card:

`

WHY this stock: [2-3 sentences with specific catalysts, sourced]

WHY XX%: [weight rationale comparing to peers, with numbers]

What could go wrong: [2-3 risks with specific metrics/thresholds]

Monitoring trigger: [If metric/event, then add/trim. Specific dates.]

`

8. Metric cross-validation — verify data against independent sources

- StockAnalysis.com, Kabutan, Yahoo Finance JP

- Flag and correct any errors (stock splits, stale data)

- Build errata table: Original | Validated | Source | Impact

5.5b. Data + Analysis flow

For each stock:

1. fetch_jquants_with_valuation(ticker) → raw fundamentals + derived metrics

2. Claude web research → macro context, policy data, supply chain evidence

3. Claude cross-validates J-Quants metrics against web sources → errata

4. Claude writes 14-section DD + stock card + dimension scores

5. PUT /api/stocks/{ticker}/deep-dd → stores everything in DB

6. GET /api/stocks/{ticker}/deep-dd → retrieves for report generation

5.5c. Task breakdown

TaskHowNotes
Fetch fundamentalsfetch_jquants_with_valuation(ticker)J-Quants paid plan, 107 columns, official JPX data
Calculate derived metricsSame function (automatic)PE, PB, ROE, margins, D/E, FCF — all from raw J-Quants data
Compute Piotroski F-Score_compute_piotroski(ticker, metrics)Formula-based, called in dd_report.py
Web search for macro/policyClaude web searchGovernment sources, industry reports, news
Cross-validate metricsClaude checks StockAnalysis/KabutanFlag yfinance/J-Quants discrepancies
Write 14-section DDClaude writesExecutive summary through verdict
Score dimensions (1-10)Claude scoresQuality, growth, valuation, health, catalyst, moat
Write stock card (WHY/RISK/TRIGGER)Claude writesThesis, weight rationale, risks, monitoring triggers
Peer comparisonClaude comparesBest at, worst at, unique edge vs peers
Rank stocksClaude ranksConviction, tier (Core/Satellite/Tactical)
Set portfolio weightsClaude decidesBased on conviction, quality, diversification
Write HTML reportClaude writesFull narrative with sourced evidence
Submit to DBPUT /api/stocks/{ticker}/deep-ddAll analysis stored for report generation

Qwen/Ollama is NOT used. All analysis is Claude. Data is J-Quants.


PHASE 6: Report Generation & Publishing

6a. Generate theme JSON data files

For each theme, create reports-site/data/{theme}_companies.json:

`python

from src.storage.database import init_db, get_dd_report

import json

init_db()

dd = get_dd_report(ticker, 'deep_dd')

c = json.loads(dd['raw_llm_response'])

vm = c.get('validated_metrics', {})

company = {

'ticker': t, 'name': c.get('name', t),

'weight': c.get('weight_pct', 0) / 100.0,

'conviction': c.get('conviction', ''),

'layer': c.get('layer', ''),

'thesis': c.get('thesis', ''),

'risk': c.get('risk', ''),

'monitoring_trigger': c.get('monitoring_trigger', ''),

'pe': vm.get('pe_ratio', 'N/A'),

'forward_pe': vm.get('forward_pe', 'N/A'),

'pb': vm.get('pb_ratio', 'N/A'),

'roe': fmt_pct(vm.get('roe')), # "12.2%"

'op_margin': fmt_pct(vm.get('operating_margin')),

'de': fmt_pct(vm.get('debt_to_equity')),

'div_yield': fmt_pct(vm.get('dividend_yield')),

'fcf': '+¥28B' or '-¥11B' or 'N/A', # formatted with +/- prefix

'market_cap': '¥165B', # formatted

'segments': [],

'supply_chain': [{'customer': '...', 'product': '...', 'evidence': 'confirmed', 'detail': '...'}],

'themes': ['Theme Name'],

'data_date': '2026-04-14',

'sources': ['https://...'],

'key_dates': [{'date': '2026-05', 'event': 'FY2026 earnings'}],

}

output = {

'theme_title': 'Theme Name',

'macro_context': 'Sourced macro text...',

'companies': [company, ...],

'data_date': '2026-04-14',

}

Write to reports-site/data/{theme}_companies.json

`

6b. Generate portfolio JSON (for cross-theme reports)

Create reports-site/data/portfolio_{name}.json with additional fields:

`python

{

'title': 'Report Title',

'subtitle': 'Description',

'date': '2026-04-14',

'method': 'Analysis methodology description',

'companies': [

# Same as theme JSON but add:

'theme': 'Crypto', # for cross-theme color coding

'weight_rationale': 'WHY X%...',

'what_market_misses': '...',

'dimension_scores': {'quality': 8, 'growth': 6, ...},

'vs_peers': {'best_at': '...', 'worst_at': '...', 'unique_edge': '...'},

'scenario': {'bull': {...}, 'base': {...}, 'bear': {...}},

],

'errata': [{'ticker': '...', 'metric': '...', 'original': '...', 'actual': '...', 'source': '...', 'impact': '...'}],

}

`

6c. Register new themes on the site

Add to THEME_CONFIG in reports-site/lib/data.ts:

`typescript

{theme_slug}: { color: "#hex", file: "{theme}_companies.json" },

`

6d. Map portfolio reports to JSON rendering

Add to `REPORT_JSON_MAP` in TWO places:

1. reports-site/app/reports/[slug]/page.tsx — for Classic site rendering

2. scripts/generate_kairos_data.py — for Kairos site rendering

`typescript

"report_slug_name": "portfolio_{name}.json",

`

This makes reports render with company cards (dimension scores, scenarios, errata)

instead of plain markdown. Reports NOT listed render as markdown-only.

6e. Also create markdown export

Write reports-site/exports/{slug}.md so the report appears on /reports listing page.

The markdown is a fallback — the JSON rendering takes priority when mapped.

6f. Update History (CRITICAL — do this for EVERY data change)

When modifying any company data in theme JSONs, ALWAYS add tracking:

Per-company — append to company.update_history[]:

`json

{

"date": "2026-04-14",

"type": "evolve", // or "explore" or "new_narrative"

"report": "nuclear_dd_evolution_2026-04-14", // slug matching exports/ filename

"summary": "Dividend raised ¥64→¥78, yield 1.1%→1.4%",

"changes": [

{"field": "div_yield", "old": "1.1%", "new": "1.4%", "source": "J-Quants"}

],

"thesis_status": "HOLD" // or "UPGRADED" / "DOWNGRADED" / "EXIT"

}

`

Per-theme — append to theme.recent_updates[]:

`json

{

"date": "2026-04-14",

"type": "evolve",

"report": "nuclear_dd_evolution_2026-04-14",

"summary": "Updated 3 stocks: JSW, Yokogawa, Organo",

"stocks_updated": ["5631.T", "6841.T", "6368.T"]

}

`

The report slug creates clickable links: stock page → /reports/{slug} → evolve report.

6g. Regenerate Kairos data files

After updating ANY theme JSON, portfolio JSON, or markdown export, ALWAYS regenerate:

`bash

python3 scripts/generate_kairos_data.py

`

This reads all data files and produces 3 JS files for the Kairos homepage:

  • reports-site/public/kairos/data.js — stocks, themes, links, prices, news
  • reports-site/public/kairos/data_meta.js — thesis, conviction, metrics, scenarios
  • reports-site/public/kairos/data_report.js — reports with full markdown + portfolio data

If you skip this step, the Kairos site at `/` will show stale data.

6h. Deploy

NEVER deploy manually with wrangler. Always:

`bash

python3 scripts/generate_kairos_data.py # Regenerate Kairos data FIRST

git add reports-site/

git commit -m "data: {type} DD — {theme}"

git push origin main

`

GitHub Actions (deploy-reports.yml) handles: npm run buildwrangler pages deploy out

Site: reports.ddbancho.com

Pages rendered at:

  • / → Kairos SPA (default homepage — force-directed graph, theme explorer, reports)
  • /kairos/ → same Kairos SPA
  • /home → Classic homepage (rankings, themes grid)
  • /themes/{slug} — Classic theme page
  • /reports/{slug} — Classic report page (PortfolioReport or markdown)
  • /portfolio — Classic portfolio view

6g. Rendering components

  • PortfolioReport (reports-site/components/PortfolioReport.tsx):

Shared component for portfolio-style rendering. Used by /reports/[slug] and /portfolio.

Renders: comparison table, conviction breakdown, stock cards (WHY/RISK/TRIGGER),

dimension scores, vs_peers, scenarios, errata table, methodology, sources.

  • Theme pages (reports-site/app/themes/[theme]/page.tsx):

Comparison table + company cards. Click through to individual stock pages.

  • Stock pages (reports-site/app/themes/[theme]/[ticker]/page.tsx):

Price chart (TradingView), thesis, risk, trigger, metrics grid, segments,

supply chain evidence, sources, peer comparison table.


PHASE 7: Quality Checklist (Before Publishing)

Data integrity

  • [ ] All financial metrics cross-checked against at least one web source
  • [ ] Forward PE validated (especially after stock splits or one-time charges)
  • [ ] Data freshness noted (fetched_at date visible in report)
  • [ ] Fiscal period noted (which quarter the data covers)

Analysis quality

  • [ ] No internal contradictions (e.g., "Buy" in text but "Avoid" in table)
  • [ ] Numbers cited in narrative match the comparison table
  • [ ] Peer comparisons are apples-to-apples (same metric definitions)
  • [ ] Scenario analysis has specific assumptions, not just "things go well"

Macro claims

  • [ ] Every policy/regulatory claim has a named source with date
  • [ ] Demand forecasts cite the research firm and report date
  • [ ] Reactor counts / status verified against official sources
  • [ ] Corporate events verified against press releases

Report formatting

  • [ ] Errata section clearly shows what was corrected and why
  • [ ] Disclaimer present
  • [ ] All sources listed with dates
  • [ ] Report date prominent

Known Data Pipeline Issues (Update as Found)

IssueDate FoundAffected StocksWorkaround
yfinance PE wrong after stock splits2026-04-14SBI (2:1 Nov 2025), KHI (5:1 Mar 2026), IHI (7:1 Oct 2025)Use J-Quants or StockAnalysis. Always cross-check when gap vs trailing >50%
J-Quants FCF can be massively wrong2026-04-14Yamato Kogyo (showed -¥27.7B, actual +¥39.9B)Always cross-validate FCF against StockAnalysis
J-Quants D/E uses total liabilities (not interest-bearing debt)2026-04-14ShinMaywa (1.42x vs 0.54x), Monex (5.04x vs 0.85x)StockAnalysis uses interest-bearing debt only. Note which definition.
yfinance operating margin can be wrong2026-04-14Nihon Kohden (showed 4.3%, actual 9.2%)Always verify against company filings
yfinance PB wrong after stock splits2026-04-14SBI (showed 1.14, actual 0.85 — below book value)Use J-Quants or StockAnalysis
yfinance dividendYield returns % not ratio for JP stocks2026-03-29All .T stocksFixed in pipeline (divide by 100 at ingestion)
yfinance debtToEquity returns % not ratio2026-03-29All .T stocksFixed in pipeline (divide by 100 at ingestion)
Piotroski F-Score requires 2 periods (usually only 1 available)2026-03-29All stocks5/9 criteria default to 0; flag as incomplete
J-Quants price data may be stale (not real-time)2026-04-14Tokyo Keiki (showed ¥4,770, actual ¥7,690)Check multiple recent dates, verify against live sources
wrangler manual deploy overwrites Next.js static export2026-04-14Site deploymentNEVER use wrangler manually. Always git push → GitHub Actions