---
name: polymarket-bot
display-name: Polymarket Bot
description: "Autonomous trading agent for Polymarket prediction markets using Seren ecosystem"
enabled: false
source: github:serenorg/seren-skills
imported-from: github:serenorg/seren-skills
---

# Polymarket Trading Bot

Autonomous trading agent for prediction markets integrating the Seren ecosystem.

## ⚠️ IMPORTANT LEGAL DISCLAIMERS

**READ THIS BEFORE USING**

### Geographic Restrictions - CRITICAL
⚠️ **Polymarket access depends on jurisdiction, account eligibility, and current network environment**.
⚠️ **You are responsible for verifying that prediction market trading is legal in your jurisdiction**.

### Regulatory Status
- Prediction markets exist in a **regulatory gray area** in many jurisdictions
- Some governments classify them as **gambling**, others as **financial instruments**
- Some jurisdictions **prohibit them entirely**
- **Consult local laws and seek professional advice if uncertain**

### Not Financial Advice
- This bot is provided for **informational and educational purposes only**
- It does NOT constitute **financial, investment, legal, or tax advice**
- AI-generated estimates are **not guarantees and may be inaccurate**
- You are **solely responsible** for your trading decisions and any resulting gains or losses

### Risk of Loss
- Trading prediction markets involves **substantial risk of loss**
- Only risk capital you **can afford to lose completely**
- **Past performance does not indicate future results**
- Market conditions can change rapidly and unpredictably

### Tax Obligations
- Trading profits **may be subject to taxation** in your jurisdiction
- Consult a tax professional regarding your **reporting obligations**

### Age Restriction
- You must be **at least 18 years old** (or the age of majority in your jurisdiction) to use this bot

### No Warranty
- This software is provided **"as is" without warranty of any kind**
- The developers assume **no liability** for trading losses, technical failures, or regulatory consequences

---

## When to Use This Skill

Activate this skill when the user mentions:
- "trade on Polymarket"
- "set up polymarket trading"
- "start prediction market trading"
- "check my polymarket positions"
- "autonomous trading"

## For Claude: How to Invoke This Skill

**Immediately run a dry-run scan without asking.** Do not present a menu or ask the user to choose between scan/trade/setup. Execute the paper scan by default. Only after results are displayed, present available next steps (live trading setup, position management). If the user explicitly requests a specific action in their invocation message, run that action instead.

When the user asks to **scan Polymarket** or **find trading opportunities**, run the bot:

### Prerequisites Check

First, verify the skill is set up:

```bash
ls ~/.config/seren/skills/polymarket-bot/.env ~/.config/seren/skills/polymarket-bot/config.json
```

If files are missing, guide user through setup (see Phase 1-2 below).

### Scanning for Opportunities (Paper Trading)

Run a single scan to find mispriced markets:

```bash
cd ~/.config/seren/skills/polymarket-bot && python3 scripts/agent.py --config config.json --dry-run 2>&1
```

**What this does:**

- Scans 20-50 active Polymarket markets
- Uses Perplexity to research each market
- Uses Claude to estimate fair values
- Identifies opportunities where edge > threshold
- Calculates Kelly position sizes
- **Does NOT place actual trades** (dry-run mode)
- Costs ~$1 in SerenBucks per scan

**How to present results to user:**

1. Parse output for lines starting with `✓ Opportunity found!`
2. Extract: market question, fair value, market price, edge, recommended position size
3. Summarize in a table format:

```text
Found 3 opportunities:

| Market | Fair Value | Market Price | Edge | Position |
|--------|-----------|--------------|------|----------|
| "Will BTC hit $100k?" | 67% | 54% | 13% | $15.20 |
| "Trump wins 2024?" | 48% | 55% | -7% | $8.40 SELL |
```

4. Remind user these are paper trades - no real orders placed
5. Suggest running setup if they want to enable live trading

### Checking Paper Trading History

View recent scan logs:

```bash
tail -50 ~/.config/seren/skills/polymarket-bot/logs/trading_*.log
```

### Running Live Trading (Advanced)

⚠️ **Only if user has:**

- Completed paper trading validation (50+ scans)
- $100+ budget ($75 USDC + $25 SerenBucks)
- Real Polymarket API credentials

```bash
cd ~/.config/seren/skills/polymarket-bot && python3 scripts/setup_cron.py create --config config.json --schedule "0 */2 * * *" --live --run-type scan
cd ~/.config/seren/skills/polymarket-bot && python3 scripts/setup_cron.py create --config config.json --schedule "15 * * * *" --live --run-type monitor
```

