crypto-trading-arena 설치부터 실전까지 — LLM 넷을 같은 봉 앞에 세워 놓고 누가 무엇을 사는지 보기

카프카까지 직접 세워 LLM 네 개를 같은 봉 앞에 앉히고, 같은 미션을 세 번 던져 판단이 얼마나 흔들리는지 재고, 그 판단을 weltiq 슬롯으로 옮겨 수수료가 6배 갈라지는 것을 확인한 기록입니다.

23편 — 트레이딩 아레나: LLM 넷을 같은 봉 앞에 세워 놓고 누가 무엇을 사는지 보기

이 글의 완료 조건: 독자는 여러 LLM 이 같은 봉을 보고 서로 다른 매매 판단을 내는 화면을 띄우면 성공입니다.

하는 일 LLM 여러 개를 같은 실시간 시세·같은 봉 앞에 세우고, 각자 페이퍼 지갑으로 사고팔게 한 뒤 한 화면에서 비교합니다
맞는 사람 모델을 고르기 전에 "얘들이 같은 자료를 보고 정말 다르게 구는가"를 자기 눈으로 보고 싶은 사람
안 맞는 사람 지금 뭘 살지 결론 하나만 받고 싶은 사람. 이 도구는 대회장이지 조언자가 아닙니다
이 글의 결과물 에이전트 4개가 각자 잔고·포지션·체결 이력을 들고 있는 대시보드 한 화면
준비물·비용 코드 0원(Apache-2.0) / 모델 유료 API 키 1개 — 이 검증은 네 모델 합쳐 약 $1.06 / 시세 0원(Binance 공개 API, 키 불필요) / weltiq 는 붙일 때만 무료 플랜
시간·난도 브로커 세우기 포함 40분. 난도 중상 — 터미널 창 네 개를 동시에 띄우고 config.json 을 직접 고칩니다
weltiq 와의 관계 통합 실험. 판단은 붙지만 수량과 시점은 사람이 다시 씁니다
검증 환경·날짜 2026-09-22 · macOS 15 (Apple Silicon) · Python 3.13 · Binance 현물
고지 필자는 weltiq 와 제휴 관계로 이 글을 씁니다. 도구 평가는 실측만 싣습니다

1. 이게 뭔가요

시장 데이터를 한 군데서 받아 여러 에이전트에게 똑같이 뿌리고, 각 에이전트가 자기 LLM 으로 판단해서 매수·매도·계산기·잔고 조회 도구를 부르는 구조입니다. 지갑은 도구 쪽 프로세스가 하나로 들고 있어서 누가 언제 얼마에 샀는지가 한 표에 모입니다.

핵심은 공정성 장치입니다. 봉을 만드는 곳이 한 곳이고, 그 한 곳이 만든 문장이 모든 에이전트에게 같은 글자로 갑니다. 에이전트마다 자기가 데이터를 긁지 않습니다. 그래서 "모델이 달라서 다른 결론이 나왔다"를 말할 수 있습니다.

저장소 ryan-yuuu/crypto-trading-arena (GitHub)
별 · 포크 128 · 40
라이선스 Apache-2.0
마지막 커밋 2026-07-08 — 두 달 반 조용합니다
자체 테스트 139개 통과. 저장소가 미해결 버그 22개를 문서로 공개하고 그중 7개를 "일부러 실패로 고정"해 뒀습니다
시세 Binance 현물 또는 Coinbase. 선물 경로 없음

미해결 버그를 목록으로 걸어 두는 저장소는 흔치 않습니다. 이 글에서 조심해야 할 대목도 대부분 그 목록에 이미 적혀 있었습니다.


2. 설치 — 검증된 한 경로

메시지 브로커(Kafka) 하나가 꼭 필요합니다. README 는 도커를 쓰라고 하는데, 도커가 없는 기계에서는 Homebrew 로 Kafka 를 직접 세우면 됩니다. 이 경로로 검증했습니다.

