๐Ÿ’

golden-cherry โ€” Resolution Momentum

ํ•ด๊ฒฐ๊นŒ์ง€ 24~720h ๋‚จ์€ 75~92% favorite์„ ๋งค์ˆ˜ํ•ด ํ•ด๊ฒฐ ์ง์ „ ์ˆ˜๋ ด(0.95+)์„ ์บก์ฒ˜ โ€” ์†์ ˆยท์ต์ ˆยทํŠธ๋ ˆ์ผ๋งยท์‹œ๊ฐ„ ์ฒญ์‚ฐ์˜ 4์ค‘ ๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ.

์œ ํ˜• ํ•ด๊ฒฐ ์ˆ˜๋ ด์ƒํƒœ ์šด์˜ ์ค‘ (์ตœ๊ณ  ์ˆ˜์ต)ํ•ต์‹ฌ ํŽธํ–ฅ favorite-longshot bias

ํ•ต์‹ฌ ์ˆ˜์‹

BUY : 0.75 โ‰ค p โ‰ค 0.92 (์–‘๋ ํฌํ•จ)  AND  24h โ‰ค (endDate - now) โ‰ค 720h
      AND liquidity โ‰ฅ 10,000  AND  condition_id๋‹น ํ‰์ƒ 1ํšŒ

SELL (์šฐ์„ ์ˆœ์œ„ ์ˆœ, ๋งค ์‚ฌ์ดํด midpoint ๊ฒ€์‚ฌ):
  โ‘  P&L โ‰ค -8%  (stop_loss)        โ‘ก P&L โ‰ฅ +10%  (take_profit)
  โ‘ข ํ˜„์žฌ๊ฐ€ < ์ตœ๊ณ ๊ฐ€ ร— 0.95 (trailing_stop)   โ‘ฃ ํ•ด๊ฒฐ 12h ์ „ (time_exit)

์ „๋žต ๊ฐœ์š”

Golden Cherry๋Š” "ํ•ด๊ฒฐ(resolution)์ด ๊ฐ€๊นŒ์›Œ์ง„ ๊ณ ํ™•๋ฅ  favorite์€ 1.0์œผ๋กœ ์ˆ˜๋ ดํ•œ๋‹ค"๋Š” ๊ฐ€์ •์— ๋ฒ ํŒ…ํ•˜๋Š” ๋ด‡์ด๋‹ค. Gamma API๋กœ ์œ ๋™์„ฑ ์žˆ๋Š” ํ™œ์„ฑ ์‹œ์žฅ์„ ์ „์ˆ˜ ์Šค์บ”ํ•ด์„œ, ํ™•๋ฅ ์ด 75~92% ๊ตฌ๊ฐ„(config ๊ธฐ์ค€)์ด๊ณ  ํ•ด๊ฒฐ๊นŒ์ง€ 24h~720h(1~30์ผ) ๋‚จ์€ ์‹œ์žฅ์˜ favorite ํ† ํฐ์„ ์‹œ์žฅ๋‹น 1ํšŒ, ๊ณ ์ • ๊ธˆ์•ก(USDC)์œผ๋กœ ๋งค์ˆ˜ํ•œ๋‹ค. ์ดํ›„ Jenkins๊ฐ€ 3~5๋ถ„๋งˆ๋‹ค ๋ด‡์„ ์žฌ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๋ณด์œ  ํฌ์ง€์…˜์˜ midpoint๋ฅผ ์กฐํšŒํ•ด ์†์ ˆ(-8%) โ†’ ์ต์ ˆ(+10%) โ†’ ํŠธ๋ ˆ์ผ๋ง ์Šคํƒ‘(์ตœ๊ณ ์  ๋Œ€๋น„ -5%) โ†’ ์‹œ๊ฐ„ ์ฒญ์‚ฐ(ํ•ด๊ฒฐ 12h ์ „) ์ˆœ์œผ๋กœ ์ฒญ์‚ฐ ์กฐ๊ฑด์„ ๊ฒ€์‚ฌํ•œ๋‹ค. ํ•ต์‹ฌ ์ˆ˜์ต ์›์ฒœ์€ "๋งค์ˆ˜๊ฐ€ 0.75~0.92 โ†’ ํ•ด๊ฒฐ ์ง์ „ 0.95~0.99 ๋งค๋„"์˜ ์ˆ˜๋ ด ๊ตฌ๊ฐ„ ์บก์ฒ˜์ด๋ฉฐ, ํ•œ ๋ฒˆ ๊ฑฐ๋ž˜(๋˜๋Š” skip)ํ•œ ์‹œ์žฅ์€ ์˜๊ตฌํžˆ ์žฌ์ง„์ž…ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์›๋ž˜ PRD๋Š” "80% ๋งค์ˆ˜ โ†’ 90% ๋งค๋„" ๋‹จ์ˆœ ์ „๋žต์ด์—ˆ๊ณ , ์ดํ›„ ๋ชจ๋ฉ˜ํ…€(๊ณจ๋“ ํฌ๋กœ์Šค) ์ „๋žต์„ ๊ฑฐ์ณ ํ˜„์žฌ์˜ Resolution Momentum(์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ์ง„์ž… + 4์ค‘ ์ฒญ์‚ฐ)์œผ๋กœ ์ •์ฐฉํ–ˆ๋‹ค.

