# How to Build a Prediction Market Trading Bot with SimpleFunctions CLI
Prediction markets have matured significantly over the past few years. Kalshi's regulatory approval, Polymarket's liquidity growth, and the proliferation of event contracts across energy, macro, and political verticals have created a genuine alpha-generation opportunity — if you have the infrastructure to act on it quickly.
Manually monitoring dozens of contracts, researching theses, and executing trades is unsustainable at scale. This is where an agentic trading bot becomes essential. In this guide, we'll walk through building one using [SimpleFunctions](https://simplefunctions.dev), a CLI-first agentic runtime purpose-built for prediction market trading.
We'll cover:
- Installing and configuring the SimpleFunctions CLI
- Scanning for liquid, tradeable markets
- Defining and attaching trading theses to your agent
- Managing live positions programmatically
- Wiring up alerts and automation
This guide assumes you're comfortable with Node.js, REST APIs, and have at least a passing familiarity with how prediction market contracts work.
---
## Why Build a Bot for Prediction Markets?
Prediction markets are informationally inefficient in specific, exploitable ways:
- **Reaction lag**: Prices often lag 10–30 minutes behind breaking data (e.g., a Fed statement, EIA inventory report, or NBER business cycle update)
- **Thin order books**: A well-reasoned thesis can move a market before arbitrageurs close the gap
- **Binary payoffs**: The math is simpler than options — you're pricing probabilities, not greeks
A bot that can scan markets, evaluate contracts against a structured thesis, and execute orders in seconds captures windows that manual traders miss entirely.
---
## Step 1: Install the SimpleFunctions CLI
SimpleFunctions distributes its tooling as an npm package. Install it globally:
npm install -g @spfunctions/cli
After installation, verify everything is working:
sf --version
You'll be prompted to authenticate with your SimpleFunctions account on first run. This links your Kalshi and/or Polymarket credentials through the SimpleFunctions secure credential vault — you never store raw API keys in your local config files.
sf auth login
For full setup details including API key configuration for both exchanges, refer to the [SimpleFunctions setup guide](https://simplefunctions.dev/docs/guide).
---
## Step 2: Scan for Actionable Markets
The `sf scan` command is your market discovery layer. It pulls live contract data, filters by configurable criteria, and surfaces markets worth trading.
sf scan --exchange kalshi --min-volume 50000 --max-spread 0.04
This returns contracts with at least $50,000 in traded volume and a bid-ask spread under 4 cents — a reasonable liquidity floor for systematic trading.
You can also scan by category:
sf scan --exchange kalshi --category economics --sort volume
Typical output looks like this:
Ticker Category Yes Bid Yes Ask Volume Spread
──────────────────────────────────────────────────────────────────
KXFEDDECISION Economics 0.72 0.74 $1.2M 0.02
KXRECSSNBER Economics 0.18 0.21 $420K 0.03
KXWTIMAX Energy 0.34 0.37 $280K 0.03
Let's break down what you're looking at:
- **KXFEDDECISION**: A contract tied to the Federal Reserve's next rate decision — highly liquid, news-driven
- **KXRECSSNBER**: Tracks whether the NBER will declare a recession within a defined window — slower-moving but thesis-heavy
- **KXWTIMAX**: WTI crude oil price ceiling contract — driven by EIA inventory data and geopolitical flow
These three contracts represent different trading archetypes: fast-twitch event contracts, macro thesis plays, and commodity-anchored price contracts. Your bot needs to handle all three meaningfully.
---
## Step 3: Understand the Agent Model
SimpleFunctions centers on the concept of a **thesis-driven agent**. Rather than building a pure algorithmic system that blindly executes signals, the agent model encourages you to encode *why* you're taking a position and let the agent validate execution against that reasoning.
This matters for prediction markets specifically because:
1. Contracts have expiration logic that's often nuanced ("closes at the end of the FOMC meeting," "resolves on NBER announcement")
2. Market microstructure changes rapidly — an agent that ignores context will thrash
3. Many profitable opportunities require combining external data (FRED, EIA, CME FedWatch) with market pricing
You define an agent in a `agent.config.json` file:
{
"agent_id": "macro-rates-bot",
"exchange": "kalshi",
"markets": ["KXFEDDECISION", "KXRECSSNBER"],
"thesis": {
"KXFEDDECISION": {
"stance": "YES",
"rationale": "CME FedWatch implied probability > 70% for hold, current Yes price at 0.72 underprices consensus",
"entry_threshold": 0.70,
"exit_target": 0.85,
"max_position_usd": 2000
},
"KXRECSSNBER": {
"stance": "NO",
"rationale": "Labor market data remains resilient; NBER declaration within window is < 15% consensus",
"entry_threshold": 0.22,
"exit_target": 0.10,
"max_position_usd": 1000
}
},
"risk": {
"max_drawdown_pct": 15,
"position_size_pct": 5
}
}
The `thesis` block isn't just documentation — the agent runtime reads it to validate that execution conditions match your stated reasoning before placing orders. If the market has moved significantly from your stated `entry_threshold`, the agent will flag the discrepancy rather than executing blindly.
---
## Step 4: Run Your Agent
With your config defined, launch the agent:
sf agent start --config ./agent.config.json --dry-run
The `--dry-run` flag is critical. Run your agent in simulation mode first. It will log every order it would have placed without actually executing anything.
[2024-01-15 09:32:11] KXFEDDECISION — Yes @ 0.72 | Thesis: MATCH | Order: BUY 200 contracts | DRY RUN
[2024-01-15 09:32:11] KXRECSSNBER — No @ 0.79 | Thesis: MATCH | Order: BUY 150 contracts | DRY RUN
[2024-01-15 09:45:03] KXFEDDECISION — Yes @ 0.75 | Thesis: PARTIAL | Price drifted above entry threshold. Holding.
Once you've validated the logic over a few hours, remove the flag to go live:
sf agent start --config ./agent.config.json
The agent runs as a persistent process, polling market data at configurable intervals (default: 30 seconds) and re-evaluating thesis validity on each cycle.
---
## Step 5: Monitor Positions
The `sf positions` command gives you a live snapshot of everything the agent holds:
sf positions --exchange kalshi
Ticker Side Contracts Avg Entry Current Unrealized P&L
────────────────────────────────────────────────────────────────────────
KXFEDDECISION YES 200 $0.72 $0.76 +$80.00
KXRECSSNBER NO 150 $0.79 $0.82 +$45.00
KXWTIMAX YES 80 $0.35 $0.31 -$32.00
You can pipe this into a monitoring script or dashboard. For teams, SimpleFunctions exposes a REST API that returns this same data in JSON format — useful for piping into Grafana, Datadog, or a custom frontend.
For real-time visualization during active trading sessions, launch the built-in dashboard:
sf dashboard
This opens a terminal UI that auto-refreshes position data, P&L, and agent activity logs. It's lightweight enough to run in a tmux session on a remote server.
---
## Step 6: Add External Data Hooks
The gap between a toy bot and a genuinely useful one is external data integration. For macro contracts like KXRECSSNBER or KXFEDDECISION, your edge comes from synthesizing data that other market participants are reacting to more slowly.
SimpleFunctions supports custom data hooks via its plugin interface. Here's a minimal example that feeds EIA weekly petroleum inventory data into the KXWTIMAX thesis evaluation:
// hooks/eia-inventory.js
const { defineHook } = require('@spfunctions/cli/sdk');
module.exports = defineHook({
name: 'eia-inventory-feed',
schedule: '0 11 * * 3', // Every Wednesday at 11am ET (EIA release time)
markets: ['KXWTIMAX'],
async fetch() {
const res = await fetch('https://api.eia.gov/v2/petroleum/sum/sndw/data/', {
headers: { 'X-Params': JSON.stringify({ api_key: process.env.EIA_API_KEY }) }
});
const data = await res.json();
const drawMB = data.response.data[0].value;
return {
signal: drawMB < -3000 ? 'BULLISH_WTI' : drawMB > 3000 ? 'BEARISH_WTI' : 'NEUTRAL',
value: drawMB,
confidence: Math.min(Math.abs(drawMB) / 5000, 1.0)
};
}
});
Register the hook in your agent config:
"hooks": ["./hooks/eia-inventory.js"]
The agent will now factor EIA inventory signal into its KXWTIMAX position decisions. A strong inventory draw (bullish for WTI prices hitting a ceiling) increases confidence in a YES position; a large build flips the signal.
This pattern — structured external data feeding into thesis validation — is what separates systematic prediction market trading from intuition-driven clicking.
---
## Step 7: Telegram Alerts and Automation
For traders who aren't watching a terminal all day, SimpleFunctions includes a Telegram bot integration. Configure it in your agent config:
"notifications": {
"telegram": {
"bot_token": "${TELEGRAM_BOT_TOKEN}",
"chat_id": "${TELEGRAM_CHAT_ID}",
"events": ["order_placed", "position_closed", "thesis_conflict", "drawdown_alert"]
}
}
You'll receive structured messages when:
- An order is placed or rejected
- A position hits your exit target and is closed
- The agent detects a thesis conflict (market has moved significantly from your stated rationale)
- Drawdown exceeds your configured threshold
The `thesis_conflict` notification is particularly valuable — it surfaces cases where the market is telling you something your thesis didn't account for, giving you a chance to update your reasoning before the agent continues execution.
---
## Step 8: Using the MCP Server for LLM Integration
For teams building LLM-augmented trading workflows, SimpleFunctions exposes an MCP (Model Context Protocol) server that lets you query market state and execute agent commands from any MCP-compatible client.
Start the MCP server:
sf mcp start --port 3001
This exposes structured tools that a language model can call to:
- Fetch current market prices and spreads
- Retrieve active positions and P&L
- Update thesis parameters based on new information
- Place or cancel orders with approval gates
This is particularly useful if you're building a research pipeline where an LLM processes news, earnings reports, or economic releases and needs to translate that analysis into actionable market positions. The MCP server gives the model a structured, safe interface to act on prediction markets without direct API key exposure.
The full MCP tool schema is documented at [simplefunctions.dev/docs](https://simplefunctions.dev/docs).
---
## Deployment Considerations
Running a prediction market bot in production requires thinking through a few operational concerns:
**Uptime**: Agent processes need to stay alive. Use PM2 or a systemd service to manage the process:
pm2 start "sf agent start --config ./agent.config.json" --name "sf-macro-bot"
pm2 save
pm2 startup
**Latency**: For fast-twitch contracts like KXFEDDECISION around FOMC announcements, deploy your bot on infrastructure close to Kalshi's API endpoints (US East is generally optimal).
**Rate limiting**: Both Kalshi and Polymarket impose API rate limits. The SimpleFunctions agent runtime handles backoff automatically, but aggressive polling intervals can still cause issues. Start with 30-second polling and tighten only if your strategy genuinely requires it.
**Position limits**: Hard-code position limits in your config that are lower than your actual risk tolerance. You want the bot's limits to be the binding constraint, not the exchange's.
---
## What This Stack Is Good For
Before you go build this, be honest about where systematic bots have genuine edge on prediction markets:
✅ **Good fit**: Fast reaction to scheduled data releases (EIA, FOMC, NFP, NBER), arbitrage between related contracts, markets where you have a persistent informational advantage
❌ **Poor fit**: Purely speculative political contracts with no underlying data signal, markets with very thin liquidity where your orders move the price, contracts resolving on subjective criteria
The SimpleFunctions CLI architecture encourages you to encode your thesis explicitly precisely because thesis-free automation in prediction markets is a fast path to consistent losses.
---
## Next Steps
This guide covers the core workflow, but there's significantly more depth available:
- **Multi-exchange arbitrage**: Running simultaneous agents on Kalshi and Polymarket for correlated contracts
- **Portfolio-level risk management**: Using the REST API to enforce cross-position exposure limits
- **Backtesting**: Replaying historical market data against your agent config to validate thesis performance
The [SimpleFunctions documentation](https://simplefunctions.dev/docs/guide) covers all of these patterns in detail, including example configurations for common macro and energy trading strategies.
Prediction markets reward speed, discipline, and clear reasoning. A well-configured agent gives you the first; building explicit thesis logic into your configuration enforces the second and third.