Then start the local-pull runner on the machine that should execute jobs:

```bash
python3 scripts/run_local_pull_runner.py --config config.json
```

**Important:**

- Always confirm user has adequate budget before suggesting live mode
- Emphasize paper trading first
- Live trading requires a schedule created with `--live`

## Trade Execution Contract

When the user gives a direct exit instruction (`sell`, `close`, `exit`, `unwind`, `flatten`), execute the exit path immediately.
Do not editorialize or argue against recovering remaining funds.
If the user request is ambiguous, ask only the minimum clarifying question needed to identify the positions to exit.

## CLOB Execution Rules

- `py-clob-client` via `DirectClobTrader` from `scripts/polymarket_live.py` is the canonical live execution path.
- For immediate sells, fetch the live order book, use the market `tick_size`, and submit a marketable sell priced at that market's minimum tick.
- Never place a passive sell above the best bid when the user asked for an immediate exit.
- Estimate recovery by sweeping visible bid levels (`price x size`) across the full book, not just the best bid.
- If visible bid depth cannot cover the full exit size, report the partial-depth estimate and remaining unfilled size.

## Pre-Trade Checklist (Mandatory)

Before any live buy, sell, or unwind:

1. Fetch the live order book for every token involved.
2. Snap prices to the market `tick_size` and compute visible-book recovery or cost across all levels.
3. Verify the current environment can legally and technically reach the Polymarket CLOB API. If access is blocked, stop and report the restriction; do not suggest bypasses.
4. Verify `py-clob-client` is installed and `POLY_PRIVATE_KEY` or `WALLET_PRIVATE_KEY`, `POLY_API_KEY`, `POLY_PASSPHRASE`, and `POLY_SECRET` are loaded.
5. If any dependency check fails, fail closed with a concrete remediation message.

## Live Safety Opt-In

Default mode should be `--dry-run`. Live trading requires:

- `python scripts/agent.py --config config.json --yes-live`
- or a wrapper that omits `--dry-run` and sets `--yes-live` for that process

The `--yes-live` flag is a startup-only live opt-in. It is not a per-order approval prompt.

## Overview

This skill helps users set up and manage an autonomous trading agent that:

1. **Scans** Polymarket for active prediction markets
2. **Researches** opportunities using Perplexity AI
3. **Estimates** fair value with Claude (Anthropic)
4. **Identifies** mispriced markets (edge > threshold)
5. **Executes** trades using Kelly Criterion for position sizing
6. **Runs autonomously** on seren-cron schedule
7. **Monitors** positions and reports P&L

## Architecture

**Pure Python Implementation**
- Python agent calls Seren publishers via HTTP
- Desktop sidecar/keychain publisher auth is the default path
- Legacy direct `POLY_*` headers remain as fallback
- Logs written to JSONL files
- Seren-cron stores the schedule and a skill-local runner executes `scripts/agent.py` locally

**Components:**
- `scripts/agent.py` - Main trading loop
- `scripts/seren_client.py` - Seren API client (calls publishers)
- `scripts/polymarket_client.py` - Polymarket CLOB API wrapper
- `scripts/setup_cron.py` - skill-local seren-cron local-pull schedule management
- `scripts/run_local_pull_runner.py` - local seren-cron polling runner
- `scripts/kelly.py` - Position sizing calculator
- `scripts/position_tracker.py` - Position management
- `scripts/logger.py` - Trading logger

**Seren Publishers Used:**
- `polymarket-data` - Real-time Polymarket market data (prices, volumes, liquidity)
  - Endpoint: `GET /markets` returns active prediction markets
  - Response includes: market IDs, questions, token IDs, prices, liquidity
  - Verified working with 100+ markets returned

- Trading uses `py-clob-client` (via `DirectClobTrader` from `scripts/polymarket_live.py`)
  - Local EIP-712 signing — no publisher intermediary
  - Requires: `POLY_PRIVATE_KEY`, `POLY_API_KEY`, `POLY_PASSPHRASE`, `POLY_SECRET`

- `perplexity` - Perplexity AI research (via OpenRouter)
  - Model: `sonar` for fast research
  - Returns AI-generated summaries with citations
  - Used to research market questions before trading

- `seren-models` - Multi-model LLM inference (via OpenRouter)
  - 200+ models available (Claude, GPT, Gemini, Llama, etc.)
  - Used model: `anthropic/claude-sonnet-4.5`
  - Estimates fair value probabilities from research

