polymarket-quant-trader

GitHub 作者 LeoYeAI/openclaw-master-skills v1.0.0

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.

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~polymarket-quant-trader
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~polymarket-quant-trader/file -o polymarket-quant-trader.md
# 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,
  e