Skip to main content

Connection Issues

WebSocket Disconnects

Symptom: Connection status shows [OFF] in redCause:
  • Chainlink WebSocket disconnected
  • Network connectivity issue
  • Polymarket API downtime
Solution:
1

Check network

ping ws-live-data.polymarket.com
2

Restart bot

The bot has auto-reconnect logic, but manual restart helps:
# Stop with Ctrl+C
pnpm start
3

Check logs

Look for WebSocket errors:
cat data/logs/$(date +%Y-%m-%d).log | grep "WebSocket"
Prevention: WebSocket client in src/feeds/chainlink.js:25 has built-in reconnection. If reconnects fail repeatedly, check your firewall settings.
Symptom: Polymarket status shows [POLY OFF] in redCause:
  • Polymarket CLOB API unavailable
  • Rate limiting
  • Market not active yet
Solution:
  1. Check market availability:
    curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false" | jq .
    
  2. Verify CLOB API:
    curl -s "https://clob.polymarket.com/price?token_id={token}" | jq .
    
  3. Check rate limits:
    • Polymarket CLOB: 10 requests/second
    • Gamma API: 100 requests/minute
    • Bot implements backoff in src/feeds/polymarket.js:45
Note: Bot continues running without Polymarket data - predictions work, but no EV/edge calculations.

Missing Strike Price

Symptom: Header shows Strike: --Cause:
  • Vatic Trading API unavailable
  • Interval timestamp not found in API
  • API key issues (if required)
Solution:
  1. Test Vatic API manually:
    TIMESTAMP=$(date -u +%s)
    curl -s "https://api.vatic.trading/api/v1/targets/${TIMESTAMP}" | jq .
    
  2. Check timestamp alignment: Vatic uses Unix timestamps rounded to 5-minute intervals:
    // Should be multiple of 300 (5 minutes)
    const intervalEpoch = Math.floor(Date.now() / 1000 / 300) * 300
    
  3. Fallback mode: Bot can run without strike price in simulation mode (no trading decisions).

Prediction Issues

Constant Abstention

Symptom: Bot never places bets, always shows ABSTENCIONCommon reasons:
ReasonFix
insufficient_dataWait for 50+ ticks (2-3 minutes). Check WebSocket is connected.
dead_zoneMarket is balanced near 50%. Normal behavior. Wait for clearer signal.
insufficient_marginLower threshold in config: abstention.minMargin (default 0.15)
insufficient_evLower threshold: abstention.minEV (default 0.05)
cold_streakAccuracy dropped <40%. Model is self-protecting. Wait for recovery.
drawdown_suspensionBankroll in RED/CRITICAL. Reduce risk or wait for recovery.
anomalous_volatilityHigh volatility period. Normal safety mechanism.
To debug:
# Check abstention reasons in logs
cat data/logs/$(date +%Y-%m-%d).log | jq 'select(.abstention != null) | .abstention.reason' | sort | uniq -c
Adjust config (config/default.json):
{
  "abstention": {
    "minMargin": 0.10,      // Lower from 0.15 (more aggressive)
    "minEV": 0.03,          // Lower from 0.05
    "deadZoneWidth": 0.08,  // Lower from 0.10
    "volatilityThreshold": 2.5  // Raise from 2.0 (tolerate more vol)
  }
}
Lowering abstention thresholds increases trade frequency but reduces win rate. Only adjust if you understand the risk/reward tradeoff.
Symptom: Predictions always show 50-60% confidenceCause:
  • Insufficient price history
  • Low volatility (price flat)
  • Model features not detecting signal
Diagnostics:
  1. Check data collection:
    # Count ticks in current interval
    tail -100 data/logs/$(date +%Y-%m-%d).log | grep "tick" | wc -l
    
    Should see 50-100 ticks per 5-minute interval.
  2. Check volatility: Low volatility = low confidence (model can’t distinguish UP/DOWN)
    # Check recent volatility values
    tail -50 data/logs/$(date +%Y-%m-%d).log | jq '.volatility.sigma'
    
  3. Review momentum indicators:
    tail -50 data/logs/$(date +%Y-%m-%d).log | jq '.momentum'
    
Solution:
  • If low data: Wait longer, check WebSocket
  • If low volatility: Normal - model won’t trade flat markets
  • If indicators broken: Check logs for NaN values, restart bot

Incorrect Predictions

Symptom: Daily report shows Early 1m accuracy below 70%Troubleshooting steps:
1

Check sample size

Need 50+ predictions for statistical significance.
jq 'length' data/history.json
2

Run daily report

pnpm report
Check:
  • Brier Score (should be <0.25)
  • Murphy Reliability (should be <0.05)
  • Confidence bands (high bands should be accurate)
3

Analyze misses

Look at “Fallos del Early 1m” section in report.
  • Are misses clustered in high volatility?
  • Are misses when price is near strike?
  • Are high-confidence predictions failing?
4

Check calibration

