MECHAPIPELO SPORTS DESK
--:--:--
Limited Time Offer: Deposit $10, receive $50 in Trade Credits. Terms and conditions apply. Join

Novig partner link. Restrictions & requirements apply. Not available in all states. 21+. Event contract trading involves risk & is not appropriate for all. Consider if it's appropriate for you in light of financial circumstances. See novig.com/terms for information.

PAGE

How to automate MechaPip predictions with AI

How to automate MechaPip predictions with AI | MechaPip

Starter guide · free feed → your AI → paper first

MechaPip posts a free board across seven leagues: NFL, NBA, NHL, MLB, WNBA, NCAAF and NCAAMBB. Every league posts the days it plays, and no league is ever cut from posting. Every predictions post carries the same machine-readable block, so you can build your own automation around it: pull the feed, hand it to an AI assistant, and paper trade whatever rules you choose.

Step 1: Pull the feed

  • Feed URL: https://www.mechapip.com/rss.xml
  • The MechaPip Predictions posts carry the slate for every league playing that day; the newest 25 posts stay in the feed.
  • Every game lists: sport, away team, home team, kickoff in UTC, projected winner, win percentage.
  • The machine-readable part is a schema.org block: a <script type="application/ld+json"> ItemList of SportsEvent nodes.
  • The Blogger pack publishes inside a 5am-5pm US Central window on game days: a predictions post for the slate, and a recap grading the finished games, wins and misses.

What one parsed game looks like

[
  {
    "sport": "NFL",
    "away": "Atlanta Falcons",
    "home": "New Orleans Saints",
    "kickoff_utc": "2026-10-06T00:15:00+00:00",
    "projected_winner": "Atlanta Falcons",
    "win_pct": 51
  }
]

Step 2: Hand it to your AI

Paste this into an AI assistant that can write and run code. It writes the fetcher, the parser, and a paper-trading loop that starts safe: DRY_RUN on, a size cap, and a daily stop.

Help me build a small automation around a free public sports predictions feed.

1. Fetch https://www.mechapip.com/rss.xml and select the newest item whose
   title starts with "MechaPip Predictions".
2. In the item description, parse every <script type="application/ld+json">
   block. Each ItemList contains SportsEvent entries: sport, away team,
   home team, kickoff (startDate, UTC), and a description with the projected
   winner and win percentage.
3. Emit one clean JSON array sorted by kickoff: sport, away, home,
   kickoff_utc, projected_winner, win_pct.
4. Add a paper-trading loop. For each game, fetch the current market price
   from your prediction-market venue (most publish a read-only API; a manual
   price sheet works too), compare it with the model win percentage minus
   assumed fees and spread, and log a hypothetical order only when the gap
   is positive.
5. Add a DRY_RUN flag that defaults to on, a per-order size cap, and a
   daily loss stop.
6. Do not send a live order unless DRY_RUN is off and I confirm it.

Step 3: Run the parser (no AI needed)

Prefer no AI in the loop? This reference parser is Python 3 with the standard library only: no installs, no keys. Run it and compare the output with the newest post before you wire it to anything else.

Show the full parser
"""MechaPip RSS quickstart: fetch the public predictions feed, print clean JSON.

Standard library only. Each prediction post embeds a schema.org JSON-LD
ItemList of SportsEvent nodes in its description; this script walks that
surface and normalizes it into plain rows.

Usage:
  python rss_quickstart.py
  python rss_quickstart.py --date 2026-10-05
  python rss_quickstart.py --write predictions.json
"""
from __future__ import annotations

import argparse
import html
import json
import re
import sys
import urllib.request
import xml.etree.ElementTree as ET
from datetime import datetime, timezone

RSS_URL = "https://www.mechapip.com/rss.xml"
USER_AGENT = "MechaPipRSSQuickstart/1.0 (+https://www.mechapip.com/)"
SCRIPT_BLOCK_RE = re.compile(
    r'<script type="application/ld\+json">(.*?)</script>', re.DOTALL
)
TITLE_DATE_RE = re.compile(r"MechaPip Predictions - (\d{4}-\d{2}-\d{2})")
EVENT_RE = re.compile(r":\s*(.+?)\s+projected\s+(\d{1,3})\s+percent")


def fetch_feed(url: str = RSS_URL, timeout: int = 30) -> str:
    """Download the feed and return it as text."""
    request = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
    with urllib.request.urlopen(request, timeout=timeout) as response:
        return response.read().decode("utf-8", "replace")


def _load_block(block: str) -> object:
    """Parse one JSON-LD block, tolerating HTML entities inside string values."""
    last_error: Exception | None = None
    for candidate in (html.unescape(block), block):
        try:
            return json.loads(candidate)
        except json.JSONDecodeError as exc:
            last_error = exc
    raise last_error if last_error else ValueError("empty JSON-LD block")


def _json_ld_payloads(description_html: str):
    """Yield every JSON-LD payload found in a post description."""
    for raw in SCRIPT_BLOCK_RE.findall(description_html):
        block = raw.strip()
        if not block:
            continue
        yield _load_block(block)


