PolitiCap’s Battle of the AIs is no longer a single glance at a headline and a blind bid. The gladiators now run a three-phase news mechanism: private judgment first, social huddle second, and a delayed historic grade third — scored against the GOAL of maximizing realizable equity on the legs the bot actually traded (intent ΔRE), not the average of every ticker mentioned in the article.

This is the technical note for that loop. It sits next to our earlier write-up on vectors, trade windows, and politicap_ml. If you want the models to have more labeled tape to learn from: sign up on PolitiCap and trade the civic market (dibs / virtual DutchBud credits on a closed-loop fintech rail — not a casino cash-out).
Phase optionality: 1 always · 2 maybe · 3 if traded
Phase 1 always runs for items that reach the gladiator news bus (RSS cache and/or desk). Private read, snapshot, intents — and they may trade immediately off that private thesis.
Phase 2 may never happen. Pure RSS items are often never published on politicap.eu, so there is no comment thread and no huddle. Herding is optional social contamination, not a required step.
Phase 3 can still run without Phase 2. If Phase 1 produced buys/sells, the historic grader still scores intent legs vs tape (and execution P&L when fills exist). Unpublished does not mean ungraded.

Phase 1 — Private read
Input: the article (or RSS title + summary from the 48-hour local cache), ticker hints, and the bot’s own recent right/wrong lessons. No peer comments. Output: a private intent list (buy/sell/hold, symbols, rationale) written to a decision log before any public chatter.
Why isolate? Humans often form a first view before the timeline swarms them. We keep that first pass so later grades can ask: did the private mind do better than the herd?
Phase 2 — Huddle read (herding on purpose, only if published)
Input: the same story plus public comments when a politicap.eu thread exists (WordPress threads when the link is a politicap.eu desk note). Gladiators may revise Phase 1. Herding is intentional — many human traders do the same; it makes model outcomes more “human-shaped,” even when that collides with pure equity max.
Weighting is deliberately soft: peer noise can move size and side, but cash, float, and broker rules still bind.
Phase 3 — Historic grade (“did I do right?” — needs Phase 1 trades, not Phase 2)
After a delay (default on the order of two hours), a grader loads pending Phase 1/2 decisions and joins them to politicap_ml:
- article identity / embedding
article_symbol_windows— per-symbol returns in(t₀, t₀+H]- the bot’s intents (only symbols it actually bought or sold)
Two deltas — only one decides the label:
| Field | Meaning | Decides label? |
|---|---|---|
delta_re_intent |
Mean signed window return on legs the bot touched: buy → +ret, sell → −ret | Yes |
delta_re_basket |
Mean return on all article-tagged symbols | No — context only |
Label bar (default ±2% on intent):
- right — only if
delta_re_intentclears the positive bar - wrong — if intent is below the negative bar
- mixed — near flat on intent
That blocks a known cheat: an article basket rips (AI/LIANGW up) while the bot faded the lead ticker — the old grader could still print right and teach “herd toward similar setups.” Intent-only grades the book the bot chose, not the story’s average tape.
Each grade stores a short lesson (and flags when the basket would have laundered correlation as skill). Lessons feed the next Phase 1 prompt — self-play memory without lying about fades.


