nothing-ever-happens-polymarket-bot

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Nothing Ever Happens Polymarket Bot

无事件发生Polymarket机器人

Skill by ara.so — Daily 2026 Skills collection.
An async Python bot that scans Polymarket standalone non-sports yes/no markets and buys the "No" outcome on any market where the NO price is below a configured cap. Designed for paper trading by default with explicit opt-in to live order transmission.

ara.so开发的Skill — 属于Daily 2026 Skills合集。
一款异步Python机器人,可扫描Polymarket平台上的独立非体育类是/否市场,当“否”选项的价格低于配置上限时买入该选项。默认采用模拟交易模式,需明确开启才能进行实盘订单传输。

What It Does

功能介绍

  • Scans Polymarket for standalone (non-grouped) yes/no markets
  • Filters out sports markets
  • Buys NO positions when NO price is below
    max_no_price
    threshold
  • Tracks open positions and persists recovery state to a database
  • Exposes a live dashboard (HTTP) showing portfolio and activity
  • Uses
    PaperExchangeClient
    unless all three live-mode env vars are set

  • 扫描Polymarket平台上的独立(非分组)是/否市场
  • 过滤掉体育类市场
  • 当“否”选项价格低于
    max_no_price
    阈值时买入该头寸
  • 跟踪未平仓头寸,并将恢复状态持久化到数据库
  • 提供实时仪表盘(HTTP)展示投资组合和交易活动
  • 除非设置了全部三个实盘模式环境变量,否则默认使用
    PaperExchangeClient

Installation

安装步骤

bash
git clone https://github.com/sterlingcrispin/nothing-ever-happens.git
cd nothing-ever-happens
pip install -r requirements.txt
cp config.example.json config.json
cp .env.example .env

bash
git clone https://github.com/sterlingcrispin/nothing-ever-happens.git
cd nothing-ever-happens
pip install -r requirements.txt
cp config.example.json config.json
cp .env.example .env

Configuration

配置说明

config.json
(non-secret runtime settings)

config.json
(非机密运行时设置)

Edit the
strategies.nothing_happens
block:
json
{
  "strategies": {
    "nothing_happens": {
      "max_no_price": 0.08,
      "order_size_usdc": 1.0,
      "max_open_positions": 50,
      "scan_interval_seconds": 60,
      "min_liquidity_usdc": 100,
      "exclude_keywords": ["sport", "nfl", "nba", "mlb", "nhl", "soccer", "tennis"]
    }
  }
}
Point to a different config file:
bash
CONFIG_PATH=/path/to/other_config.json python -m bot.main
编辑
strategies.nothing_happens
区块:
json
{
  "strategies": {
    "nothing_happens": {
      "max_no_price": 0.08,
      "order_size_usdc": 1.0,
      "max_open_positions": 50,
      "scan_interval_seconds": 60,
      "min_liquidity_usdc": 100,
      "exclude_keywords": ["sport", "nfl", "nba", "mlb", "nhl", "soccer", "tennis"]
    }
  }
}
指定其他配置文件:
bash
CONFIG_PATH=/path/to/other_config.json python -m bot.main

.env
(secrets and runtime flags)

.env
(机密信息与运行时标志)

dotenv
undefined
dotenv
undefined

Safety flags — ALL three required for live order transmission

安全标志 — 全部三个都设置才能进行实盘订单传输

BOT_MODE=paper # set to "live" for real orders DRY_RUN=true # set to "false" for real orders LIVE_TRADING_ENABLED=false # set to "true" for real orders
BOT_MODE=paper # 设置为"live"以启用实盘交易 DRY_RUN=true # 设置为"false"以启用实盘交易 LIVE_TRADING_ENABLED=false # 设置为"true"以启用实盘交易

Required only in live mode

仅实盘模式下需要

PRIVATE_KEY=$PRIVATE_KEY FUNDER_ADDRESS=$FUNDER_ADDRESS DATABASE_URL=$DATABASE_URL POLYGON_RPC_URL=$POLYGON_RPC_URL
PRIVATE_KEY=$PRIVATE_KEY FUNDER_ADDRESS=$FUNDER_ADDRESS DATABASE_URL=$DATABASE_URL POLYGON_RPC_URL=$POLYGON_RPC_URL

Optional

可选配置

PORT=8080 DASHBOARD_PORT=8080

> **Never hardcode secrets.** Always use environment variable references.