๋งค์ˆ˜ยท๋งค๋„ ์กฐ๊ฑด

๋งค์ˆ˜ โ€” ์Šค์บ” ์กฐ๊ฑด (์•„๋ž˜๋ฅผ ๋ชจ๋‘ ํ†ต๊ณผํ•ด์•ผ ํ›„๋ณด):

#์กฐ๊ฑด๊ตฌํ˜„๋น„๊ณ 
1ํ™œ์„ฑ ์‹œ์žฅGamma GET /markets?active=true&closed=false ํŽ˜์ด์ง€๋„ค์ด์…˜(100๊ฐœ์”ฉ, offsetโ‰ฅ5000 ์•ˆ์ „ ์ค‘๋‹จ)
2์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐis_sports_market() โ€” excluded_categories๊ฐ€ ๋นˆ ๋ฐฐ์—ด์ด๋ฉด ํ•„ํ„ฐ ์™„์ „ ๋น„ํ™œ์„ฑํ™”ํ˜„์žฌ config๋Š” [] โ†’ ์Šคํฌ์ธ  ํฌํ•จ ์ „์ฒด ์Šค์บ”
3์œ ๋™์„ฑliquidity โ‰ฅ min_liquidity (ํด๋ผ์ด์–ธํŠธ ์ธก)config 10,000 / ์ฝ”๋“œ ๊ธฐ๋ณธ 50,000
4side ์„ ํƒ๊ธฐ๋ณธ: Yes/No ์ค‘ ํ™•๋ฅ  ๋†’์€ ์ชฝ. --yes-only: ๋ฌด์กฐ๊ฑด index 0(Yes) ํ† ํฐ๋งŒ ํ‰๊ฐ€์•„๋ž˜ yes-only ์„ค๋ช… ์ฐธ๊ณ 
5ํ™•๋ฅ  ๊ตฌ๊ฐ„buy_threshold โ‰ค p โ‰ค sell_threshold (์–‘๋ ํฌํ•จ)0.75 โ‰ค p โ‰ค 0.92
6์‹œ๊ฐ„ ๊ตฌ๊ฐ„entry_hours_min โ‰ค (endDate - now) โ‰ค entry_hours_max (time_based ํ™œ์„ฑ ์‹œ). endDate ์—†์Œ/๊ณผ๊ฑฐ๋ฉด ์ œ์™ธ24h ~ 720h

๋งค์ˆ˜ โ€” ์‹คํ–‰ ์žฌ๊ฒ€์ฆ (ํ›„๋ณด๋ณ„):