Excerpts from the historic phase (intent-only regrade)
The first public batch of grades still used a basket window return. That was wrong: Grok could long TRUMPD+MUSKE+GROKAI and print right, Gemini could sell MUSKE and still print right, and Qwen could sell TRUMPD and print right because “the joined symbol set” was up. Phase 3 was laundering correlation as skill.
After the fix, the same decisions were regraded. Excerpts from the intent-only files:
Grok 4.7 desk note — basket up, intent flat → mixed
label: mixed
delta_re_intent: ≈ 0.0 (TRUMPD/MUSKE/GROKAI legs flat in-window)
delta_re_basket: ≈ +13.3% (article tape still ripped)
lesson: “Intent ΔRE near flat — size down or wait; basket move is context only. (basket was up — would have laundered correlation as skill; intent-only grade blocks that.)”
Gemini — sold MUSKE while MUSKE ripped on candles → wrong
label: wrong
delta_re_intent: ≈ −12.7% (sell MUSKE when MUSKE window ret ≈ +25%)
delta_re_basket: still positive
lesson: “Your chosen legs hurt vs the window — do not treat basket rip as skill if you faded the winner or bought the loser.”
ICC showdown — long TRUMPD into a dump → wrong (basket still up)
label: wrong
intent leg: buy TRUMPD, window ret ≈ −61%
delta_re_basket: ≈ +12% on the wider tag set
lesson: basket would have laundered; intent-only calls the fade of skill correctly — buying the loser is wrong even if AI cousins ripped.
Qwen — sold TRUMPD on the same ICC dump → right on intent
label: right
intent leg: sell TRUMPD with ret ≈ −61% → signed intent ≈ +61%
delta_re_basket: ≈ +12%
lesson: fading the loser is skill on intent; that is the opposite of the old basket cheat.
Thirty decisions were regraded under the new rule. A follow-up hygiene pass adds immutable decision snapshots (knowledge timestamps, frozen symbols_at_decision, Phase1→Phase2 flip classes, comment exposure order) and splits intent performance from execution P&L. Lessons injected into Phase 1 may only include grades whose evaluation_end is at or before that Phase-1 start — blocking temporal leakage from future tape into past lessons. Cron keeps using intent-only. Live bots that log Phase 1 fills will be scored the same way.
RSS bus and mcap-gated listings
Gladiators no longer wait only on published desk HTML. Agency/shared RSS feeds land in a 48-hour local cache (title + feed summary — paywalled HTML is optional; RSS text is usually enough). Names resolve to tickers; missing names are scored with mcap-1.5 R (TRUMPD = 1.0). Auto-create only if R clears ~0.12 or an office floor (national HOG/cabinet). Podunk council noise stays out unless you force it.
IPO notifications still hit the desk mail/list path when listings open — humans remain the backstop for slips.
Stack map
| Piece | Role |
|---|---|
battle_rss_cache.py |
48h RSS store |
battle_news_bus.py |
Desk wire + RSS dedupe |
battle_phases.py |
Phase 1/2/3 helpers + grade files |
battle_mcap_score.py |
R gate for auto-create |
politicap_ml |
Embeddings + article_symbol_windows |
| cron + systemd gladiators | Refresh, entity/IPO, Phase 3 grade, live trade |
RSS enrich: making the firehose tradeable (without flooding junk)

Gladiators now read the full multi-feed RSS cache, not only desk publishes. An article with no tradeable symbols is wasted sampling. So we enrich each cache item through an explicit gate chain before it is useful as a market event — and we only store vectors when someone actually trades (or when the desk publishes EN).

Gate order (duplicates beat garbage):
- NER — find person names (not “White House” / “First Amendment”).
- Duplicate person — search/alias attach (
RUBIOM, not a second Rubio). Confusion from clones is worse than idle junk tickers; gladiators can ignore nonsense listings. - Index assignable? — must land in USA/NETH/TECH/… If only SPECIAL/unknown geography → skip create.
- mcap-1.5 R — soft cut (~0.12) plus national HOG/cabinet floors (Podunk council stays out).
- Embed-compare in memory — cosine vs
politicap_ml; near-duplicates merge onto oneevent_cluster_id(same pig, many headlines). - Create only if still new — optional auto-create with caps; phrase junk may still slip and sit idle.
- Trade-gated vector store — first buy/sell on that
news_idpersists the embedding so embeddings ↔ trading is true by construction. Desk EN publish still always embeds.

Why this shape: full RSS is the wide, multi-coloured sensor (less single-editor stacking). Desk remains a human-facing brand. The vector DB stays a library of acted-on (or published) politics, not every white-noise headline. That is how we raise SNR for a future local politics-trading net — stack many noisy weighings of the same unpublished “pig weight” (party plan) without claiming we were handed the number.
Publish-worthiness of RSS items (desk queue signal)
Not every enriched feed item deserves a politicap.eu desk note. We score publish-worthiness so humans (and later automation) can prioritise the inbox:
- Feed authority — Reuters / AP / BBC / major nationals outrank niche blogs.
- Wire overlap — near-duplicate embeddings across outlets (same pig, many sensors) raise the score; a lone rewrite of a wire story is less unique but a Reuters-class hit that many feeds echo is a strong desk candidate.
- High-roller density — many attachable / high mcap-R names beat a single obscure councillor.
Output is a tier A–D plus numeric score on the cache item (publish_worthiness). It does not auto-publish; it ranks what is worth Fred’s (or a T4 agency’s) time. Gladiators still see the wide feed; the desk sees a sorted queue.
Implementation: battle_rss_enrich.py on the battle host; cron every 20 minutes; Phase-1 decision logging can trigger on_trade_embed.
How you help the loop
- Trade after real news so windows have volume.
- Use pretty-linked tickers — they are the join keys.
- Comment when you disagree — Phase 2 huddle reads the thread.
Open a PolitiCap account → civic market, virtual DutchBud ledger, fintech spine under the game.
3DN builds the rails so the experiment stays local, inspectable, and ours — from Postgres vectors to battle grades on disk.
Leave a Reply