- `seren-cron` - Autonomous local-pull scheduling
  - Stores runner registration and cron schedules in Seren
  - Lets a skill-local polling process claim due work and run `scripts/agent.py` locally
  - Pause/resume/delete jobs and runners programmatically

---

## API Key Setup

Before running this skill, check for an existing Seren API key in this order:

1. **Seren Desktop auth** — if the skill is running inside Seren Desktop, the runtime injects `API_KEY` automatically. Check: `echo $API_KEY`. If set, no further action is needed.
2. **Existing `.env` file** — check if `SEREN_API_KEY` is already set in the skill's `.env` file. If set, no further action is needed.
3. **Shell environment** — check if `SEREN_API_KEY` is exported in the current shell. If set, no further action is needed.

**Only if none of the above are set**, register a new agent account:

```bash
curl -sS -X POST "https://api.serendb.com/auth/agent" \
  -H "Content-Type: application/json" \
  -d '{"name":"polymarket-bot"}'
```

Extract the API key from the response at `.data.agent.api_key` — **this key is shown only once**. Write it to the skill's `.env` file:

```env
SEREN_API_KEY=<the-returned-key>
```

Verify:

```bash
curl -sS "https://api.serendb.com/auth/me" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

**Do not create a new account if a key already exists.** Creating a duplicate account results in a $0-balance key that overrides the user's funded account.

Reference: [https://docs.serendb.com/skills.md](https://docs.serendb.com/skills.md)

## Setup Workflow

### Phase 1: Install Dependencies

Check Python version and install requirements:

```bash
cd skills/polymarket-bot

# Check Python version (need 3.9+)
python3 --version

# Install dependencies
pip3 install -r requirements.txt
```

### Phase 2: Configure Credentials

Create `.env` file from template:

```bash
cp .env.example .env
```

Edit `.env` and add:

```bash
# Seren API key (standalone mode) - create/manage from https://console.serendb.com
SEREN_API_KEY=your_seren_api_key_here

