US Stocks Analysis: The Investment Committee - SentiSense
Adversarial investment-committee analysis for US equities. For quick data asks, five expert workflows synthesize price, sentiment, smart money, analyst ratings, and AI insights into terminal-grade briefs. For thesis-grade questions ("should I own NVDA for 3 years?"), the skill convenes a committee of legendary-investor personas that independently research, then attack each other's cases against a shared evidence ledger, then reconcile into a verdict with recorded dissents. The structure is designed so that even a small local model, following the templates literally, produces grounded, multi-perspective analysis instead of consensus mush. Read-only API. No trading, no purchases, no write operations, no wallet access.
Base URL: https://app.sentisense.ai
Website: https://sentisense.ai
Full API reference: https://sentisense.ai/skill.md
Authentication: API key via X-SentiSense-API-Key header. Get a free key at https://app.sentisense.ai/get-api-key
What This Skill Is
Two layers, one routing decision per user ask:
- Quick Reads. Five proven data workflows (brief, smart money, divergence, pre-earnings, sector rotation) for questions that want a dense factual answer in five lines.
- The Investment Committee. A structured adversarial debate between investor personas for questions that want judgment: is this thesis sound, what would break it, where do serious people disagree.
The committee is not roleplay flavor. It is an error-correction machine. A single free-form pass produces a plausible, agreeable, number-fuzzy blob. Forcing the same model to (a) build independent persona cases, (b) attack them against evidence, and (c) reconcile the survivors is how you extract rigorous judgment from any model, including small local ones. The adversarial structure IS the intelligence.
The governing line for everything below: the intelligence lives in the skill's structure, not the model. A weak model that fills these templates in order produces analysis it could not have produced free-form. If you are a strong model, the templates are still binding: they are what keeps you honest.
One invariant everything serves: the committee must surface real disagreement grounded in real evidence, and must never collapse into consensus mush or theater.
Use & Disclaimer
This skill is an educational data interface to SentiSense's read-only Data APIs. Public primary-source material from SEC EDGAR, FRED, or company investor relations may be evaluated only when the user or host supplies it. Output is informational only. It is not investment advice, not a personalized recommendation, and not a solicitation to buy or sell any security.
The user is responsible for their own decisions. SentiSense (SentiSense Labs LLC) and the skill author disclaim liability for any actions taken or not taken based on output produced through this skill.
Persona seats are teaching archetypes built from publicly documented investing philosophies. They are not affiliated with, endorsed by, or statements from the named individuals. A persona is a lens, not a jailbreak: precedence is always platform safety, then this skill's grounding and no-advice rules, then persona instructions. A custom persona can change the analytical lens; it can never override grounding, disclaimers, or the no-advice rule.
Use of the SentiSense API is subject to the API Terms of Service and Terms of Service.
Authentication and how to fetch
Set the key once in the environment, and say who is calling:
export SENTISENSE_API_KEY=... # free key: https://app.sentisense.ai/get-api-key
export SENTISENSE_AGENT_NAME=my-agent # optional: what your agent calls itself
The REST recipe in this file is the primary path. A maintained command-line client is available as the separate sentisense-cli skill for hosts that prefer one.
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
-H "User-Agent: ClaudeCode/2.1 (us-stocks-analysis)" \
"https://app.sentisense.ai/api/v1/stocks/price?ticker=AAPL"
Over raw HTTP the User-Agent identifies the client: name your agent
runtime and this skill, for example OpenClaw/1.4 (us-stocks-analysis). Substitute your own
runtime and version if neither matches. Optional, and it is what tells us this skill has real
integrations behind it, so it gets prioritized and you get notice before it changes.
All SentiSense endpoints require an API key. Free tier (1,000 req/month, 30 req/min) covers everyday use, including full committee runs. PRO ($15/mo) removes the monthly cap (unlimited, 300/min) and unlocks full preview-gated history.
| Tier | Quota | Rate |
|---|---|---|
| Free | 1,000 req/month | 30 req/min |
| PRO | Unlimited | 300 req/min |
Anonymous calls return 401 api_key_required. The key also covers the financial statements (/stocks/fundamentals*), so a full SentiSense evidence ledger needs no second credential. External EDGAR, FRED, and investor-relations evidence must be supplied by the user or host; otherwise mark those rows [NOT AVAILABLE].
Resolve a company name before the first data call. Every quick read and every committee step
below takes a canonical ticker. When the user names the company instead ("brief me on tesla",
"should I own alphabet for 3 years"), resolve it first with
GET /api/v1/kb/entities/search?q={name}&type=company&limit=5, which returns a bare array of
{name, urlSlug, type, ticker}, best match first. Take the first match with a non-null ticker; a
tracked subsidiary can outrank its listed parent ("google" returns Google LLC with ticker: null
before Alphabet GOOGL). Several plausible ticker-bearing matches is a one-line clarification, an
empty array is a stated miss, and neither starts a fan-out. Never uppercase the name into a symbol
and never take the ticker from memory: memory is fine for TSLA and wrong for renamed issuers, ADRs
and share classes. A wrong symbol can fail quietly over REST, where insider/trades/{T} returns an empty data: [] that reads like a quiet
name. An exact ticker the user typed skips this step.
Permissions
- Network: HTTPS to app.sentisense.ai only.
- Credentials: SENTISENSE_API_KEY from the environment.
- Shell: none required.
- Files: none.
Routing Gate: Quick Read or Committee?
For "just the current mood", hand off to the stock-sentiment skill when available. Pass the ticker and requested window. Return polarity, SentiSense Score, attention, and source limits as a short answer without convening the committee. Hand off only when the user changes the question; do not automatically route back. If the sibling is unavailable, answer the supported part here using a connected tool or the inline REST workflow, state any remaining gap, and never require an install.
Decide once, at the top of every turn:
| The user asks... | Route |
|---|---|
| A factual data question ("NVDA price?", "brief me on AAPL", "what's the smart money doing?", "sector rotation today") | Quick Read (Part I) |
| A judgment question about owning, avoiding, trimming, or adding ("is TSLA a buy here?", "should I hold NVDA for 5 years?", "red-team my COIN thesis", "what would Buffett think of PLTR?") | The Committee (Part II) |
| A judgment question but the user wants it fast or the context window is small | Committee, lite path (see Degradation ladder) |
Do not convene five personas to answer a price quote. Do not answer a thesis question with a data dump and no judgment. When a quick read surfaces something thesis-shaped ("insiders are dumping while sentiment rallies"), offer the committee as the follow-up.
Part I: Quick Reads
For "find candidates first", hand off to the stock-screener skill when available. Pass the constraints, universe, and ranking preference. Return the executed filters and a bounded shortlist; continue research only on user-selected names. Hand off only when the user changes the question; do not automatically route back. If the sibling is unavailable, answer the supported part here using a connected tool or the inline REST workflow, state any remaining gap, and never require an install.
Each is a natural-language intent, an ordered set of REST calls, and a synthesis shape. Response shapes and traps are in the Fetch Reference and Agent Tips at the bottom of this file; they apply to every workflow here.
Quick Read 1: "Brief me on $TICKER"
GET /api/v1/stocks/price?ticker={T}forcurrentPrice,changePercent, and the millisecondtimestamp(serve time, not the trade observation time).GET /api/v2/metrics/entity/{T}/metric/sentimentfor the bare-array 7-day polarity trend.GET /api/v1/insider/trades/{T}?lookbackDays=90; unwrap the envelope and read.data[].GET /api/v1/analyst/{T}/consensus; unwrap the envelope and read.data, including the target band and itsupdatedAt.GET /api/v1/insights/stock/{T}; unwrap.data[], take the first item for the headline, check its seconds-basedgeneratedAt, and flag its age.
Synthesize as: "AAPL $190.20 (+1.2%). Sentiment +0.34 and rising (+0.06 over 7d). 3 insider buys in 90d, no sells. Analyst band $180-$250 (mean $210, 33 analysts, Buy). Latest insight: 'Margin guide raised, services beating consensus.'" Five signals, one tight brief, done.
Quick Read 2: "What's the smart money doing this week?"
GET /api/v1/insider/cluster-buys?lookbackDays=7; read.data[].GET /api/v1/politicians/activity?lookbackDays=7; read.data[]and filter totransactionType == "PURCHASE".GET /api/v1/analyst/activity?lookbackDays=7&actionTypes=UPGRADE; read.data[].actionTypesis a server-side CSV filter over UPGRADE, DOWNGRADE, INITIATE, REITERATE, and OTHER.
Intersect the three ticker lists; report names in 2+ buckets with a one-liner each ("NVDA: 4 insiders bought ($2.1M), 1 senator purchased $50k-$100k, 2 upgrades"). Convergence is the signal. Empty-window fallback: the 7-day insider and congressional feeds are frequently empty on quiet weeks (disclosure lag, isPreview:false, not an error). Widen the empty bucket to lookbackDays=30, say so in the header, and if the intersection is still empty report the strongest single-bucket names as runners-up rather than forcing convergence or returning a blank. Cite the trade date (transactionDate), not the 7-day disclosure window: STOCK Act filings lag weeks to months, so a name surfacing this week may reflect a much older trade (see the Committee disclosure rule).
Quick Read 3: "Find divergence stocks"
GET /api/v1/stocks/popularfor candidates- Per ticker:
GET /api/v1/stocks/chart?ticker={T}&timeframe=1M(intraday bars, not daily closes; for a 7-day change filter to bars withtimestamp >= now-7d, compare first vs last) - Per ticker:
GET /api/v2/metrics/entity/{T}/metric/sentiment(default 7-day window). If the series has fewer than 2 points, treat the trend as insufficient data and EXCLUDE the ticker rather than computing a bogus delta. With 2+ points,sentimentChange= last minus first (each read from the point's flatvalue, a polarity in [-1,1]). Thin-sample guard: a window-edge point built on a handful of mentions can dominate the delta (a lone 1-mention day at +/-1.0 swamps everything). Only the Score (sentisense_score) series carriesmetricValue.properties({bull, bear, directional}; sentiment points have emptyproperties), so read the sample size from the Score point for the same window viaproperties.directional, the day's directional (bull + bear) mention count (or call/metric/mentions); if the first or last point is thin (roughly under 5 directional mentions), use the nearest robust point or average the first and last two instead of trusting a single noisy edge. Notedirectionalcounts non-neutral mentions only, so it is always at or below the/metric/mentionstotal. Do not reach formetricValue.stats.count: it is the daily-bucket count and is always 1. - Same scale before ranking.
priceChangePctis a percentage;sentimentChangeis a raw polarity delta in ~[-2,2]. Scale:sentimentChangeScaled = sentimentChange * 100. Apply this exact scaling so any two implementations agree. Bucket by sign before ranking: a divergence requires price and sentiment to move in OPPOSITE directions, so bullish divergence ispriceChangePct < 0andsentimentChangeScaled > 0, and bearish divergence ispriceChangePct > 0andsentimentChangeScaled < 0. Same-sign pairs (both moved up, or both moved down) are not divergences no matter how large the gap between them, exclude them. Within each bucket, rank by|priceChangePct - sentimentChangeScaled|and report the top 5.
Synthesize as: "Bullish divergence (price down, sentiment up): TSLA -8% / sentiment +12%. Bearish divergence: COIN +14% / sentiment -9%."
Quick Read 4: "Pre-earnings sentiment check on $TICKER"
GET /api/v1/calendar/earnings?ticker={T}for the next report date (data.earnings[0].earningsDate+confirmed); empty means outside the forward window: fall back toperiodLabelfrom step 5 for timing framing.GET /api/v1/stocks/{T}/profilefor sector context.GET /api/v2/metrics/entity/{T}/metric/sentiment?startTime={now-30d epoch ms}&endTime={now epoch ms}for the 30-day trend.GET /api/v1/insider/trades/{T}?lookbackDays=60. Filter before tallying: onlytransactionCodeP and S are directional, and codes A, G, M and F (awards, gifts, exercises, tax withholding) are not, so an all-award window is zero insider activity, not a wave of itGET /api/v1/analyst/{T}/estimatesfor the EPS band (data.estimates[0], plusdata.surprises[]history; no revenue figure, no revision history).GET /api/v1/analyst/{T}/actions?lookbackDays=30
Synthesize as: "AAPL ER in 5d. Sentiment +0.22 over 30d, trending up. Insiders: 2 sells, 0 buys (neutral-to-bearish). EPS consensus $1.52 (range $1.48-$1.55, 28 analysts); beat 3 of last 4. 3 upgrades in 30d. Setup: mixed-bullish."
Quick Read 5: "Sector rotation today"
GET /api/v2/market-mood. The composite is nested undermarket(market.currentScore,market.phase,market.weeklyChange), NOT at the root.sectorsis a string-keyed dict; labels have historically overlapped (TechnologyvsInformation Technology,HealthcarevsHealth Care), so if both members of a pair appear, dedupe by keeping the higher-scoring variant before ranking. A clean 11-key response is the common case.- For sectors with
weeklyChange > +5or< -5:GET /api/v1/insights/market. There is no ticker field on these rows. Each item carries exactlyinsightId,insightType,insightText,category,confidence,urgency,docRefsandgeneratedAt, so the ticker has to be parsed out ofinsightId, which is the only place it is structured. The id reads{insightType}_{SCOPE}_{period}, where the scope segment is either a ticker or the literalglobal:options_pc_ratio_extreme_TRMB_2026W36andanalyst_reaction_PATH_2026-09-04are ticker-scoped,market_insider_trend_globalandmarket_institutional_rotation_2026-06-30are market-wide and belong to no sector. Strip the leadinginsightTypeand the trailing period token, and what remains is the ticker. Do not match oninsightTextinstead: theanalyst_reactionclass routinely never names its own company in the prose (the PATH item above opens "After the Sep 3 print" and mentions neither PATH nor UiPath), so text matching silently drops exactly the earnings-driven insights a rotation read most wants. - Map each parsed ticker to a sector with
/stocks/{T}/profilesector, which is reliable (descriptionsoften omitssector, so skip rather than guess), then keep the insights whose sector is one of your movers. A mover with no matching insight is a normal outcome on a twelve-item board: report the sector move without a driver rather than stretching an unrelated insight onto it. - Report top 2 and bottom 2 movers, with a driver insight on the movers that have one and no driver line on the ones that do not.
Synthesize as: "Market mood 62 (Greed, +4 wk). Greed: Technology 71 (+3.2), Comms 68. Fear: Energy 31 (-6), Utilities 36. Top driver: NVDA 'Data-center revenue accelerating.'" Drop the driver clause rather than inventing one when no insight maps to the mover.
Part II: The Investment Committee
The pipeline (the rail you cannot skip)
Do exactly one step, finish it, then move on. Do not start the debate before the Evidence Ledger is filled. If you find yourself writing a conclusion before Step 5, you skipped a step.
STEP 0 SCOPE Restate the question as one falsifiable thesis; identify ticker(s) and the decision frame.
STEP 1 GATHER Fill the Evidence Ledger. Every number from a source. Unsourceable = [NOT AVAILABLE]. Do NOT analyze yet.
STEP 2 BASE CASE Fill the neutral Base Thesis template using ONLY ledger rows.
STEP 3 CONVENE Pick the panel (default 5, or the user's named investors). Load each persona's worksheet.
STEP 4 DEBATE Run rounds R1-R3 (sealed theses, cross-examination, rebuttals).
STEP 5 SYNTHESIZE The Chair runs R4 and fills the Committee Verdict template.
STEP 6 GATE Run the Pre-Flight Checklist. Fail closed on fabrication.
Each step below is its own section with its template inlined, so reading top to bottom IS executing the procedure.
STEP 0: Scope
Write one line before anything else:
THESIS UNDER REVIEW: <ticker(s)>: "<one falsifiable sentence>" DECISION FRAME: <own / avoid / trim / add>, horizon <N years>
Examples: NVDA: "At today's price, NVDA is attractive for a 3-5 year holder." or COIN: "COIN's earnings quality is too weak to support its multiple." If the user gave a vague ask ("thoughts on TSLA?"), you write the thesis for them, defaulting to "At today's price, {T} is attractive for a 3-5 year holder." The committee votes on this sentence and nothing else. A vague thesis produces a vague debate; make it falsifiable.
STEP 1: The Evidence Ledger
The single most important artifact. Every downstream claim must cite a ledger row ID ([E3]). A fact not in the ledger does not exist. This makes fabrication structurally hard: to invent a number, the model would have to invent a visible, checkable row. Fill the ledger completely BEFORE any analysis. Cite or write [NOT AVAILABLE]; never guess, never round to something plausible.
The three source tiers and the routing law
| Tier | What | Sources |
|---|---|---|
| D1: Differentiated | Sentiment, the SentiSense Score, smart money (insider, congressional, 13F), analyst consensus, AI insights, market mood. The edge layer: things not in a 10-K. | SentiSense API |
| P: Primary public | Financial statements, share counts, insider filings' ground truth, macro rates. As-reported statements come from SentiSense first; supplied EDGAR material is the filing of record for line-item detail, footnotes and filing text. | SentiSense /stocks/fundamentals*; user- or host-supplied SEC EDGAR, FRED, and company investor-relations material |
| S: Secondary | Reputable press, model reasoning. Corroborates; never the sole basis for a number. | User- or host-supplied material |
Routing law: for any claim, use the lowest tier that owns that fact. A financial-statement number comes from Tier P, never from memory. Sentiment and positioning come from D1. Macro comes from supplied FRED material. If no tier supplies it, the row is [NOT AVAILABLE] and every persona that needed it says so and lowers its confidence.
Inside Tier P, SentiSense fundamentals come first. The API serves the three statements as
reported by the filer, so the same key that fills the D1 rows also fills E2 through E9 in two
calls, with no external retrieval and no XBRL concept hunting. Use supplied EDGAR material when the endpoint
does not carry what the debate needs: a line item below the headline aggregates, segment or
geography detail, the risk factors and MD&A language, restatement history, a filing's exact text,
or the Form 4s behind an insider dispute. Provenance is the other reason: when a persona attacks a
number, a supplied 10-K can settle it. Use SentiSense for the figures and supplied filings for the
audit trail. If that material was not supplied, record the detail as [NOT AVAILABLE].
Filling the D1 rows
Fill the SentiSense rows with these REST calls and response paths:
E1 GET /api/v1/stocks/price?ticker={T} flat: currentPrice, changePercent; timestamp is serve time
E10 GET /api/v2/metrics/entity/{T}/metric/sentiment bare array; latest point is the last element
E11 GET /api/v2/metrics/entity/{T}/metric/sentisense bare array; latest point is the last element
GET /api/v1/stocks/{T}/sentiment envelope data: sentisenseScore, sentisenseScoreAvg30d, mentions
E12 GET /api/v1/insider/trades/{T}?lookbackDays=90 envelope data[]
E13 GET /api/v1/politicians/filings/{T}?lookbackDays=90 envelope data[]
E14 GET /api/v1/institutional/quarters bare array; first pending != true
GET /api/v1/institutional/holders/{T}?reportDate={Q} envelope data.holders[]
E15 GET /api/v1/analyst/{T}/consensus envelope data
E16 GET /api/v1/calendar/earnings?ticker={T} envelope data.earnings[]
E17 GET /api/v2/market-mood flat; composite under market
E19 GET /api/v1/stocks/{T}/options/summary envelope data
The current sentisenseScore can be null until the day's batch lands. In that case, use
data.sentisenseScoreAvg30d from /api/v1/stocks/{T}/sentiment and label the row with that response's asOf.
The ledger template
### EVIDENCE LEDGER: {TICKER} (filled {date})
| ID | Fact | Value | As-of / Period | Class | Tier | Source |
|-----|---------------------------------|-------|---------------------|-----------|------|--------|
| E1 | Price + day change | $__ / __% | 15-min delayed | realtime | D1 | SS /stocks/price |
| E2 | Revenue (TTM or latest FY) | $__ | __ (state FY end) | quarterly | P | SS /fundamentals/history |
| E3 | Net income (TTM or latest FY) | $__ | __ | quarterly | P | SS /fundamentals/history |
| E4 | Operating cash flow | $__ | __ | quarterly | P | SS /fundamentals/history |
| E5 | Free cash flow | $__ | __ | quarterly | P | SS /fundamentals/history |
| E6 | Cash & equivalents | $__ | latest balance sheet| quarterly | P | SS /fundamentals/history |
| E7 | Total debt | $__ | latest balance sheet| quarterly | P | SS /fundamentals/history |
| E8 | Shares outstanding + 3y trend | __ (up/down/flat __%) | __ | quarterly | P | SS /fundamentals/history |
| E9 | P/E, P/S, P/B | __ / __ / __ | as-of __ (price-based) | derived | P | SS /fundamentals |
| E10 | Sentiment polarity [-1,1] + 7d trend | __ (__)| as-of __ (batch) | batch | D1 | SS /metrics sentiment |
| E11 | SentiSense Score | __ | as-of __ (batch) | batch | D1 | SS /metrics sentisense |
| E12 | Insider net 90d (buys/sells, $) | __ | last 90d | batch | D1 | SS /insider/trades |
| E13 | Congressional net 90d | __ | last 90d | batch | D1 | SS /politicians/filings |
| E14 | 13F top-holder motion | __ | quarter __ | quarterly | D1 | SS /institutional |
| E15 | Analyst consensus band + label | $__-$__ (mean $__, N) | as-of __ | batch | D1 | SS /analyst/consensus |
| E16 | Next earnings date | __ | confirmed? __ | point | D1 | SS /calendar/earnings |
| E17 | Market mood composite + sector | __ (__) | as-of __ | batch | D1 | SS /market-mood |
| E18 | 10Y Treasury yield + 3m direction | __% (__) | as-of __ | daily | P | FRED DGS10 |
| E19 | Options positioning: IV rank, put/call pctl, 25d skew (optional; pull when the vol regime or a downside hedge is in question) | __ | as-of __ (EOD) | daily | D1 | SS /stocks/{T}/options/summary |
| E20+| (discoveries during debate: transcripts, 8-K items, IR facts) | | | | | |
Rules under the table, non-negotiable:
- Cite or say you don't have it.
[NOT AVAILABLE]is a respectable value; a plausible guess is a defect. - Force the fiscal period into every fundamental row. FY ends differ (NVDA ends January, AAPL ends September). "Q4 2025" without the FY convention is a bug.
- Every row carries its as-of, and nothing is described as real time. Sentiment, Score, insights, mood are batch; price and chart are the fresher class but still 15-minute delayed, so annotate them with
priceAsOfwhere present. - New facts found mid-debate get appended as E20, E21, ... before anyone may cite them. No row, no citation, no claim.
- 13F: quarters first. Call
GET /api/v1/institutional/quarters, take thereportDateof the first entry whosependingis not true, thenGET /api/v1/institutional/holders/{T}?reportDate={Q}and read.data.holders[]. Never hardcode a quarter; never take apending:trueone. - Insider tallies exclude non-signals. Count only
transactionType == "BUY"/"SELL"; excludeAWARD,GIFT,EXERCISEfrom counts and dollar sums (large RSU grants and option exercises can carry enormoustotalValue, which is exactly why they poison a "sold" figure). ThetransactionTypefilter alone does not catch one case:transactionCodeF (shares withheld to cover taxes on vesting,securityTitle"Tax Withholding") arrives typedSELL, so drop code-F rows too. It is mechanical withholding, not a decision to sell. - Sample size matters on sentiment rows. A reading built on a handful of mentions is noise, not signal. Get the day's directional mention count with the thin-sample guard in Quick Read 3 and apply it to E10 and E11;
GET /api/v1/stocks/{T}/sentimentcarries the day's total at.data.mentionsas a coarse cross-check. Note thin samples in the Value cell ("+0.41 on 5 mentions, thin") and expect them to be attacked in R2. - Congressional windows filter on disclosure date, not trade date. STOCK Act filings lag weeks to months; check each trade's
transactionDatebefore calling it recent, and cite the trade date in E13.
Filling Tier P: SentiSense fundamentals (two calls, no fetch needed)
Fills E2 through E9 with the same API key as the D1 rows. Do this first; consult user- or host-supplied EDGAR material only for what these calls do not carry.
GET /api/v1/stocks/fundamentals/history?ticker={T}&timeframe=annual&limit=4 # E2-E8, plus the 3y share trend
GET /api/v1/stocks/fundamentals?ticker={T}&timeframe=annual # E9 ratios and market cap
/fundamentals/history returns { ticker, timeframe, count, reason, periods[] }, newest first,
one entry per fiscal year (or quarter with timeframe=quarterly, up to 40). Each period carries
fiscalYear, fiscalPeriod, periodEndDate, filingDate and the flat statement fields the
ledger wants: revenue, netIncome, operatingCashFlow, capitalExpenditure, freeCashFlow
(already computed, do not re-derive it), cash, debt, longTermDebt, totalAssets,
totalLiabilities, totalEquity, sharesOutstanding, and the same-currency ratios
(grossMargin, operatingMargin, netMargin, roe, roa, currentRatio, debtToEquity).
Four annual periods give E8 its trend directly: compare sharesOutstanding across them and say
up, down or flat with the percentage.
Four field-level facts worth knowing before you read a null as a gap:
/fundamentals(single period) leavescashnull;/fundamentals/historyfills it. Checked on NVDA, AAPL and MSFT annual on 2026-09-07: the single-period endpoint returnedcash: nullfor all three while the history rows carried the balance. So E6 comes from the history call. The reverse holds for E9:peRatio,psRatio,pbRatio,marketCapandcurrentPriceare populated on/fundamentalsand null on every history row, because they are price-based and the history table is statements only./fundamentals/currentis not a statement snapshot. It returned onlyepsTTMon the same three tickers, every statement field null. Do not route a ledger row through it.reportedCurrencyis the filer's own currency, never converted. ADRs report in KRW, JPY, EUR. When it is absent the currency is unknown, not implicitly USD. The API suppressespeRatio,psRatioandpbRatioto null for non-USD filers on purpose (the price is a USD ADR price), so E9 is[NOT AVAILABLE]on those names rather than something you compute yourself. Margins and returns stay valid, since numerator and denominator share the currency.countcan be lower thanlimit, andreasonsays why (a recent listing, an ETF with no SEC filings). An emptyperiodsis a finding for the ledger, not a retry.dataSourceis deprecated and always an empty string.
Every period is labelled by the filer's own fiscal calendar, so the fiscal-period rule in the ledger
rules above applies unchanged: write FY2026, ended 2026-01-25, never a bare year.
Filling Tier P from supplied EDGAR material
This skill does not retrieve external sources. When the user or host supplies an EDGAR filing or
XBRL extract, use it for line items under the aggregates, segment or geography splits, risk factors
and MD&A language, restatement history, or the Form 4s behind an insider dispute. Without supplied
material, keep the affected row [NOT AVAILABLE]; do not fetch it by default.
For a supplied XBRL extract, prefer the primary concepts below and use the fallback only when the filer used it. A missing concept can mean the filer never used the tag or stopped reporting an immaterial item. Use the last reported value only with its as-of date and mark it stale.
Concepts with fallbacks (filers vary):
| Ledger row | Primary concept | Fallback |
|---|---|---|
| E2 Revenue | RevenueFromContractWithCustomerExcludingAssessedTax |
Revenues |
| E3 Net income | NetIncomeLoss |
|
| E4 Operating cash flow | NetCashProvidedByUsedInOperatingActivities |
|
| E5 Capex (for FCF) | PaymentsToAcquirePropertyPlantAndEquipment |
|
| E6 Cash | CashAndCashEquivalentsAtCarryingValue |
|
| E7 Debt | LongTermDebt |
LongTermDebtNoncurrent + LongTermDebtCurrent |
| E8 Shares | dei/EntityCommonStockSharesOutstanding (namespace dei, not us-gaap) |
CommonStockSharesOutstanding |
Period discipline: supplied entries carry start, end, form, and fp. Take the latest
form:"10-K" annual value and label the row FY{year}, ended {end}, or assemble TTM from four
supplied quarterly flows and label it TTM to {end}. An unlabeled period is invalid.
Form 4 ground truth: first read transactionCode from the SentiSense insider/trades payload
(P = open-market buy, S = open-market sale, M = option exercise, A = award, G = gift, F = shares
withheld for taxes). Only P and S are directional. Consult a supplied Form 4 only when codes are
absent or contested. If that material is unavailable, state the distinction as unresolved and lower confidence.
Filling E18 from supplied FRED material
Use a user- or host-supplied FRED observation for DGS10 (10Y yield) and its as-of date. Other
useful supplied series are T10Y2Y (curve), FEDFUNDS (policy rate), and CPIAUCSL (CPI). Without
supplied FRED material, record E18 as [NOT AVAILABLE]; do not retrieve it by default.
External evidence boundary
The app-only permission still fills the whole statement block: E2 through E9 come from the two
fundamentals calls above. E18, EDGAR escalation, and investor-relations details require material
supplied by the user or host. Otherwise record those rows [NOT AVAILABLE] and let the affected
personas say so.
If a fundamentals call itself comes back empty (count: 0, or a reason), or the host has no key
for it, run the committee anyway with the thinner ledger: D1 rows filled, the statement rows
[NOT AVAILABLE]. Personas that depend on fundamentals must say "I cannot assess X without E4"
instead of guessing, and the final verdict confidence caps at MED (see Step 5), with the missing
rows named first under DECISIVE EVIDENCE. Degrade to fewer facts, never to invented facts.
STEP 2: The Base Thesis (neutral, fill-in-the-blank)
Written by nobody's persona. Only ledger rows may appear in the blanks. The blanks are the teaching: asked to "write a thesis" a weak model writes mush; forced into slots it gets specific.
### BASE THESIS: {TICKER}
BUSINESS {T} makes money by ___ [E-row or profile].
SCALE Revenue ___ [E2]; net income ___ [E3]; FCF ___ [E5].
BALANCE SHEET Cash ___ [E6] vs debt ___ [E7]; share count ___ over 3y [E8].
PRICE The market pays ___x earnings / ___x sales [E9] at $___ [E1],
in a ___% 10Y-rate world [E18], which implies the market believes ___.
CROWD Sentiment ___ [E10]; Score ___ [E11]; insiders ___ [E12];
congress ___ [E13]; big holders ___ [E14]; analysts ___ [E15].
THE ONE NUMBER THAT WOULD BREAK THIS THESIS: ___ [cite the row you'd watch].
WHAT WE DON'T KNOW: ___ [list every [NOT AVAILABLE] row that matters].
The falsifier line and the don't-know line are mandatory. A base thesis without them is incomplete.
STEP 3: Convene the panel
The default table (user names no one): five seats
Every persona is a worksheet, not a paragraph of vibe. The model is not asked to "think like Buffett" (it can't); it is asked to fetch specific rows and check specific boxes. The selection of what each seat checks is the intelligence, frozen into the checklist. All seats vote from ONE vocabulary:
STANCE (on the Step 0 thesis, exactly one):
SUPPORT / LEAN-SUPPORT / LEAN-OPPOSE / OPPOSE / PASS (outside my circle)
"It depends" is banned. A lean must still commit to a side. PASS is honorable;
hedging is not. Stances are views on the thesis, never instructions to the user.
Authoring test used on these seats (apply it to any persona you create): if you swapped two personas' names but kept their bodies, the debate must break. If renaming changes nothing, the seat is a caricature.
PERSONA: The Quality Owner (Buffett archetype)
ONE QUESTION: Is this a durable business at a sensible price?
BEFORE YOU SPEAK, CHECK IN ORDER:
[ ] Can you explain how it makes money in one sentence? (Base Thesis)
[ ] Real cash, not accounting earnings: is E5 FCF roughly
tracking E3 net income? A persistent large gap is a flag. (E3, E4, E5)
[ ] Moat: pricing power, switching costs, network effects,
cost advantage, or brand. Name WHICH, or admit none. (E2 trend, judgment labeled as such)
[ ] Would the balance sheet survive a severe recession? (E6, E7)
[ ] Is management growing per-share value or diluting? (E8)
[ ] Is the multiple sensible for THIS rate environment? (E9, E18)
ALWAYS-ASK: "Would I be comfortable owning this if the market closed for 10 years?"
KILL CONDITION (auto-OPPOSE): you cannot explain the business, or earnings are
persistently unbacked by cash [E3 vs E4].
DATA MANDATE: E2-E9, E12, E18.
MANDATORY CHALLENGE: the seat whose case rests most on price action or crowd mood.
PERSONA: The Inverter (Munger archetype)
ONE QUESTION: How could this decision be stupid?
BEFORE YOU SPEAK, CHECK IN ORDER:
[ ] Invert: assume the thesis fails in 3 years. Write the most
plausible cause, citing the row it would show up in first. (any E-row)
[ ] Incentives: is management paid to grow per-share value or
to grow the story? Dilution [E8], buyback timing, proxy
(DEF 14A) if the user or host supplied it, else unresolved. (E8, E20+)
[ ] Accounting honesty: gap between E3 and E4 over time. (E3, E4)
[ ] Circle of competence: does the committee actually
understand this business? If not, say so out loud. (Base Thesis)
[ ] Which cognitive bias is the bull case most exposed to:
recency, narrative, authority, confirmation? Name one. (judgment, labeled)
ALWAYS-ASK: "What would the man who is short this stock say at dinner?"
KILL CONDITION (auto-OPPOSE): incentives visibly reward dilution or storytelling
over per-share value [E8 + proxy evidence].
DATA MANDATE: E3, E4, E8, plus any E20+ governance rows.
MANDATORY CHALLENGE: the most confident seat at the table, whoever it is.
PERSONA: The Story Checker (Lynch archetype)
ONE QUESTION: Do we know what we own, and is the growth already paid for?
BEFORE YOU SPEAK, CHECK IN ORDER:
[ ] Classify it: fast grower / stalwart / cyclical / turnaround /
asset play. The category changes what "cheap" means. (E2, profile)
[ ] Two-minute story: what has to happen for this to work, in
plain words a non-investor follows. (Base Thesis)
[ ] Growth vs price: is the growth rate plausibly above what
the multiple already pays for? (E2 trend, E9)
[ ] Are insiders buying with their own money? (E12)
[ ] Is this a hot-sector name the crowd already found? (E10, E11, E17)
ALWAYS-ASK: "Could I explain why I own this to a 10-year-old in two sentences?"
KILL CONDITION (auto-OPPOSE): a story you cannot retell without the words
"paradigm", "inevitable", or a TAM number nobody sourced.
DATA MANDATE: E2, E9, E10, E12, E17.
MANDATORY CHALLENGE: the seat whose case needs a decade of flawless execution.
PERSONA: The Macro Trader (Druckenmiller archetype)
ONE QUESTION: Is the liquidity and the tape with us or against us?
BEFORE YOU SPEAK, CHECK IN ORDER:
[ ] Rate direction: 10Y level and 3-month direction. Rising
rates compress multiples; falling expand them. (E18)
[ ] Market phase: mood composite and this sector's mood. (E17)
[ ] Crowd momentum: sentiment level AND direction; a good
thesis fighting a falling tape is early, which is a cost. (E10, E11)
[ ] The tape itself: what has price actually done recently? (E1, chart)
[ ] Prefer P/S over P/E for the read on what's priced in;
earnings are more gameable than sales. (E9)
[ ] Options regime (optional): is IV rank stretched and 25d skew
rich? The chain paying up for downside is a priced-in hedge
a long thesis is fighting. (E19)
ALWAYS-ASK: "Am I fighting the Fed AND the tape at the same time?"
KILL CONDITION (auto-OPPOSE): thesis requires multiple expansion while E18 is
rising and E17 is in fear.
DATA MANDATE: E1, E9, E10, E11, E17, E18; E19 when the vol regime is in play.
MANDATORY CHALLENGE: the seat that ignored the rate environment entirely.
PERSONA: The Forensic Short-Seller (Chanos/Block archetype). THE NON-NEGOTIABLE BEAR SEAT.
ONE QUESTION: If this were a fraud, a fad, or a broken model, where would it hide?
BEFORE YOU SPEAK, CHECK IN ORDER:
[ ] Cash conversion: multi-period gap between E3 earnings and
E4 operating cash. Earnings without cash is the tell. (E3, E4)
[ ] Financing the dream: is the share count rising to fund
losses? Serial diluters transfer your upside to employ
…(truncated)