🍈

golden-honeydew — Night Watch

한산 시간대 복원 매수 — 미 동부 새벽·주말에 뉴스 없이 발생한 가격 이탈(dislocation)을 복원 방향으로 매수한다.

유형 역행 (복원)상태 신규 · 검증 대기핵심 편향 주의(attention) 희소성

핵심 수식

quiet  = UTC 06–13시 ([start, end)) or 주말(토/일 UTC)   # 아니면 사이클 전체 skip
median = median(최근 24h YES 스냅샷)
dev    = p_yes_now − median
ENTER iff quiet
      AND |dev| ≥ 0.05                                    # 유의미한 이탈
      AND avg(vol24h, 3h) < 1.5 × avg(vol24h, 24h)        # 거래량 급증 = 진짜 뉴스 → 배제
      AND 매수 토큰 가격 ∈ [0.30, 0.90]
방향: dev < 0 → YES 매수(반등 기대) · dev > 0 → NO 매수(페이드)

왜 이 전략인가

Polymarket 참여자 대다수는 미국 시간대의 인간이다. UTC 06:00-13:00(미 동부 01-08시)와 주말에는 orderbook이 얇아지고, 정보가 아닌 유동성 요인만으로도 가격이 밀린다. 주의(attention)가 없는 시간의 가격 변화는 "정보"가 아니라 "노이즈"일 확률이 높고, 노이즈는 평균으로 회귀한다. 반대로 거래량이 급증하며 움직이는 가격은 진짜 뉴스일 가능성이 크므로 거래량 급증 시장은 배제한다.

레포 리서치(golden-cherry/docs/polymarket-strategy-momentum.md 계열)의 "10%+ 급변은 mean-revert" — 단기 과잉 이동의 회귀 성향은 이 레포에서 반복적으로 확인된 관찰이다. Night Watch는 그 회귀를 "정보가 없는 시간대"로 한정해 신호 대 잡음비를 높인다. 구조적 우위도 있다: 봇은 Jenkins로 24/7, 3-5분 간격으로 돈다. 사람은 이 시간대에 깨어있을 수 없다 — 이 전략은 그 인프라 우위를 정면으로 수익화한다.

기존 봇(STRATEGY_ANALYSIS.md)에서 배운 교정도 반영했다: banana의 스냅샷 "개수" 기반 윈도우 → timestamp 기반 윈도우 + 커버리지 검증(is_window_valid), 과도하게 관대한 cold-start 폴백 → invalid 윈도우면 백필 시도 후에도 부족하면 진입 안 함, cherry/banana의 condition_id당 영구 1회 거래 → 재진입 쿨다운(기본 24h), 해결된 시장의 영구 HOLDING 좀비 → EXPIRED 마감 + 수동 redeem 경고, take_profit 목표가 1.0 초과 → 0.99 캡, LOG_LEVEL env 지원, Gamma 전량 sweep 2회/사이클 → 1회(Phase 0/2 공유), 그리고 트레일링 스탑이 손절을 사실상 대체하는 whipsaw → 빠른 회전 전략이므로 trailing 자체를 제거.

진입 규칙

모든 조건을 충족해야 매수한다.

#조건값 (기본)이유
1한산 시간대UTC quiet.hours_utc(기본 06-13시, [start, end)) 또는 주말(토/일 UTC, quiet.weekends=true일 때). 사이클당 1회 판정 — 아니면 스캔 전체 skip주의 희소 구간에서만 노이즈 가설이 성립
2유동성 / 시간liquidity ≥ $15,000 · 해결까지 ≥ 24h (min_volume_24h는 기본 0=비활성)체결 가능성 + 복원 시간 확보
3편차24h 스냅샷(YES 가격)의 median(statistics.median) 대비 |현재 YES 가격 − median| ≥ 0.05유의미한 이탈만 선별
4뉴스 배제최근 3h 스냅샷의 volume24hr 평균 < 24h 윈도우 평균 × 1.5급증 = 진짜 뉴스 → skip
5복원 방향dev < 0 → YES 매수(반등 기대), dev > 0 → NO 매수(페이드, 매수가는 실제 NO 가격 outcomePrices[1] 기준)복원 방향으로만 베팅
6가격 밴드매수할 토큰 가격 ∈ [0.30, 0.90] (양끝 포함)극단 가격의 왜곡 배제
7윈도우 유효성포인트 ≥ 5개 AND 커버 시간 ≥ lookback의 50%. 부족하면 prices-history 백필 후 재평가, 그래도 부족하면 진입 안 함데이터 없이는 베팅하지 않는다
8재진입 쿨다운HOLDING 존재, 24h 내 COMPLETED 청산, 24h 내 skip 기록 중 하나라도 있으면 skip과잉 재진입 방지

