import os
import requests
API = "https://api.routeur.app"
session = requests.Session()
session.headers["X-API-Key"] = os.environ["ROUTEUR_API_KEY"]
rules = session.get(f"{API}/v1/insights/strategies", params={"venue": "kalshi", "limit": 20}, timeout=30).json()["data"]
rule = next((r for r in rules if r["open_matches"] > 0), None)
if rule is None:
raise SystemExit("No rule has open markets right now.")
side = rule["side"].upper()
print(f"Buy {side} at {float(rule['from_usd']) * 100:.0f}–{float(rule['to_usd']) * 100:.0f}¢, "
f"{rule['horizon_days']} day(s) before close, {rule['category']}")
print(f" {rule['markets']:,} settled · won {float(rule['win_rate']):.0%} · "
f"${float(rule['return_per_100_usd']):+.0f} per $100 "
f"(range ${float(rule['return_low_usd']):+.0f} to ${float(rule['return_high_usd']):+.0f})")
page = session.get(f"{API}/v1/insights/strategies/{rule['id']}", params={"limit": 10}, timeout=30).json()["data"]
for match in page["matches"]:
market = match["market"]
print(f" {side} {float(match['price_usd']) * 100:3.0f}¢ {market['title']} · closes {match.get('closes_at', '?')}")
const API = 'https://api.routeur.app';
const headers = { 'X-API-Key': process.env.ROUTEUR_API_KEY! };
type Strategy = {
id: string; side: 'yes' | 'no'; category: string; horizon_days: number; from_usd: string; to_usd: string;
markets: number; win_rate: string; return_per_100_usd: string; return_low_usd: string; return_high_usd: string; open_matches: number;
};
type Match = { market: { venue: string; id: string; title: string }; price_usd: string; closes_at?: string };
const get = async <T,>(path: string): Promise<T> => {
const res = await fetch(`${API}${path}`, { headers });
if (!res.ok) throw new Error(`${path}: ${res.status}`);
return (await res.json()).data as T;
};
const rules = await get<Strategy[]>('/v1/insights/strategies?venue=kalshi&limit=20');
const rule = rules.find(r => r.open_matches > 0);
if (!rule) throw new Error('No rule has open markets right now.');
const cents = (v: string) => `${Math.round(Number(v) * 100)}¢`;
console.log(`Buy ${rule.side.toUpperCase()} at ${cents(rule.from_usd)}–${cents(rule.to_usd)}, ${rule.horizon_days} day(s) out, ${rule.category}`);
console.log(` ${rule.markets} settled · won ${Math.round(Number(rule.win_rate) * 100)}% · $${Math.round(Number(rule.return_per_100_usd))} per $100`);
const { matches } = await get<{ matches: Match[] }>(`/v1/insights/strategies/${encodeURIComponent(rule.id)}?limit=10`);
for (const m of matches) console.log(` ${rule.side.toUpperCase()} ${cents(m.price_usd)} ${m.market.title} · closes ${m.closes_at ?? '?'}`);
Returns are historical, before fees, and measured at each band’s average midpoint. The price in
price_usd is today’s ask, which can be worse. Size positions for being wrong.