Polymarket Bot Tutorial · 32개 중 10장
Bot builder를 위한 Polymarket order type 설명: Fill-or-Kill (FOK), Fill-and-Kill (FAK), Good-til-Cancelled (GTC), 그리고 limit-vs-market 트레이드오프. production-grade decision rule 포함.
이 장에서 다루는 내용
order-type 혼동은 새로운 bot builder에게 가장 비싼 버그 유형입니다. GTC가 필요한데 FOK를 보내면 진입 기회를 놓치고, FOK가 필요한데 GTC를 보내면 몇 시간 뒤 끔찍한 가격에 체결되는 resting order가 남습니다. 이 장은 그 decision tree와, 수천 건의 order를 통해 검증된 production default를 정리합니다.
- Quick decision tree
- FOK: 반드시 fill되거나 건너뛰어야 할 때
- FAK: partial fill이 허용될 때
- GTC: book에 남겨둘 때
- Limit vs market와 spread tax
- 우리의 production defaults (FOK buys, GTC sells)
- Code: 각 order type을 배치하는 방법
Quick decision tree
모든 order placement는 세 가지 질문으로 결정됩니다.
- 지금 반드시 fill되어야 하며, 지금 못 받으면 아예 안 되는가? → FOK.
- 지금 가능한 만큼만 받고, partial fill을 허용하며, resting order는 원하지 않는가? → FAK.
- 원하는 price에 book에 남겨두고 누군가 오기를 기다릴 것인가? → GTC.
그게 전부입니다. order type과 관련된 대부분의 bot bug는 #1이 필요했는데 #3을 선택해서 생깁니다. ("buy"가 "spread가 너무 넓어서 position 없음"으로 바뀜) 또는 #3이 필요했는데 #1을 선택해서 생깁니다. ("buy"가 몇 시간 뒤 잘못된 순간에 체결되는 resting order가 됨)
FOK: 반드시 fill되거나 건너뛰어야 할 때
Fill-or-Kill은 요청한 price 또는 더 나은 price로 전체 order를 즉시 매칭합니다. 전체 size를 즉시 fill할 수 없으면 order는 reject되고 아무 일도 일어나지 않습니다. resting도 없고, partial도 없습니다.
다음과 같은 경우에 FOK를 사용합니다: news-arbitrage 진입(현재가가 아니라 news price에서만 진입하고 싶을 때); partial이 bookkeeping을 흐리게 만들 수 있는 특정 target의 take-profit exit; 전략이 atomic execution을 가정하는 모든 경우.
트레이드오프: FOK는 다른 order type보다 더 자주 reject됩니다. 특히 illiquid book에서는 더 그렇습니다. 항상 fallback path를 두세요-strategy condition을 다시 평가하고 여전히 유효하면 retry하거나, 아니면 넘어가세요.
FAK: partial fill이 허용될 때
Fill-and-Kill(“immediate or cancel”라고도 함)은 지금 가능한 만큼만 매칭한 뒤, fill되지 않은 나머지를 취소합니다. 전체 size를 받을 수도 있고, partial일 수도 있고, 전혀 못 받을 수도 있습니다.
다음과 같은 경우에 FAK를 사용합니다: 특정 price ceiling이 있는 market-buy(mid보다 N cents 위까지 ask를 올려 받기); inventory를 급히 줄여야 할 때 book을 훑는 sweep-the-book sell; "아무 포지션도 없는 것보다 일부 포지션이 낫다"는 전략.
운영상 FOK보다 더 까다롭습니다. bot이 다음 단계를 결정하기 전에 100%를 받았는지 30%만 받았는지 알아야 하기 때문입니다. fill response에는 filled_size 필드가 포함됩니다-항상 읽으세요.
GTC: book에 남겨둘 때
Good-til-Cancelled는 fill되거나 직접 취소할 때까지 price 그대로 book에 남아 있습니다. timeout은 없습니다(v2 API의 다른 order type에는 expiry가 있는 GTD가 포함됩니다).
다음과 같은 경우에 GTC를 사용합니다: entry 대비 +Nc에서 take-profit sell; entry 대비 -Nc에서 stop-loss sell(주의 사항 있음-아래 참조); 양방향 quote를 내는 market-making; bot이 더 좋은 price를 기다릴 의향이 있는 모든 position.
중요한 규칙: GTC는 ≥ 5 shares가 필요합니다. 5 shares 미만의 order는 CLOB에서 Size (X) lower than the minimum: 5로 reject됩니다. 4-share GTC sell을 올리는 bot은 exit 설정에 조용히 실패하고 position을 resolution까지 끌고 가게 됩니다. GTC를 올리기 전에 항상 inventory가 ≥ 5인지 확인하세요; 더 작으면 FAK 또는 ride-to-resolve로 대체하세요.
Limit vs market와 spread tax
모든 Polymarket order는 기술적으로 limit order입니다-bot이 "market buy"라고 부르는 것도 price ceiling을 지정합니다. 차이는 그 price가 best ask인지(사실상 market order처럼 book을 치며 fill됨) 아니면 그보다 낮은지(책에 남음)입니다.
Spread tax는 crossing의 비용입니다-bid 0.45, ask 0.47, mid 0.46. ask를 사고 bid를 파는 왕복 거래는 share당 2 cents를 지불합니다. +3c/-4c target의 60% win-rate 전략에서는 그 2c spread가 profit과 loss를 가르는 차이입니다.
Maker pattern(예: bid 또는 그 아래에 GTC를 걸고 hit되기를 기다림)은 spread를 지불하는 대신 spread를 가져갑니다. 비용은 fill의 불확실성입니다-아예 hit되지 않을 수도 있습니다. 확신이 높은 거래라면 spread를 지불하세요. passive accumulation이라면 book을 work하세요.
우리의 production defaults (FOK buys, GTC sells)
대부분의 production bot이 수렴하는 패턴은 다음과 같습니다:
- Entries: ask + 0-2 cents에서 FOK. bot이 사기로 결정했다면, 지금 사거나 아니면 건너뛰어야 합니다. entry order를 resting 상태로 두는 일은 거의 가치가 없습니다-buy decision을 유발한 상황은 order가 resting하는 동안보다 더 빨리 변합니다.
- Take-profit exits: target price에서 GTC. entry fill 직후 즉시 제출합니다. 우리는 시장이 우리에게 오기를 기다리며, bid를 따라 내려가지 않습니다. ≥ 5 shares 조건을 충족해야 합니다.
- Stop-loss: case-by-case. 가격 변동이 제한적인 느린 전략에서는 GTC가 잘 맞습니다. 빠르게 움직이는 시장에서는 GTC stop이 price를 통과해 버려도 fill되지 않을 수 있습니다. 그런 경우 option-D 방식으로 resolution까지 유지합니다(기억: trader-gtc-sell.md).
이 패턴은 보수적입니다-fill은 줄고 slippage도 줄어듭니다. 더 공격적인 변형은 FAK entry와 FAK exit를 사용해 partial fill을 허용합니다. 하나를 선택하고 일관되게 유지하세요. trade마다 다르게 섞으면 혼란이 생깁니다.
Code: 각 order type을 배치하는 방법
py-clob-client(v0.34.6)로 Python에서 order placement를 참조합니다.
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 등으로 바꾸면 됩니다. method는 createAndPostOrder입니다. negRisk flag(11장)는 multi-outcome market의 두 번째 argument에 설정해야 합니다-빠뜨리면 잘못된 exchange contract로 라우팅됩니다.