---
PORT=8080 DASHBOARD_PORT=8080

> **切勿硬编码机密信息**,始终使用环境变量引用。

---

Running Locally

本地运行

bash
undefined
bash
undefined

Paper trading (default — safe, no real orders)

模拟交易(默认模式 — 安全,无真实订单)

python -m bot.main
python -m bot.main

Enable live trading (requires all three flags)

启用实盘交易(需设置全部三个标志)

BOT_MODE=live DRY_RUN=false LIVE_TRADING_ENABLED=true python -m bot.main

The dashboard will bind to `$PORT` or `$DASHBOARD_PORT` when set.

---
BOT_MODE=live DRY_RUN=false LIVE_TRADING_ENABLED=true python -m bot.main

仪表盘将绑定到`$PORT`或`$DASHBOARD_PORT`(若已设置)。

---

Project Structure

项目结构

bot/
  main.py               # Entry point — starts the runtime loop
  strategies/
    nothing_happens.py  # Core strategy: scan, filter, buy NO
  exchange/
    client.py           # Live exchange client (Polymarket CLOB API)
    paper_client.py     # PaperExchangeClient for safe simulation
  dashboard.py          # HTTP dashboard server
  recovery.py           # Persist and restore open positions

scripts/
  db_stats.py           # Inspect DB table counts and recent activity
  export_db.py          # Export live DB tables
  wallet_history.py     # Positions, trades, balances for configured wallet
  parse_logs.py         # Convert Heroku JSON logs to readable output

tests/                  # Unit and regression tests

bot/
  main.py               # 入口文件 — 启动运行循环
  strategies/
    nothing_happens.py  # 核心策略:扫描、过滤、买入“否”选项
  exchange/
    client.py           # 实盘交易所客户端(Polymarket CLOB API)
    paper_client.py     # PaperExchangeClient用于安全模拟交易
  dashboard.py          # HTTP仪表盘服务器
  recovery.py           # 持久化和恢复未平仓头寸

scripts/
  db_stats.py           # 查看数据库表计数和近期活动
  export_db.py          # 导出实盘数据库表
  wallet_history.py     # 查看配置钱包的头寸、交易和余额
  parse_logs.py         # 将Heroku JSON日志转换为可读格式

tests/                  # 单元测试和回归测试

Key Commands

关键命令

Run Tests

运行测试

bash
python -m pytest -q
bash
python -m pytest -q

Operational Scripts

运维脚本

bash
undefined
bash
undefined

Inspect live database

查看实盘数据库

python scripts/db_stats.py
python scripts/db_stats.py

Export database tables (uses DATABASE_URL or Heroku app)

导出数据库表(使用DATABASE_URL或Heroku应用)

python scripts/export_db.py
python scripts/export_db.py

Pull wallet history

获取钱包历史记录

python scripts/wallet_history.py
python scripts/wallet_history.py

Parse Heroku JSON logs into readable output

将Heroku JSON日志解析为可读格式

python scripts/parse_logs.py

---
python scripts/parse_logs.py

---

Heroku Deployment

Heroku部署

One-time setup

一次性设置

bash
export HEROKU_APP_NAME=my-polymarket-bot
bash
export HEROKU_APP_NAME=my-polymarket-bot

Set runtime flags

设置运行时标志

heroku config:set BOT_MODE=live DRY_RUN=false LIVE_TRADING_ENABLED=true
-a "$HEROKU_APP_NAME"
heroku config:set BOT_MODE=live DRY_RUN=false LIVE_TRADING_ENABLED=true
-a "$HEROKU_APP_NAME"

Set secrets

设置机密信息

heroku config:set
PRIVATE_KEY="$PRIVATE_KEY"
FUNDER_ADDRESS="$FUNDER_ADDRESS"
POLYGON_RPC_URL="$POLYGON_RPC_URL"
DATABASE_URL="$DATABASE_URL"
-a "$HEROKU_APP_NAME"
heroku config:set
PRIVATE_KEY="$PRIVATE_KEY"
FUNDER_ADDRESS="$FUNDER_ADDRESS"
POLYGON_RPC_URL="$POLYGON_RPC_URL"
DATABASE_URL="$DATABASE_URL"
-a "$HEROKU_APP_NAME"

Deploy

部署

git push heroku main:main
git push heroku main:main

Scale — ONLY the web dyno

调整实例数 — 仅运行web dyno

heroku ps:scale web=1 worker=0 -a "$HEROKU_APP_NAME"