#์กฐ๊ฑด๋™์ž‘
1is_already_traded(condition_id)trades ๋˜๋Š” skipped_markets์— ์žˆ์œผ๋ฉด skip (์˜๊ตฌ)
2max_positions (>0์ผ ๋•Œ๋งŒ)HOLDING ์ˆ˜ ๋„๋‹ฌ ์‹œ skip. ๊ธฐ๋ณธ -1(๋ฌด์ œํ•œ)
3CLOB get_midpoint๋กœ ํ˜„์žฌ๊ฐ€ ์žฌ์กฐํšŒ์กฐํšŒ ์‹คํŒจ ์‹œ skip
4ํ˜„์žฌ๊ฐ€ > sell_thresholdrapid_jump๋กœ skipped_markets์— ์˜๊ตฌ ๋“ฑ๋ก ํ›„ skip
5ํ˜„์žฌ๊ฐ€ < buy_thresholdskip (์˜๊ตฌ ์•„๋‹˜, ๋‹ค์Œ ์‚ฌ์ดํด ์žฌ๋„์ „ ๊ฐ€๋Šฅ)
6buy_shares = buy_amount_usdc รท ํ˜„์žฌ๊ฐ€ < 5.0skip โ€” Polymarket ์ตœ์†Œ ์ฃผ๋ฌธ 5์ฃผ
7limit order (midpoint 0.01 tick ๋ฐ˜์˜ฌ๋ฆผ, [0.01, 0.99] clamp, BUY, GTC)์„ฑ๊ณต ์‹œ ์ฆ‰์‹œ HOLDING ๊ธฐ๋ก, max_price = buy_price๋กœ ์ดˆ๊ธฐํ™” (์ฒด๊ฒฐ ํ™•์ธ ์—†์Œ)

์‚ฌ์ด์ง•: buy_amount_usdc๋Š” USDC ๋‹ฌ๋Ÿฌ ๋‹จ์œ„. ์ฃผ์ˆ˜ = ๊ธˆ์•ก รท ๊ฐ€๊ฒฉ โ€” ์˜ˆ: $5 @ 0.80 โ†’ 6.25์ฃผ. ๊ฐ€๊ฒฉ 0.92์—์„œ๋Š” 5์ฃผ ์ตœ์†Œ์š”๊ฑด ๋•Œ๋ฌธ์— ์ตœ์†Œ $4.6 ํ•„์š”.

๋งค๋„ (๋งค ์‚ฌ์ดํด ๋ณด์œ  ํฌ์ง€์…˜ ์ „์ˆ˜ ๊ฒ€์‚ฌ. midpoint ์กฐํšŒ โ†’ max_price ๊ฐฑ์‹  โ†’ P&L = (ํ˜„์žฌ๊ฐ€-๋งค์ˆ˜๊ฐ€)/๋งค์ˆ˜๊ฐ€):

์ˆœ์œ„์กฐ๊ฑดํŒŒ๋ผ๋ฏธํ„ฐconfig ๊ฐ’exit_reason
1P&L โ‰ค ์†์ ˆ์„ stop_loss_percent-0.08stop_loss
2P&L โ‰ฅ ์ต์ ˆ์„ take_profit_percent+0.10 (์ฝ”๋“œ ๊ธฐ๋ณธ 0.15)take_profit
3ํ˜„์žฌ๊ฐ€ < ์ตœ๊ณ ๊ฐ€ร—(1-ํŠธ๋ ˆ์ผ๋ง)trailing_stop.percent0.05trailing_stop
4ํ•ด๊ฒฐ๊นŒ์ง€ < ์ฒญ์‚ฐ์‹œ๊ฐ„time_based.exit_hours12htime_exit

๋งค๋„ = ํ˜„์žฌ midpoint์— ์ง€์ •๊ฐ€ GTC SELL(๋ณด์œ  ์ฃผ์ˆ˜ ์ „๋Ÿ‰). ์„ฑ๊ณต ํŒ์ • ์ฆ‰์‹œ COMPLETED + realized_pnl = (๋งค๋„๊ฐ€-๋งค์ˆ˜๊ฐ€)ร—์ฃผ์ˆ˜ ๊ธฐ๋ก, ์›”๋ณ„ CSV(data/{job}/trades_YYYY-MM.csv) append.