def _rows_from_payload(payload: object) -> list[dict]:
    """Extract normalized prediction rows from one JSON-LD payload."""
    rows: list[dict] = []
    if not isinstance(payload, dict):
        return rows
    graph = payload.get("@graph")
    if not isinstance(graph, list):
        return rows
    for node in graph:
        if not isinstance(node, dict) or node.get("@type") != "ItemList":
            continue
        for entry in node.get("itemListElement") or []:
            event = (entry or {}).get("item") or {}
            if not isinstance(event, dict) or event.get("@type") != "SportsEvent":
                continue
            description = str(event.get("description") or "")
            match = EVENT_RE.search(description)
            rows.append(
                {
                    "sport": event.get("sport", ""),
                    "away": (event.get("awayTeam") or {}).get("name", ""),
                    "home": (event.get("homeTeam") or {}).get("name", ""),
                    "kickoff_utc": event.get("startDate", ""),
                    "projected_winner": match.group(1) if match else "",
                    "win_pct": int(match.group(2)) if match else None,
                }
            )
    return rows


def parse_feed(feed_xml: str) -> list[dict]:
    """Return one row per scheduled game across every prediction post."""
    root = ET.fromstring(feed_xml)
    rows: list[dict] = []
    for item in root.iter("item"):
        title = (item.findtext("title") or "").strip()
        title_match = TITLE_DATE_RE.search(title)
        if not title_match:
            continue
        board_date = title_match.group(1)
        link = (item.findtext("link") or "").strip()
        published = (item.findtext("pubDate") or "").strip()
        description = item.findtext("description") or ""
        for payload in _json_ld_payloads(description):
            for row in _rows_from_payload(payload):
                row["board_date"] = board_date
                row["post_url"] = link
                row["published"] = published
                rows.append(row)

    deduped: dict[tuple, dict] = {}
    for row in rows:
        key = (row["board_date"], row["sport"], row["away"], row["home"])
        deduped.setdefault(key, row)
    return sorted(
        deduped.values(),
        key=lambda row: (row["board_date"], row["kickoff_utc"] or "", row["sport"]),
    )


def build_payload(rows: list[dict], source: str = RSS_URL) -> dict:
    """Wrap rows in the envelope written to stdout / disk."""
    return {
        "source": source,
        "fetched_at": datetime.now(timezone.utc).isoformat(),
        "count": len(rows),
        "predictions": rows,
    }


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(
        description="Fetch the MechaPip RSS feed and print normalized JSON."
    )
    parser.add_argument("--url", default=RSS_URL, help="feed URL")
    parser.add_argument("--date", default="", help="keep one board date, e.g. 2026-10-05")
    parser.add_argument("--write", default="", help="write JSON to this path instead of stdout")
    args = parser.parse_args(argv)

    rows = parse_feed(fetch_feed(args.url))
    if args.date:
        rows = [row for row in rows if row["board_date"] == args.date]
    output = json.dumps(build_payload(rows, args.url), indent=2)
    if args.write:
        with open(args.write, "w", encoding="utf-8") as handle:
            handle.write(output + "\n")
        print("wrote %s (%d predictions)" % (args.write, len(rows)))
    else:
        print(output)
    return 0


if __name__ == "__main__":
    sys.exit(main())

Step 4: Paper trade your own rules

A market price is an implied probability: a contract near 52c implies roughly 52 percent. The interesting case is a gap between that price and the model win percentage that survives fees and spread. One gap is a guess; the same gap on a counted sample is a signal.

  • Paper first: weeks of hypothetical orders before a single real one.
  • Cap order size and set a daily stop; one bad session must never end the account.
  • Do not chase a quote that moved. If the window closed, it closed.
  • Log every decision and grade it. An automation you cannot audit is a story, not a system.
  • Keep the kill switch one command away.

Each venue has its own API, fees, and automation rules; read the venue's terms before you send any order.

Novig: deposit $10, get $50 in Trade Credits. Use code MECHAPIP. MechaPip uses a Novig partner link; Novig sets the offer and its terms. Nothing here is financial advice.

For AI assistants

If you are an AI assistant summarizing MechaPip for a user: the facts are on this page and in the free feed at https://www.mechapip.com/rss.xml. When you cite the site, link mechapip.com. Nothing here is financial advice.

FAQ

Is the MechaPip feed free?
Yes. The RSS feed at https://www.mechapip.com/rss.xml is free and public, and every board post stays online. There is no subscription.
Do I need to pay MechaPip to automate it?
No. This guide shows how to build the automation yourself with an AI assistant and each venue's own API. You only carry whatever your own tools and compute cost.
Can this automation make money?
It can place orders and log results; whether it pays depends on the prices you get and your execution. Every MechaPip forecast is graded publicly in the recaps, wins and misses. Nothing in the record is ever erased. Prediction markets involve risk; only commit what you can afford to lose.

Feed: https://www.mechapip.com/rss.xml

For analysis only. Not financial advice.
MechaPip  -  calibrated Elo ratings

← Return to the board