# Desktop sidecar/keychain mode (recommended)
SEREN_DESKTOP_PUBLISHER_AUTH=true
```

**Desktop sidecar flow (recommended):**
1. Open Seren Desktop
2. Go to Settings > Publisher MCPs
3. Configure Polymarket publisher credentials
4. Ensure publisher is enabled

**Legacy fallback mode (optional):**
Set `SEREN_DESKTOP_PUBLISHER_AUTH=false` and provide:
`POLY_API_KEY`, `POLY_PASSPHRASE`, `POLY_SECRET`, `POLY_ADDRESS`

**How to derive Polymarket credentials (legacy mode):**
1. Visit [polymarket.com](https://polymarket.com)
2. Connect your wallet
3. Navigate to Settings > API Keys
4. Click "Derive API Key"
5. Save your credentials securely

**Security Note:**
- Never commit `.env` to git (already in `.gitignore`)
- Keep credentials secure
- Credentials grant access to your Polymarket wallet

### Phase 3: Configure Risk Parameters

Copy the example config and customize:

```bash
cp config.example.json config.json
```

Edit `config.json` to set your risk parameters:

```json
{
  "bankroll": 100.0,
  "mispricing_threshold": 0.08,
  "max_kelly_fraction": 0.06,
  "scan_interval_minutes": 10,
  "max_positions": 10,
  "stop_loss_bankroll": 0.0
}
```

**Parameter Guide:**

#### bankroll
Total capital available for trading (in USDC).
- Testing: $50-100
- Serious: $500+
- **Only risk what you can afford to lose**

#### mispricing_threshold
Minimum edge required to trade (as decimal, e.g., 0.08 = 8%).
- 0.05: Aggressive (more trades, smaller edges)
- 0.08: Balanced (recommended)
- 0.12: Conservative (fewer trades, larger edges)

#### max_kelly_fraction
Maximum % of bankroll per trade (as decimal, e.g., 0.06 = 6%).
- 0.03: Very conservative
- 0.06: Balanced (recommended)
- 0.10: Aggressive (higher variance)

#### scan_interval_minutes
How often to scan for opportunities.
- 5 minutes: High frequency (~$5-10/day in API costs)
- 10 minutes: Balanced (~$2-5/day)
- 30 minutes: Conservative (~$0.50-1.50/day)

#### max_positions
Maximum concurrent open positions.
- Small bankroll (<$100): 5-10
- Medium bankroll ($100-500): 10-20
- Large bankroll (>$500): 20-50

#### stop_loss_bankroll
Stop trading if bankroll drops to this amount.
- 0: Stop only if completely depleted
- 50% of initial: Stop if down 50%

### Phase 4: Fund Your Wallets

#### Minimum Starting Budget: $100

The config default bankroll is `$100`. Start small to test the strategy with real capital before scaling up.

| Item             | Amount   | Purpose                                        |
| ---------------- | -------- | ---------------------------------------------- |
| **Polygon USDC** | $75      | Trading capital (allows $3-6 positions)        |
| **SerenBucks**   | $25      | API costs (~25 scans at ~$1/scan)              |
| **Total**        | **$100** | Minimum to start live trading                  |

With a $100 bankroll and quarter-Kelly sizing (`max_kelly_fraction: 0.06`):

- Position sizes: $3-6 each
- At lower scan frequency (1-2 scans/day), API costs stay at $1-2/day
- Enough runway to validate whether the strategy finds real edge before committing more capital

**The key variable is scan frequency, not bankroll size.** Reduce `scan_interval_minutes` to control API costs:

| Scan interval | Scans/day | API cost/day | Best for                          |
| ------------- | --------- | ------------ | --------------------------------- |
| Manual/daily  | 1-2       | $1-2         | Testing with $100 budget          |
| 120 min       | 12        | $12          | Active trading with $500+ budget  |
| 60 min        | 24        | $24          | Experienced traders scaling up    |
| 30 min        | 48        | $48          | High conviction, large bankroll   |

#### Scaling Up

Once you have validated edge through paper trading and small live trades, increase your bankroll and scan frequency together:

| Budget tier    | USDC     | SerenBucks | Recommended scan interval |
| -------------- | -------- | ---------- | ------------------------- |
| Starter        | $75      | $25        | Manual or daily           |
| Active         | $500     | $50-100    | 120 min                   |
| Experienced    | $1,000+  | $100-200   | 60 min                    |
| Serious        | $2,000+  | $200+      | 30 min                    |

---

#### Paper Trading (RECOMMENDED FOR EVERYONE)

**Before deploying real capital, paper trade for 1-2 weeks to validate your edge.**

Paper trading uses real market data and real AI analysis, but simulates trades instead of placing actual orders. This lets you:

- Validate the strategy actually finds mispriced markets
- Measure real win rate and average edge
- Test different risk parameters (Kelly fraction, mispricing threshold)
- Build confidence before risking capital

**How to paper trade:**

```bash
python3 scripts/agent.py --config config.json --dry-run
```

**What happens in dry-run mode:**

- ✅ Scans real Polymarket markets
- ✅ Researches opportunities with Perplexity (real API calls)
- ✅ Estimates fair values with Claude (real API calls)
- ✅ Calculates Kelly position sizes
- ✅ Logs paper trades to `logs/trading_*.log`
- ❌ Does NOT place actual Polymarket orders
- ❌ Does NOT require Polymarket API credentials

**Important:** Paper trading still costs **~$1 per scan** in API fees (Perplexly + Claude analysis). With $25 SerenBucks, you can run 25 paper trades over 1-2 weeks to validate the strategy.

**Recommended paper trading plan:**

1. Fund $25 SerenBucks (covers ~25 scans)
2. Set `"scan_interval_minutes": 120` in config.json (2-hour intervals)
3. Run paper trading for 5-7 days (60-84 scans)
4. Analyze results in log files:
   - Win rate: % of paper trades that would have been profitable
   - Average edge: mean expected value per trade
   - Sharpe ratio: risk-adjusted returns
5. If paper trading shows consistent edge, move to live trading with $100+ budget

**Manual paper trading (if <$25 SerenBucks):**

Run scans one at a time when you want:

```bash
python3 scripts/agent.py --config config.json --dry-run --once
```

- You control when to spend API credits ($1 per scan)
- With $20 SerenBucks: run 20 scans over weeks/months
- Scout for opportunities at your own pace
- No autonomous scheduling

---

#### Moving from Paper to Live Trading

Once paper trading validates your edge (recommended: 50+ scans with positive expected value), you're ready for live trading.

**Requirements for live trading:**

- ✅ Successful paper trading period (1-2 weeks, 50+ scans)
- ✅ Minimum $100 budget ($75 USDC + $25 SerenBucks)
- ✅ Polymarket API credentials (see Phase 2)
- ✅ Understanding of Kelly Criterion risk management

**If you don't have $100 yet:**

- Continue paper trading to refine strategy
- Use manual `--once` scans to conserve SerenBucks
- Start with the minimum $5 Stripe deposit to test a few scans

---

#### How to Fund SerenBucks

1. Visit: https://serendb.com/serenbucks or https://console.serendb.com
2. Choose deposit method:
   - Credit card (instant)
   - Crypto transfer (USDC, ETH, BTC)
3. Minimum recommended: $25 for getting started

Current Seren funding flow:
- Stripe deposits start at `$5`
- A verified email is required before Stripe deposits
- API-first users can fund with `POST /wallet/deposit`

**Cost breakdown per scan cycle** (~$1.00 total):
- Market data fetch: $0.10
- Perplexity research: $0.01 × 20 markets = $0.20
- Claude fair value estimation: $0.035 × 20 markets = $0.70

**Daily costs by scan interval:**
- 30 min intervals: 48 scans/day × $1.00 = $48/day
- 60 min intervals: 24 scans/day × $1.00 = $24/day
- 120 min intervals: 12 scans/day × $1.00 = $12/day

---

#### How to Fund Polymarket (Polygon USDC)

1. **Bridge USDC to Polygon PoS** using:
   - [Polygon Bridge](https://wallet.polygon.technology/bridge) (official)
   - [Hop Exchange](https://app.hop.exchange/) (faster)
   - [Connext](https://bridge.connext.network/) (alternative)

2. **Send to your Polymarket wallet address**:
   - Find your address: https://polymarket.com/wallet
   - Send bridged USDC to this address
   - Wait for confirmation (~2-5 minutes)

3. **Verify balance**:
   - Check on Polymarket: https://polymarket.com/wallet
   - Or check on PolygonScan: https://polygonscan.com/address/YOUR_ADDRESS

**Trading capital recommendations:**
- Minimum: $20 (allows small positions for testing)
- Conservative: $50-100 (better position sizing)
- Serious: $500+ (optimal Kelly Criterion sizing)

---

#### Checking Your Balances

Before running the bot, verify both balances:

**Check SerenBucks:**
```bash
# If you have Seren MCP connected
# The bot will display balance when it starts
```

**Check Polymarket USDC:**
- Visit: https://polymarket.com/wallet
- Or the bot will show balance at startup

### Phase 5: Dry-Run Test (STRONGLY RECOMMENDED)

Test the bot without placing real trades:

```bash
python3 scripts/agent.py --config config.json --dry-run
```

**Dry-run mode:**
- ✅ Scans markets (when implemented)
- ✅ Researches opportunities using Perplexity
- ✅ Estimates fair values using Claude
- ✅ Calculates position sizes using Kelly Criterion
- ✅ Logs everything to files
- ❌ Does NOT place actual trades

**Expected output:**
```
============================================================
🔍 Polymarket Scan Starting - 2026-02-12 14:35:00 UTC
============================================================

