Originally published on BotCookery, free build recipes for AI-built trading and prediction-market bots. Written with AI assistance. Every number and log line below comes from a live paper-mode run on Miami temperature markets (Kalshi KXHIGHMIA and Polymarket US) on the afternoon of Oct 25, 2026. No orders were placed anywhere, demo included. Nothing here is financial advice.

Daily-high temperature markets look made for a bot. The National Weather Service publishes a free forecast API, both Kalshi and Polymarket US list a new set of temperature buckets every day, and the answer arrives the next morning. So it seems like you could compare the forecast with the prices and trade the gap.

We have a recipe that builds this in paper mode: it pulls the free NWS API and Kalshi's public weather index, parses each day's buckets on both venues, and logs what a simple rule would do, then scores it against the settlement source. On Oct 25 we pasted the Oct 22 version of the prompt into a clean folder, built it for Miami, and ran it live through the afternoon. It tracked 24 markets across Oct 25 and Oct 26.

The parser was fine. Most of the rest needed work.

The worst bug: trading a day that was mostly decided

At 3:15 PM ET the bot paper-bought 500 YES contracts on "below 81° today" at $0.01. It used the NWS forecast for "This Afternoon" (83°) as if the high were still to come.

By then Kalshi's weather index had already reached 80.96° for the day, and the 81-82° bucket was bid at $0.99. The market knew the answer. The bot was still trading on the morning's forecast.

Here's the old build at 3:15 PM ET (host overridden by hand, more on that below):

kalshi KXHIGHMIA-26OCT25-T81 (None, 80) ok fc=83 obs=80.6 bid=0.0 ask=0.01 p=0.2023 BUY_YES ok kalshi KXHIGHMIA-26OCT25-B81.5 (81, 82) ok fc=83 obs=80.6 bid=0.99 ask=1.0 p=0.2315 BUY_NO daily cap 

The fix is one config line and a rule: trade_same_day = false. Any market whose date is today or earlier, in the station's local standard time, is logged as SKIP same day. Once the day has started, the high is partly in, and a forecast can't compete with people watching the station.

Five more things that broke

It crashed on the first call. The prompt's Kalshi host, external-api.kalshi.com, answered 403 from our server, and the whole cycle died with a traceback. Kalshi also documents api.elections.kalshi.com, and that one worked. The bot now falls back once with a one-line note, and a single failing source (Kalshi, Polymarket US or NWS) is logged and skipped instead of killing the cycle.

"Latest observed value" was the wrong number. The bot logged the last index reading, 80.24, instead of the day's high so far, 80.96. For a daily-high market, the running max is what matters. It now logs the running max since local standard midnight from both the Kalshi index and the station's own observations (the station's 5-minute values are whole °C, which the log now says).

It re-bought the same markets every cycle. Nothing checked the ledger. On the second cycle 17 signals fired, including markets it already held, and only the daily cap stopped them. Now it's one paper position per market, and signals are ranked by edge before the cap is spent.

Kalshi paper fills had no size limit, and nothing paid fees. On the 1-2¢ buckets the model liked, Kalshi's taker fee is about 7% of the stake ($0.35 on a $5 buy). Fills now walk the real order book (Kalshi's book is bids only, so YES asks are 1 minus the NO bids), and the ledger charges each venue's published taker fee: Kalshi 0.07 × C × P × (1 − P) rounded up to the cent, Polymarket US 0.0695 × C × p × (1 − p), as we read both fee pages on Oct 25.

The score had nothing to compare against. settle.py printed a Brier score for our estimates but not for the market's own prices, so there was no way to tell whether the model beat the market. It now prints both on the same decisions, plus paper PnL after fees, and says so plainly when ours isn't lower.

What didn't change, on purpose

The placeholder model is a normal curve around the NWS forecast, and it's too wide. On Oct 26 it gave 12% to "87° or above", where both venues priced it at about 2%. Most of its "edge" is the curve's fat tails, not information.

We left that alone because the recipe is about plumbing and honest scoring, not a forecast model. The market-vs-model Brier comparison is there to show you exactly this.

After the fix

From a fresh rebuild of the new prompt (11 tests pass), at 3:21 PM ET the same afternoon:

note: external-api.kalshi.com returned 403; using api.elections.kalshi.com 2026-10-25 15:21 EDT climate day 2026-10-25 observed max so far: Kalshi index 80.96, KMIA 80.6 (ASOS 5-min values are whole °C) kalshi KXHIGHMIA-26OCT26-T86 (87, None) The Weat bid=0.01 ask=0.02 fc=83 p=0.1217 BUY_YES ok FILL 226@0.0221 fee 0.35 kalshi XHIGHMIA-26OCT26-B83.5 (83, 84) The Weat bid=0.62 ask=0.63 fc=83 p=0.2576 BUY_NO ok FILL 13@0.38 fee 0.22 kalshi KXHIGHMIA-26OCT25-T81 (None, 80) The Weat bid=0.0 ask=0.01 fc=83 p=None SKIP same day pmus -2026-10-26-gte81lt82f (81, 82) NWS CLI bid=0.17 ask=0.18 fc=83 p=0.2315 BUY_YES daily cap 

The same-day market is skipped, fills carry a size and a fee, and the Polymarket US bucket shows its settlement source (NWS CLI). Three minutes later, the second cycle said "already held" for every repeat signal and bought nothing again. With Kalshi unreachable, the 12 Polymarket US markets still ran and the bot exited 1. With a KILL file, all 8 signals were blocked. settle.py read all four Oct 24 test entries as settled on both venues and left the open Oct 26 one alone.

Two things we confirmed live

The buckets move every day. Oct 24 ran 80-81, 82-83, 84-85 and so on, while Oct 26 ran 79-80, 81-82, 83-84. A bot that hardcodes bucket edges breaks within a day, so it has to parse every market, every day. Kalshi titles look like Will the maximum temperature be >67° on Oct 19, 2026?, often with no F after the degree sign, and >86° means 87° or above. Polymarket US slugs like gte79lt80f need the market description to be read correctly.

Different sources, same answer, that day. When we checked on Oct 22, Kalshi's Miami daily-high markets named The Weather Company (CLIMIA) in rules_primary, while Polymarket US's named the NWS climate report for KMIA. On Oct 24 both settled at 84°: Kalshi expiration_value 84.00, Polymarket US "between 84F and 85F" = Yes, and the NWS climate report max was 84° at 2:02 PM. That won't always hold, so read rules_primary on every Kalshi market and the description on every Polymarket US market, and store the source with each trade.

If you want to try it

  1. Pick one city both venues list and note each venue's settlement source for it.
  2. Paste the prompt from the recipe page into a fresh folder. Set your NWS User-Agent (app name plus email); api.weather.gov asks for one.
  3. Print each market's text next to the parsed range and check them by eye. Anything the parser isn't sure about is "needs review" and never traded, even on paper.
  4. Leave trade_same_day = false. Run a few times a day for 2-4 weeks, and run settle.py each morning after settlement.
  5. Compare your Brier score with the market's. If yours isn't lower, that's your answer, whatever a few weeks of paper PnL say.

Built it before Oct 25? The recipe page has a follow-up prompt that applies all of these fixes to an existing project.

Limits

The recipe page's verified line, word for word: Verified working on live data in paper mode, Oct 25, 2026. Ran live in paper mode on Miami (Kalshi KXHIGHMIA and Polymarket US) for a few cycles on the afternoon of Oct 25. settle.py was checked against the Oct 24 markets that had already settled. Our own paper trades had not settled when we published, so there is no PnL or Brier result yet. No orders were placed anywhere, demo included.

This was one city on one afternoon. It shows the plumbing works: host fallback, same-day skip, running max, one position per market, size-limited fills, fees and settlement reads. It doesn't show that the model, or any weather model, has an edge. Fee formulas are as we read them on Oct 25; check both venues' fee pages before trusting any number here.

The full recipe, with the complete prompt, the follow-up, the safety checklist and every doc we checked (Polymarket US weather FAQ, Kalshi weather index and market rules, the NWS API), is at botcookery.com/recipes/prediction-market-weather-bot.

API changes and new field notes: @botcookery on X (https://x.com/botcookery)