Skip to content

Repository files navigation

Cross-Platform Event Matching

This repository contains a methodology and CLI tools for matching records that refer to the same real-world event across platforms such as Kalshi and Polymarket, even when names, tags, and IDs differ.

Methodology

  1. Canonicalize records Normalize every platform export into a common shape: source, event_id, title, description, tags, category, and date-like fields. Preserve the raw record for audit/debugging.

  2. Normalize comparable text Lowercase, strip punctuation/accents, remove platform boilerplate words, and tokenize the title, tags, and description. Extract structured signals such as dates, years, percentages, prices, and other numeric thresholds.

  3. Generate candidates with blocking Avoid all-pairs comparison at scale. Put records into blocks based on shared title tokens, tags, dates, years, entities, metrics, geography, and numeric thresholds. For large files, also add TF-IDF nearest-neighbor candidates when scikit-learn is installed. For small files, the tool scans all pairs.

  4. Score multiple signals Pair scores combine:

    • title token overlap
    • full text token overlap
    • character n-gram similarity
    • fuzzy token-set/token-sort similarity via RapidFuzz when installed
    • tag/category overlap
    • date compatibility
    • number/threshold compatibility
    • structured entity/domain/metric/geography/comparator compatibility
    • optional sentence-transformer semantic similarity

    Date, numeric, entity, domain, metric, geography, and comparator contradictions apply penalties. The score remains explainable, which is useful for human review and threshold tuning.

  5. Label and cluster Pairs above --threshold are labeled match; pairs above --review-threshold are labeled review. Matched pairs are connected into cluster IDs so the same event can span more than two sources.

  6. Evaluate and tune Build a labeled set of known matches and non-matches. Track precision for match rows and recall across match + review rows. Tune thresholds and feature weights with that labeled set before automating downstream merges.

  7. Train when labels exist Use labeled pairs to train a logistic regression scoring model. The trainer exports a small JSON model that the main matcher can load without depending on scikit-learn at runtime.

Install

The matcher itself has fallbacks for missing optional packages. Install requirements for the better fuzzy scorer and model training:

python3 -m pip install -r requirements.txt

Install the heavier embedding dependency only if you plan to use --embeddings:

python3 -m pip install -r requirements-embeddings.txt

Usage

python3 event_matcher.py examples/events.jsonl --output matches.csv

Multiple files are supported. If a record lacks a source, the filename stem is used.

python3 event_matcher.py kalshi_events.json polymarket_events.csv --output matches.json

Use a review queue:

python3 event_matcher.py events.jsonl \
  --threshold 0.80 \
  --review-threshold 0.60 \
  --output matches.csv

Emit every scored pair, including non-matches:

python3 event_matcher.py events.jsonl --all-pairs --output scored_pairs.csv

Use optional embeddings for semantic similarity:

python3 event_matcher.py events.jsonl --embeddings --output matches.csv

Evaluation

Create a labeled CSV with known matches and non-matches:

source_a,id_a,source_b,id_b,is_match
kalshi,KXPRESTRUMP-24,polymarket,0xtrump2024,1
kalshi,KXPRESTRUMP-24,polymarket,0xsenate2024,0

Run the evaluator:

python3 evaluate.py examples/labels.csv examples/events.jsonl --errors errors.csv

Example report:

pairs: 6
positive_labels: 2
negative_labels: 4
auto_match precision=1.000 recall=1.000 f1=1.000 tp=2 fp=0 tn=4 fn=0
match_or_review precision=1.000 recall=1.000 f1=1.000 tp=2 fp=0 tn=4 fn=0

auto_match measures only confident matches. match_or_review measures how many true matches would be caught by either automatic matching or the human review queue.

Training

Train a lightweight logistic-regression model from labeled pairs:

python3 train_matcher.py examples/labels.csv examples/events.jsonl --output matcher_model.json

Include embeddings as a trainable feature after installing requirements-embeddings.txt:

python3 train_matcher.py examples/labels.csv examples/events.jsonl --embeddings --output matcher_model.json

Use that model for scoring:

python3 event_matcher.py examples/events.jsonl --model matcher_model.json --output matches.csv

Input Schema

The loader accepts JSON, JSONL/NDJSON, and CSV. Field names are flexible:

  • source: source, platform, venue, exchange
  • ID: event_id, id, ticker, slug, market_id, condition_id
  • title: title, name, question, headline, event_title
  • text: description, subtitle, details, rules, resolution_criteria
  • tags: tags, tag, categories, category, topics, topic
  • dates: date, event_date, end_date, close_time, expiration_time, resolution_date

Example JSONL:

{"source":"kalshi","event_id":"KXPRESTRUMP-24","title":"Will Donald Trump win the 2024 US presidential election?","tags":["Politics","Elections"],"end_date":"2024-11-05"}
{"source":"polymarket","event_id":"0xabc","question":"Donald Trump wins 2024 U.S. Presidential Election?","tags":["Politics"],"resolution_date":"2024-11-05"}

Output

CSV/JSON output includes:

  • label: match, review, or no_match when --all-pairs is used
  • score: normalized 0-1 similarity score
  • cluster_id: connected component ID for confident matches
  • source/ID/title for both records
  • explanation: top feature scores and shared signals

Production Extensions

The highest-leverage improvement is more labeled data. Keep adding hard positives and hard negatives to the evaluation file, especially same-topic non-matches such as candidate vs party, month-specific CPI markets, different thresholds, different leagues, and different offices. Then use evaluate.py after every scoring change and train_matcher.py once the label set is large enough to support a learned model.

About

Explainable event-matching system for cross-platform market and prediction-market analysis

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages