trading-bot-agent — 주식용 다중 에이전트 프레임워크를 크립토로 옮기면 무엇이 깨지나

별 0개짜리 TradingAgents 파생판을 깔아 아홉 판을 돌리고, 원본이 보인 매수 편향을 그대로 물려받았는지 같은 방식으로 재 봅니다.

28편. trading-bot-agent — 주식 프레임워크를 크립토로 옮기면 무엇이 깨지나

이 글의 완료 조건: 독자는 주식용 다중 에이전트 프레임워크를 크립토에 쓰면 무엇이 달라지는지 알고 나면 성공입니다.


이 도구 한 장 요약

하는 일 에이전트 열한 명이 토론해 비트코인 등급(Buy~Sell)과 배분 지시를 냅니다. 12편 TradingAgents 를 Binance 현물로 옮긴 파생판입니다
맞는 사람 12편을 읽고 "이걸 크립토로 옮기면 어떻게 되나"가 궁금한 사람. 오픈소스 이식이 실제로 어디서 깨지는지 보고 싶은 사람
안 맞는 사람 지금 당장 쓸 크립토 분석 도구를 찾는 사람. 원본을 쓰세요 — 원본도 크립토를 지원하고, 4개월 더 고쳐졌습니다
이 글의 결과물 BTCUSDT 판정 한 장 (등급 + 배분 지시 + 근거 글)
준비물·비용 코드 무료(Apache-2.0) / 모델 키 1개, 한 판 $0.03 / 시세 Binance 공개 API 키 불필요 / weltiq 계정(5절만)
시간·난도 설치 5분, 한 판 3분. 중 — 가상환경과 환경변수를 다룰 수 있어야 합니다
weltiq 와의 관계 비교한다. 이 도구는 주문을 내지 않고, 낸 판정도 대부분 "줄여라"라서 weltiq 슬롯으로 옮기기가 까다롭습니다 (5절은 통합 실험)
검증 환경·날짜 2026-09-22 · macOS 26.6.2 / arm64 / Python 3.12 · 커밋 e478951 고정 · 모델 openai/gpt-5.6-luna
제휴 고지 필자는 weltiq 의 제휴 기고자입니다. 이 글의 모든 명령과 출력은 위 환경에서 실제로 돌려 얻은 것이고, 숫자는 손대지 않았습니다. 주문은 전부 모의입니다

1. 이게 뭔가요

ardhanurfan/trading-bot-agent 는 TradingAgents 를 Binance 현물로 옮긴 판입니다. 애널리스트가 자료를 읽고, 강세론자와 약세론자가 토론하고, 트레이더가 실행안을 쓰고, 리스크 팀 셋이 또 논쟁하고, 포트폴리오 매니저가 최종 등급을 내는 구조는 12편 과 똑같습니다. 바뀐 것은 자료를 어디서 받고 주문을 어디로 보내느냐입니다.

먼저 관계를 정확히 적어 둡니다. 이 저장소는 깃허브 API 상 포크 표시가 없습니다(fork: false, 상위 저장소 없음). 그런데 README 첫머리가 이렇게 밝힙니다.

"This project is a heavily modified and upgraded version of the original TauricResearch/TradingAgents."

README 의 별 이력 그래프도 원본(TauricResearch/TradingAgents)을 가리키고, assets/ 폴더에는 원본 로고가 그대로 들어 있고, 명령줄 화면에도 "Built by Tauric Research"가 찍힙니다. 소스를 새 저장소로 다시 올린 형태이고, 실질은 파생판입니다. 라이선스(Apache-2.0)는 지켰습니다.

항목 값
주소 github.com/ardhanurfan/trading-bot-agent
별 / 포크 / 열린 이슈 0 / 0 / 0
개설 → 마지막 푸시 2026-05-12 → 2026-05-24 · 커밋 156 · 아카이브 아님
라이선스 Apache-2.0
패키지 버전 0.2.4 — 원본의 2026-04-25 판