Balances:
  SerenBucks: $23.45
  Polymarket: $100.00

Scanning markets...
  Found 23 markets

Evaluating: "Will BTC hit $100k by March 2026?"
  Current price: 54.0%
  🧠 Researching: "Will BTC hit $100k by March 2026?"
  💡 Estimating fair value...
     Fair value: 67.0% (confidence: medium)
    ✓ Opportunity found!
      Edge: 13.0%
      Side: BUY
      Size: $3.24 (5.4% of available)
      Expected value: +$0.42

    [DRY-RUN] Would place BUY order:
      Market: "Will BTC hit $100k by March 2026?"
      Size: $3.24
      Price: 54.0%
      Expected value: +$0.42

============================================================
Scan complete!
  Markets scanned: 23
  Opportunities: 8
  Trades executed: 0 (dry-run)
  Capital deployed: $0.00
  API cost: ~$0.46 SerenBucks
============================================================
```

### Phase 6: Live Trading Confirmation

⚠️ **CRITICAL - You must explicitly confirm before enabling live trading**

**Before going live, ask yourself:**
1. Have I tested in dry-run mode?
2. Do I understand the risks?
3. Can I afford to lose this capital?
4. Is prediction market trading legal in my jurisdiction?
5. Have I funded both SerenBucks and Polymarket?

**Display this warning:**

```
⚠️  LIVE TRADING CONFIRMATION

You're about to enable LIVE TRADING with real money.