์ค‘์š”ํ•œ ์ƒํ˜ธ์ž‘์šฉ: max_price๊ฐ€ ๋งค์ˆ˜๊ฐ€๋กœ ์ดˆ๊ธฐํ™”๋˜๋ฏ€๋กœ, ๊ฐ€๊ฒฉ์ด ์˜ค๋ฅด์ง€ ๋ชปํ•˜๋ฉด ํŠธ๋ ˆ์ผ๋ง -5%๊ฐ€ ์†์ ˆ -8%๋ณด๋‹ค ๋จผ์ € ๋ฐœ๋™ํ•œ๋‹ค. ์ฆ‰ ์‹คํšจ ์†์ ˆ์„ ์€ -5%์ด๊ณ , -8% ์†์ ˆ์€ ํ•œ ์‚ฌ์ดํด(3~5๋ถ„) ์‚ฌ์ด 3%p ์ด์ƒ ๊ฐญ ํ•˜๋ฝํ•  ๋•Œ๋งŒ ์ž‘๋™ํ•˜๋Š” ๋ฐฑ์—…์ด๋‹ค. ๋˜ TP +10%๋Š” ๋งค์ˆ˜๊ฐ€ โ‰ค 0.909์ผ ๋•Œ๋งŒ ๋„๋‹ฌ ๊ฐ€๋Šฅ(๊ฐ€๊ฒฉ ์ƒํ•œ 1.0) โ€” 0.91~0.92 ์ง„์ž… ๊ฑด์€ ์ต์ ˆ ๋ถˆ๊ฐ€, ํŠธ๋ ˆ์ผ๋ง/์‹œ๊ฐ„ ์ฒญ์‚ฐ์œผ๋กœ๋งŒ ๋‚˜๊ฐ„๋‹ค. ์‹ค์ œ ์ˆ˜์ต์˜ ๋ณธ๋ฅ˜๋Š” "์ˆ˜๋ ด ํ›„ ํ•ด๊ฒฐ 12h ์ „ time_exit์œผ๋กœ 0.95+ ๋งค๋„"๋‹ค.

--yes-only์™€ side ์„ ํƒ: ๊ธฐ๋ณธ ๋ชจ๋“œ๋Š” Yes/No ์ค‘ ๋†’์€ ์ชฝ์„ favorite์œผ๋กœ ์„ ํƒํ•ด NO ํ† ํฐ๋„ ๋งค์ˆ˜ํ•œ๋‹ค(longshot ์‹œ์žฅ์˜ No @ 0.9 ๋“ฑ, ๋กœ๊ทธ์—์„œ ๋‹ค์ˆ˜ ํ™•์ธ). --yes-only(Jenkins ์šด์˜ ๋ชจ๋“œ)๋Š” ํ•ญ์ƒ index 0 ํ† ํฐ๋งŒ ๋ฐ˜ํ™˜ โ†’ NO ํ† ํฐ์€ ์ ˆ๋Œ€ ๋งค์ˆ˜ ๋ถˆ๊ฐ€, Yes ํ™•๋ฅ  75% ๋ฏธ๋งŒ ์‹œ์žฅ(= No๊ฐ€ favorite)์€ ํ™•๋ฅ  ํ•„ํ„ฐ์—์„œ ํƒˆ๋ฝ. negRisk ๋‹คํ›„๋ณด ์ด๋ฒคํŠธ์—์„œ๋Š” "1์œ„ ํ›„๋ณด๋งŒ ์‚ฐ๋‹ค"๋Š” ์˜๋ฏธ๊ฐ€ ๋œ๋‹ค. ์ฃผ์˜: CLI --yes-only๋Š” ์ผœ๊ธฐ๋งŒ ๊ฐ€๋Šฅ(๋„๋ ค๋ฉด ํ”Œ๋ž˜๊ทธ ์ƒ๋žต + env/yaml false), --simulate๋„ ๋™์ผ ๊ตฌ์กฐ.

