공개 WebSocket 피드에 연결하고 Polymarket에서 가격이 잘못 책정된 토큰을 발견했습니다
Source: Dev.to
위에 제공된 링크 외에 번역할 텍스트가 포함되어 있지 않습니다. 번역을 원하는 본문을 알려주시면 한국어로 번역해 드리겠습니다.
개요
두 개의 WebSocket 피드를 연결했습니다: 하나는 Polymarket의 15분 암호화폐 시장을 정산하는 Chainlink 오라클에, 또 다른 하나는 Polymarket 주문서에 연결했습니다. 두 피드를 나란히 관찰한 결과 일관된 지연이 발견되었습니다. 오라클은 1초 미만에 업데이트되는 반면, 주문서는 동일한 움직임을 반영하는 데 약 55 초가 걸립니다. 거의 1분에 가까운 시간 동안 토큰은 오래된 데이터에 머물게 됩니다. 정산 소스는 공개되어 있어 누구나 연결할 수 있으며, 정산 대상 시장보다 거의 1분 앞서 지속적으로 작동합니다. 이는 버그가 아니라 시장이 작동하는 방식이지만, 이렇게 깔끔하게 측정할 수 있는 경우는 드뭅니다.
전략
핵심 논리는 간단합니다:
-
매 오라클 가격 틱마다 세 가지 조건을 확인합니다:
- 가격이 시장 개시 시점 대비 > 0.07 % 이동했는지
- 남은 시간이 > 5 분인지
- 토큰 가격이 < $0.62인지
-
세 조건 모두 충족되면, 저가 측을 매수하고 정산을 기다린 뒤 $1을 회수합니다 (또는 스테이크를 잃을 수 있습니다).
흥미로운 점은 전략 자체가 아니라 이를 안정적으로 실행하도록 만든 것이었습니다.
Source: …
Implementation
Architecture
단일 프로세스가 열려 있는 WebSocket을 통해 초단위 업데이트를 수신하고, 16개의 겹치는 시장을 추적하며, 매 틱마다 신호를 평가하고, 가격 피드를 차단하지 않고 주문을 실행하고, Telegram 알림을 전송하며, 충돌 복구를 위해 상태를 영구 저장하고, 자체 건강 상태를 모니터링합니다—모두 동시에 수행됩니다.
asyncio가 명백한 선택이었습니다: 거의 CPU 작업이 없고, 모든 것이 I/O‑바운드이기 때문입니다. 하나의 이벤트 루프에서 7개의 동시 작업이 실행됩니다:
tasks = [
oracle.run(shutdown),
market_lifecycle_loop(...),
signal_evaluation_loop(...),
telegram.run(shutdown),
state_persist_loop(...),
redeem_loop(...),
sanity_check_loop(...),
]
await asyncio.gather(*tasks)
스레드도, 락도, 멀티프로세싱도 없습니다.
Handling Zombie WebSocket Connections
가장 까다로운 버그는 좀비 WebSocket이었습니다: 연결은 살아 있었고 ping/pong은 정상 작동했으며 예외도 발생하지 않았지만, 가격 데이터가 조용히 흐르지 않게 된 것이었습니다. 심장박동 프레임은 계속 도착했기 때문에 단순히 recv 타임아웃을 설정해도 도움이 되지 않았습니다.
해결책: 단조 시계(monotonic clock)를 사용해 마지막 실제 가격 업데이트 시점을 추적하고, 매 타임아웃마다 이를 확인합니다. 설정한 임계값 내에 실제 데이터가 도착하지 않으면 연결을 종료하고 강제로 재연결합니다.
Verifying External Credentials
또 다른 미묘한 문제: 봇은 시작되었고 로그는 완벽해 보였지만, 20분이 지나면 Telegram 채팅 ID가 잘못되어 모든 알림이 조용히 실패했습니다.
해결책: 메인 루프에 들어가기 전에 모든 외부 자격 증명을 검증합니다:
# Verify Telegram
telegram.get_me()
telegram.send_message(test_chat_id, "test")
# Verify Polymarket API keys
polymarket.verify_keys()
무언가 잘못되면 봇은 첫 2초 이내에 명확한 오류와 함께 종료됩니다. 예시:
ERROR: Telegram chat_id=123456 is invalid.
Tip: send any message to @your_bot first, then use getUpdates to find your chat_id.
백테스트 결과
- 평가된 시장: 8,876개의 해결된 시장
- 가격 포인트: 146,000
- 플래그된 거래: 5,017
- 승률: BTC, ETH, XRP, SOL 전반에 걸쳐 61.4 %
나는 시스템을 깨기 위해 날짜 분할, 파라미터 그리드 서치, 수수료 두 배, 일일 분해 등 일곱 가지 다른 방법을 시도했다. 그 중 어느 것도 시스템을 파괴하지 못했지만, 실제 환경은 더 어려울 것이다: 주문서가 얇아지고, 슬리피지가 커지며, 시간이 지남에 따라 지연이 감소한다. 이것은 은퇴 계획이 아니다.
오픈 소스
전체 프로젝트는 오픈 소스이며, API 키 없이 실시간 데이터와 페이퍼 트레이드에 연결되는 데모 모드를 포함합니다.
https://github.com/JonathanPetersonn/oracle-lag-sniper
협업 요청
비슷한 실시간 asyncio 시스템을 구축한 경험이 있다면, 구조를 어떻게 설계했는지 알려주세요. 이 “많은 동시 장기 실행 작업이 상태를 공유하는” 패턴은 흔한 것 같지만, 이를 구현하면서 좋은 오픈‑소스 참고 자료를 찾지 못했습니다.