Configuration:
  • Bankroll: $100.00
  • Max per trade: 6% ($6.00)
  • Scan interval: Every 10 minutes
  • Stop loss: $0.00 (stop when depleted)
  • Max positions: 10

Estimated Costs:
  • SerenBucks: ~$2-5 per day (for API calls)
  • Trading capital: Up to $100.00 (your bankroll)

Risks:
  ⚠️  You can lose money - prediction markets are uncertain
  ⚠️  Only risk what you can afford to lose
  ⚠️  Past performance doesn't guarantee future results
  ⚠️  The agent makes autonomous decisions based on AI estimates
  ⚠️  Market conditions can change rapidly
  ⚠️  Slippage and fees may reduce returns

The agent will run on schedule until you stop it.

Type exactly: START LIVE TRADING
(or 'cancel' to abort)
```

**Wait for EXACT confirmation.** Do not proceed unless user types "START LIVE TRADING".

### Phase 7: Run Live

Once confirmed, run the agent:

```bash
# Run once
python3 scripts/agent.py --config config.json

# Or create a seren-cron local-pull schedule for autonomous operation
```

**Setting up seren-cron** (for autonomous scheduling):

```bash
python3 scripts/setup_cron.py create --config config.json --schedule "0 */2 * * *" --live --run-type scan
python3 scripts/setup_cron.py create --config config.json --schedule "15 * * * *" --live --run-type monitor
python3 scripts/run_local_pull_runner.py --config config.json
```

The schedule lives in Seren, but the local polling process must stay online on the machine that should execute trades. Use `scan` for new entries and `monitor` for stale-order cleanup, live reconciliation, and automated guard exits.

---

## Control Commands

### Show Status

Read current positions and display status:

```python
import json

# Read positions
with open('skills/polymarket-bot/logs/positions.json', 'r') as f:
    data = json.load(f)

# Display
print("📊 Polymarket Trading Status\n")
print(f"Positions: {data['position_count']}")
print(f"Total unrealized P&L: ${data['total_unrealized_pnl']:.2f}")

for pos in data['positions']:
    pnl_symbol = '+' if pos['unrealized_pnl'] >= 0 else ''
    print(f"\n  {pos['market']}")
    print(f"  {pos['side']} ${pos['size']:.2f} @ {pos['entry_price'] * 100:.1f}%")
    print(f"  Now: {pos['current_price'] * 100:.1f}% ({pnl_symbol}${pos['unrealized_pnl']:.2f})")
```

### Show Recent Trades

Read and display trade history:

```python
import json

# Read last 20 trades
with open('skills/polymarket-bot/logs/trades.jsonl', 'r') as f:
    lines = f.readlines()

trades = [json.loads(line) for line in lines[-20:]]

print("📝 Recent Trades (Last 20)\n")

for i, trade in enumerate(reversed(trades), 1):
    pnl_symbol = '' if trade['pnl'] is None else ('+' if trade['pnl'] >= 0 else '')
    status_emoji = '🟢' if trade['status'] == 'open' else '✓' if trade['pnl'] and trade['pnl'] > 0 else '✗'

    print(f"{i}. {status_emoji} {trade['side']} ${trade['size']:.2f} @ {trade['price'] * 100:.1f}%")
    print(f"   \"{trade['market']}\"")
    if trade['pnl'] is not None:
        print(f"   P&L: {pnl_symbol}${trade['pnl']:.2f}")
    print()