# 1) 브로커
brew install kafka                     # JDK 포함, 4분
cat > server.properties <<'EOF'
process.roles=broker,controller
node.id=1
controller.quorum.bootstrap.servers=localhost:9243
listeners=PLAINTEXT://localhost:9242,CONTROLLER://localhost:9243
advertised.listeners=PLAINTEXT://localhost:9242
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.dirs=/tmp/arena-kafka
EOF
kafka-storage format -t $(kafka-storage random-uuid) -c server.properties --standalone
kafka-server-start server.properties &

# 2) 도구
git clone https://github.com/ryan-yuuu/crypto-trading-arena && cd crypto-trading-arena
uv sync
cp config.example.json config.json     # 모델·키·심볼·수수료를 여기서 고칩니다
export OPENROUTER_API_KEY=...          # config.json 이 ${...} 로 참조하는 이름과 같게

config.json 에서 세 군데를 고쳤습니다.

"trading": {
  "exchange": "binance",
  "binance_symbols": ["BTCUSDT", "ETHUSDT", "SOLUSDT"],
  "fees": { "taker_bps": 60 }
}

그리고 창 네 개(또는 백그라운드 네 개)로 띄웁니다.

uv run python -m exchanges.binance             --bootstrap-servers localhost:9242
uv run python -m deploy.tools_and_dashboard    --bootstrap-servers localhost:9242
uv run python -m deploy.response_viewer        --bootstrap-servers localhost:9242
uv run python -m deploy.agent --from-config <이름> --strategy default \
                              --bootstrap-servers localhost:9242   # 모델 수만큼

막히는 자리

증상 원인 넘어가는 법
You cannot specify controller.quorum.voters and format the node with --standalone Kafka 4.x 는 동적 쿼럼 controller.quorum.voters 대신 controller.quorum.bootstrap.servers
시세 커넥터가 Environment variable 'OPENROUTER_API_KEY' is not set 로 죽음 시세 커넥터는 모델 키가 전혀 필요 없는데도 설정 파일 전체를 해석합니다. 게다가 이 프로세스만 .env 를 안 읽습니다 실행 전에 export 로 환경에 넣어 줍니다
Coinbase 로 띄웠는데 에이전트가 봉을 못 봄 저장소가 공개한 미해결 버그(우선순위 높음) — Coinbase 쪽 커넥터에 봉 저장소가 연결돼 있지 않습니다 Binance 로 띄웁니다. 이 글의 결과는 전부 Binance 입니다
대시보드가 깨져 보임 터미널 폭 170칸 이상으로 넓히거나 COLUMNS=170

3. 첫 결과 — 이렇게 나오면 성공

에이전트를 넷 띄우고 10분쯤 두면 이런 화면이 됩니다. 네 모델이 같은 시각·같은 봉을 받았는데 행동이 다릅니다.

에이전트 4개의 잔고·포지션·체결 이력. 같은 11번의 시세 갱신을 받았는데 gemini 는 10번 체결했고 haiku 와 gpt-5-nano 는 한 번도 주문하지 않았습니다.

이 화면이 뜨면 성공입니다. 읽는 법은 이렇습니다.

같은 봉을 보고 무슨 생각을 했는지는 별도 창에서 원문으로 볼 수 있습니다.

deepseek 이 세 종목을 분석한 뒤 "60bp 수수료 때문에 신규 진입을 조심해야 한다"고 적은 대목


4. 제일 잘 쓰는 법 — 수수료 한 줄을 바꿔 보기

이 도구가 다른 다중 에이전트 실험과 갈리는 자리는 수수료를 판단 입력으로 준다는 것입니다. 매 틱 에이전트에게 가는 문장 맨 앞에 이런 줄이 붙습니다.

A taker fee of 60 bps (0.60%) is charged on every fill (both buys and sells).
Factor this into your sizing and P&L targets — a round-trip costs 120 bps.