> Do **not** run the `worker` dyno. It exists only to fail fast if started accidentally.
heroku ps:scale web=1 worker=0 -a "$HEROKU_APP_NAME"

> 请勿运行`worker` dyno,它仅用于在意外启动时快速失败。

Shell helpers

Shell辅助脚本

bash
./alive.sh              # Check if the app is alive
./logs.sh               # Tail logs
./live_enabled.sh       # Enable live trading
./live_disabled.sh      # Disable live trading (back to paper)
./kill.sh               # Stop the bot
All helpers use
$HEROKU_APP_NAME
or accept an app name as an argument:
bash
./logs.sh my-polymarket-bot

bash
./alive.sh              # 检查应用是否运行
./logs.sh               # 查看实时日志
./live_enabled.sh       # 启用实盘交易
./live_disabled.sh      # 禁用实盘交易(切换回模拟模式)
./kill.sh               # 停止机器人
所有辅助脚本使用
$HEROKU_APP_NAME
,或接受应用名称作为参数:
bash
./logs.sh my-polymarket-bot

Safety Model

安全模型

The bot defaults to
PaperExchangeClient
(simulated orders, no real money) unless all three of these are set:
VariableRequired value
BOT_MODE
live
LIVE_TRADING_ENABLED
true
DRY_RUN
false
If any one is missing or wrong, paper mode is used. This is intentional — it makes accidental live trading very hard.
Additional live-mode requirements:
  • PRIVATE_KEY
    — wallet private key
  • FUNDER_ADDRESS
    — required for signature types
    1
    and
    2
  • DATABASE_URL
    — for recovery state persistence
  • POLYGON_RPC_URL
    — for proxy-wallet approvals and redemption

机器人默认使用
PaperExchangeClient
(模拟订单,无真实资金),除非同时设置以下全部三个变量:
变量必填值
BOT_MODE
live
LIVE_TRADING_ENABLED
true
DRY_RUN
false
若任一变量缺失或设置错误,将使用模拟模式。这是有意设计的,可大幅降低意外实盘交易的风险。
实盘模式额外要求:
  • PRIVATE_KEY
    — 钱包私钥
  • FUNDER_ADDRESS
    — 签名类型
    1
    2
    所需
  • DATABASE_URL
    — 用于持久化恢复状态
  • POLYGON_RPC_URL
    — 用于代理钱包授权和赎回

Code Examples

代码示例

Check if bot will use live or paper mode

检查机器人将使用实盘还是模拟模式

python
import os

def is_live_mode() -> bool:
    return (
        os.getenv("BOT_MODE") == "live"
        and os.getenv("LIVE_TRADING_ENABLED", "").lower() == "true"
        and os.getenv("DRY_RUN", "true").lower() == "false"
    )

print("Live mode:", is_live_mode())
python
import os

def is_live_mode() -> bool:
    return (
        os.getenv("BOT_MODE") == "live"
        and os.getenv("LIVE_TRADING_ENABLED", "").lower() == "true"
        and os.getenv("DRY_RUN", "true").lower() == "false"
    )

print("Live mode:", is_live_mode())

Load strategy config

加载策略配置

python
import json, os

config_path = os.getenv("CONFIG_PATH", "config.json")
with open(config_path) as f:
    config = json.load(f)

strategy_cfg = config["strategies"]["nothing_happens"]
max_no_price = strategy_cfg["max_no_price"]       # e.g. 0.08
order_size   = strategy_cfg["order_size_usdc"]    # e.g. 1.0
print(f"Will buy NO when price <= {max_no_price} USDC, size={order_size} USDC")
python
import json, os

config_path = os.getenv("CONFIG_PATH", "config.json")
with open(config_path) as f:
    config = json.load(f)

strategy_cfg = config["strategies"]["nothing_happens"]
max_no_price = strategy_cfg["max_no_price"]       # 示例:0.08
order_size   = strategy_cfg["order_size_usdc"]    # 示例:1.0
print(f"当价格 <= {max_no_price} USDC时买入‘否’选项,订单规模={order_size} USDC")

Run the bot programmatically

以编程方式运行机器人

python
import asyncio
from bot.main import main

asyncio.run(main())
python
import asyncio
from bot.main import main

asyncio.run(main())

Inspect DB stats

查看数据库统计信息

bash
DATABASE_URL=$DATABASE_URL python scripts/db_stats.py
bash
DATABASE_URL=$DATABASE_URL python scripts/db_stats.py

