폴리마켓 봇 튜토리얼 · 32장 중 10장
봇 빌더를 위한 폴리마켓 주문 유형 설명: Fill-or-Kill (FOK), Fill-and-Kill (FAK), Good-til-Cancelled (GTC), 그리고 지정가와 시장가의 트레이드오프. 실전 수준의 의사결정 규칙을 포함합니다.
이 장에서 다루는 내용
주문 유형 혼동은 새로운 봇 빌더가 겪는 가장 값비싼 버그 유형입니다. GTC가 필요한데 FOK를 보내면 진입 기회를 놓치고, FOK가 필요한데 GTC를 보내면 몇 시간 뒤 끔찍한 가격에 체결되는 미체결 주문이 남습니다. 이 장에서는 그 의사결정 트리와, 수천 건의 주문을 통해 검증된 실전 기본값을 정리합니다.
- 빠른 의사결정 트리
- FOK: 반드시 체결되거나 건너뛰어야 할 때
- FAK: 부분 체결이 허용될 때
- GTC: 호가창에 남겨둘 때
- 지정가 대 시장가, 그리고 스프레드 세금
- 저희의 실전 기본값(FOK 매수, GTC 매도)
- 코드: 각 주문 유형을 넣는 방법
빠른 의사결정 트리
모든 주문 실행은 세 가지 질문으로 결정됩니다.
- 지금 반드시 체결되어야 하며, 지금 못 받으면 아예 안 되는가? → FOK.
- 지금 가능한 만큼만 받고, 부분 체결을 허용하며, 미체결 주문은 원하지 않는가? → FAK.
- 원하는 가격에 호가창에 남겨두고 누군가 오기를 기다릴 것인가? → GTC.
그게 전부입니다. 주문 유형과 관련된 대부분의 봇 버그는 #1이 필요했는데 #3을 선택해서 생기거나(매수가 스프레드가 너무 넓어 포지션 없음으로 바뀜), #3이 필요했는데 #1을 선택해서 생깁니다(매수가 몇 시간 뒤 잘못된 순간에 체결되는 미체결 주문이 됨).
FOK: 반드시 체결되거나 건너뛰어야 할 때
Fill-or-Kill은 요청한 가격 또는 그보다 나은 가격으로 전체 주문을 즉시 매칭합니다. 전체 수량을 즉시 체결할 수 없으면 주문은 거부되고 아무 일도 일어나지 않습니다. 호가창에 남지도 않고, 부분 체결도 없습니다.
다음과 같은 경우에 FOK를 사용합니다: 뉴스 차익거래 진입(현재가가 아니라 뉴스 가격에서만 진입하고 싶을 때), 부분 체결이 장부 관리를 흐릴 수 있는 특정 목표가에서의 이익 실현 청산, 전략이 원자적 실행을 가정하는 모든 경우.
트레이드오프: FOK는 다른 주문 유형보다 더 자주 거부됩니다. 특히 유동성이 낮은 호가창에서는 더 그렇습니다. 항상 대체 경로를 마련해 두세요. 전략 조건을 다시 평가해 여전히 유효하면 재시도하고, 그렇지 않으면 넘어가세요.
FAK: 부분 체결이 허용될 때
Fill-and-Kill(“immediate or cancel”이라고도 함)은 지금 가능한 만큼만 매칭한 뒤, 체결되지 않은 나머지를 취소합니다. 전체 수량을 받을 수도 있고, 일부만 받을 수도 있으며, 전혀 못 받을 수도 있습니다.
다음과 같은 경우에 FAK를 사용합니다: 특정 가격 상한이 있는 시장가 매수(중간값보다 N cents 위까지 매도 호가를 끌어올려 받기), 재고를 급히 줄여야 할 때 호가창을 훑어 담는 매도, "아무 포지션도 없는 것보다 일부 포지션이 낫다"는 전략.
운영상 FOK보다 더 까다롭습니다. 봇이 다음 단계를 결정하기 전에 100%를 받았는지 30%만 받았는지 알아야 하기 때문입니다. 체결 응답에는 filled_size 필드가 포함됩니다. 항상 읽으세요.
GTC: 호가창에 남겨둘 때
Good-til-Cancelled는 체결되거나 직접 취소할 때까지 지정한 가격 그대로 호가창에 남아 있습니다. 시간 제한은 없습니다(v2 API의 다른 주문 유형에는 만료 시각이 있는 GTD가 포함됩니다).
다음과 같은 경우에 GTC를 사용합니다: 진입가 대비 +Nc에서의 이익 실현 매도, 진입가 대비 -Nc에서의 손절 매도(주의 사항 있음, 아래 참조), 양방향 호가를 내는 마켓 메이킹, 봇이 더 좋은 가격을 기다릴 의향이 있는 모든 포지션.
중요한 규칙: GTC는 5 지분 이상이 필요합니다. 5 지분 미만의 주문은 CLOB에서 Size (X) lower than the minimum: 5로 거부됩니다. 4 지분짜리 GTC 매도를 올리는 봇은 청산 설정에 조용히 실패하고 포지션을 정산까지 끌고 가게 됩니다. GTC를 올리기 전에 항상 재고가 5 이상인지 확인하고, 더 작으면 FAK 또는 정산까지 보유하는 방식으로 대체하세요.
지정가 대 시장가, 그리고 스프레드 세금
모든 폴리마켓 주문은 기술적으로 지정가 주문입니다. 봇이 "시장가 매수"라고 부르는 것도 가격 상한을 지정합니다. 차이는 그 가격이 최우선 매도 호가인지(사실상 시장가 주문처럼 호가창을 치며 체결됨), 아니면 그보다 낮은지(호가창에 남음)입니다.
스프레드 세금은 호가를 넘어가는 데 드는 비용입니다. 매수 호가 0.45, 매도 호가 0.47, 중간값 0.46이라고 합시다. 매도 호가에 사고 매수 호가에 파는 왕복 거래는 지분당 2 cents를 지불합니다. +3c/-4c 목표의 승률 60% 전략에서는 그 2c 스프레드가 수익과 손실을 가르는 차이입니다.
메이커 패턴(예: 매수 호가 또는 그 아래에 GTC를 걸어 두고 체결되기를 기다림)은 스프레드를 지불하는 대신 스프레드를 가져갑니다. 그 대가는 체결의 불확실성입니다. 아예 체결되지 않을 수도 있습니다. 확신이 높은 거래라면 스프레드를 지불하세요. 소극적으로 물량을 쌓아 가는 경우라면 호가창을 활용해 천천히 채우세요.
저희의 실전 기본값(FOK 매수, GTC 매도)
대부분의 실전 봇이 수렴하는 패턴은 다음과 같습니다:
- 진입: 매도 호가 + 0~2 cents에서 FOK. 봇이 사기로 결정했다면 지금 사거나 아니면 건너뛰어야 합니다. 진입 주문을 호가창에 남겨 두는 일은 거의 가치가 없습니다. 매수 결정을 유발한 상황은 주문이 대기하는 동안보다 더 빨리 변하기 때문입니다.
- 이익 실현 청산: 목표가에서 GTC. 진입 체결 직후 즉시 제출합니다. 저희는 시장이 우리에게 오기를 기다리며, 매수 호가를 따라 내려가지 않습니다. 5 지분 이상 조건을 충족해야 합니다.
- 손절: 사안별 판단. 가격 변동이 제한적인 느린 전략에서는 GTC가 잘 맞습니다. 빠르게 움직이는 시장에서는 GTC 손절이 가격을 통과해 버려도 체결되지 않을 수 있습니다. 그런 경우 option-D 방식으로 정산까지 유지합니다(참고: trader-gtc-sell.md).
이 패턴은 보수적입니다. 체결은 줄지만 슬리피지도 줄어듭니다. 더 공격적인 변형은 FAK 진입과 FAK 청산을 사용해 부분 체결을 허용합니다. 하나를 선택하고 일관되게 유지하세요. 거래마다 다르게 섞으면 혼란이 생깁니다.
코드: 각 주문 유형을 넣는 방법
py-clob-client(v0.34.6)를 사용한 Python 주문 실행 예시입니다.
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType
c = ClobClient(host="https://clob.polymarket.com", chain_id=137,
key=PRIVATE_KEY, signature_type=2, funder=PROXY)
c.set_api_creds(creds)
# FOK buy: fill 10 shares at price 0.45 or skip
args = OrderArgs(token_id=TOKEN, price=0.45, size=10, side="BUY")
resp = c.create_and_post_order(args, OrderType.FOK)
# FAK buy: take as much as you can at 0.45 or below
resp = c.create_and_post_order(args, OrderType.FAK)
# GTC sell: rest a sell at 0.85 for 10 shares
sell_args = OrderArgs(token_id=TOKEN, price=0.85, size=10, side="SELL")
resp = c.create_and_post_order(sell_args, OrderType.GTC)
@polymarket/clob-client-v2를 쓰는 Node에서도 동일합니다. OrderType.FOK를 clob.OrderType.GTC 등으로 바꾸면 됩니다. 메서드는 createAndPostOrder입니다. negRisk 플래그(11장)는 다중 결과 시장에서 두 번째 인자로 설정해야 합니다. 빠뜨리면 잘못된 거래소 컨트랙트로 라우팅됩니다.