config.json 의 taker_bps 를 0 으로 바꾸면 같은 자리가 Trading is fee-free in this deployment. 로 바뀝니다. 그래서 다른 조건을 전부 고정하고 이 한 줄만 바꿔 두 판을 돌려 봤습니다.

4-1. 실시간 두 판 — 같은 에이전트 넷, 각각 11번의 시세 갱신

수수료 60bp 수수료 0bp
체결 12건 43건
주문한 에이전트 2 / 4 4 / 4
체결 명목액 $169,332 $1,439,744 (8.5배)
낸 수수료 $1,016 $0

60bp 판에서 한 번도 주문하지 않았던 두 모델(haiku·gpt-5-nano)이 0bp 판에서는 둘 다 주문했습니다.

수수료를 0으로 바꾼 뒤의 같은 화면. 네 에이전트가 모두 거래했고 "Fees paid"는 전부 $0.00 입니다.

4-2. 같은 봉으로 다시 — 60회 재생

두 판은 시장 시각이 다릅니다. 그래서 커넥터가 실제로 내보낸 프롬프트 하나를 그대로 떠서 수수료 문장만 바꿔 같은 도구·같은 계좌 초기값으로 10번씩 재생했습니다. 시장은 완전히 고정됩니다.

모델 60bp 에서 주문한 회차 0bp 에서 주문한 회차
deepseek-v3.2 1 / 10 5 / 10
gemini-3.1-flash-lite 8 / 10 6 / 10
gpt-5-nano 0 / 10 2 / 10
합계 체결액 $156,392 $462,480 (3.0배)

결론은 달라집니다. 다만 모델마다 다릅니다. 두 모델은 수수료를 없애면 확실히 손이 커지고, gemini-flash-lite 는 오히려 반대로 움직였습니다 — 수수료가 붙어 있든 없든 비슷하게 칩니다. 그리고 실시간 60bp 판에서 그 모델이 어떻게 됐는지가 첫 화면에 그대로 나옵니다: 10번 체결해서 수수료로만 $1,004 를 내고 총자산이 $99,065 가 됐습니다.

즉 이 도구로 알 수 있는 것은 "이 전략이 수수료를 이기는가"가 아니라 "이 모델이 수수료를 보고 있기는 한가" 입니다. 모델 고르기에는 이쪽이 더 쓸모 있습니다.

4-3. 하기 전에 알아 둘 것 두 가지

기본 요율이 시세를 준 거래소와 다릅니다. 설정 파일 기본값 60bp 는 Coinbase 기본 티어이고, 이 글이 봉을 받은 Binance 현물은 10bp 입니다. 기본값 그대로 Binance 로 돌리면 실제의 6배를 뭅니다. 수수료 실험을 할 거면 여기부터 맞추십시오.

수량은 소수 첫째 자리까지만 받습니다. BTC 기준 실측입니다.

0.05 BTC  거절   0.09 BTC  거절   0.15 BTC  거절
0.1  BTC  통과   0.2  BTC  통과

주문이 막히는 것은 아니지만, $100,000 계좌에서 BTC 포지션은 8.6% 단위로만 조절됩니다. "자본의 2%만 건다"가 BTC 에는 불가능합니다. 실제로 deepseek 은 100000 * 0.02 를 계산해 $2,000 을 뽑아 놓고 BTC 를 포기하고 SOL 로 갔습니다.


5. weltiq 로 옮기기 — 통합 실험

weltiq 준비 (전 편 공통): 가입({{CTA_URL}}) → 마이 → 연결 관리에서 키 발급 → claude mcp add weltiq https://weltiq.ai/mcp --header "Authorization: Bearer <키>"

이 도구는 "비트코인을 거래해서 수익을 내줘, 그리고 왜 그렇게 했는지 설명해줘"라고 시키면 방향·수량·목표가·무효화 가격을 한 번에 냅니다. 같은 미션을 세 번 던진 결과입니다.

