Use cases / Forecasting and research

Event forecasting against an evidence bundle

Will it happen? One probability per market, from the evidence you collected.

Unit
One market: criterion, date, evidence bundle
Ask
Met by the date? Which kind of evidence decides it?
Get
A review queue with p(yes) next to the market price

Files · 1 reducers · 2 questions · updated Sep 21, 2026

The flow

0 evidence items source snapshot 2026-09-20
0 Group by market group no model call
0 Attach criterion and price join from markets.jsonl
0 Judge the proposition reducer requests, 2 questions each
0 Keep conviction ≥ 0.70 filter p(yes) ≥ 0.70
0 Review queue output with the market price beside p

Evidence is the volume. Markets are the unit. One request reads the whole bundle. 310 requests for 2,140 items. 92 in the review queue. 218 excluded, kept for calibration.

Follow one record

What comes out

Forecast desk, review queuerun 3be07d21, 92 rows, sorted by p(yes)
Marketp(yes)PriceDecisive kindResolvesItems
M-2044 Vendor ships v2 before Q40.880.81primary document2026-09-309
M-2031 Council approves transit levy0.740.58primary document2026-10-146
M-2019 Injunction ruling before Oct 10.720.70official statement2026-09-3011
M-2052 Merger review completes by Nov 300.710.44reporting2026-11-3014
M-2007 Stadium bond passes at referendum0.700.66market data2026-11-038

Synthetic rows in the app's Outputs layout. The model never sees the price; it is joined from the markets file so the reviewer can see the disagreement.

Details, if you want them

whyWhy this shape

Why this shape

  • The bundle is the state. Every item read together, once.
  • The criterion is the question. Verbatim, date included.
  • The price stays out of the request. Joined for the reviewer only.
  • Disagreement is the queue. p(yes) next to price, sorted.

How it gets scored

  1. Run weekly on fresh snapshots.
  2. Add resolutions as markets settle. Join on market_id.
  3. Bucket by p(yes). Read the resolved share per bucket.
  4. Replay with another model or wording. Compare the tables.

Nothing here trades.

questionsThe 2 questions, verbatim
  • Judge the proposition outcomebinary, noul

    Based only on `evidence`, will the criterion in `market.resolution_criterion` be met on or before `market.resolution_date`?

  • Judge the proposition decisive_kindcategorical, choice

    Which kind of item in `evidence` most determines the answer to the previous proposition?

    primary documentofficial statementreportingmarket datanone
buildHow each stage is built, as JSON
1 group Group by market
Deterministic. Evidence items are grouped on market_id. Each group is the bundle the model will read for that market, and only that market. Nothing outside the bundle reaches the request.

stage definition

{
  "id": "by_market",
  "input": "source:evidence",
  "key": [
    "market_id"
  ],
  "kind": "group",
  "name": "Group by market"
}
2 join Attach criterion and price
A join against the markets snapshot adds the resolution criterion text, the resolution date and the price at snapshot time. The price is not shown to the model; it is carried for the outputs table so a human can compare.

stage definition

{
  "id": "with_market",
  "input": "by_market",
  "kind": "join",
  "left_key": [
    "input",
    "key"
  ],
  "name": "Attach criterion and price",
  "right": "source:markets",
  "right_key": [
    "id"
  ]
}
3 reducer Judge the proposition
One request per market. outcome is a probability for the exact criterion text with the date written into it. decisive_kind says which kind of item carried the answer, so a reviewer knows whether to trust a primary document or a news report. The instructions say “based only on evidence” because Jev fetches nothing.

stage definition

{
  "id": "judge",
  "input": "with_market",
  "kind": "evaluate",
  "model": "jev",
  "name": "Judge the proposition",
  "questions": {
    "decisive_kind": {
      "criteria": {
        "market_data": "Prices, polls or other measured indicators",
        "none": "No item is decisive",
        "official_statement": "A statement by a party with authority over the outcome",
        "primary_document": "An official record, filing, agenda, ruling or vote tally",
        "reporting": "Journalism or analysis about the outcome"
      },
      "instructions": "Which kind of item in `evidence` most determines the answer to the previous proposition?",
      "type": "choice"
    },
    "outcome": {
      "instructions": "Based only on `evidence`, will the criterion in `market.resolution_criterion` be met on or before `market.resolution_date`?",
      "type": "noul"
    }
  },
  "state_path": []
}
4 filter Keep conviction ≥ 0.70
A comparison on the stored probability. It shortens the review queue; it does not delete anything. The 218 markets below the line keep their probabilities, which the calibration join needs later.

stage definition

{
  "comparison": "gte",
  "field": [
    "answers",
    "outcome",
    "probability"
  ],
  "id": "conviction",
  "input": "judge",
  "kind": "filter",
  "name": "Keep conviction ≥ 0.70",
  "value": 0.7
}
5 definition The whole workflow, as saved

Saving publishes an immutable version. A run freezes this definition, the snapshot IDs and each reducer’s model profile, so the trace can always show exactly what ran. Edits create a new version; old runs keep theirs.

jevreduce.local.v1

{
  "name": "Event forecasting against an evidence bundle",
  "schema_version": "jevreduce.local.v1",
  "sources": {
    "evidence": "snap_evidence_2026-09-20",
    "markets": "snap_markets_2026-09-20"
  },
  "stages": [
    {
      "id": "by_market",
      "input": "source:evidence",
      "key": [
        "market_id"
      ],
      "kind": "group",
      "name": "Group by market"
    },
    {
      "id": "with_market",
      "input": "by_market",
      "kind": "join",
      "left_key": [
        "input",
        "key"
      ],
      "name": "Attach criterion and price",
      "right": "source:markets",
      "right_key": [
        "id"
      ]
    },
    {
      "id": "judge",
      "input": "with_market",
      "kind": "evaluate",
      "model": "jev",
      "name": "Judge the proposition",
      "questions": {
        "decisive_kind": {
          "criteria": {
            "market_data": "Prices, polls or other measured indicators",
            "none": "No item is decisive",
            "official_statement": "A statement by a party with authority over the outcome",
            "primary_document": "An official record, filing, agenda, ruling or vote tally",
            "reporting": "Journalism or analysis about the outcome"
          },
          "instructions": "Which kind of item in `evidence` most determines the answer to the previous proposition?",
          "type": "choice"
        },
        "outcome": {
          "instructions": "Based only on `evidence`, will the criterion in `market.resolution_criterion` be met on or before `market.resolution_date`?",
          "type": "noul"
        }
      },
      "state_path": []
    },
    {
      "comparison": "gte",
      "field": [
        "answers",
        "outcome",
        "probability"
      ],
      "id": "conviction",
      "input": "judge",
      "kind": "filter",
      "name": "Keep conviction ≥ 0.70",
      "value": 0.7
    }
  ]
}
limitsWhat it will not do
  • Conditioned on your bundle. Missing evidence, missing signal.
  • Dates are a documented Jev weak spot. Put the date in the criterion text.
  • Calibration is measured against resolutions, not assumed.
  • A research desk tool. No orders, no investment advice.
  • Text only. Extract charts and PDFs first.
relatedRelated pages

Try it on your own records.