ํŒŒ๋ผ๋ฏธํ„ฐ ์ดํ‘œ (์šฐ์„ ์ˆœ์œ„: env > config.yaml > ์ฝ”๋“œ ๊ธฐ๋ณธ๊ฐ’)

ํŒŒ๋ผ๋ฏธํ„ฐenvyaml ํ‚ค์ฝ”๋“œ ๊ธฐ๋ณธํ˜„์žฌ yaml์˜๋ฏธ
๋งค์ˆ˜ ํ•˜ํ•œPOLYBOT_BUY_THRESHOLDtrading.buy_threshold0.750.75์ด ํ™•๋ฅ  ์ด์ƒ๋งŒ ๋งค์ˆ˜
๋งค์ˆ˜ ์ƒํ•œPOLYBOT_SELL_THRESHOLDtrading.sell_threshold0.920.92์ด ํ™•๋ฅ  ์ดˆ๊ณผ ์‹œ rapid_jump ์˜๊ตฌ skip
๋งค์ˆ˜ ๊ธˆ์•กPOLYBOT_BUY_AMOUNTtrading.buy_amount_usdc5.05.0๊ฑด๋‹น USDC (๋‹ฌ๋Ÿฌ ๋‹จ์œ„)
์ตœ์†Œ ์œ ๋™์„ฑPOLYBOT_MIN_LIQUIDITYtrading.min_liquidity5000010000$ ๊ธฐ์ค€
์ตœ๋Œ€ ํฌ์ง€์…˜POLYBOT_MAX_POSITIONStrading.max_positions-1-1-1=๋ฌด์ œํ•œ
์ต์ ˆPOLYBOT_TAKE_PROFITtrading.take_profit_percent0.150.10์ง„์ž…๊ฐ€ ๋Œ€๋น„
์†์ ˆPOLYBOT_STOP_LOSStrading.stop_loss_percent-0.08-0.08์ง„์ž…๊ฐ€ ๋Œ€๋น„
ํŠธ๋ ˆ์ผ๋ง on/offPOLYBOT_TRAILING_STOP_ENABLEDtrading.trailing_stop.enabledtruetrue
ํŠธ๋ ˆ์ผ๋ง %POLYBOT_TRAILING_STOP_PERCENTtrading.trailing_stop.percent0.050.05์ตœ๊ณ ์  ๋Œ€๋น„
์‹œ๊ฐ„ํ•„ํ„ฐ on/offPOLYBOT_TIME_BASED_ENABLEDtrading.time_based.enabledtruetruefalse ์‹œ ๋งค์ˆ˜ ๋กœ๊ทธ f-string crash ๋ฒ„๊ทธ ์žˆ์Œ (์•ฝ์  9)
์ง„์ž… ์ตœ๋Œ€ ์ž”์—ฌPOLYBOT_ENTRY_HOURS_MAXtrading.time_based.entry_hours_max24720์‹œ๊ฐ„
์ง„์ž… ์ตœ์†Œ ์ž”์—ฌPOLYBOT_ENTRY_HOURS_MINtrading.time_based.entry_hours_min424์‹œ๊ฐ„
์ฒญ์‚ฐ ์ž”์—ฌPOLYBOT_EXIT_HOURStrading.time_based.exit_hours412์‹œ๊ฐ„
YES-OnlyPOLYBOT_YES_ONLY (CLI --yes-only๊ฐ€ ์ตœ์šฐ์„ )trading.yes_only_modefalse(์—†์Œ)
์ œ์™ธ ์นดํ…Œ๊ณ ๋ฆฌ(env ์—†์Œ)trading.excluded_categories์Šคํฌ์ธ  10์ข…[] (๋น„ํ™œ์„ฑ)
์‹œ๋ฎฌ๋ ˆ์ด์…˜(CLI --simulate)simulation_modefalsefalse

