polymarket-quant-trader
Professional-grade Polymarket prediction market trading system. Includes Kelly Criterion position sizing, EV calculator, Bayesian probability updater, cross-platform arbitrage detector (Polymarket vs 1WIN), and autoresearch loop that self-improves strategy overnight via Brier score optimisation. Use when: user wants to trade prediction markets, find arbitrage opportunities, build a trading bot, or improve prediction accuracy. Triggers: polymarket, prediction markets, kelly criterion, EV trading, arb detector, brier score, prediction market bot, market making, quant trading, sports betting math, cross-platform arbitrage.
What this skill does
# Polymarket Quant Trader
A professional quant trading system for Polymarket prediction markets, built and battle-tested in production. Three alpha streams. One integrated system.
---
## Overview
This skill gives you a complete quantitative trading system for Polymarket with three independent alpha streams:
1. **EV-Based Signal Trading** — Kelly Criterion position sizing + Bayesian probability updating. Find edges, size them correctly, update beliefs as evidence arrives.
2. **Self-Improving Strategy (Autoresearch Loop)** — An autonomous hill-climbing optimizer that tunes your strategy parameters overnight using Brier score as the objective function. Wake up to a better strategy.
3. **Cross-Platform Arbitrage (PM x 1WIN)** — Detect spread discrepancies between Polymarket and 1WIN bookmaker. Fuzzy title matching, confidence tiering, Kelly-sized positions.
Each stream works independently or together. The system ships with TypeScript source, npm scripts for every workflow, and a backtester to validate before going live.
**Current production performance:** Brier score 0.18 (meaningful edge territory — baseline random is 0.25, professional is sub-0.12).
---
## Stream 1: EV-Based Signal Trading
### How It Works
The core loop: estimate a probability, compare it to the market price, calculate expected value, size the position with Kelly Criterion, and update beliefs as new evidence arrives.
### Kelly Criterion Position Sizing
Kelly answers: "Given my edge, what fraction of my bankroll should I bet?"
**The formula:**
```
f* = (p * b - q) / b
where:
f* = optimal fraction of bankroll to wager
p = probability of winning (your estimate, 0-1)
b = net odds multiplier (payout per $1 risked)
q = 1 - p (probability of losing)
```
In prediction markets, odds derive from the market price:
```
b = (1 - marketYesPrice) / marketYesPrice
```
If YES trades at $0.40, then b = 0.60/0.40 = 1.5 (you risk $0.40 to win $0.60).
**Implementation:**
```typescript
// kelly-criterion.ts
export function kelly(p: number, b: number, q?: number): number {
const qVal = q ?? 1 - p;
return (p * b - qVal) / b;
}
export function quarterKelly(p: number, b: number): number {
return 0.25 * kelly(p, b);
}
export function kellySizing(
bankroll: number,
p: number,
b: number,
mode: 'full' | 'half' | 'quarter' = 'quarter'
): number {
const fraction = mode === 'full' ? kelly(p, b)
: mode === 'half' ? 0.5 * kelly(p, b)
: quarterKelly(p, b);
return Math.max(0, bankroll * Math.min(fraction, 0.15));
}
```
**Why quarter Kelly?** Full Kelly maximizes long-run growth rate but produces brutal drawdowns (50%+ swings). Quarter Kelly captures ~75% of the growth rate with dramatically lower variance. Every serious quant fund uses fractional Kelly.
### EV Calculator
Expected value quantifies your edge per dollar risked:
```typescript
// ev-calculator.ts
export interface MarketEV {
marketId: string;
ourP: number; // Your estimated probability
marketP: number; // Market-implied probability (= YES price)
b: number; // Net odds: (1 - marketP) / marketP
ev: number; // Expected value per dollar risked
edgePct: number; // Edge as percentage of market price
kellyFraction: number; // Quarter Kelly optimal fraction
recommend: boolean; // Worth trading? (ev > 0 && edgePct >= 2%)
}
export function calcEV(ourProbability: number, marketYesPrice: number) {
const b = (1 - marketYesPrice) / marketYesPrice;
const ev = ourProbability * b - (1 - ourProbability);
const edgePct = (ev / marketYesPrice) * 100;
return { ev, edgePct, b };
}
export function scoreMarket(market: any, ourP: number): MarketEV {
const { ev, edgePct, b } = calcEV(ourP, market.yesPrice);
const kellyFraction = quarterKelly(ourP, b);
return {
marketId: market.id,
ourP,
marketP: market.yesPrice,
b,
ev,
edgePct,
kellyFraction,
recommend: ev > 0 && edgePct >= 2,
};
}
export function rankByEV(markets: MarketEV[]): MarketEV[] {
return [...markets].sort((a, b) => b.ev - a.ev);
}
```
**Reading the output:** An `edgePct` of 5% means your model thinks the market is mispriced by 5%. The `recommend` flag fires when EV is positive AND edge exceeds 2% (below that, transaction costs eat your edge).
### Bayesian Probability Updater
Update your probability estimates as new evidence arrives:
```typescript
// bayesian-updater.ts
export interface BayesianState {
marketId: string;
priorP: number;
currentP: number;
evidence: Evidence[];
lastUpdated: Date;
}
export interface Evidence {
description: string;
likelihoodRatio: number; // > 1 supports YES, < 1 supports NO
timestamp: Date;
}
export function bayesUpdate(prior: number, likelihoodRatio: number): number {
const posterior = (prior * likelihoodRatio) /
(prior * likelihoodRatio + (1 - prior));
return Math.max(0.001, Math.min(0.999, posterior));
}
export function addEvidence(
state: BayesianState,
evidence: Evidence
): BayesianState {
const newP = bayesUpdate(state.currentP, evidence.likelihoodRatio);
return {
...state,
currentP: newP,
evidence: [...state.evidence, evidence],
lastUpdated: evidence.timestamp,
};
}
export function getRecommendation(
state: BayesianState,
marketPrice: number
): { action: 'buy' | 'sell' | 'hold'; confidence: number; reason: string } {
const diff = state.currentP - marketPrice;
if (Math.abs(diff) < 0.02) return { action: 'hold', confidence: 0, reason: 'Within noise' };
if (diff > 0) return { action: 'buy', confidence: diff, reason: `Model ${(diff*100).toFixed(1)}% above market` };
return { action: 'sell', confidence: -diff, reason: `Model ${(-diff*100).toFixed(1)}% below market` };
}
```
**Likelihood ratios:** A ratio of 2.0 means "this evidence is twice as likely if YES is true." A ratio of 0.5 means "this evidence is twice as likely if NO is true." The Bayesian updater chains multiple evidence items — each update feeds the next as a new prior.
### Market Scorer (Composite Ranking)
Combines all signals into a single score for market selection:
```typescript
// market-scorer.ts — Weighted scoring model
// EV Score: 40% weight — edge percentage
// Kelly Fraction: 30% weight — optimal sizing (higher = more confident)
// Expiry Window: 20% weight — sweet spot 6-72 hours
// Volume Score: 10% weight — log-normalized liquidity
```
Markets scoring highest get traded first. The expiry window filter avoids two failure modes: too-short expiry (can't exit if wrong) and too-long expiry (capital locked up, edge decays).
---
## Stream 2: Self-Improving Strategy (Autoresearch Loop)
### The Brier Score Metric
Brier score measures prediction calibration — how close your probability estimates are to actual outcomes:
```
brierScore = mean((predictedProbability - actualOutcome)^2)
where actualOutcome = 1 if resolved YES, 0 if resolved NO
```
**Interpretation scale:**
| Score | Level | Meaning |
|-------|-------|---------|
| 0.25 | Random | Coin-flip predictions |
| 0.22 | Weak edge | Slightly better than random |
| 0.18 | Meaningful edge | Consistent alpha |
| 0.12 | Professional | Elite forecaster territory |
| < 0.10 | Superforecaster | Top 1% calibration |
Lower is better. The system tracks Brier score as the primary optimization objective.
### Strategy Configuration
The strategy is defined by tunable parameters:
```typescript
// research/strategy.ts
export interface StrategyConfig {
minVolume: number; // Minimum market volume ($)
minEdgePct: number; // Minimum edge to trade (%)
kellyMode: "full"|"half"|"quarter";
maxKellyFraction: number; // Cap on position size
expiryMinHours: number; // Earliest expiry to consider
expiryMaxHours: number; // Latest expiry to consider
}
export const DEFAULT_CONFIG: StrategyConfig = {
minVolume: 10000,
minEdgePct: 3.0,
kellyMode: "quarter",
maxKellyFraction: 0.15,
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.