마지막 줄이 이 글에서 제일 중요합니다. 원본은 지금 0.5.0 입니다. 즉 이 파생판은 원본의 4월 판에서 갈라져 나온 뒤 원본을 따라오지 않았습니다. 그래서 둘을 비교할 때 나오는 차이는 두 종류가 섞여 있습니다 — 파생판이 새로 더한 것(크립토 이식)과 원본이 그 뒤에 더한 것. 이걸 구분하지 않으면 판단이 통째로 틀립니다.

파생판이 더한 것: Binance 현물 클라이언트와 봉·지표 함수, 온체인·펀딩비 도구, 거래대금으로 종목을 스스로 고르는 스캐너, 24시간 상주 데몬, 판정을 주문으로 바꾸는 검증기, 현물 주문기.

원본이 그 뒤에 더해 파생판에 없는 것: 다섯 번째 애널리스트, 거시 지표 도구, 수치 검증 장치, 장부를 넘겨 주는 자리, 그리고 자산 종류에 맞춰 애널리스트를 걸러 주는 가드. 마지막 것이 2절에서 바로 사고를 냅니다.


2. 설치

검증된 한 경로입니다.

git clone --depth 1 https://github.com/ardhanurfan/trading-bot-agent.git
cd trading-bot-agent
uv venv -p 3.12 /어디든/.venv-tba
uv pip install --python /어디든/.venv-tba/bin/python -r requirements.txt

설치 자체는 막히지 않습니다. 키는 환경변수로 줍니다. 이 글은 OpenRouter 를 썼습니다.

export OPENROUTER_API_KEY=...
export BINANCE_TESTNET=false        # ← 이 한 줄이 제일 중요합니다. 3절에서 설명합니다

명령줄 화면이 뜨면 설치는 된 것입니다.

PYTHONPATH=. python -m cli.main

설치가 끝난 화면 — 명령줄 첫 기동

초록 상자와 그 아래 다섯 단계(Analyst Team → Research Team → Trader → Risk Management → Portfolio Management)가 뜨면 제대로 깔린 것입니다. 그런데 이 화면을 자세히 보세요. 맨 아래 Step 1: Ticker Symbol 의 기본값이 SPY 이고, 예시가 SPY, CNC.TO, 7203.T, 0700.HK — 전부 주식입니다. 크립토 예시가 하나도 없습니다. 상자 안 서명도 "Built by Tauric Research"(원본 팀)입니다. 크립토 에디션이라는데 사람이 들어가는 문은 주식 시절 그대로입니다.**

대시보드는 없습니다. 웹 UI 도, 접속할 주소도 없습니다. 위 명령줄 화면과 파이썬 호출이 전부입니다. 그리고 크립토를 쓰려면 명령줄이 아니라 파이썬 쪽으로 들어가야 합니다 — 명령줄에는 크립토 경로가 준비돼 있지 않습니다.

from tradingagents.default_config import DEFAULT_CONFIG
from tradingagents.graph.trading_graph import TradingAgentsGraph

cfg = dict(DEFAULT_CONFIG)
cfg.update({"llm_provider": "openrouter",
            "backend_url": "https://openrouter.ai/api/v1",
            "deep_think_llm": "openai/gpt-5.6-luna",
            "quick_think_llm": "openai/gpt-5.6-luna",
            "memory_log_path": "/어디든/이번판.md"})     # 3절에서 설명합니다

graph = TradingAgentsGraph(debug=False, config=cfg,
                           selected_analysts=["market", "social", "news"])
state, rating = graph.propagate("BTCUSDT", "2026-09-22")
print(rating)      # Buy / Overweight / Hold / Underweight / Sell

막히는 자리