๋กœ๊ทธ(2026-05-20) ๊ธฐ์ค€ ์‹ค์ œ ์šด์˜ ์ธ์Šคํ„ด์Šค๋Š” env override๋กœ 85%~95% / ์œ ๋™์„ฑ $20k / buy $2,000 ์กฐํ•ฉ๋„ ์‚ฌ์šฉ๋œ ์ ์ด ์žˆ๋‹ค. yaml์€ baseline์ผ ๋ฟ, Jenkins env๊ฐ€ ์‹ค์ œ ์šด์˜๊ฐ’์ด๋‹ค. ํ•„์ˆ˜ credential์€ POLYMARKET_PRIVATE_KEYยทPOLYMARKET_FUNDER_ADDRESS(์—†์œผ๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒ, private key์˜ hex prefix๋Š” ์ž๋™ ์ œ๊ฑฐ).

์ด์šฉํ•˜๋Š” ์‹ฌ๋ฆฌ

๊ฐ•์ 

์•ฝ์  (ํ—ˆ์ )

๊ฐœ์„  ๋ฐ˜์˜์ฒ˜

A/B ๊ฒ€์ฆ ๊ณ„ํš

โ‘  ์‹œ๋ฎฌ๋ ˆ์ด์…˜: --simulate / yaml simulation_mode / scripts/simulate.py 3๊ฒฝ๋กœ. DB๊ฐ€ trades_sim.db๋กœ ๋ถ„๋ฆฌ๋˜๊ณ  ์ฃผ๋ฌธ๋งŒ ๊ฐ€์งœ ์„ฑ๊ณต(SIM_BUY_xxxx)์œผ๋กœ ๋ฆฌํ„ดํ•˜๋˜, ๊ฐ€๊ฒฉ ์กฐํšŒ(midpoint)๋Š” ์‹ค์ œ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—๋„ ์‹คํ‚ค(.env)๊ฐ€ ํ•„์š”ํ•˜๋‹ค. โ‘ก ์†Œ์•ก ์‹ค๊ฑฐ๋ž˜: yaml buy_amount_usdc: 5.0. โ‘ข ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€ํ˜• ํ›„ ์ฆ์•ก: Jenkins env override๋กœ ๋ณ€ํ˜• ์šด์˜(์‹ค๋กœ๊ทธ ๊ธฐ์ค€ 85~95% / ์œ ๋™์„ฑ $20k / ๊ฑด๋‹น $2,000 ์กฐํ•ฉ ์ด๋ ฅ). ํŒ๋‹จ ๊ธฐ์ค€: ์›”๋ณ„ CSV์— ์Œ“์ด๋Š” hours_until_resolution_at_buyยทentry_reason์œผ๋กœ ์ž”์—ฌ์‹œ๊ฐ„ ๋ฒ„ํ‚ท๋ณ„(24-72h / 72-240h / 240-720h) ์Šน๋ฅ ยท์ˆ˜์ต์„ ์ง‘๊ณ„ํ•ด ์ง„์ž…์ฐฝ์˜ ์šฐ์—ด์„ ๋ฐ์ดํ„ฐ๋กœ ๊ฒ€์ฆํ•œ๋‹ค.

์‹คํ–‰ (Jenkins)

# Jenkins cron (3~5๋ถ„ ์ฃผ๊ธฐ, one-shot โ€” ๋ด‡ ๋‚ด๋ถ€ ๋ฃจํ”„ ์—†์Œ)
cd ./golden-cherry
export POLYMARKET_PRIVATE_KEY=<Jenkins credential>
export POLYMARKET_FUNDER_ADDRESS=<Jenkins credential>
uv sync --frozen
uv run polybot run --yes-only        # ์šด์˜ ๋ชจ๋“œ: Yes(index 0) ํ† ํฐ๋งŒ ๋งค์ˆ˜
# ์ƒํƒœ๋Š” data/{job}/trades.db, ์›”๋ณ„ CSV๋Š” data/{job}/trades_YYYY-MM.csv