← Back

#1 — Фикс realized PnL в демоне copy-trader-mu (СПЕКА ДЛЯ РЕВЬЮ, НЕ ЗАДЕПЛОЕНО)

⚠️ MONEY-PATH. Файл /root/poly-exec/copy-loop-mu.mjs (off-box, Node, вне репо). Менять ТОЛЬКО осознанно, с тестом (--selftest / OBSERVE-режим) и явным «да» Rick. Этот документ — план, не правка.

Корень (строки 287-290)

if (patch.close) {
  p.status = 'closed'; p.closedReason = patch.close; p.closedAt = now;
  // worthless-aged = resolved $0 loser → -cost. onchain-absent = sold/redeemed → last mark.
  p.realizedPnl = patch.close === 'resolved-worthless-aged' ? -(Number(p.cost)||0) : (Number(p.markPnl)||0);
}

Проблема различения

onchain-absent неоднозначен: токен = 0 на чейне И при продаже (mirror-sell, есть proceeds в markPnl), И при редиме победителя ($1/share), И у $0-лузера. По одному балансу не отличить.

Предлагаемый фикс

При resolved-onchain-absent определить исход рынка и считать payout, а не markPnl:

  1. Узнать резолюцию рынка для p.marketId/p.outcome:
    • Вариант A (on-chain, авторитетно): CTF payoutNumerators(conditionId) → выиграл ли индекс исхода позиции.
    • Вариант B (проще): GET к нашему сервисному API → screener_markets.winning_outcome (демон уже ходит в наш API). Менее «честно» (наша БД), но дёшево.
  2. Если рынок резолвнут:
    • won = (p.outcome === winningOutcome)
    • realized = won ? (Number(p.size) - Number(p.cost)) : -(Number(p.cost)) // size шар × $1 payout − затраты
  3. Если рынок НЕ резолвнут (токен исчез из-за продажи, не редима) → оставить markPnl (proceeds продажи).

Безопасный rollout

  1. Написать патч + прогнать node copy-loop-mu.mjs --selftest (есть в файле, dump resolved-контекста) — сверить realized на исторических позициях.
  2. Дев-прогон в OBSERVE/без живых ордеров, сверить банки с ожиданием.
  3. Только потом pm2 restart copy-trader-mu в тихое окно, мониторить логи банков.
  4. Бэкап copy-loop-mu.mjs перед правкой.

Важно

📜 Git History

628ccb0docs: #1 daemon realized-PnL fix SPEC (review artifact, NOT deployed)12 days ago
Show last diff
Loading...