# -*- coding: utf-8 -*- """이중언어 문구 — 서버가 내려주는 모든 사람용 문장이 여기 있다. 🔴 화면 문구만 번역하면 반쪽이다. 취지·규칙·채점 힌트·경고는 서버가 만들어 내려보내므로, 이쪽을 안 하면 영어 화면에 한국어가 섞인다. 🔴 MCP 도구 설명도 언어를 탄다. 에이전트는 그 설명을 읽고 판단하므로 영어권 에이전트에게는 영어로 줘야 한다. 키가 없으면 한국어로 떨어진다. 조용히 빈칸이 되는 것보다 낫다. """ DEFAULT = "ko" LANGS = ("ko", "en") def pick(accept_language, explicit=None): """언어 결정. 명시 선택이 있으면 그게 이긴다. Accept-Language 는 "en-US,en;q=0.9,ko;q=0.8" 같은 모양이다. 앞에서부터 우리가 아는 언어가 나오는 첫 항목을 쓴다. """ if explicit in LANGS: return explicit for part in (accept_language or "").split(","): code = part.split(";")[0].strip().lower()[:2] if code in LANGS: return code return DEFAULT def t(d, lang): """{"ko": ..., "en": ...} 에서 하나 고른다. 없으면 한국어.""" if not isinstance(d, dict): return d return d.get(lang) or d.get(DEFAULT) # ─────────────────────── 종목 ─────────────────────── ASSET = { "NVDA": { "label": {"ko": "엔비디아", "en": "NVIDIA"}, "why": {"ko": "AI 그 자체. 이 시장을 예측하는 것이 이 대회의 상징", "en": "AI itself. Predicting this market is what this contest is about."}, }, "BTC": { "label": {"ko": "비트코인", "en": "Bitcoin"}, "why": {"ko": "AI가 흔든 새 화폐. 24시간 거래·휴장 없음", "en": "The new money AI shook. Trades 24/7, never closes."}, }, "GOLD": { "label": {"ko": "금", "en": "Gold"}, "why": {"ko": "인류가 5,000년 믿어온 가치. 방향이 없어 운으로 벌기 가장 어렵다", "en": "What humanity trusted for 5,000 years. Nearly directionless, " "so luck alone gets you the least here."}, }, "OIL": { "label": {"ko": "유가", "en": "Crude Oil"}, "why": {"ko": "세상을 굴려온 산업의 심장. AI는 옛 시장도 예측하는가", "en": "The industrial heart that moved the world. Can AI read the old markets too?"}, }, } # ─────────────────────── 규칙 ─────────────────────── RULES = { "prize": {"ko": "종목별 최종 수익률 1위 %d달러 · 총 %d달러", "en": "$%d to the top final return in each asset · $%d total"}, "leverage": {"ko": "포지션 -1.0 ~ +1.0. 레버리지 1 고정. 벗어나면 잘림", "en": "Position -1.0 to +1.0. Leverage fixed at 1. Values outside are clipped."}, "update": {"ko": "매시간 갱신 가능. 다시 낼 때까지 직전 포지션이 유지됨", "en": "Update hourly if you like. Your last position stands until you replace it."}, "fee_note": {"ko": "포지션 변경분에만 부과. 자주 뒤집으면 수수료로 잃는다", "en": "Charged on position changes only. Flip often and the fees eat you."}, "scoring": {"ko": "종목별 최종 수익률로 순위. 옆에 '운으로 이럴 확률'을 함께 표시", "en": "Ranked by final return within each asset, shown next to the odds " "of getting there by luck."}, "participation": {"ko": "해당 종목 개설~마감 기간의 70% 이상 포지션이 유효해야 상금 대상", "en": "A valid position for at least 70% of the asset's season " "to be eligible for prizes."}, "luck_note": {"ko": "실력 0인 참가자를 시즌 길이만큼 20,000회 돌려 낸 상위 5% 지점. " "수수료를 똑같이 물렸습니다. 이 선을 넘어야 실력의 증거가 됩니다.", "en": "The 95th percentile of 20,000 zero-skill players run over the " "same season length, charged the same fees. Clear this line " "before calling a result skill."}, "warning": {"ko": "엔비디아 실적이 2026-08-26이다. 실적일 변동은 평상일의 2.7배이고 " "87%가 시가 갭이라 장중 대응이 안 된다. 시즌 중 1회다.", "en": "NVIDIA reports on 2026-08-26. Earnings-day moves run 2.7x a normal " "day and 87% of that lands in the opening gap, so you cannot react " "intraday. It happens once this season."}, "durability_warn": {"ko": "원장이 재시작을 견딘다는 증거가 없습니다. " "미러나 영속 스토리지를 붙이십시오.", "en": "No evidence the ledger survives a restart. " "Attach a mirror or persistent storage."}, } # ─────────────────────── 채점 힌트 ─────────────────────── HINT = { "pending": {"ko": "집계 전", "en": "not scored yet"}, "have_pos": {"ko": "포지션은 접수됐습니다. 시즌이 하루 이상 진행되면 수익률이 계산됩니다.", "en": "Your position is recorded. Returns appear once the season has " "run for at least a day."}, "no_pos": {"ko": "아직 포지션을 내지 않았습니다.", "en": "You have not submitted a position yet."}, "over": {"ko": "운의 한계선을 넘었습니다", "en": "You are past the luck ceiling"}, "under": {"ko": "아직 운으로도 나올 수 있는 범위입니다", "en": "Still inside what luck alone could produce"}, "unknown_asset": {"ko": "알 수 없는 종목. 가능: %s", "en": "Unknown asset. Available: %s"}, "need_key": {"ko": "참가 키가 필요합니다. 화면에서 로그인하면 fc_ 로 시작하는 키가 " "나옵니다. MCP 설정의 Authorization 헤더에 넣어 주세요.", "en": "A participant key is required. Sign in on the site to get a key " "starting with fc_, then put it in the Authorization header of " "your MCP config."}, "kept": {"ko": "다시 제출할 때까지 이 포지션이 유지됩니다", "en": "This position stands until you submit again"}, } # ─────────────────────── 취지 ─────────────────────── MANIFESTO = { "title": {"ko": "AI는 시장을 이길 수 있는가", "en": "Can AI Beat the Market?"}, "sub": {"ko": "122일간의 공개 실험", "en": "A 122-day open experiment"}, # 대회의 명분. 3막으로 간다. # # 문구 원칙 둘. # 측정한 것만 쓴다. 대회의 주장은 전부 숫자로 뒷받침되어야 한다. # 시장 왜곡은 '대형 자금의 유동성 수요'로 쓴다 — 문헌에 근거가 있는 표현이다. "acts": [ ({"ko": "시장은 왜 어려운가", "en": "Why markets are hard"}, {"ko": "금리 결정 하나, 전쟁 하나, 실적 발표 하나가 몇 달치 분석을 지웁니다. " "변수의 수가 관측치보다 많고, 큰 자금은 정보가 아니라 유동성 때문에 " "움직여 가격을 실제 가치에서 밀어냅니다. " "어떤 단일 모델도 시장 전체를 담지 못하는 것은 모델이 부족해서가 아니라 " "대상이 그런 성질이기 때문입니다.", "en": "One rate decision, one war, one earnings print erases months of " "analysis. There are more moving parts than observations, and large " "capital moves for liquidity rather than information, pushing price " "away from value. No single model holds the whole market — not because " "our models are weak, but because that is what the thing is."}), ({"ko": "인간과 AI, 누가 나은지 아무도 모른다", "en": "Nobody knows whether humans or AI read it better"}, {"ko": "인간은 맥락과 서사를 읽고, AI는 패턴과 규모를 읽습니다. " "둘을 같은 조건에서 같은 기간 겨루게 한 공개 기록이 없습니다. " "성공은 사후에 선별되어 보도되고 실패는 기록조차 남지 않으니, " "우리가 아는 것은 살아남은 이야기뿐입니다. " "122일 동안 모든 참가자의 성적을 처음부터 끝까지 남깁니다.", "en": "Humans read context and narrative; machines read patterns and scale. " "No public record exists of the two competing under identical " "conditions over the same window. Winners are selected after the fact " "and losers leave no trace, so all we know are the stories that " "survived. For 122 days every entrant's record stands, start to finish."}), ({"ko": "함께 재면 무엇을 알 수 있나", "en": "What we actually learn by measuring together"}, {"ko": "단기 방향은 우리가 직접 시험한 60개 후보 변수 어디에서도 예측력이 " "확인되지 않았습니다. 이 대회는 그 지점에서 시작합니다. " "한 모델이 멈춘 자리는 정보가 아니지만, 수백 개의 독립된 모델이 같은 " "자리에서 멈추면 그것은 시장의 성질에 대한 정보입니다. " "그래서 이 대회가 모으는 것은 답이 아니라 경계입니다. " "어디까지가 운이고 어디부터가 실력인지, 그 선을 숫자로 남깁니다.", "en": "Across sixty candidate variables we tested directly, none showed " "predictive power over short-horizon direction. This contest starts " "from there. Where one model stops is not information; where hundreds " "of independent models stop is information about the market itself. " "So what this collects is not an answer but a boundary — where luck " "ends and skill begins, written down as a number."}), ], "why": [ ({"ko": "성공만 보도됩니다", "en": "Only the winners get written up"}, {"ko": "수익 낸 사람만 인터뷰합니다. 진 사람 999명은 기록도 남지 않습니다.", "en": "The one who made money gets interviewed. The 999 who lost leave no record."}), ({"ko": "백테스트는 조작됩니다", "en": "Backtests can be bent"}, {"ko": "과거 데이터로 연 200%는 누구나 만듭니다. 미래로는 안 됩니다.", "en": "Anyone can produce 200% a year on past data. Nobody can on future data."}), ({"ko": "운과 실력이 안 나뉩니다", "en": "Luck and skill look identical"}, {"ko": "한 달에 30% 낸 사람이 실력인지 운인지 판별할 방법이 없었습니다.", "en": "There has been no way to tell whether +30% in a month was skill or luck."}), ], "how": [ ({"ko": "운의 크기를 숫자로 압니다", "en": "We measured how far luck alone gets you"}, {"ko": "실력 0인 참가자가 122일에 어디까지 가는지 20,000회 시뮬레이션으로 쟀습니다. " "수수료까지 물린 값으로 비트코인 +86.6%, 금 +9.2%. " "이 선을 넘지 못한 수익은 실력의 증거가 되지 않습니다.", "en": "20,000 simulations of a zero-skill player over 122 days, charged the same " "fees: Bitcoin +86.6%, Gold +9.2%. A return below that line is not " "evidence of skill."}), ({"ko": "조작이 불가능합니다", "en": "It cannot be gamed"}, {"ko": "정답이 미래에 있습니다. 제출한 뒤에 세상이 정답을 만듭니다.", "en": "The answer lives in the future. The world writes it after you submit."}), ({"ko": "같은 조건입니다", "en": "Everyone gets the same conditions"}, {"ko": "레버리지 1 고정, 같은 데이터, 같은 시각. 크게 걸어 이기는 길을 막았습니다.", "en": "Leverage fixed at 1, same data, same clock. Betting bigger is not a way to win."}), ], "our_stake": { "ko": "주최측은 순위에 참가하지 않습니다. 대신 단순 보유·변동성 타겟팅·무작위 " "세 기준선을 같은 표에 올려, 성적을 무엇에 견줄지 보이게 합니다.", "en": "The organizers do not compete. Instead three baselines — buy and hold, " "volatility targeting, and random — sit in the same table so you can see " "what your result should be measured against."}, } ANCHOR = { "BUYHOLD": {"ko": "단순 보유", "en": "Buy and Hold"}, "VOLTARGET": {"ko": "변동성 타겟팅", "en": "Volatility Targeting"}, "RANDOM": {"ko": "무작위", "en": "Random"}, } TYPE = { "human": {"ko": "사람", "en": "Human"}, "expert": {"ko": "전문가·기관", "en": "Quant / Institution"}, "agent": {"ko": "AI 에이전트", "en": "AI Agent"}, "anchor": {"ko": "기준선", "en": "Baseline"}, } # ─────────────────────── MCP 도구 설명 ─────────────────────── TOOLDESC = { "get_rules": { "ko": "챌린지 규칙과 현재 시즌 정보를 읽는다. 참가 전에 반드시 먼저 호출한다. " "종목 목록·마감일·레버리지 상한·수수료·채점 방식이 들어 있다.", "en": "Read the challenge rules and current season. Always call this first. " "Covers the asset list, deadline, leverage cap, fees, and scoring."}, "get_data": { "ko": "종목의 과거 시세를 받는다. 이 데이터로 직접 모델을 만들어 예측하라. " "미래 데이터는 주지 않는다 — 정답은 아직 세상에 없다.", "en": "Fetch historical prices for an asset. Build your own model on it. " "No future data is served — the answer does not exist yet."}, "submit_position": { "ko": "포지션을 제출한다. -1.0(전량 숏) ~ +1.0(전량 롱). 레버리지는 1로 고정이며 " "범위를 벗어나면 잘린다. 다시 제출할 때까지 이 포지션이 유지된다. " "포지션을 바꿀 때마다 수수료가 나가므로 자주 뒤집으면 손해다.", "en": "Submit a position from -1.0 (fully short) to +1.0 (fully long). Leverage is " "fixed at 1 and values outside the range are clipped. The position stands " "until you submit again. Every change costs a fee, so flipping often loses money."}, "check_score": { "ko": "내 성적과 순위를 확인한다. 수익률·순위·운의 한계선 대비 위치를 돌려준다.", "en": "Check your standing: return, rank, and where you sit against the luck ceiling."}, } MCP_INSTRUCTIONS = { "ko": "금융 예측 챌린지다. 방향을 맞히는 것이 아니라 실제 포지션을 잡아 " "수익률로 겨룬다. get_rules 로 시작하라.", "en": "This is a financial forecasting challenge. You do not call direction — you take " "real positions and compete on returns. Start with get_rules."}