회차 판단 목표가 무효화
1 BTC 매수 0.5 85,845 85,400
2 BTC 매수 1.1 87,290 −2%
3 BTC 매수 1.1 86,800~87,000 —

방향은 세 번 다 같았고, 수량은 0.5~1.1 로 두 배 넘게 벌어졌습니다. 2회차가 목표가를 뽑은 방식이 이 도구답습니다 — "왕복 수수료 120bp 를 넘기면서 1~2% 남기려면 $85,532 × 1.021 = $87,290".

1회차 판단을 weltiq 슬롯으로 옮기면 다섯 단계입니다.

  1. 규칙 문서로 씁니다. 진입 close > 85400, 지정가 청산 85845, 보호 손절 0.5%, 수량 0.1
  2. POST /v1/strategy-rules 로 제출하면 문서가 한 줄로 되읽어 옵니다 — 진입: (close > 85400) → 진입 long E · True → 가격 조건 청산 (limit=85845) → 청산: 보호 손절 0.5%
  3. POST /v1/ai/thesis 로 왜 그렇게 판단했는지를 사람 말로 함께 냅니다. 근거 없이는 슬롯이 안 만들어집니다
  4. POST /v1/containers 로 슬롯을 만듭니다. 중지 조건(최대 손실·시간 한도)이 필수입니다
  5. 체결을 확인하고 정지·삭제합니다

이날 결과입니다.

매수 0.1 BTC @ 85,483.07 · 수수료 $8.55
매도(정지 청산) 0.1 BTC @ 85,471.36 · 수수료 $8.55
실현 손익 −$1.17
수수료 합 $17.10
순 −$18.27 (−0.18%), 14분

옮겨지지 않는 것

저쪽 수익률을 그대로 쓰면 안 되는 이유

같은 왕복 거래를 두 장부가 이렇게 계산했습니다.

아레나 페이퍼 지갑 weltiq 슬롯
요율 60bp (설정 기본값) 10bp (Binance 현물 실제)
왕복 수수료 $102.64 $17.10

같은 판단·같은 시장인데 비용이 6배 다릅니다. 게다가 저장소 스스로 장부 문제 세 건을 미해결로 적어 놨습니다 — 그중 하나는 "실현 손익은 청산 수수료를 빼는데 미실현 손익은 안 뺀다"입니다. 두 수를 더하면 안 됩니다. 이 도구는 판단을 재는 데 쓰고, 성적은 판단을 옮긴 쪽에서 재는 것이 맞습니다.


6. 써 보니

좋았던 것

아쉬운 것

비용

코드·시세 0원
모델 이 검증 전체 약 $1.06 (네 모델, 실시간 88회 호출 + 재생 63회)
틱 하나당 저렴한 모델 기준 $0.001~0.01, 에이전트당
weltiq 무료 플랜으로 슬롯 3개

7. 다음 행동

모델을 고르는 중이라면 이 도구를 모델 성향 계측기로 쓰십시오. 수익률 순위가 아니라 "수수료를 보는가 / 기다릴 줄 아는가 / 한 번에 얼마를 거는가"를 보면 값이 나옵니다. 그 뒤에 남는 질문은 하나입니다 — 판단은 받았는데, 이걸 24시간 누가 지키고 있나.

다음 편은 같은 질문을 반대쪽에서 봅니다. 여럿을 세우는 대신 하나에게 오래 맡기는 도구입니다.

weltiq 준비 — 3줄

  1. 가입: {{CTA_URL}}
  2. 마이 → 연결 관리에서 키 발급
  3. claude mcp add weltiq https://weltiq.ai/mcp --header "Authorization: Bearer <키>"

판단을 규칙으로 적어 내면 실시간 봉 위에서 모의로 돌려 주고, 체결·수수료·슬리피지를 원장으로 남겨 줍니다. 모의 전용입니다.


검증 기록 전문(설치 우회 과정·미션 3회 원문·수수료 A/B 60회 원문·결함 목록)은 reports/a/23-crypto-trading-arena/ 에 있습니다.