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

Build docs developers (and LLMs) love