Enable Platt calibration:
{
  "calibration": {
    "enabled": true,
    "method": "platt"
  }
}
Restart bot and monitor for 50+ intervals.
Common causes:
  • Trending market: Model assumes mean reversion but market is trending
    • Solution: Increase momentum weight in config
  • High volatility: Predictions less reliable in chaotic markets
    • Solution: Model already abstains via anomalous_volatility - working as intended
  • Strike proximity: Hard to predict when price ≈ strike
    • Solution: Increase dead_zone threshold to abstain near 50/50 calls

Data Issues

Missing History

Symptom: Console table is empty or shows very few rowsCause:
  • data/history.json missing or corrupted
  • Bot just started (no history yet)
  • Permissions issue
Solution:
  1. Check file exists:
    ls -lh data/history.json
    
  2. Verify JSON validity:
    jq . data/history.json > /dev/null && echo "Valid" || echo "Invalid"
    
  3. If corrupted, restore from backup:
    # Bot creates backups in logs
    cp data/logs/history-backup-*.json data/history.json
    
  4. If missing, create empty array:
    echo '[]' > data/history.json
    
Prevention: History is persisted after every interval close in src/tracker/history.js:23. If you see frequent corruption, check disk space:
df -h
Symptom: Table columns show -- instead of predictionsPossible causes:
ColumnCauseFix
Early 1mBot started <1min before closeNormal - prediction not captured yet
E.AcNo Early 1m predictionWait for next interval
qPolymarket data unavailableCheck [POLY] status, see “Connection Issues”
BetAbstainingCheck abstention reason in header
Pr 30sBot started <30s before closeNormal - wait for capture
F.AcInterval still ACTIVENormal - accuracy calculated on close

Log File Issues

Symptom: data/logs/ directory emptyCause:
  • Logger not initialized
  • Permissions issue
  • Disk full
Solution:
  1. Check directory permissions:
    ls -ld data/logs/
    # Should be drwxr-xr-x
    
  2. Create directory:
    mkdir -p data/logs
    chmod 755 data/logs
    
  3. Check disk space:
    df -h .
    
  4. Verify logger config: In config/default.json:
    {
      "logging": {
        "enabled": true,
        "directory": "data/logs",
        "level": "info"
      }
    }
    
Logger creates daily files: YYYY-MM-DD.log

Performance Issues

High CPU Usage

Symptom: High CPU usage, fans spinningCause:
  • Tick logging creating too many writes
  • Console rendering in tight loop
  • Memory leak in WebSocket handler
Diagnostics:
# Check process stats
ps aux | grep node

# Profile with Node.js
node --prof src/index.js
# Run for 5 minutes, then Ctrl+C
node --prof-process isolate-*.log > profile.txt
Solutions:
  1. Reduce console refresh rate: In src/ui/display.js, the render is called on every tick. Add throttling:
    // Render max once per second
    if (Date.now() - lastRender < 1000) return
    
  2. Disable tick logging: In config/default.json:
    {
      "logging": {
        "tickLogging": false
      }
    }
    
  3. Reduce history retention: Display shows last 15 rows only, but full history is loaded:
    // In src/ui/display.js:186
    const recentHistory = allHistory.slice(-15)  // Already optimized
    

Memory Leaks

Symptom: Bot memory usage increases steadily, eventually crashesCause:
  • WebSocket event listeners not cleaned up
  • History array growing unbounded
  • Tick data accumulating
Diagnostics:
# Monitor memory
watch -n 5 'ps aux | grep node | grep -v grep'

# Heap snapshot (requires --inspect)
node --inspect src/index.js
# Chrome DevTools > Memory > Take Heap Snapshot
Solutions:
  1. Restart daily via cron:
    # crontab -e
    0 0 * * * pkill -f "node.*index.js" && cd /path/to/bot && pnpm start
    
  2. Limit history size: In src/tracker/history.js, add rotation:
    if (history.length > 1000) {
      history = history.slice(-500)  // Keep last 500
    }
    
  3. Check WebSocket cleanup: In src/feeds/chainlink.js, ensure:
    ws.on('close', () => {
      ws.removeAllListeners()  // Clean up
    })
    

Trading Simulation Issues

Bet Sizes Too Large

Symptom: Bet size exceeds 20% of bankrollCause:
  • Very high confidence prediction (95%+)
  • Large edge vs market
  • Kelly alpha set too high
Risk: Large bets increase variance - one wrong prediction = significant loss.Solution:
  1. Lower Kelly alpha: In config/default.json:
    {
      "risk": {
        "kelly": {
          "tiers": {
            "excellent": 0.15,  // Lower from 0.25
            "good": 0.10,
            "acceptable": 0.05,
            "poor": 0.02
          }
        }
      }
    }
    
  2. Add bet size cap: In src/risk/position-sizer.js:34, add:
    const cappedBet = Math.min(kellySuggestion, bankroll * 0.10)  // Max 10%
    
  3. Increase drawdown sensitivity:
    {
      "risk": {
        "drawdown": {
          "levels": {
            "yellow": 0.05,  // Start caution at 5% (was 10%)
            "red": 0.10,
            "critical": 0.20
          }
        }
      }
    }
    

Drawdown Not Recovering

Symptom: Drawdown stays in RED or CRITICAL, no trades executedCause:
  • String of losses pushed bankroll down
  • High-water mark too high
  • Not enough winning trades to recover