Parse Heroku logs to HTML

将Heroku日志解析为HTML格式

bash
heroku logs --num=1500 -a "$HEROKU_APP_NAME" | python scripts/parse_logs.py --html > report.html
bash
heroku logs --num=1500 -a "$HEROKU_APP_NAME" | python scripts/parse_logs.py --html > report.html

Export DB from a Heroku app

从Heroku应用导出数据库

bash
python scripts/export_db.py --app "$HEROKU_APP_NAME"

bash
python scripts/export_db.py --app "$HEROKU_APP_NAME"

Common Patterns

常见模式

Disabling live trading quickly (kill switch)

快速禁用实盘交易(紧急开关)

bash
heroku config:set LIVE_TRADING_ENABLED=false -a "$HEROKU_APP_NAME"
bash
heroku config:set LIVE_TRADING_ENABLED=false -a "$HEROKU_APP_NAME"

or use the helper:

或使用辅助脚本:

./live_disabled.sh

The bot will immediately fall back to paper mode on next cycle without a restart.
./live_disabled.sh

机器人将在下一个循环中立即切换回模拟模式,无需重启。

Adjusting the NO price cap without redeploying

无需重新部署即可调整“否”选项价格上限

Edit
config.json
, commit, and push:
bash
undefined
编辑
config.json
,提交并推送:
bash
undefined

Lower the cap to only buy very cheap NOs

降低上限,仅买入价格极低的“否”选项

jq '.strategies.nothing_happens.max_no_price = 0.05' config.json > tmp.json && mv tmp.json config.json git add config.json && git commit -m "lower max_no_price to 0.05" git push heroku main:main
undefined
jq '.strategies.nothing_happens.max_no_price = 0.05' config.json > tmp.json && mv tmp.json config.json git add config.json && git commit -m "lower max_no_price to 0.05" git push heroku main:main
undefined

Adding more keyword exclusions

添加更多排除关键词

json
{
  "strategies": {
    "nothing_happens": {
      "exclude_keywords": ["sport", "nfl", "nba", "mlb", "nhl", "soccer", "tennis", "golf", "ufc", "esport"]
    }
  }
}

json
{
  "strategies": {
    "nothing_happens": {
      "exclude_keywords": ["sport", "nfl", "nba", "mlb", "nhl", "soccer", "tennis", "golf", "ufc", "esport"]
    }
  }
}

Troubleshooting

故障排查

SymptomLikely CauseFix
Bot uses paper mode unexpectedlyOne of the three live flags is missing/wrongCheck all three:
BOT_MODE
,
LIVE_TRADING_ENABLED
,
DRY_RUN
DATABASE_URL
errors in live mode
Postgres not provisioned
heroku addons:create heroku-postgresql -a "$HEROKU_APP_NAME"
Orders never transmit
DRY_RUN
still
true
heroku config:set DRY_RUN=false
Dashboard not accessible
PORT
not set
heroku config:set PORT=8080
Worker dyno crashes immediatelyDon't run worker dyno
heroku ps:scale worker=0
Bot buys sports marketsKeywords not in
exclude_keywords
Add sport/league names to config
Logs unreadable (JSON)Heroku structured loggingPipe through
scripts/parse_logs.py

症状可能原因解决方法
机器人意外使用模拟模式三个实盘标志中有一个缺失或设置错误检查全部三个标志:
BOT_MODE
LIVE_TRADING_ENABLED
DRY_RUN
实盘模式下出现
DATABASE_URL
错误
未配置Postgres
heroku addons:create heroku-postgresql -a "$HEROKU_APP_NAME"
订单始终无法传输
DRY_RUN
仍设置为
true
heroku config:set DRY_RUN=false
仪表盘无法访问未设置
PORT
heroku config:set PORT=8080
Worker dyno立即崩溃请勿运行worker dyno
heroku ps:scale worker=0
机器人买入体育类市场排除关键词列表中缺少相关词汇将体育/联赛名称添加到配置中
日志不可读(JSON格式)Heroku使用结构化日志通过
scripts/parse_logs.py
管道处理

Disclaimer

免责声明

FOR ENTERTAINMENT ONLY. PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. USE AT YOUR OWN RISK. NOT FINANCIAL ADVICE.
仅供娱乐使用。按“原样”提供,不提供任何明示或暗示的担保。风险自负。非财务建议。