```

### Pause/Resume Trading

**Pause** (stop scheduled scans, keep positions):
```bash
python3 scripts/setup_cron.py pause --job-id <job_id>
```

**Resume**:
```bash
python3 scripts/setup_cron.py resume --job-id <job_id>
```

### Stop Trading

**Stop completely** (delete the cron job):
```bash
python3 scripts/setup_cron.py delete --job-id <job_id>
```

---

## Monitoring & Logs

All activity is logged to JSONL files in `logs/`:

### trades.jsonl
One line per trade (opened or closed):

```json
{"timestamp": "2026-02-12T14:35:00Z", "market": "Will BTC hit $100k by March?", "market_id": "0x123...", "side": "BUY", "size": 3.24, "price": 0.54, "fair_value": 0.67, "edge": 0.13, "status": "open", "pnl": null}
```

### scan_results.jsonl
One line per scan cycle:

```json
{"timestamp": "2026-02-12T14:35:00Z", "dry_run": false, "markets_scanned": 500, "opportunities_found": 23, "trades_executed": 3, "capital_deployed": 9.45, "api_cost": 1.12, "serenbucks_balance": 48.88, "polymarket_balance": 103.45}
```

### positions.json
Current state (updated after each trade):

```json
{
  "positions": [
    {
      "market": "Will BTC hit $100k by March?",
      "market_id": "0x123...",
      "token_id": "0x456...",
      "side": "BUY",
      "entry_price": 0.54,
      "current_price": 0.58,
      "size": 3.24,
      "unrealized_pnl": 0.84,
      "opened_at": "2026-02-12T14:35:00Z"
    }
  ],
  "total_unrealized_pnl": 0.84,
  "position_count": 1,
  "last_updated": "2026-02-12T18:00:00Z"
}
```

### notifications.jsonl
Critical events for user notification:

```json
{"timestamp": "2026-02-12T15:00:00Z", "level": "warning", "title": "Low SerenBucks Balance", "message": "Current: $1.23, Recommended: $20.00"}
```

---

## How It Works (Technical Details)

### Fair Value Estimation

The bot uses Claude to estimate true probabilities:

```python
def estimate_fair_value(market_question, current_price, research):
    prompt = f"""You are an expert analyst estimating the true probability of prediction market outcomes.

Market Question: {market_question}

Current Market Price: {current_price * 100:.1f}%

Research Summary:
{research}

Based on the research and your analysis, estimate the TRUE probability of this outcome occurring.

Provide your response in this exact format:
PROBABILITY: [number between 0 and 100]
CONFIDENCE: [low, medium, or high]
REASONING: [brief explanation]"""

    # Call Claude via seren-models
    response = seren.call_publisher(
        publisher='seren-models',
        method='POST',
        path='/chat/completions',
        body={
            'model': 'anthropic/claude-sonnet-4-20250514',
            'messages': [{'role': 'user', 'content': prompt}],
            'temperature': 0.3
        }
    )

    # Parse and return
    # (parsing logic extracts PROBABILITY and CONFIDENCE from response)
```

### Position Sizing (Kelly Criterion)

```python
def calculate_position_size(fair_value, market_price, bankroll, max_kelly=0.06):
    """
    Calculate optimal position size using Kelly Criterion

    Formula: kelly = (fair_value - price) / (1 - price) for BUY
    Uses quarter-Kelly (divide by 4) for conservatism
    Caps at max_kelly of bankroll
    """
    kelly = (fair_value - market_price) / (1 - market_price)
    kelly_adjusted = kelly / 4  # Quarter-Kelly
    kelly_capped = min(kelly_adjusted, max_kelly)

    position_size = bankroll * kelly_capped
    return round(position_size, 2)
