Polymarket Bot Tutorial · Chapter 29 of 32

Побудуйте paper trading engine для Polymarket перед запуском у live: симулюйте orders за реальними цінами, відстежуйте P&L, впровадьте 30-trade gate (>=55% win rate, +PnL) перед будь-яким live capital, і створіть code skeleton.

Що охоплює ця глава

Paper trading - це обов'язковий крок між ідеєю стратегії та live deployment. Ця глава описує простий paper engine, який стояв за кожним live bot, що ми запускали - менше ніж 200 рядків Python, відстежує кожну trade у JSONL diary, застосовує ті самі fees/slippage, що й live path.

  • Чому paper перед live (завжди)
  • 30-trade gate (підтверджені +55% WR + positive PnL)
  • Створення простого paper engine
  • Ведення paper diary паралельно з live diary
  • Коли paper diverges від live (і чому)
  • Перехід до live: невеликий перший deposit
  • Code: мінімальний paper engine

Чому paper перед live (завжди)

30-trade paper gate - це єдина дисципліна, що відділяє 7.6% прибуткових Polymarket traders від 84.1% тих, хто втрачає гроші. Більшість builder-ів пропускають цей крок і платять за навчання. Чесна причина, чому це працює: paper trading показує реальний win rate стратегії на достатній вибірці, щоб відрізнити сигнал від luck.

Пропуск paper коштує більше, ніж економить. Стратегія, яка виглядає прибутковою у backtest, але насправді є coin flip, спалить $200-500 live capital, перш ніж накопичиться 30-sample size live data. Paper-trading тих самих 30 trades коштує $0.

Paper engine не має бути складним. Він має бути чесним - ті самі fees, той самий slippage, та сама fill latency, що й у live path. Чим простіше, тим краще, бо все необов'язкове зріжеться, і bot вийде в live раніше, ніж слід.

30-trade gate (підтверджені +55% WR + positive PnL)

Gate є бінарним: 30 закритих paper trades, заздалегідь визначені критерії успіху (зазвичай WR ≥ 55% для стратегії з positive EV), або жодного live deployment.

30 - це мінімальний sample size, за якого 95% confidence interval для true win rate достатньо вузький, щоб відрізнити signal від noise. Нижче 30 спостережуваний rate 60% може відповідати true rate 45-75%. На 30+ інтервал звужується приблизно до ~50-70% - все ще широкий, але вже достатній, щоб відкинути думку «стратегія - це coin flip».

Критерії успіху потрібно встановити ДО початку paper run. Якщо робити це після, виникає post-hoc rationalization (ви знайдете спосіб інтерпретувати будь-які 30 trades як «достатньо добре»).

Створення простого paper engine

Paper engine - це, по суті, live trading code, у якому функцію order-placement замінено на simulated fill. Симуляція:

  • Read live order book: той самий виклик, який зробив би live bot.
  • Simulate fill: якщо buying на FOK із ціною ≥ best ask, заповніть order за volume-weighted average of asks consumed; запишіть fill у paper diary.
  • Apply fees: відніміть ті самі fees, які сплатив би live path.
  • Track inventory: підтримуйте паралельні paper-balance та paper-positions dictionary.

Увесь engine вміщується в 100-200 рядків Python. Головна дисципліна: кожне припущення, яке робить live path (fill rate, latency, fee), має бути відтворене в paper, навіть якщо трохи гірше за реальність - paper має бути floor, а не ceiling.

Ведення paper diary паралельно з live diary

Paper trading run створює JSONL diary, який за структурою не відрізняється від live diary, що bot писатиме пізніше. Ті самі поля: timestamp, action, market_slug, side, size, price, expected_fill_price, simulated_pnl_at_exit.

Є дві причини використовувати той самий формат. По-перше, analysis tools, які читають live trades (PnL reports, win-rate calculators), працюють на paper без змін. По-друге, пізніше порівняння paper із live допомагає виявити divergences, які вказують на bugs.

Порада для production: нехай paper engine записує в per_trade_paper.jsonl у тій самій директорії, що й live per_trade.jsonl. Одна команда порівнює обидва: diff -y <(jq -r .market_slug per_trade.jsonl) <(jq -r .market_slug per_trade_paper.jsonl).

Коли paper diverges від live (і чому)

Неминучі divergences між paper і live. Три найпоширеніші.

  • Slippage: paper виконує fill за snapshot ask; live проходить по book і може заповнитися на 1-2c гірше на thin markets. Рішення: симулюйте slippage в paper, додаючи per-trade penalty, що дорівнює половині spread.
  • Fill latency: paper заповнюється миттєво; live займає 200-500ms, за які price може змінитися. Рішення: симулюйте це, чекаючи й повторно читаючи book перед «fill» у paper.
  • Adverse selection: paper припускає, що ви отримуєте best ask; live конкурує з іншими bots, які могли вже забрати той ask. Рішення: важче симулювати; чесно визнайте собі, що paper переоцінює результат.