매수 실행 직전 CLOB midpoint로 재검증한다: 가격이 밴드 상한(0.90) 초과면 rapid_jump로 skip 기록(쿨다운 동안만 차단 — 기존 봇의 영구 밴 아님), 하한(0.30) 미만이면 기록 없이 skip.

청산 규칙

우선순위 순으로 매 사이클 검사한다.

순위조건파라미터exit_reason
1P&L ≤ -6%stop_loss_percent=-0.06stop_loss
2현재가 ≥ min(매수가 × 1.06, 0.99)take_profit_percent=0.06take_profit
3보유 ≥ 24h (복원 실패 → 회전)max_holding_hours=24max_holding
4해결까지 < 12hexit_hours=12time_exit
-midpoint 조회 실패 + endDate 24h 경과-resolved_unredeemed (status=EXPIRED, 수동 redeem 필요)

trailing stop 없음 — 목표 수익폭(+6%)이 작은 빠른 회전 전략이라, trailing이 손절을 대체해버리는 cherry/banana의 whipsaw 문제를 원천 차단한다.

파라미터 (환경변수)

우선순위: 환경변수 > config.yaml > 코드 기본값.

envyaml 키기본값의미
POLYBOT_QUIET_HOURS_UTCtrading.quiet.hours_utc"6-13"진입 허용 UTC 시간대. 자정 넘는 "22-4" 지원
POLYBOT_QUIET_WEEKENDStrading.quiet.weekendstrue주말(토/일 UTC) 전체 진입 허용
POLYBOT_MEDIAN_LOOKBACK_HOURStrading.signal.median_lookback_hours24median 계산 윈도우 (시간)
POLYBOT_DEV_MINtrading.signal.dev_min0.05최소 편차 |현재가 − median|
POLYBOT_VOL_SPIKE_BLOCKtrading.signal.vol_spike_block1.5거래량 급증 차단 배수
POLYBOT_ENTRY_PROB_MINtrading.signal.entry_prob_min0.30매수 토큰 가격 하한
POLYBOT_ENTRY_PROB_MAXtrading.signal.entry_prob_max0.90매수 토큰 가격 상한
POLYBOT_ENTRY_HOURS_MINtrading.time_based.entry_hours_min24해결까지 최소 잔여 시간
POLYBOT_MAX_HOLDING_HOURStrading.time_based.max_holding_hours24최대 보유 시간
POLYBOT_EXIT_HOURStrading.time_based.exit_hours12해결 N시간 전 청산
POLYBOT_TAKE_PROFITtrading.take_profit_percent0.06익절 (+6%, 목표가 0.99 캡)
POLYBOT_STOP_LOSStrading.stop_loss_percent-0.06손절 (-6%)
POLYBOT_BUY_AMOUNTtrading.buy_amount_usdc5.01회 매수 USDC
POLYBOT_MIN_LIQUIDITYtrading.min_liquidity15000최소 유동성 $
POLYBOT_MIN_VOLUME_24Htrading.min_volume_24h0최소 24h 거래량 $ (0=비활성)
POLYBOT_MAX_POSITIONStrading.max_positions-1최대 동시 포지션 (-1=무제한)
POLYBOT_REENTRY_COOLDOWN_HOURStrading.reentry_cooldown_hours24재진입 쿨다운
POLYBOT_HISTORY_BACKFILLtrading.history_backfilltrueprices-history 백필
POLYBOT_EXCLUDED_CATEGORIEStrading.excluded_categories""제외 카테고리 (comma 구분, 기본 비활성)
LOG_LEVEL-INFO로그 레벨 (--verbose가 최우선)

이 전략이 실패하는 경우

A/B 검증 계획

실행 (Jenkins)

#!/bin/bash
export POLYBOT_BUY_AMOUNT=20
export POLYMARKET_PRIVATE_KEY=<Jenkins credential>
export POLYMARKET_FUNDER_ADDRESS=<Jenkins credential>
export LOG_LEVEL=INFO
# 전략 주요 파라미터 (필요 시 조정)
export POLYBOT_QUIET_HOURS_UTC="6-13"
export POLYBOT_DEV_MIN=0.05
export POLYBOT_MAX_HOLDING_HOURS=24

cd ./golden-honeydew
uv sync
uv run python ./main.py run

3-5분 간격 cron 트리거를 권장한다. 한산 시간대(UTC 06-13시/주말)가 아니면 봇이 스스로 진입 스캔을 skip하므로 24시간 내내 돌려도 된다 (스냅샷 축적을 위해 오히려 계속 돌려야 한다).