증상 원인 어떻게
첫 실행이 ALPHA_VANTAGE_API_KEY ... is not set 으로 죽는다 펀더멘털 애널리스트가 비트코인의 재무제표를 달라고 한다. 원본에 있는 "크립토면 이 애널리스트를 빼라"는 가드가 없다 selected_analysts 에서 fundamentals 를 빼세요. 위 코드가 그 구성입니다
200일 이동평균이 50일과 똑같이 나온다 BINANCE_TESTNET 기본값이 true export BINANCE_TESTNET=false (3절)
스위치를 바꿨는데 여전히 이상하다 저장해 둔 봉 파일이 실시장/모의를 구분하지 않는다 rm ~/.tradingagents/cache/*Binance*.csv
같은 질문인데 답이 전 판을 인용한다 판정이 파일에 쌓이고 다음 판이 그걸 읽는다 memory_log_path 를 판마다 새 파일로
CoinGecko news fetch failed ... 404 / 429 그쪽이 막았거나 호출 제한 뉴스 칸만 얇아집니다. 판은 그대로 돕니다
명령줄에서 BTCUSDT 를 넣어도 크립토로 안 잡힌다 명령줄이 주식 시절 판이다 파이썬 쪽으로 부르세요

3. 첫 결과 — 그리고 초보자가 여기서 헷갈립니다

기본값이 모의 거래소를 봅니다

이 도구의 Binance 클라이언트는 기본이 테스트넷(testnet.binance.vision) 입니다. 환경변수를 안 건드리면 그쪽을 봅니다.

문제는 테스트넷이 오류를 내지 않는다는 데 있습니다. 공개 시세 엔드포인트가 열려 있어서 값이 멀쩡히 돌아옵니다. 가격도 실시장과 비슷합니다. 그래서 잘못 쓰고 있다는 신호가 없습니다. 실제로 재 보면 이렇습니다.

같은 요청, 다른 거래소 — 돌아오는 일봉 개수

같은 요청을 두 주소에 던졌습니다. 왼쪽 숫자를 보세요 — 실시장은 일봉 1,000개(2023-12-28부터), 테스트넷은 14개(2026-09-09부터)입니다. 이 도구의 시장 애널리스트는 10일 EMA·50일 SMA·200일 SMA·MACD·RSI·볼린저·ATR 을 계산합니다. 14일치로는 200일 이동평균이 성립하지 않습니다.**

숨겨진 함정이 아닙니다. 도구 자신이 알아챕니다. 테스트넷으로 돌린 판의 시장 보고서 원문입니다.

The reported close_200_sma was not emphasized in the signal interpretation
because it is identical to the 50 SMA in the supplied output, indicating that
the data window is insufficient or the vendor has substituted the available average.

"200일선이 50일선과 똑같다, 자료 창이 부족하다는 뜻이다." 보고서 한가운데 이 문장이 있는데, 등급은 그대로 나옵니다. 읽지 않으면 모릅니다.

공개 실시장 자료로 바꾸는 법 — 두 줄입니다.

bash export BINANCE_TESTNET=false rm ~/.tradingagents/cache/*Binance*.csv

둘째 줄을 꼭 같이 하세요. 저장해 둔 봉 파일 이름이 실시장과 모의를 구분하지 않습니다. 파일 이름은 5년 범위인데 내용은 테스트넷 14일치일 수 있고, 그러면 스위치를 바꿔도 예전 자료를 계속 읽습니다. 필자는 이걸 모르고 세 판을 버렸습니다.

그리고 공개 시세만 읽을 거면 Binance 키가 필요 없습니다. 키가 필요한 것은 내장 주문기를 쓸 때뿐이고, 이 글은 쓰지 않았습니다.

이렇게 나오면 성공

3분쯤 지나면 이렇게 끝납니다.

한 판이 끝난 화면 — 등급과 실행안

굵은 줄 사이의 PORTFOLIO MANAGER RATING : Underweight 가 최종 등급이고, 그 아래가 트레이더의 실행안입니다. Action: Hold 와 Position Sizing: Reduce existing BTCUSDT exposure by approximately 20%–30% 두 줄이 이 도구가 실제로 내주는 것입니다. Reasoning 한가운데 resistance near $87,400 과 a confirmed daily breakout above $87,400 이 보이는데, 이게 5절에서 규칙으로 옮길 레벨입니다. 맨 아래 [tokens] calls=15 in=90459 out=16619 이 이 한 판에 쓴 토큰이고 179초 걸렸습니다. 이 화면이 나오면 성공입니다.

읽는 순서는 이렇습니다. 등급(Underweight)은 다섯 단계 중 하나, Action 은 세 단계(Buy/Hold/Sell), Position Sizing 이 실제 지시입니다. Reasoning 에 왜 그랬는지가 글로 있고, 위 판은 "87,400 을 일봉 종가로 확정 돌파한 뒤에, 또는 81,000~82,000 으로 눌린 뒤에 추가하라"고 레벨까지 말합니다.


4. 제일 잘 쓰는 법 — 같은 질문을 아홉 번 던지기

이 도구를 쓰는 제일 나은 방법은 한 판을 믿지 않는 것입니다. 12편 에서 원본에 같은 질문을 열세 번 던져 봤더니, 한 번의 판정으로 도구 성격을 적으면 안 된다는 게 분명해졌습니다. 그 실험을 파생판에 그대로 재현했습니다.

고정한 것: 모델 openai/gpt-5.6-luna(12편과 같음), 애널리스트 3종, 토론 1라운드, 리스크 논의 1라운드, 커밋 e478951. 바꾼 것: 날짜와, 판정 기억을 공유하는지 여부뿐입니다.

판 날짜 자료 기억 등급 Action
1 2026-09-22 테스트넷 공유 Underweight Sell
2 2026-09-22 실시장 공유 Hold Hold
3 2026-09-22 실시장 공유 Underweight Sell
4 2026-09-22 실시장 공유 Underweight Sell
5 2026-06-30 실시장 공유 Underweight Sell
6 2026-09-22 실시장 격리 Underweight Hold
7 2026-09-22 실시장 격리 Sell Sell
8 2026-09-22 실시장 격리 Underweight Sell
9 2026-09-22 실시장 격리 Underweight Hold

매수(Buy·Overweight)는 아홉 판 중 0번입니다. 원본이 열세 판에서 0번이었던 것과 같습니다. 5번 판은 12편이 물어봤던 것과 같은 날짜입니다 — 비트코인이 고점 대비 53% 내려앉아 RSI 가 30 이던 날. 원본은 그날 "과매도는 맞지만 바닥을 확인해 주지 않는다"며 매수를 거절했고, 파생판도 거절했습니다.

자료원을 야후 파이낸스에서 Binance 로 갈아 끼우고, 감성 자료원을 통째로 바꾸고, 프롬프트가 한 세대 뒤진 판인데 부호가 안 바뀝니다. 이식에서 살아남은 것 중 가장 확실한 것이 이 편향입니다.

달라진 것은 결단성입니다. 원본은 열세 판에서 Hold 를 한 번도 안 냈습니다. 파생판은 아홉 판에서 Action 기준 세 번 냈습니다. 소스를 열어 보면 방향이 맞습니다 — 원본의 포트폴리오 매니저 프롬프트에는 이런 문장이 들어 있습니다.

The risk debate always contains conflicting stances; deciding which is stronger
is the job, so conflict alone is not a reason to Hold.

"의견이 갈렸다는 것만으로는 Hold 의 이유가 못 된다." 파생판의 같은 자리는 "Be decisive..." 한 줄입니다. 원본이 4월 이후에 넣은 문장이고, 파생판은 그 이전에서 멈춰 있습니다.

같은 자리가 하나 더 있습니다. 원본의 트레이더 프롬프트는 진입가와 손절을 절대 가격으로 못 박으라고 지시하고, 그러라고 시장 보고서 원문을 따로 넘겨 줍니다. 파생판에는 그 지시가 없습니다. 결과가 그대로 나옵니다.

이 도구가 매 판 내주는 것 아홉 판 중
배분 지시 ("정상 배분의 75~85%로 줄여라") 9 / 9
진입가 칸 1 / 9
손절 칸 2 / 9

이 도구의 판정은 "방향 + 크기"입니다. 레벨은 구조화된 칸이 아니라 글 속에 있습니다. 진입가가 나온 유일한 한 판은 진입 86,625 / 손절 87,383 이었는데, 매도 판정인데 손절이 진입 위에 있습니다. 본문에서 저항 구간으로 인용한 두 숫자를 그대로 두 칸에 나눠 넣은 것에 가깝습니다. 그 칸의 숫자는 믿지 말고, 글을 읽으세요.

판마다 답이 다른 이유 하나 — 기억이 파일에 쌓입니다

표의 "기억" 칸이 그겁니다. 이 도구는 판정을 끝낼 때마다 ~/.tradingagents/memory/trading_memory.md 에 적고, 다음 같은 종목 판이 그걸 읽습니다. 2번 판(유일한 Hold)의 근거 원문에 이렇게 나옵니다.

Prior BTCUSDT outcomes reinforce this balance: the recent Underweight calls
correctly warned against chasing extended momentum, while the earlier
Overweight and Hold calls underperformed

"최근의 Underweight 판정들이 옳았다" — 자기가 몇 분 전에 쓴 판정을 근거로 삼고 있습니다. 되먹임을 원한다면 장점이지만, "같은 질문을 N번 던져 답이 얼마나 흔들리나"를 재려 한다면 이건 독립된 N번이 아닙니다. 그래서 6~9번 판은 판마다 기억 파일을 새로 만들어 돌렸습니다. 이 도구로 실험하실 분은 memory_log_path 를 꼭 갈아 주세요.

현물인가 선물인가

크립토 도구를 볼 때 꼭 확인해야 하는 것입니다. 이 도구는 거의 전부 현물입니다. 봉·시세·주문이 전량 Binance 현물 경로(/api/v3/...)를 씁니다. 선물 쪽 주소(fapi)는 두 군데뿐이고, 둘 다 펀딩비와 프리미엄 지수를 참고 지표로 읽는 용도입니다. 판단을 현물에 그대로 적용할 수 있다는 뜻입니다.

다만 현물에서 걸리는 것이 하나 있습니다. 아홉 판 중 여덟 판이 "줄여라"입니다. 현금으로 시작한 현물 계좌에는 줄일 것이 없습니다. 그리고 이 도구의 내장 주문기는 주문 전에 잔고를 확인하지 않습니다. 보유가 없어도 매도 주문을 큐에 넣습니다. 이 글은 내장 주문기를 켜지 않았습니다.


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

미리 말씀드립니다. 이 도구는 weltiq 와 잘 안 맞습니다. 정보를 주는 도구이고, 그 정보가 대부분 "보유를 줄여라"라서 현금에서 시작하는 슬롯에 옮길 것이 없습니다. 12편이 원본에서 만난 벽과 같은 벽이고, 파생판에서도 그대로입니다. 그 편의 5절을 먼저 읽으시는 편이 낫습니다.

그래도 옮길 수 있는 칸이 하나 있었습니다. 위 2번 판의 판정문에 조건부 매수 분기가 글로 적혀 있었습니다.

consider incremental additions only after a controlled pullback toward
83,500–84,500 or a confirmed close above 87,400, and reassess defensively
below 81,270

표시: 이 판의 최종 행동은 Hold 입니다. 옮긴 것은 판정문이 명시한 "87,400 을 확정 돌파하면 추가하라"는 분기이고, 방향(롱)과 두 레벨(87,400 / 81,270)은 도구 원문 그대로입니다. 수량은 필자가 정했습니다 — Hold 판정이라 신규 진입 수량을 말하지 않았기 때문입니다.

성공 경로는 네 단계였습니다.

  1. 규칙으로 쓴다 — close > 87400 이고 보유가 0이면 롱 진입. 손절은 도구가 준 두 숫자에서 나옵니다: (87,400 − 81,270) ÷ 87,400 = 7.0%
  2. 근거를 자기 말로 쓴다 — 근거와 무효 조건(81,270 아래로 종가가 내려가면 이 논리는 깨진다)을 함께 냅니다. 이게 없으면 weltiq 가 슬롯 생성을 거절합니다
  3. 중지 조건을 건다 — 최대 손실과 시한을 반드시 지정해야 합니다
  4. 슬롯을 띄운다 — 사람도 이 도구도 꺼져 있어도 슬롯이 1분봉을 보며 규칙을 지킵니다

관측 결과(직접 확인): 슬롯이 실시간 1분봉을 받으며 조건을 계속 평가했습니다. 마지막 확인에서 종가 85,548 대 기준값 87,400 — 조건이 성립하지 않아 진입이 없었습니다. 도구가 지목한 돌파선이 당시 가격보다 2.2% 위였고, 관측 창 안에 닿지 않았습니다. 확인한 뒤 슬롯은 정지·삭제했습니다.

옮겨지지 않은 것

무엇 왜
"정상 배분의 75~85%" 같은 배분 지시 배분은 규칙이 아닙니다. 도구 성질이고 12편에도 같은 줄이 있습니다
완결된 주문 (매도 0.05 BTC, 지정가 87,400, 손절 92,000) 현금에서 시작하는 현물 슬롯은 보유가 없으면 매도할 수 없습니다
확신도 값 아래를 보세요

확신도에 대해 한 줄. 이 도구의 주문 검증기에는 confidence 칸이 있고 0.60 미만이면 주문을 거절합니다. 그런데 그 값은 열한 명의 토론에서 나오지 않습니다. 판정문을 별도의 모델이 다시 읽어 뽑아내고, "값이 언급되지 않았으면 합리적으로 추정하라"고 지시받습니다. 실제로 돌려 보니 0.82~0.86 이 나왔는데, 어떤 에이전트도 그런 숫자를 말한 적이 없습니다. 수량(0.05 BTC)도 마찬가지입니다. 판정문에 없는 숫자는 근거로 쓰지 마세요.


6. 써 보니

좋았던 것

아쉬운 것

비용

항목 값
코드 무료 (Apache-2.0)
모델 판당 $0.0323 실측 (openai/gpt-5.6-luna, 입력 약 7.5만 · 출력 약 1.4만 토큰)
시세 (Binance) 무료, 키 불필요
뉴스 (CoinGecko) 무료. 이 글을 쓰는 동안 404/429 로 자주 비었습니다
아홉 판 총계 $0.29

7. 다음 행동

이 도구를 지금 쓰실 생각이라면 원본을 쓰세요. 원본도 크립토를 지원하고, 4개월 더 고쳐졌고, 자산 종류를 스스로 알아봅니다. 12편 이 그 설치 안내입니다.

가져가실 것은 도구가 아니라 방법입니다. 오픈소스를 다른 시장으로 옮긴 판을 만나면 셋을 먼저 확인하세요. ① 패키지 버전이 원본의 언제 판인가 — 갈라진 뒤 원본이 고친 것은 안 들어옵니다. ② 기본값이 어디를 보는가 — 테스트넷이 조용히 돌면 알 수 없습니다. ③ 사람이 들어가는 문이 새 시장을 아는가 — 이식이 끝났다면 첫 화면의 예시부터 바뀌어 있어야 합니다.

그리고 판단을 내는 도구는 한 판으로 성격을 적지 마세요. 아홉 판을 돌린 이유이고, 그 아홉 판이 원본의 열세 판과 같은 것을 말해 줬습니다.

다음 편은 같은 계열을 미국 주식에서 다시 봅니다 — 레벨과 무효 조건을 처음부터 구조화해 내는 도구가 어떻게 다른지 나란히 놓습니다.

weltiq 준비

이 도구의 판정을 규칙으로 옮겨 24시간 돌려 보고 싶으시다면:

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

주문은 전부 모의입니다.


이 글의 상세 검증 기록 — 열두 판의 판정 원문, 원본과의 소스 대조, 결함 목록, 우회 과정 전부는 reports/a/28-trading-bot-agent/ 에 있습니다.