Коли paper показує +5%/month, а live працює на -2%/month, розрив зазвичай спричиняє один із цих факторів. Перевіряйте їх по одному, а не припускайте, що сама strategy була неправильною.

Перехід до live: невеликий перший deposit

Paper проходить 30 trades. План live deployment:

  1. Deposit $25-50 як smoke-test capital. Сприймайте це як навчання; якщо втратите гроші, урок був того вартий.
  2. Запустіть bot у live mode на 5-10 trades з positions мінімального розміру (5 shares).
  3. Перевірте, що кожен fill відповідає paper expectations у межах 2c. Дослідіть будь-який більший розрив перед продовженням.
  4. Якщо 5-10 live trades збігаються з paper, внесіть $200-500 і запускайте positions нормального розміру.
  5. Якщо не збігаються, зупиніться, debug, виправте, перезапустіть із кроку 1.

Найпоширеніший live-paper gap під час першого deployment - це пропущені fees або неправильна оцінка slippage. Виправити це просто; дисципліна полягає в тому, щоб виявити gap до масштабування capital.

Code: мінімальний paper engine

Reference: простий paper engine, який читає live book + симулює FOK fill.

import json, time
PAPER_BAL = 10_000.0   # USD starting
positions = {}         # token_id -> shares

def paper_fok_buy(token_id, max_price, size):
    book = fetch_book(token_id)
    # Walk asks, fill what we can within max_price
    filled = 0; cost = 0
    for level in book.asks:
        px = float(level["price"])
        if px > max_price: break
        avail = float(level["size"])
        take = min(avail, size - filled)
        filled += take
        cost += take * px
        if filled >= size: break
    if filled < size:
        return {"status":"rejected","filled":0}  # FOK semantics

    global PAPER_BAL
    PAPER_BAL -= cost
    positions[token_id] = positions.get(token_id, 0) + filled

    log_paper({"ts": int(time.time()), "action":"buy",
               "token": token_id, "size": filled, "price": cost/filled})
    return {"status":"matched","filled":filled,"cost":cost}

Production additions: paper sell function (mirror of buy), paper GTC simulation (post on book at price, simulate fill when mid reaches price), reconciliation between paper diary and "would-have-been" live diary.

Поширені запитання

Що таке 30-trade gate?
Наше внутрішнє правило переходу з paper у live: щонайменше 30 закритих paper trades, win rate >= 55% і net PnL позитивний після врахування slippage. Якщо не виконано хоча б одну умову, ви залишаєтеся в paper. Ми вигадали це правило після кількох передчасних спроб go-live, які у 2025 році спустошили рахунки.
Чому 30 trades, а не 100?
Статистична потужність. На 30 trades win rate 55% має приблизно 70% імовірності бути справжнім edge, а не noise. На 100 trades ця впевненість зростає до 90%+. Ми обрали 30 як мінімальну межу, бо довші paper periods часто провокують overfitting - traders занадто довго підкручують стратегію замість того, щоб протестувати її.
Чи можу я пропустити paper trading, якщо впевнений?
Саме коли ви впевнені, пропускати не можна. Боти, які найкраще працюють на Polymarket, створюють люди, які вже помилялися раніше. 30-trade gate існує, щоб відловлювати стратегії, які виглядають правильними, але такими не є. Більшість наших власних стратегій спочатку не пройшли paper - у цьому й цінність.
Чи збігаються paper results із live results?
Зазвичай так для повільних стратегій (politics, weather), ні для швидких (5-min crypto, sports microstructure). Розрив у тому, що "paper trading does not pay slippage" - реальні fills гірші за ціну, яку ви бачили. Ми знижуємо paper returns на 30-50%, перш ніж вірити в них для live, особливо для швидких стратегій.
Як реалізувати paper engine на Python?
Підпишіться на реальний CLOB WebSocket для markets, якими ви торгуєте. Коли ваша strategy вирішує «place an order», логайте це в JSONL file з ціною, за якою це стало б fill-ом (поточний bid для buy, поточний ask для sell). Ведіть positions віртуально. Mark-to-market за live price. Увесь engine - це приблизно 200 рядків Python.
Як довго слід paper trade перед live?
Поки не виконано 30-trade gate або 2-4 тижні, залежно від того, що довше. Якщо ви досягаєте gate занадто швидко, це overfitting; сповільніться й перевірте, чи стійкий ваш win rate до невеликих змін параметрів. Якщо не можете досягти gate за місяці, у стратегії, ймовірно, немає edge, і її слід закрити.