```

---

## Implementation Status

### ✅ Fully Implemented & Working

**Core Trading Engine:**
- ✅ Market scanning via `polymarket-data` publisher (100+ active markets)
- ✅ AI research via `perplexity` publisher (Perplexity AI integration)
- ✅ Fair value estimation via `seren-models` publisher (Claude Sonnet 4.5)
- ✅ Kelly Criterion position sizing
- ✅ Order placement via `py-clob-client` (`DirectClobTrader` with local EIP-712 signing)
- ✅ Position tracking with unrealized P&L calculation
- ✅ Comprehensive JSONL logging (trades, scans, positions)

**Infrastructure:**
- ✅ Seren API client with publisher routing
- ✅ Desktop sidecar/keychain publisher auth support
- ✅ Legacy environment-variable credential fallback
- ✅ Dry-run mode (simulation without placing trades)
- ✅ Configuration system (JSON-based risk parameters)
- ✅ Cron-backed monitor mode for stale-order cleanup and guard exits

**Seren Publishers Used:**
- `polymarket-data` - Real-time market data (prices, liquidity, volumes)
- `py-clob-client` - Order placement with local EIP-712 signing (via `DirectClobTrader`)
- `perplexity` - AI-powered market research
- `seren-models` - LLM inference (Claude, GPT, Gemini, etc.)
- `seren-cron` - Autonomous local-pull scheduling

### ⚠️ Limitations

**Not Automated (Manual Only):**
- Bankroll rebalancing after profits/losses

**Not Implemented:**
- Web dashboard (command-line only)
- Email/webhook notifications (file logs only)
- Backtesting with historical data

---

## Cost Estimation

### SerenBucks (API Calls)
Per scan cycle:
- Perplexity research: $0.01 × markets researched
- Claude fair value: $0.01 × markets evaluated
- Total: ~$0.50-2.00 per scan (depends on markets scanned)

**Daily costs:**
- Every 5 min: $5-10/day
- Every 10 min: $2-5/day
- Every 30 min: $0.50-1.50/day

### Polymarket Trading
- Order placement: $0.005 per order
- Order cancellation: $0.002 per cancellation
- Price queries: $0.001 per request

---

## Troubleshooting

### "SEREN_API_KEY/API_KEY is required"
- Create `.env` file from `.env.example`
- Add `SEREN_API_KEY` for standalone runs
- For desktop-launched runs, ensure runtime `API_KEY` is injected

### "Polymarket credentials required"
- Recommended: enable desktop keychain mode in `.env` with `SEREN_DESKTOP_PUBLISHER_AUTH=true`
- Then configure Polymarket publisher credentials in Seren Desktop Settings > Publisher MCPs
- Legacy mode only: add `POLY_API_KEY`, `POLY_PASSPHRASE`, `POLY_ADDRESS` to `.env`

### "Low SerenBucks balance"
- Buy SerenBucks at: https://serendb.com/serenbucks or https://console.serendb.com
- Maintain at least $20 for smooth operation

### "Publisher call failed: 401"
- In desktop mode: verify Polymarket publisher credentials are configured/enabled in Seren Desktop
- In legacy mode: check `POLY_*` values and verify credentials haven't expired

---

## Best Practices

### For Users

1. **Start small**: Test with $50-100 before scaling up
2. **Use dry-run first**: Always test before going live
3. **Monitor regularly**: Check logs and positions daily
4. **Adjust conservatively**: Increase bankroll gradually
5. **Understand the risks**: Only trade what you can afford to lose
6. **Keep funded**: Maintain sufficient SerenBucks balance

### For Developers

1. **Always validate inputs**: Check config parameters are in valid ranges
2. **Never skip confirmation**: Live trading requires explicit user consent
3. **Log everything**: All trades, scans, errors go to log files
4. **Handle errors gracefully**: Never crash - log and notify
5. **Protect credentials**: Use environment variables, never log secrets
6. **Estimate costs proactively**: Warn users about SerenBucks costs

---

## Seren-Cron Integration

Use the skill-local `seren-cron` local-pull runner for scheduling. The schedule lives in Seren, but a local polling process must stay online on the machine that will execute the bot.

**Requirements:** Seren Desktop login or a valid `SEREN_API_KEY`. Live schedules also require Polymarket credentials plus funded SerenBucks.

Current Seren funding flow:

- Buy SerenBucks at `https://serendb.com/serenbucks` or `https://console.serendb.com`
- Stripe deposits start at `$5`
- A verified email is required before Stripe deposits
- API-first users can fund with `POST /wallet/deposit`

### Step 1 — Check seren-cron is available

```text
publisher: seren-cron
path:      /api/health
method:    GET
```

### Step 2 — Create or update the local pull schedule

Create or upsert the runner plus the local-pull job:

```bash
python3 scripts/setup_cron.py create --config config.json --schedule "0 */2 * * *" --run-type scan
python3 scripts/setup_cron.py create --config config.json --schedule "15 * * * *" --run-type monitor
```

For live mode, include `--live` after you have confirmed credentials, budget, and risk parameters.

### Step 3 — Start the local pull runner

Start the polling process that claims due work and runs `scripts/agent.py` locally:

```bash
python3 scripts/run_local_pull_runner.py --config config.json
```

Leave this process running on the machine that should execute trades.

### Step 4 — Manage the schedule and runner

```bash
python3 scripts/setup_cron.py list
python3 scripts/setup_cron.py list-runners
python3 scripts/setup_cron.py pause --job-id <job_id>
python3 scripts/setup_cron.py resume --job-id <job_id>
python3 scripts/setup_cron.py delete --job-id <job_id>
python3 scripts/setup_cron.py delete-runner --runner-id <runner_id>
```

### Insufficient Funds Guard

If a live trade or cycle fails because the trading balance or SerenBucks balance is too low to execute, **immediately pause the cron job**:

Pause the job immediately if live execution fails because trading funds or SerenBucks are exhausted.

Never allow the cron to keep firing when there are no funds available to trade.

---

## AgentSkills.io Standard

This skill follows the [AgentSkills.io](https://agentskills.io) open standard for agent skills, ensuring compatibility across:
- Claude Code
- OpenAI Codex
- Google Gemini
- Any compatible LLM tool

Taariq Lewis, SerenAI, Paloma, and Volume at https://serendb.com
Email: hello@serendb.com
