← back to lessons

Investment Intelligence Methodology - Cycle 148

Target: ARGUS /investments route + Invariant Operator cross-correlation layer Date: 2026-05-18 Origin cycle: 148

Hard-banked rules from this cycle

Rule INV-1: For any "watch N actors" intelligence problem, the cross-correlation layer is the structural moat

The per-actor tracker is incremental (any researcher can build a Bloomberg-lite per-name dashboard). The cross-correlation layer surfaces emergent patterns no individual actor can see - and that's the genuine moat.

Three concrete scoring functions implement this:

  1. Convergence Score - per macro theme, count distinct watched actors whose recent activity aligns. Score = N_aligned_active / N_total. Theme-level threshold for HIGH = >= 4/12 (~33%).
  2. Divergence Score - per ticker held by 2+ watched actors, flag buy-vs-sell direction conflict. conflict_score = 2 * min(buy, sell) / total (1.0 = perfect 50/50 split).
  3. Meta-Trigger Detector - per macro signal, threshold-gate the recent move; on trigger, list the theses most affected. Mapping is curated (signal.affects_theses[]) - explicit, not LLM-inferred.

This pattern generalizes: - Big-player investment moves (this cycle) - Audit-firm methodology drift across N firms (extension of lessons-library) - Bug-bounty competitor velocity across N hunter accounts (extension of EYE 14-20) - Pejji-client behavior across N SMEs (Pejji BI layer)

Rule INV-2: Manual-seed data must be tagged at the row level, not the file level

Every JSONL disclosure row carries "source": "manual_seed_cycle148". This way, when real scrapers come online (NGX RNS adapter, Nairametrics RSS, Notion DB pull), the rows from those sources can carry distinct source tags and the manual-seed rows decay out of the visible feed naturally. File-level tagging would force a destructive migration; row-level lets the dataset evolve gracefully.

UI surfaces the source tag as a small badge next to each disclosure so operator can mentally weight reliability per row.

Rule INV-3: NGX has no reliable machine-readable disclosures API (as of 2026-05)

Surveyed: - NGX RNS (Real-time News Service): web-only feed, no documented JSON API. Scrape requires session handling + sometimes auth. - Nairametrics: has RSS but coverage is editorial (not raw filings). - BusinessDay corporate-disclosures: web-only. - AfricanFinancials: paywall.

Decision: v0.1 ships with manual JSONL seed under ~/bounty/lessons-library/investments-data/ngx-disclosures.jsonl. The JSONL contract is stable; future scraper adapters (Nairametrics RSS first, then NGX RNS HTML scrape if needed) write to the same file. The Invariant Operator scoring works on whatever rows are in the JSONL - data source pluggable behind the same contract.

Rule INV-4: LLM prompt-box behind CF Worker needs hard cost caps

The /api/research endpoint must: - Cap input prompt at 4KB - Cap max_output_tokens at 512 (~$0.005-0.05 per call on Sonnet) - Use a stable system prompt that REQUIRES the model to refuse financial advice - Return a safe stub when API key is not configured, so the UI doesn't break during initial deploy

This pattern (stub + real LLM path behind the same response shape) is reusable for any Worker that calls a paid external API.

Rule INV-5: The hash-gate + content-hash pattern from Cycle 146 generalizes

Same pattern reused from Cycle 146 /lessons: 1. Compute sha256 of all data inputs 2. Compare to state file 3. Skip if unchanged, else regenerate + wrangler pages deploy

For /investments, the input set is players.json + ngx-disclosures.jsonl + macro-signals.json + thesis/*.md. Cron-friendly idempotency; wrangler API rate-limit safe.

Multi-surface disclaimer: - Visible warning banner near top of /investments and every drill-in page - Footer reaffirmation - LLM system prompt that explicitly bans recommendations - Each thesis card has explicit INVALIDATION-CONDITIONS section so the operator (and any reader) sees how the analysis falsifies, not just how it confirms

This is risk hygiene for the operator (regulatory + reputation) and intellectual hygiene for the analysis (forces the analyst to articulate falsification ex-ante).

Anti-patterns to avoid

AP-1: Don't conflate "rich JSON schema" with "valid data"

The seeded NGX disclosure rows have null shares + null value_ngn. That's correct - we don't have those numbers, so we represent the absence explicitly with null, not with fabricated estimates. Schema permissiveness > schema fabrication.

AP-2: Don't let Invariant Operator devolve into "LLM summary of everything"

The 3 scoring functions are deterministic Python with explicit thresholds. They are auditable, replicable, and falsifiable. If we replaced them with "ask the LLM what's interesting," we would: - Lose reproducibility - Add per-cycle cost - Make it impossible to A/B different threshold settings - Drift toward overconfident summary-style outputs

The Invariant Operator surfaces three CLASSES of signal explicitly because those are the three real cross-correlation mechanics: convergence (alignment), divergence (conflict), and meta-trigger (impact propagation).

AP-3: Don't deploy LLM endpoints without an auth gate

The /api/research Worker validates Cf-Access-Authenticated-User-Email header. The CF Access edge is the primary gate; the Worker's email-allowlist is defense-in-depth. Both are required because: - CF Access could be misconfigured - A token leak shouldn't yield free LLM access - Operator-only research keeps the moat private

Files produced this cycle

Next-cycle candidates

Generated 2026-07-02 13:15:05 UTC | auto-sync /15min