Understanding drawdown:
drawdown = (highWaterMark - currentBankroll) / highWaterMark
To exit RED (20%), bankroll must recover to within 20% of all-time high.Solutions:
  1. Reset high-water mark (CAUTION):
    // In src/risk/drawdown-tracker.js
    // Only do this if starting fresh
    this.highWaterMark = this.bankroll
    
  2. Lower drawdown thresholds:
    {
      "risk": {
        "drawdown": {
          "levels": {
            "red": 0.30,      // Was 0.20
            "critical": 0.40   // Was 0.30
          }
        }
      }
    }
    
    This increases risk - bot will keep trading deeper into losses.
  3. Wait for recovery: Drawdown protection is working as intended. Bot needs winning streak to recover naturally.
Check recovery progress:
# Last 20 trades
tail -20 data/history.json | jq '.[] | select(.betSize > 0) | {index, betSize, result, earlyPredictionCorrect}'

Report Generation Issues

Symptom: pnpm report outputs “No hay datos para generar reporte.”Cause:
  • No intervals closed today
  • data/history.json empty or missing
  • Date filter excluding all records
Solution:
  1. Check history file:
    jq 'length' data/history.json
    
    Should show number of intervals.
  2. Check date filtering:
    # Today's records
    jq "[.[] | select(.closedAt | startswith(\"$(date -u +%Y-%m-%d)\"))]
    
| length” data/history.json

3. **Generate for specific date:**
```bash
node src/reporter/daily.js 2026-02-23
  1. Generate for all data (no date filter):
    # Edit src/reporter/daily.js:317
    const date = null  // Instead of process.argv[2]
    node src/reporter/daily.js
    
Symptom: Report generated but not visible in Obsidian vaultCause:
  • Vault path misconfigured
  • Obsidian not synced
  • File permissions
Solution:
  1. Verify vault path: In src/reporter/daily.js:9-10:
    const VAULT_ROOT = '/Users/rperaza/Library/Mobile Documents/...'
    const VAULT_DEST = 'joicodev/ideas/polymarket/reports'
    
    Check path exists:
    ls -la "$VAULT_ROOT/$VAULT_DEST/"
    
  2. Check file was created:
    ls -lh "$VAULT_ROOT/$VAULT_DEST/reporte-$(date +%Y-%m-%d).md"
    
  3. Force Obsidian refresh:
    • Open Obsidian
    • Command Palette (Cmd+P)
    • “Reload app without saving”
  4. Check iCloud sync: Obsidian uses iCloud - sync can take 1-2 minutes.

Configuration Issues

Symptom: Modified config/default.json but bot behavior unchangedCause:
  • Bot not restarted
  • Config cache
  • Syntax error in JSON
Solution:
  1. Validate JSON:
    jq . config/default.json > /dev/null && echo "Valid" || echo "Invalid"
    
  2. Check config loading:
    # Bot loads config on startup
    grep "Config loaded" data/logs/$(date +%Y-%m-%d).log
    
  3. Restart bot:
    # Stop with Ctrl+C
    pnpm start
    
  4. Verify config in logs:
    # Check what config was loaded
    head -50 data/logs/$(date +%Y-%m-%d).log | jq '.config'
    

Emergency Procedures

Immediate actions:
1

Stop the bot

# Ctrl+C or:
pkill -f "node.*index.js"
2

Backup current state

cp data/history.json data/history-backup-$(date +%Y%m%d-%H%M%S).json
cp config/default.json config/default-backup-$(date +%Y%m%d-%H%M%S).json
3

Analyze recent performance

pnpm report
Check:
  • Early 1m accuracy
  • Recent misses
  • Drawdown level
4

Increase abstention thresholds

Make bot more conservative:
{
  "abstention": {
    "minMargin": 0.20,
    "minEV": 0.08
  }
}
5

Restart in monitor-only mode

Comment out trade execution code, run read-only to collect data without risk.

Getting Help

Check Logs

tail -100 data/logs/$(date +%Y-%m-%d).log | jq .

Generate Report

pnpm report

Inspect State

jq '.[-5:]' data/history.json

Test APIs

# Chainlink
wscat -c wss://ws-live-data.polymarket.com

# Vatic
curl -s https://api.vatic.trading/api/v1/targets/$(date +%s) | jq .

Common Error Messages

ErrorMeaningSolution
WebSocket closed unexpectedlyChainlink feed disconnectedAuto-reconnects, check network
Strike price not availableVatic API returned 404Interval may not exist yet, wait 30s
Insufficient data for prediction< 50 ticks collectedWait longer, check WebSocket
NaN detected in volatilityMath error in calculationCheck for zero variance, restart
Market data not availablePolymarket CLOB downBot continues, no EV calcs
ENOSPC: no space left on deviceDisk fullClean up old logs, increase storage

Diagnostic Commands

ps aux | grep node
netstat -an | grep ESTABLISHED | grep polymarket

Next Steps

Reading Output

Understand the console display

Daily Reports

Deep dive into performance metrics

Configuration

Full config reference and tuning guide

API Reference

Internal API documentation