upbit-mcp-sse

restful3/upbit-mcp-sse

3.2

If you are the rightful owner of upbit-mcp-sse and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

This project is an implementation of an MCP (Model Context Protocol) server for the Upbit cryptocurrency exchange OpenAPI.

Tools
  1. get_ticker

    Retrieves current price information for a specific cryptocurrency market.

  2. get_orderbook

    Fetches real-time bid/ask order book information for a specific market.

  3. get_trades

    Retrieves the most recent trade details for a specific market.

  4. get_accounts

    Fetches the user's total account balance and asset information.

  5. create_order

    Creates a buy/sell order at a specified price or market price.

Upbit MCP ์„œ๋ฒ„

์ด ํ”„๋กœ์ ํŠธ๋Š” Upbit ์•”ํ˜ธํ™”ํ ๊ฑฐ๋ž˜์†Œ OpenAPI๋ฅผ ์œ„ํ•œ MCP(Model Context Protocol) ์„œ๋ฒ„ ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค. Upbit ๊ฑฐ๋ž˜์†Œ์˜ ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค(์‹œ์„ธ, ํ˜ธ๊ฐ€์ฐฝ, ์ฒด๊ฒฐ ๋‚ด์—ญ, ์ฐจํŠธ ๋ฐ์ดํ„ฐ ์กฐํšŒ, ๊ณ„์ • ์ •๋ณด ํ™•์ธ, ์ฃผ๋ฌธ ์ƒ์„ฑ ๋ฐ ์ทจ์†Œ, ์ž…์ถœ๊ธˆ ๊ด€๋ฆฌ, ๊ธฐ์ˆ ์  ๋ถ„์„ ๋“ฑ)์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ณธ ํ”„๋กœ์ ํŠธ๋Š” solangii/upbit-mcp-server๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์›๋ณธ ํ”„๋กœ์ ํŠธ๋Š” MCP stdio ํ†ต์‹  ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋˜์–ด n8n๊ณผ ๊ฐ™์€ ์›Œํฌํ”Œ๋กœ์šฐ ์ž๋™ํ™” ๋„๊ตฌ์™€์˜ ์ง์ ‘์ ์ธ ์—ฐ๋™์— ์–ด๋ ค์›€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฒ„์ „์€ n8n๊ณผ์˜ ์›ํ™œํ•œ ์—ฐ๋™์„ ์œ„ํ•ด SSE(Server-Sent Events)๋ฅผ ์ง€์›ํ•˜๋„๋ก ํ•ต์‹ฌ ๋กœ์ง์ด ์ˆ˜์ •๋˜์—ˆ์œผ๋ฉฐ, Docker ๋ฐ Docker Compose๋ฅผ ํ™œ์šฉํ•œ ๋ฐฐํฌ ๋ฐฉ์‹์„ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, FastMCP 1.0.0 ๋ฒ„์ „์— ๋งž๊ฒŒ ๋‚ด๋ถ€ ๋กœ์ง ๋ฐ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ๊ฐœ์„ ๋˜์—ˆ๊ณ , ๊ธฐ์ˆ ์  ๋ถ„์„ ๋„๊ตฌ์˜ ์ •ํ™•์„ฑ๊ณผ ์•ˆ์ •์„ฑ์ด ํ–ฅ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ

  • ์‹ค์‹œ๊ฐ„ ์‹œ์žฅ ๋ฐ์ดํ„ฐ ์กฐํšŒ (ํ˜„์žฌ๊ฐ€, ํ˜ธ๊ฐ€์ฐฝ, ์ตœ๊ทผ ์ฒด๊ฒฐ ๋‚ด์—ญ, ์บ”๋“ค ๋ฐ์ดํ„ฐ ๋“ฑ)
  • ๊ณ„์ • ์ •๋ณด ํ™•์ธ (์ „์ฒด ์ž”๊ณ , ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ, ๊ฐœ๋ณ„ ์ฃผ๋ฌธ ์ƒ์„ธ, ์ž…์ถœ๊ธˆ ๋‚ด์—ญ ๋“ฑ)
  • ์ฃผ๋ฌธ ์‹คํ–‰ ๋ฐ ์ทจ์†Œ (์ง€์ •๊ฐ€/์‹œ์žฅ๊ฐ€ ์ฃผ๋ฌธ, ์ฃผ๋ฌธ ์ทจ์†Œ)
  • ๊ธฐ์ˆ ์  ๋ถ„์„ ์ง€ํ‘œ ๋ฐ ์‹ ํ˜ธ ์ œ๊ณต (EMA ๊ธฐ๋ฐ˜ MACD ๊ณ„์‚ฐ, API ์—”๋“œํฌ์ธํŠธ ์ˆ˜์ • ๋“ฑ ์ •ํ™•๋„ ํ–ฅ์ƒ)
  • ๋ฐฑํ…Œ์ŠคํŒ… ์‹œ์Šคํ…œ (SMA, RSI, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ, MACD ์ „๋žต ์ง€์›, ์ž์—ฐ์–ด ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ)
  • ์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๊ธฐ๋Šฅ (์บ”๋“ค์Šคํ‹ฑ, ๋ผ์ธ, OHLC ์ฐจํŠธ ์ง€์›, ๋‚ ์งœ ๋ฒ”์œ„ ์ง€์ • ๊ฐ€๋Šฅ, ์›น ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€ URL ์ œ๊ณต)
  • LLM ์—์ด์ „ํŠธ์˜ ๋‹ต๋ณ€ ๋ฐ ํ–‰๋™์„ ๊ฐ€์ด๋“œํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กฌํ”„ํŠธ ๋ฐ ๋ฆฌ์†Œ์Šค ์ œ๊ณต
  • FastMCP 1.0.0 ๊ธฐ๋ฐ˜์˜ SSE(Server-Sent Events) ํ†ต์‹  ์ง€์›์œผ๋กœ n8n ๋“ฑ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ์œ ์—ฐํ•œ ์—ฐ๋™
  • ์ฃผ์š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ƒ์„ธ ๋กœ๊น… ์ถ”๊ฐ€๋กœ ๋””๋ฒ„๊น… ํŽธ์˜์„ฑ ์ฆ๋Œ€
  • FastMCP 1.0.0 ํ‘œ์ค€์— ๋งž์ถ˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ (ํˆด ์‹คํ–‰ ์˜ค๋ฅ˜ ์‹œ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํฌํ•จํ•œ JSON ๊ฐ์ฒด ๋ฐ˜ํ™˜)

์ œ๊ณต ํˆด (Tools)

๋ณธ MCP ์„œ๋ฒ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํˆด๋“ค์„ ์ œ๊ณตํ•˜์—ฌ LLM ์—์ด์ „ํŠธ๊ฐ€ ์—…๋น„ํŠธ API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

ํˆด ์ด๋ฆ„๊ธฐ๋Šฅ ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ (์˜ˆ์‹œ)
get_tickerํŠน์ • ์•”ํ˜ธํ™”ํ ๋งˆ์ผ“์˜ ํ˜„์žฌ ์‹œ์„ธ ์ •๋ณด(๊ฐ€๊ฒฉ, ๋ณ€๋™๋ฅ  ๋“ฑ)๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.symbol="KRW-BTC"
get_orderbookํŠน์ • ๋งˆ์ผ“์˜ ์‹ค์‹œ๊ฐ„ ๋งค์ˆ˜/๋งค๋„ ํ˜ธ๊ฐ€ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.symbol="KRW-BTC"
get_tradesํŠน์ • ๋งˆ์ผ“์˜ ๊ฐ€์žฅ ์ตœ๊ทผ ๋‹จ์ผ ์ฒด๊ฒฐ ๋‚ด์—ญ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. (API ๊ธฐ๋ณธ๊ฐ’)symbol="KRW-BTC"
get_accounts์‚ฌ์šฉ์ž์˜ ์ „์ฒด ๊ณ„์ขŒ ์ž”๊ณ  ๋ฐ ๋ณด์œ  ์ž์‚ฐ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.-
create_order์ง€์ •๊ฐ€ ๋˜๋Š” ์‹œ์žฅ๊ฐ€๋กœ ๋งค์ˆ˜/๋งค๋„ ์ฃผ๋ฌธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.market, side, ord_type, volume, price
get_orders์‚ฌ์šฉ์ž์˜ ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.market (์„ ํƒ)
get_orderํŠน์ • ์ฃผ๋ฌธ์˜ ์ƒ์„ธ ๋‚ด์—ญ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.uuid
cancel_orderํŠน์ • ์ฃผ๋ฌธ์„ ์ทจ์†Œํ•ฉ๋‹ˆ๋‹ค.uuid
get_market_summaryKRW ์ „์ฒด ๋งˆ์ผ“์˜ ํ˜„์žฌ ์ƒํ™ฉ์„ ๋™์ ์œผ๋กœ ์š”์•ฝํ•˜์—ฌ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.major_n, top_n, sort_by
get_deposits_withdrawals์‚ฌ์šฉ์ž์˜ ์ž…์ถœ๊ธˆ ๋‚ด์—ญ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.currency (์„ ํƒ)
get_markets์—…๋น„ํŠธ์—์„œ ๊ฑฐ๋ž˜ ๊ฐ€๋Šฅํ•œ ์ „์ฒด ๋งˆ์ผ“ ์ฝ”๋“œ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.-
get_candles์ง€์ •๋œ ๋งˆ์ผ“์˜ ์บ”๋“ค(์‹œ๊ณ ์ €์ข…) ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.market, interval, count
create_withdraw๋””์ง€ํ„ธ ์ž์‚ฐ ๋˜๋Š” ์›ํ™” ์ถœ๊ธˆ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.currency, amount, address
technical_analysis์ง€์ •๋œ ๋งˆ์ผ“๊ณผ ์ธํ„ฐ๋ฒŒ์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ๊ธฐ์ˆ ์  ์ง€ํ‘œ ๋ฐ ๋ถ„์„ ์‹ ํ˜ธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (API ์—”๋“œํฌ์ธํŠธ ์ˆ˜์ • ๋ฐ MACD ๊ณ„์‚ฐ ๋กœ์ง ๊ฐœ์„ )market, interval
backtesting์ง€์ •๋œ ์ „๋žต์œผ๋กœ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•œ ๋ฐฑํ…Œ์ŠคํŒ…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์„ฑ๊ณผ ์ง€ํ‘œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (SMA, RSI, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ, MACD ์ „๋žต ์ง€์›)market, strategy_type, start_date, end_date, strategy_params
generate_chart_image์ง€์ •๋œ ๋งˆ์ผ“์˜ ์ฐจํŠธ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์›น ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ URL์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (์บ”๋“ค์Šคํ‹ฑ, ๋ผ์ธ, OHLC ์ฐจํŠธ, ๋‚ ์งœ ๋ฒ”์œ„ ์ง€์ • ๊ฐ€๋Šฅ)market, interval, chart_type, start_date, end_date

์ œ๊ณต ํ”„๋กฌํ”„ํŠธ (Prompts)

LLM ์—์ด์ „ํŠธ๊ฐ€ ํŠน์ • ์ƒํ™ฉ์— ๋” ์ ์ ˆํ•˜๊ฒŒ ์‘๋‹ตํ•˜๊ฑฐ๋‚˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์•ˆ๋‚ดํ•˜๋Š” ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กฌํ”„ํŠธ ์ด๋ฆ„๊ธฐ๋Šฅ ์„ค๋ช…
explain_tickerget_ticker๋กœ ์–ป์€ ์‹œ์„ธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•œ ํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
analyze_portfolioget_accounts๋กœ ์–ป์€ ๊ณ„์ขŒ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํฌํŠธํด๋ฆฌ์˜ค ๋ถ„์„์„ ์š”์ฒญํ•˜๋Š” ํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
order_helpcreate_order ํˆด ์‚ฌ์šฉ๋ฒ• ๋ฐ ์ฃผ๋ฌธ ๊ด€๋ จ ๋„์›€๋ง์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
trading_strategyํŠธ๋ ˆ์ด๋”ฉ ์ „๋žต ์ˆ˜๋ฆฝ ๊ณผ์ •์„ ์•ˆ๋‚ดํ•˜๊ณ  ๊ด€๋ จ ํˆด ์‚ฌ์šฉ์„ ์œ ๋„ํ•˜๋Š” ํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
backtesting_guide์ž์—ฐ์–ด ๋ฐฑํ…Œ์ŠคํŒ… ์š”์ฒญ์„ ํˆด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฐ€์ด๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ œ๊ณต ๋ฆฌ์†Œ์Šค (Resources)

MCP ํด๋ผ์ด์–ธํŠธ๋‚˜ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ์ •์  ๋˜๋Š” ๋™์  ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค URI์ œ๊ณต ๋ฐ์ดํ„ฐ๊ด€๋ จ ํˆด/๊ธฐ๋Šฅ
market://list์—…๋น„ํŠธ์—์„œ ๊ฑฐ๋ž˜ ๊ฐ€๋Šฅํ•œ ์ „์ฒด ๋งˆ์ผ“ ์ฝ”๋“œ ๋ชฉ๋กget_market_list.py

๊ธฐ์ˆ ์  ๋ถ„์„ ๋„๊ตฌ ์ƒ์„ธ

tools/technical_analysis.py ์—์„œ ์ œ๊ณตํ•˜๋Š” technical_analysis ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์˜ ๊ธฐ์ˆ ์  ์ง€ํ‘œ ๋ฐ ๋ถ„์„ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์บ”๋“ค ๋ฐ์ดํ„ฐ ์กฐํšŒ ์‹œ Upbit API์˜ ์ •ํ™•ํ•œ ์—”๋“œํฌ์ธํŠธ(์ผ/์ฃผ/์›”๋ด‰์˜ ๊ฒฝ์šฐ /candles/days, /candles/weeks, /candles/months ์‚ฌ์šฉ)๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •๋˜์—ˆ์œผ๋ฉฐ, MACD ๊ณ„์‚ฐ ์‹œ ๋‹จ์ˆœ ์ด๋™ ํ‰๊ท (SMA) ๋Œ€์‹  ์ง€์ˆ˜ ์ด๋™ ํ‰๊ท (EMA)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •ํ™•๋„๋ฅผ ๋†’์˜€์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ ๋ถ„๋ฅ˜์„ธ๋ถ€ ์ง€ํ‘œ/ํ•ญ๋ชฉ๊ธฐ๋ณธ ์„ค์ •/์ฐธ๊ณ ์ œ๊ณต ์‹ ํ˜ธ
์บ”๋“ค ๋ฐ์ดํ„ฐ์ง€์ •๋œ ๋งˆ์ผ“ ๋ฐ ์ธํ„ฐ๋ฒŒ์˜ ์บ”๋“ค ์กฐํšŒUpbit API ์‚ฌ์šฉ (๊ธฐ๋ณธ 200๊ฐœ, ์ •ํ™•ํ•œ ์—”๋“œํฌ์ธํŠธ ์‚ฌ์šฉ)-
์ด๋™ ํ‰๊ท ์„  (SMA)20, 50, 200์ผ(์ถฉ๋ถ„ํ•œ ๋ฐ์ดํ„ฐ ์‹œ) ๋‹จ์ˆœ ์ด๋™ ํ‰๊ท "bullish", "bearish", "neutral"
์ƒ๋Œ€๊ฐ•๋„์ง€์ˆ˜ (RSI)14์ผ RSI"overbought", "oversold", "neutral"
๋ณผ๋ฆฐ์ € ๋ฐด๋“œ20์ผ ๊ธฐ์ค€ ์ค‘๊ฐ„, ์ƒ๋‹จ, ํ•˜๋‹จ ๋ฐด๋“œ"overbought", "oversold", "neutral"
MACDMACD ์„  (12, 26์ผ EMA), ์‹ ํ˜ธ์„  (9์ผ EMA), ํžˆ์Šคํ† ๊ทธ๋žจEMA ๊ธฐ๋ฐ˜ ๊ณ„์‚ฐ"bullish", "bearish", "neutral"
๊ฑฐ๋ž˜๋Ÿ‰ ๋ถ„์„ํ˜„์žฌ ๊ฑฐ๋ž˜๋Ÿ‰, 20์ผ ํ‰๊ท  ๊ฑฐ๋ž˜๋Ÿ‰, ๋น„์œจ"high", "low", "neutral"
์ข…ํ•ฉ ์‹ ํ˜ธํˆฌ์ž ํŒ๋‹จ ๋ณด์กฐ ์‹ ํ˜ธ์—ฌ๋Ÿฌ ์ง€ํ‘œ ์‹ ํ˜ธ ์ข…ํ•ฉ (MA, RSI, BB, MACD ๊ธฐ๋ฐ˜)"strong_buy", "buy", "strong_sell", "sell", "neutral"

์ฐธ๊ณ : technical_analysis ํ•จ์ˆ˜๋Š” market (์˜ˆ: "KRW-BTC") ๋ฐ interval (์˜ˆ: "day", "minute60")์„ ์ธ์ž๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ œ๊ณต๋˜๋Š” ์‹ ํ˜ธ๋Š” ํˆฌ์ž ๊ฒฐ์ •์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์ž๋ฃŒ์ด๋ฉฐ, ์‹ค์ œ ํˆฌ์ž๋Š” ์‚ฌ์šฉ์ž์˜ ์‹ ์ค‘ํ•œ ํŒ๋‹จ ํ•˜์— ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋ถ€์กฑ ์‹œ ์ง€ํ‘œ ๊ฐ’์€ "N/A"๋กœ ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฑํ…Œ์ŠคํŒ… ๋„๊ตฌ ์ƒ์„ธ

tools/backtesting.py์—์„œ ์ œ๊ณตํ•˜๋Š” backtesting ํ•จ์ˆ˜๋Š” ๋‹ค์–‘ํ•œ ๊ฑฐ๋ž˜ ์ „๋žต์„ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ์— ์ ์šฉํ•˜์—ฌ ์„ฑ๊ณผ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ณ  ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. 2025๋…„ 1์›” ๊ธฐ์ค€์œผ๋กœ ์™„์ „ํžˆ ๊ตฌํ˜„๋˜์–ด ๋ชจ๋“  ์ฃผ์š” ๊ธฐ๋Šฅ์ด ์ •์ƒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ง€์›ํ•˜๋Š” ๋ฐฑํ…Œ์ŠคํŒ… ์ „๋žต

์ „๋žต ํƒ€์ž…์ „๋žต๋ช…์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
sma_crossoverSMA ๊ต์ฐจ ์ „๋žต๋‹จ๊ธฐ/์žฅ๊ธฐ ์ด๋™ํ‰๊ท ์„ ์˜ ๊ณจ๋“ ํฌ๋กœ์Šค/๋ฐ๋“œํฌ๋กœ์Šค ๊ธฐ๋ฐ˜ ๋งค๋งคfast_period, slow_period
rsi_oversoldRSI ๊ณผ๋งค๋„/๊ณผ๋งค์ˆ˜ ์ „๋žตRSI ์ง€ํ‘œ์˜ ๊ณผ๋งค๋„/๊ณผ๋งค์ˆ˜ ๊ตฌ๊ฐ„ ์ง„์ž… ์‹œ ๋งค๋งคrsi_period, oversold_threshold, overbought_threshold
bollinger_bands๋ณผ๋ฆฐ์ € ๋ฐด๋“œ ์ „๋žต๋ณผ๋ฆฐ์ € ๋ฐด๋“œ ๋‚ด ์ƒ๋Œ€์  ์œ„์น˜ ๊ธฐ๋ฐ˜ ๋งค๋งคperiod, std_dev, buy_threshold, sell_threshold
macd_signalMACD ์‹ ํ˜ธ์„  ์ „๋žตMACD์„ ๊ณผ ์‹ ํ˜ธ์„ ์˜ ๊ต์ฐจ ๊ธฐ๋ฐ˜ ๋งค๋งคfast_period, slow_period, signal_period

์ง€์›ํ•˜๋Š” ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ

  • ๋ถ„๋ด‰: 1๋ถ„(minute1), 3๋ถ„(minute3), 5๋ถ„(minute5), 10๋ถ„(minute10), 15๋ถ„(minute15), 30๋ถ„(minute30)
  • ์‹œ๊ฐ„๋ด‰: 1์‹œ๊ฐ„(minute60), 4์‹œ๊ฐ„(minute240)
  • ์ผ๋ด‰: day
  • ์ฃผ๋ด‰: week
  • ์›”๋ด‰: month

์ œ๊ณตํ•˜๋Š” ์„ฑ๊ณผ ์ง€ํ‘œ

๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒ์„ธํ•œ ์„ฑ๊ณผ ์ง€ํ‘œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

์ง€ํ‘œ ๋ถ„๋ฅ˜์„ธ๋ถ€ ์ง€ํ‘œ์„ค๋ช…
ํฌํŠธํด๋ฆฌ์˜ค ์š”์•ฝinitial_capital์ดˆ๊ธฐ ์ž๋ณธ๊ธˆ
final_cash_balance์ตœ์ข… ํ˜„๊ธˆ ์ž”๊ณ 
final_asset_quantity์ตœ์ข… ์ž์‚ฐ ๋ณด์œ ๋Ÿ‰
final_asset_price์ตœ์ข… ์ž์‚ฐ ๊ฐ€๊ฒฉ
final_asset_value์ตœ์ข… ์ž์‚ฐ ํ‰๊ฐ€๊ฐ€์น˜
final_total_value์ตœ์ข… ์ด ํฌํŠธํด๋ฆฌ์˜ค ๊ฐ€์น˜
absolute_profit์ ˆ๋Œ€ ์ˆ˜์ต ๊ธˆ์•ก
position_statusํฌ์ง€์…˜ ์ƒํƒœ (CASH/HOLDING_ASSET/MIXED)
์ˆ˜์ต๋ฅ  ์ง€ํ‘œtotal_return๋ฐฑํ…Œ์ŠคํŠธ ๊ธฐ๊ฐ„ ์ด ์ˆ˜์ต๋ฅ 
annualized_return์—ฐํ™˜์‚ฐ ์ˆ˜์ต๋ฅ 
realized_return์‹คํ˜„ ์ˆ˜์ต๋ฅ 
unrealized_return๋ฏธ์‹คํ˜„ ์ˆ˜์ต๋ฅ 
์†์ต ๋ถ„์„realized_profit์‹คํ˜„ ์†์ต (์™„๋ฃŒ๋œ ๊ฑฐ๋ž˜์˜ ์†์ต)
unrealized_profit๋ฏธ์‹คํ˜„ ์†์ต (๋ณด์œ  ํฌ์ง€์…˜์˜ ์†์ต)
์œ„ํ—˜ ์ง€ํ‘œvolatility์—ฐ์œจํ™” ๋ณ€๋™์„ฑ
sharpe_ratio์ƒคํ”„ ์ง€์ˆ˜ (์œ„ํ—˜ ๋Œ€๋น„ ์ˆ˜์ต๋ฅ )
max_drawdown์ตœ๋Œ€ ๋‚™ํญ
๊ฑฐ๋ž˜ ์„ฑ๊ณผwin_rate์Šน๋ฅ  (์ˆ˜์ต ๊ฑฐ๋ž˜ ๋น„์œจ)
profit_factorํ”„๋กœํ• ํŒฉํ„ฐ (์ด ์ด์ต/์ด ์†์‹ค)
total_trades์ด ๊ฑฐ๋ž˜ ํšŸ์ˆ˜
์ƒ์„ธ ๋ถ„์„monthly_returns์›”๋ณ„ ์ˆ˜์ต๋ฅ  ์ƒ์„ธ
drawdown_periods์ฃผ์š” ๋“œ๋กœ์šฐ๋‹ค์šด ๊ตฌ๊ฐ„ ๋ถ„์„
trade_history๋ชจ๋“  ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์ƒ์„ธ (๊ฐœ๋ณ„ ๊ฑฐ๋ž˜ ์†์ต ํฌํ•จ)

์ž์—ฐ์–ด ๋ฐฑํ…Œ์ŠคํŒ… ์‚ฌ์šฉ ์˜ˆ์‹œ

backtesting_guide ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ†ตํ•ด ์ž์—ฐ์–ด๋กœ ๋ฐฑํ…Œ์ŠคํŒ…์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

๐Ÿ“ ์‚ฌ์šฉ์ž ์š”์ฒญ ์˜ˆ์‹œ
"๋น„ํŠธ์ฝ”์ธ 20์ผ์„ ๊ณผ 50์ผ์„  ๊ณจ๋“ ํฌ๋กœ์Šค ์ „๋žต์œผ๋กœ 2024๋…„ ์ „์ฒด ๊ธฐ๊ฐ„ ์ผ๋ด‰ ๋ฐฑํ…Œ์ŠคํŒ…ํ•ด์ค˜"
"์ด๋”๋ฆฌ์›€ RSI 14์ผ ๊ณผ๋งค๋„ 25, ๊ณผ๋งค์ˆ˜ 75 ์ „๋žต, 2024๋…„ ํ•˜๋ฐ˜๊ธฐ 4์‹œ๊ฐ„๋ด‰์œผ๋กœ ๋ถ„์„ํ•ด์ค˜"
"๋ฆฌํ”Œ ๋ณผ๋ฆฐ์ €๋ฐด๋“œ 20์ผ 2์‹œ๊ทธ๋งˆ ์ „๋žต์œผ๋กœ 2024๋…„ ์ƒ๋ฐ˜๊ธฐ ๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ ๋ณด์—ฌ์ค˜"
"๋„์ง€์ฝ”์ธ MACD 12-26-9 ์‹ ํ˜ธ์„  ๊ต์ฐจ ์ „๋žต์œผ๋กœ 2024๋…„ 6์›”~12์›” ๋ฐฑํ…Œ์ŠคํŒ… ๋ถ„์„ํ•ด์ค˜"
๐Ÿค– LLM ์—์ด์ „ํŠธ ์‘๋‹ต ์˜ˆ์‹œ (ํ”„๋กฌํ”„ํŠธ ํ™œ์šฉ)

์‚ฌ์šฉ์ž: "๋น„ํŠธ์ฝ”์ธ 20์ผ์„ ๊ณผ 50์ผ์„  ๊ณจ๋“ ํฌ๋กœ์Šค ์ „๋žต์œผ๋กœ 2024๋…„ ์ „์ฒด ๊ธฐ๊ฐ„ ์ผ๋ด‰ ๋ฐฑํ…Œ์ŠคํŒ…ํ•ด์ค˜"

LLM: ๋น„ํŠธ์ฝ”์ธ SMA ๊ต์ฐจ ์ „๋žต ๋ฐฑํ…Œ์ŠคํŒ…์„ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ถ„์„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค:

  • ๋งˆ์ผ“: KRW-BTC
  • ์ „๋žต: SMA ๊ต์ฐจ (20์ผ์„ ๊ณผ 50์ผ์„ )
  • ๊ธฐ๊ฐ„: 2024๋…„ 1์›” 1์ผ ~ 2024๋…„ 12์›” 31์ผ
  • ์‹œ๊ฐ„๊ฐ„๊ฒฉ: ์ผ๋ด‰(day)
{
  "market": "KRW-BTC",
  "strategy_type": "sma_crossover",
  "start_date": "2024-01-01",
  "end_date": "2024-12-31",
  "interval": "day",
  "strategy_params": {
    "fast_period": 20,
    "slow_period": 50
  }
}

์‚ฌ์šฉ์ž: "๋ฆฌํ”Œ ๋ณผ๋ฆฐ์ €๋ฐด๋“œ ์ „๋žต์œผ๋กœ ์ตœ๊ทผ 3๊ฐœ์›” 4์‹œ๊ฐ„๋ด‰ ๋ฐฑํ…Œ์ŠคํŒ…ํ•ด์ค˜"

LLM: ๋ฆฌํ”Œ(XRP) ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ ์ „๋žต ๋ฐฑํ…Œ์ŠคํŒ…์„ ์‹คํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค:

  • ๋งˆ์ผ“: KRW-XRP
  • ์ „๋žต: ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ (๊ธฐ๋ณธ 20์ผ, 2์‹œ๊ทธ๋งˆ)
  • ๊ธฐ๊ฐ„: ์ตœ๊ทผ 3๊ฐœ์›”
  • ์‹œ๊ฐ„๊ฐ„๊ฒฉ: 4์‹œ๊ฐ„๋ด‰
{
  "market": "KRW-XRP",
  "strategy_type": "bollinger_bands",
  "start_date": "2024-10-01",
  "end_date": "2024-12-31",
  "interval": "minute240",
  "strategy_params": {
    "period": 20,
    "std_dev": 2.0,
    "buy_threshold": 0.2,
    "sell_threshold": 0.8
  }
}
๐Ÿ’ก ํ”„๋กฌํ”„ํŠธ ๋ณ€ํ™˜ ๊ฐ€์ด๋“œ

backtesting_guide ํ”„๋กฌํ”„ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž์—ฐ์–ด ํ‘œํ˜„์„ ํˆด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

์ž์—ฐ์–ด ํ‘œํ˜„ํˆด ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€ํ™˜
"20์ผ์„ ๊ณผ 50์ผ์„  ๊ณจ๋“ ํฌ๋กœ์Šค"strategy_type: "sma_crossover", fast_period: 20, slow_period: 50
"RSI ๊ณผ๋งค๋„ 25, ๊ณผ๋งค์ˆ˜ 75"strategy_type: "rsi_oversold", oversold_threshold: 25, overbought_threshold: 75
"๋ณผ๋ฆฐ์ €๋ฐด๋“œ 20์ผ 2์‹œ๊ทธ๋งˆ"strategy_type: "bollinger_bands", period: 20, std_dev: 2.0
"MACD 12-26-9"strategy_type: "macd_signal", fast_period: 12, slow_period: 26, signal_period: 9
"2024๋…„ ์ƒ๋ฐ˜๊ธฐ"start_date: "2024-01-01", end_date: "2024-06-30"
"์ตœ๊ทผ 3๊ฐœ์›”"ํ˜„์žฌ ๋‚ ์งœ ๊ธฐ์ค€ 3๊ฐœ์›” ์ „๋ถ€ํ„ฐ
"4์‹œ๊ฐ„๋ด‰"interval: "minute240"
"์ผ๋ด‰"interval: "day"

๋ฐฑํ…Œ์ŠคํŒ… ์‹œ์Šคํ…œ ํŠน์ง•

  • ์ •ํ™•ํ•œ API ์—ฐ๋™: Upbit API์˜ ๋ชจ๋“  ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ์—”๋“œํฌ์ธํŠธ ์‚ฌ์šฉ
  • ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ: 200๊ฐœ ์ œํ•œ์„ ๋„˜๋Š” ๊ธด ๊ธฐ๊ฐ„ ๋ฐ์ดํ„ฐ๋„ ์ž๋™์œผ๋กœ ์ˆ˜์ง‘
  • ์•ˆ์ •์ ์ธ ๊ณ„์‚ฐ: ๋ฌดํ•œ ๋ฃจํ”„ ๋ฐ API ์˜ค๋ฅ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ ์™„๋ฃŒ
  • ์ƒ์„ธํ•œ ๋ถ„์„: ๋‹จ์ˆœ ์ˆ˜์ต๋ฅ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฆฌ์Šคํฌ ์กฐ์ • ์ง€ํ‘œ๊นŒ์ง€ ์ œ๊ณต
  • ์œ ์—ฐํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ: ๊ฐ ์ „๋žต๋ณ„๋กœ ์„ธ๋ถ€ ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐ์ • ๊ฐ€๋Šฅ
  • ๐Ÿ†• ์™„์ „ํ•œ ํฌํŠธํด๋ฆฌ์˜ค ์ถ”์ : ์ตœ์ข… ์ž”๊ณ , ํฌ์ง€์…˜ ์ƒํƒœ, ์‹คํ˜„/๋ฏธ์‹คํ˜„ ์†์ต ๋ช…ํ™• ํ‘œ์‹œ
  • ๐Ÿ†• ๊ฐœ๋ณ„ ๊ฑฐ๋ž˜ ๋ถ„์„: ๊ฐ ๊ฑฐ๋ž˜์˜ ์†์ต๋ฅ ๊ณผ ํฌํŠธํด๋ฆฌ์˜ค ์˜ํ–ฅ ์ƒ์„ธ ์ œ๊ณต

๊ฐœ์„ ๋œ ๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ ์˜ˆ์‹œ

{
  "portfolio_summary": {
    "initial_capital": 1000000,
    "final_cash_balance": 0,
    "final_asset_quantity": 0.00899,
    "final_asset_price": 139300000,
    "final_asset_value": 1252507,
    "final_total_value": 1252507,
    "absolute_profit": 252507,
    "position_status": "HOLDING_ASSET",
    "realized_profit": -218101,
    "unrealized_profit": 470608,
    "realized_return": -0.218,
    "unrealized_return": 0.471
  },
  "performance_metrics": {
    "total_return": 0.2525,
    "annualized_return": 0.2971,
    "volatility": 0.2554,
    "sharpe_ratio": 1.16,
    "max_drawdown": -0.2928,
    "win_rate": 0.0,
    "profit_factor": 0,
    "total_trades": 5
  },
  "trade_history": [
    {
      "date": "2024-05-30",
      "action": "BUY",
      "price": 94593000,
      "quantity": 0.01053,
      "commission": 500,
      "portfolio_value": 995500,
      "trade_profit": 0,
      "trade_return": 0
    },
    {
      "date": "2024-06-26", 
      "action": "SELL",
      "price": 86027000,
      "quantity": 0.01053,
      "commission": 453,
      "portfolio_value": 905185,
      "trade_profit": -90315,
      "trade_return": -0.096
    }
  ]
}

์ด์ œ **"์ดˆ๊ธฐ ์ž๋ณธ 1,000,000์›์œผ๋กœ ์‹œ์ž‘ํ•ด์„œ ์ตœ์ข…์ ์œผ๋กœ 1,252,507์›์ด ๋˜์—ˆ๋‹ค"**๋Š” ๊ฒƒ์„ ๋ช…ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

โš ๏ธ ๋ฉด์ฑ… ์กฐํ•ญ: ๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ๋Š” ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด๋ฉฐ, ๋ฏธ๋ž˜ ์ˆ˜์ต์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ํˆฌ์ž ๊ฒฐ์ •์€ ์‹ ์ค‘ํ•œ ํŒ๋‹จ ํ•˜์— ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋„๊ตฌ ์ƒ์„ธ

tools/generate_chart_image.py์—์„œ ์ œ๊ณตํ•˜๋Š” generate_chart_image ํ•จ์ˆ˜๋Š” ์ง€์ •๋œ ๋งˆ์ผ“์˜ ์‹œ๊ฐ์  ์ฐจํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์›น์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€ URL์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. 2025๋…„ 1์›” ๊ธฐ์ค€์œผ๋กœ ์™„์ „ํžˆ ๊ตฌํ˜„๋˜์–ด ๋ชจ๋“  ์ฃผ์š” ๊ธฐ๋Šฅ์ด ์ •์ƒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ง€์›ํ•˜๋Š” ์ฐจํŠธ ๊ธฐ๋Šฅ

๊ธฐ๋Šฅ ๋ถ„๋ฅ˜์„ธ๋ถ€ ์˜ต์…˜์„ค๋ช…๊ธฐ๋ณธ๊ฐ’
์ฐจํŠธ ํƒ€์ž…candlestick์บ”๋“ค์Šคํ‹ฑ ์ฐจํŠธ (์‹œ๊ฐ€, ๊ณ ๊ฐ€, ์ €๊ฐ€, ์ข…๊ฐ€ ํ‘œ์‹œ)โœ… ๊ธฐ๋ณธ๊ฐ’
line๋ผ์ธ ์ฐจํŠธ (์ข…๊ฐ€๋งŒ ํ‘œ์‹œ)
ohlcOHLC ๋ฐ” ์ฐจํŠธ (์‹œ๊ณ ์ €์ข… ํ‘œ์‹œ)
์‹œ๊ฐ„ ๊ฐ„๊ฒฉminute1 ~ minute2401๋ถ„๋ด‰๋ถ€ํ„ฐ 4์‹œ๊ฐ„๋ด‰๊นŒ์ง€day
day, week, month์ผ๋ด‰, ์ฃผ๋ด‰, ์›”๋ด‰
๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜countํ‘œ์‹œํ•  ์บ”๋“ค ๊ฐœ์ˆ˜ (10~200๊ฐœ)100๊ฐœ
๋‚ ์งœ ๋ฒ”์œ„start_date์‹œ์ž‘ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹)์—†์Œ (์ตœ์‹  ๋ฐ์ดํ„ฐ)
end_date์ข…๋ฃŒ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹)์—†์Œ (์ตœ์‹  ๋ฐ์ดํ„ฐ)
์ถ”๊ฐ€ ์ง€ํ‘œinclude_volume๊ฑฐ๋ž˜๋Ÿ‰ ์ฐจํŠธ ํฌํ•จ ์—ฌ๋ถ€โœ… ํฌํ•จ
include_ma์ด๋™ํ‰๊ท ์„ (MA20, MA50) ํฌํ•จ ์—ฌ๋ถ€โœ… ํฌํ•จ

์ฐจํŠธ ์ƒ์„ฑ ํ”Œ๋กœ์šฐ

  1. ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘: Upbit API์—์„œ ์ง€์ •๋œ ๋งˆ์ผ“๊ณผ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์˜ ์บ”๋“ค ๋ฐ์ดํ„ฐ ์กฐํšŒ
  2. ๋‚ ์งœ ํ•„ํ„ฐ๋ง: start_date์™€ end_date๊ฐ€ ์ง€์ •๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฒ”์œ„์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœ
  3. ์ฐจํŠธ ์ƒ์„ฑ: Matplotlib์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ๊ฐ์  ์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
    • ์บ”๋“ค์Šคํ‹ฑ/๋ผ์ธ/OHLC ์ฐจํŠธ
    • ๊ฑฐ๋ž˜๋Ÿ‰ ์„œ๋ธŒ์ฐจํŠธ (์„ ํƒ ์‹œ)
    • ์ด๋™ํ‰๊ท ์„  ์˜ค๋ฒ„๋ ˆ์ด (์„ ํƒ ์‹œ)
  4. ํŒŒ์ผ ์ €์žฅ: /app/uploads/charts/ ๋””๋ ‰ํ† ๋ฆฌ์— PNG ํŒŒ์ผ๋กœ ์ €์žฅ
  5. URL ๋ฐ˜ํ™˜: https://charts.resteful3.shop/ํŒŒ์ผ๋ช….png ํ˜•ํƒœ์˜ ์›น ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ URL ์ œ๊ณต

์ฐจํŠธ ์ด๋ฏธ์ง€ ์ ‘๊ทผ

์ƒ์„ฑ๋œ ์ฐจํŠธ๋Š” ๋ณ„๋„ ์„œ๋ธŒ๋„๋ฉ”์ธ์„ ํ†ตํ•ด ์›น์—์„œ ๋ฐ”๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๋„๋ฉ”์ธ: charts.resteful3.shop
  • SSL ์ธ์ฆ์„œ: Let's Encrypt ์ž๋™ ๊ฐฑ์‹ 
  • CORS ์„ค์ •: ๋ชจ๋“  ๋„๋ฉ”์ธ์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅ
  • ์บ์‹œ ์„ค์ •: 1์‹œ๊ฐ„ ์บ์‹œ๋กœ ์„ฑ๋Šฅ ์ตœ์ ํ™”

์‚ฌ์šฉ ์˜ˆ์‹œ

๐Ÿ“ ๊ธฐ๋ณธ ์ฐจํŠธ ์ƒ์„ฑ
{
  "market": "KRW-BTC",
  "interval": "day",
  "chart_type": "candlestick",
  "count": 100
}
๐Ÿ“… ๋‚ ์งœ ๋ฒ”์œ„ ์ง€์ • ์ฐจํŠธ
{
  "market": "KRW-BTC", 
  "interval": "day",
  "chart_type": "candlestick",
  "start_date": "2024-06-01",
  "end_date": "2024-12-31",
  "count": 200
}
๐Ÿ’ฌ ์ž์—ฐ์–ด ์š”์ฒญ ์˜ˆ์‹œ
  • "๋น„ํŠธ์ฝ”์ธ ์ผ๋ด‰ ์บ”๋“ค์Šคํ‹ฑ ์ฐจํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”"
  • "2024๋…„ 6์›”๋ถ€ํ„ฐ 12์›”๊นŒ์ง€ ์ด๋”๋ฆฌ์›€ ์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ์„ธ์š”"
  • "๋ฆฌํ”Œ 4์‹œ๊ฐ„๋ด‰ ๋ผ์ธ ์ฐจํŠธ๋ฅผ ๊ฑฐ๋ž˜๋Ÿ‰๊ณผ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”"
  • "๋„์ง€์ฝ”์ธ 15๋ถ„๋ด‰ ์ฐจํŠธ๋ฅผ ์ด๋™ํ‰๊ท ์„  ์—†์ด ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”"

๊ธฐ์ˆ ์  ์„ธ๋ถ€์‚ฌํ•ญ

  • ์ด๋ฏธ์ง€ ํ˜•์‹: PNG (๊ณ ํ•ด์ƒ๋„ 150 DPI)
  • ์ฐจํŠธ ํฌ๊ธฐ: 12x8 ๋˜๋Š” 12x10 (๊ฑฐ๋ž˜๋Ÿ‰ ํฌํ•จ ์‹œ)
  • ํ•œ๊ธ€ ํฐํŠธ: ์‹œ์Šคํ…œ ๊ธฐ๋ณธ ํฐํŠธ ์‚ฌ์šฉ
  • ์ƒ‰์ƒ ๊ตฌ์„ฑ:
    • ์ƒ์Šน ์บ”๋“ค: ๋นจ๊ฐ„์ƒ‰
    • ํ•˜๋ฝ ์บ”๋“ค: ํŒŒ๋ž€์ƒ‰
    • MA20: ์ฃผํ™ฉ์ƒ‰
    • MA50: ๋นจ๊ฐ„์ƒ‰
  • ํŒŒ์ผ๋ช… ํ˜•์‹: {๋งˆ์ผ“}_{๊ฐ„๊ฒฉ}_{ํƒ€์ž…}_{ํƒ€์ž„์Šคํƒฌํ”„}.png

Docker ํ™˜๊ฒฝ ์„ค์ •

์ฐจํŠธ ์ƒ์„ฑ์„ ์œ„ํ•œ Docker ํ™˜๊ฒฝ์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

# ์˜์กด์„ฑ ํŒจํ‚ค์ง€
matplotlib>=3.7.0
pillow>=10.0.0

# ๋ณผ๋ฅจ ๋งˆ์šดํŠธ
/app/uploads/charts -> Nginx ์ •์  ํŒŒ์ผ ์„œ๋น™

์ฐจํŠธ ๊ธฐ๋Šฅ์˜ ์žฅ์ 

  1. ์ฆ‰์‹œ ์‹œ๊ฐํ™”: ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•… ๊ฐ€๋Šฅํ•œ ์ฐจํŠธ๋กœ ๋ณ€ํ™˜
  2. ์›น ์ ‘๊ทผ์„ฑ: ์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๋กœ ์›น์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ
  3. ์œ ์—ฐํ•œ ์„ค์ •: ๋‹ค์–‘ํ•œ ์ฐจํŠธ ํƒ€์ž…๊ณผ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ์ง€์›
  4. ๋‚ ์งœ ๋ฒ”์œ„: ํŠน์ • ๊ธฐ๊ฐ„์˜ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ ์ฐจํŠธ ์ƒ์„ฑ ๊ฐ€๋Šฅ
  5. ๊ธฐ์ˆ ์  ๋ถ„์„: ์ด๋™ํ‰๊ท ์„ ๊ณผ ๊ฑฐ๋ž˜๋Ÿ‰์œผ๋กœ ์ถ”๊ฐ€ ์ธ์‚ฌ์ดํŠธ ์ œ๊ณต
์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ ๋ชฉ๋ก (์„ธ๋ถ€)
์‹œ์žฅ ๋ฐ์ดํ„ฐ ์กฐํšŒ
  • ํŠน์ • ์•”ํ˜ธํ™”ํ์˜ ํ˜„์žฌ ์‹œ์„ธ(๊ฐ€๊ฒฉ, ๋ณ€๋™๋ฅ  ๋“ฑ) ์กฐํšŒ (get_ticker)
  • ํŠน์ • ๋งˆ์ผ“์˜ ์‹ค์‹œ๊ฐ„ ๋งค์ˆ˜/๋งค๋„ ํ˜ธ๊ฐ€ ์ •๋ณด ์กฐํšŒ (get_orderbook)
  • ํŠน์ • ๋งˆ์ผ“์˜ ๊ฐ€์žฅ ์ตœ๊ทผ ๋‹จ์ผ ์ฒด๊ฒฐ ๋‚ด์—ญ ์กฐํšŒ (get_trades)
  • (get_market_summary๋Š” ํ˜„์žฌ get_ticker์™€ ์œ ์‚ฌ ๊ธฐ๋Šฅ ์ œ๊ณต ๊ฐ€๋Šฅ์„ฑ)
  • ์ง€์ •๋œ ๋งˆ์ผ“์˜ ์บ”๋“ค(์‹œ๊ณ ์ €์ข…) ๋ฐ์ดํ„ฐ ์กฐํšŒ (get_candles)
  • ์ง€์ •๋œ ๋งˆ์ผ“๊ณผ ์ธํ„ฐ๋ฒŒ์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ๊ธฐ์ˆ ์  ์ง€ํ‘œ ๋ฐ ๋ถ„์„ ์‹ ํ˜ธ ํ™•์ธ (technical_analysis)
  • ์‹œ๊ฐ์  ์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ์›น URL ์ œ๊ณต (generate_chart_image)
  • ์—…๋น„ํŠธ ๊ฑฐ๋ž˜ ๊ฐ€๋Šฅ ์ „์ฒด ๋งˆ์ผ“ ์ฝ”๋“œ ๋ชฉ๋ก ํ™•์ธ (get_markets, market://list ๋ฆฌ์†Œ์Šค)
๊ณ„์ • ์ •๋ณด ์กฐํšŒ
  • ์ „์ฒด ๊ณ„์ขŒ ์ž”๊ณ  ๋ฐ ๋ณด์œ  ์ž์‚ฐ ์ •๋ณด ํ™•์ธ (get_accounts)
  • ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํšŒ (get_orders)
  • ํŠน์ • ์ฃผ๋ฌธ์˜ ์ƒ์„ธ ๋‚ด์—ญ ์กฐํšŒ (get_order)
  • ์ž…์ถœ๊ธˆ ๋‚ด์—ญ ์กฐํšŒ (get_deposits_withdrawals)
๊ฑฐ๋ž˜ ๊ธฐ๋Šฅ
  • ์ง€์ •๊ฐ€ ๋˜๋Š” ์‹œ์žฅ๊ฐ€ ๋งค์ˆ˜/๋งค๋„ ์ฃผ๋ฌธ ์ƒ์„ฑ (create_order)
  • ํŠน์ • ์ฃผ๋ฌธ ์ทจ์†Œ (cancel_order)
  • ๋””์ง€ํ„ธ ์ž์‚ฐ ๋˜๋Š” ์›ํ™” ์ถœ๊ธˆ ์š”์ฒญ (create_withdraw)
LLM ์—์ด์ „ํŠธ ๋ณด์กฐ
  • ์‹œ์„ธ ์ •๋ณด ์‚ฌ์šฉ์ž ์„ค๋ช… ์ƒ์„ฑ (explain_ticker ํ”„๋กฌํ”„ํŠธ)
  • ํฌํŠธํด๋ฆฌ์˜ค ๋ถ„์„ ์š”์ฒญ ์ƒ์„ฑ (analyze_portfolio ํ”„๋กฌํ”„ํŠธ)
  • ์ฃผ๋ฌธ ๋ฐฉ๋ฒ• ์•ˆ๋‚ด (order_help ํ”„๋กฌํ”„ํŠธ)
  • ํŠธ๋ ˆ์ด๋”ฉ ์ „๋žต ์ˆ˜๋ฆฝ ๊ฐ€์ด๋“œ (trading_strategy ํ”„๋กฌํ”„ํŠธ)
๋ฐฑํ…Œ์ŠคํŒ… ๋ฐ ์ „๋žต ๋ถ„์„
  • ๋‹ค์–‘ํ•œ ๊ฑฐ๋ž˜ ์ „๋žต์˜ ๊ณผ๊ฑฐ ์„ฑ๊ณผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (backtesting)
  • SMA ๊ต์ฐจ, RSI ๊ณผ๋งค๋„/๊ณผ๋งค์ˆ˜, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ, MACD ์‹ ํ˜ธ์„  ์ „๋žต ์ง€์›
  • ์ƒ์„ธํ•œ ์„ฑ๊ณผ ์ง€ํ‘œ ๋ฐ ์œ„ํ—˜ ๋ถ„์„ (์ˆ˜์ต๋ฅ , ์ƒคํ”„ ์ง€์ˆ˜, ์ตœ๋Œ€ ๋‚™ํญ ๋“ฑ)
  • ์ž์—ฐ์–ด ๋ฐฑํ…Œ์ŠคํŒ… ์š”์ฒญ ์ฒ˜๋ฆฌ (backtesting_guide ํ”„๋กฌํ”„ํŠธ)
์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
  • ์บ”๋“ค์Šคํ‹ฑ, ๋ผ์ธ, OHLC ์ฐจํŠธ ์ƒ์„ฑ (generate_chart_image)
  • ๋‚ ์งœ ๋ฒ”์œ„ ์ง€์ • ๊ฐ€๋Šฅ (๊ณผ๊ฑฐ ํŠน์ • ๊ธฐ๊ฐ„ ์ฐจํŠธ ์ƒ์„ฑ)
  • ๊ฑฐ๋ž˜๋Ÿ‰ ๋ฐ ์ด๋™ํ‰๊ท ์„  ํฌํ•จ/์ œ์™ธ ์„ ํƒ
  • ์›น ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€ URL ์ž๋™ ์ƒ์„ฑ
  • ๋‹ค์–‘ํ•œ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ์ง€์› (1๋ถ„๋ด‰~์›”๋ด‰)
์ฑ„ํŒ… ์˜ˆ์‹œ (์›๋ณธ ํ”„๋กœ์ ํŠธ ๊ธฐ์ค€)

์•„๋ž˜๋Š” ์›๋ณธ ํ”„๋กœ์ ํŠธ([solangii/upbit-mcp-server](https://github.com/solangii/upbit-mcp-server))์˜ ์ฑ„ํŒ… ์˜ˆ์‹œ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ n8n ์—ฐ๋™ ๋ฐ ๊ธฐ๋Šฅ ๊ฐœ์„ ์ด ์ด๋ฃจ์–ด์กŒ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  • main.py: FastMCP ์„œ๋ฒ„์˜ ๋ฉ”์ธ ์‹คํ–‰ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ํˆด, ํ”„๋กฌํ”„ํŠธ, ๋ฆฌ์†Œ์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • config.py: Upbit API ํ‚ค, ๊ธฐ๋ณธ API URL ๋“ฑ์˜ ์„ค์ •์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (์‹ค์ œ ํ‚ค๋Š” .env ํŒŒ์ผ์— ์ €์žฅ)
  • docker-compose.yml: Docker๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ • ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. n8n๊ณผ์˜ ๋„คํŠธ์›Œํฌ ์—ฐ๋™ ์„ค์ • ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • requirements.txt / pyproject.toml / uv.lock: Python ํ”„๋กœ์ ํŠธ์˜ ์˜์กด์„ฑ ํŒจํ‚ค์ง€๋“ค์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (uv ์‚ฌ์šฉ ๊ถŒ์žฅ)
  • .env: Upbit API ํ‚ค์™€ ๊ฐ™์ด ๋ฏผ๊ฐํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ €์žฅํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. (๋ฒ„์ „ ๊ด€๋ฆฌ์—์„œ ์ œ์™ธ๋จ)
  • tools/: ์—…๋น„ํŠธ API ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฐœ๋ณ„ MCP ํˆด ํŒŒ์ด์ฌ ํŒŒ์ผ๋“ค์ด ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: get_ticker.py, create_order.py)
  • prompts/: LLM ์—์ด์ „ํŠธ์˜ ํ–‰๋™์„ ๊ฐ€์ด๋“œํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์ž‘์—… ํ…œํ”Œ๋ฆฟ์„ ์ œ๊ณตํ•˜๋Š” ํ”„๋กฌํ”„ํŠธ ํŒŒ์ด์ฌ ํŒŒ์ผ๋“ค์ด ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: order_help.py)
  • resources/: MCP ์„œ๋ฒ„๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฆฌ์†Œ์Šค(์˜ˆ: ๊ฑฐ๋ž˜ ๊ฐ€๋Šฅ ๋งˆ์ผ“ ๋ชฉ๋ก)๋ฅผ ์ •์˜ํ•˜๋Š” ํŒŒ์ด์ฌ ํŒŒ์ผ๋“ค์ด ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: get_market_list.py)
  • README.md: ๋ณธ ํ”„๋กœ์ ํŠธ ์„ค๋ช… ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

์‚ฌ์ „ ์ค€๋น„ ์‚ฌํ•ญ

์‹œ์ž‘ํ•˜๊ธฐ ์ „์— Upbit API ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  1. Upbit์— ๊ณ„์ •์ด ์—†๋‹ค๋ฉด ๋จผ์ € ํšŒ์›๊ฐ€์ž…์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. Upbit ๊ฐœ๋ฐœ์ž ์„ผํ„ฐ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ƒˆ๋กœ์šด API ํ‚ค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  4. API ํ‚ค์— ํ•„์š”ํ•œ ๊ถŒํ•œ(์กฐํšŒ, ์ฃผ๋ฌธ, ์ถœ๊ธˆ ๋“ฑ)์„ ์ ์ ˆํžˆ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  5. ๋ฐœ๊ธ‰๋ฐ›์€ API ํ‚ค(UPBIT_ACCESS_KEY, UPBIT_SECRET_KEY)๋ฅผ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— .env ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค (์„ค์น˜ ์„น์…˜ ์ฐธ์กฐ).

์„ค์น˜ ๋ฐฉ๋ฒ•

  1. ์ €์žฅ์†Œ ๋ณต์ œ:

    git clone <ํ˜„์žฌ_ํ”„๋กœ์ ํŠธ_์ €์žฅ์†Œ_URL> # ์ด ๋ถ€๋ถ„์€ ์‹ค์ œ ์ €์žฅ์†Œ URL๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.
    cd upbit-mcp-server
    
  2. ์˜์กด์„ฑ ํŒจํ‚ค์ง€ ์„ค์น˜ (uv ๊ถŒ์žฅ): uv๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Python ํ”„๋กœ์ ํŠธ์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋“ค์„ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์„ ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. uv๋Š” ๊ธฐ์กด pip ๋ฐ venv๋ณด๋‹ค ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ์ฃผ์š” ์˜์กด์„ฑ ํŒจํ‚ค์ง€:

    • fastmcp>=0.1.8 (ํ•˜์ง€๋งŒ requirements.txt์—์„œ๋Š” 1.0.0 ์‚ฌ์šฉ)
    • httpx>=0.27.0 (HTTP ํด๋ผ์ด์–ธํŠธ)
    • pyjwt (JWT ํ† ํฐ ์ƒ์„ฑ)
    • python-dotenv (ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ด€๋ฆฌ)
    • numpy (๊ธฐ์ˆ ์  ๋ถ„์„)
    • pyupbit (์—…๋น„ํŠธ API ์ง€์›)
    • uvicorn (ASGI ์„œ๋ฒ„)
    • matplotlib>=3.7.0 (์ฐจํŠธ ์ƒ์„ฑ)
    • pillow>=10.0.0 (์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ)

    ๋งŒ์•ฝ uv๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ๋‹ค์Œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋จผ์ € ์„ค์น˜ํ•ด์ฃผ์„ธ์š”:

    # uv ์„ค์น˜ (Linux, macOS, Windows WSL)
    curl -Ls https://astral.sh/uv/install.sh | sh
    
    # Windows (Powershell):
    # irm https://astral.sh/uv/install.ps1 | iex
    
    # ์„ค์น˜ ํ›„, ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์— ๋งž๊ฒŒ PATH ์„ค์ •์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    # (์˜ˆ: ์‰˜ ์„ค์ • ํŒŒ์ผ(~/.bashrc, ~/.zshrc ๋“ฑ)์— export PATH="$HOME/.astral/bin:$PATH" ์ถ”๊ฐ€ ํ›„ source ~/.bashrc ๋˜๋Š” ํ„ฐ๋ฏธ๋„ ์žฌ์‹œ์ž‘)
    # Windows์˜ ๊ฒฝ์šฐ, ์„ค์น˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ PATH๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋ ค๊ณ  ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    

    uv ์„ค์น˜ ํ›„, ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์—ฌ uv.lock ํŒŒ์ผ์— ๋ช…์‹œ๋œ ์ •ํ™•ํ•œ ๋ฒ„์ „์˜ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค:

    uv sync
    

    ์ด ๋ช…๋ น์€ ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ฑฐ๋‚˜ ์ƒ์„ฑํ•˜๋ฉฐ( .venv ํด๋”), ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

    (๋Œ€์•ˆ: ๊ธฐ์กด pip ์‚ฌ์šฉ ์‹œ - ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ)

    # python3 -m venv .venv  # ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ (ํ•„์š”์‹œ)
    # source .venv/bin/activate # ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™” (Linux/macOS)
    # .venv\\Scripts\\activate # ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™” (Windows)
    # pip install -r requirements.txt
    
  3. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •: ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— .env ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ , ๋ฐœ๊ธ‰๋ฐ›์€ Upbit API ํ‚ค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค:

    UPBIT_ACCESS_KEY=์—ฌ๊ธฐ์—_๋ฐœ๊ธ‰๋ฐ›์€_ACCESS_KEY๋ฅผ_์ž…๋ ฅํ•˜์„ธ์š”
    UPBIT_SECRET_KEY=์—ฌ๊ธฐ์—_๋ฐœ๊ธ‰๋ฐ›์€_SECRET_KEY๋ฅผ_์ž…๋ ฅํ•˜์„ธ์š”
    

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ด ์„œ๋ฒ„๋Š” n8n๊ณผ์˜ ์›ํ™œํ•œ ์—ฐ๋™์„ ์œ„ํ•ด Docker Compose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

Docker Compose๋ฅผ ์ด์šฉํ•œ ์‹คํ–‰ (n8n ์—ฐ๋™ ๊ถŒ์žฅ)

  1. docker-compose.yml ์„ค์ • ํ™•์ธ: ํ”„๋กœ์ ํŠธ์— ํฌํ•จ๋œ docker-compose.yml ํŒŒ์ผ์€ Upbit MCP ์„œ๋ฒ„๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ์š” ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

    • ports: ์„œ๋ฒ„์˜ ํฌํŠธ(์˜ˆ: 8001:8001)๋ฅผ ํ˜ธ์ŠคํŠธ ๋จธ์‹ ์— ๋…ธ์ถœ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด๋Š” n8n์ด (ํ˜ธ์ŠคํŠธ๋‚˜ ๋‹ค๋ฅธ Docker ๋„คํŠธ์›Œํฌ์—์„œ ์‹คํ–‰ ์ค‘์ผ ๊ฒฝ์šฐ) ์„œ๋ฒ„์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
    • networks: ์„œ๋ฒ„๋ฅผ ํŠน์ • Docker ๋„คํŠธ์›Œํฌ(์˜ˆ: nginx-n8n-net)์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. n8n๊ณผ ์ด ์„œ๋ฒ„๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ Docker ๋„คํŠธ์›Œํฌ ์ƒ์—์„œ ์ปจํ…Œ์ด๋„ˆ๋กœ ์‹คํ–‰๋  ๋•Œ ์„œ๋กœ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ์ค‘์ธ n8n ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์—ฐ๊ฒฐ๋œ Docker ๋„คํŠธ์›Œํฌ ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•˜๊ฑฐ๋‚˜, ํ•„์š”ํ•œ ๊ฒฝ์šฐ docker-compose.yml ํŒŒ์ผ ๋‚ด์˜ networks ์„น์…˜์„ ์ง์ ‘ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค. (์˜ˆ: nginx-n8n-net -> ์‚ฌ์šฉ์ž์˜ n8n ๋„คํŠธ์›Œํฌ ์ด๋ฆ„)
    • env_file: .env ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
    • volumes: ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์— ๋งˆ์šดํŠธํ•˜์—ฌ, ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ ์—†์ด ์ฝ”๋“œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค (๊ฐœ๋ฐœ ์‹œ ์œ ์šฉ).
  2. ์„œ๋ฒ„ ์‹œ์ž‘:

    docker-compose up -d --build
    

    --build ์˜ต์…˜์€ Docker ์ด๋ฏธ์ง€๋ฅผ ๊ฐ•์ œ๋กœ ๋‹ค์‹œ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋ฅผ ์ค‘์ง€ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

    docker-compose down
    
  3. ๋กœ๊ทธ ํ™•์ธ: ์„œ๋ฒ„ ๋กœ๊ทธ๋Š” ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

    docker-compose logs -f upbit-mcp-server
    

n8n ์—ฐ๋™

์œ„ ์„ค๋ช…๋Œ€๋กœ Upbit MCP ์„œ๋ฒ„๊ฐ€ Docker Compose๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๊ณ  n8n ์ธ์Šคํ„ด์Šค์™€ ๋™์ผํ•œ Docker ๋„คํŠธ์›Œํฌ์— ์—ฐ๊ฒฐ๋˜์—ˆ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด n8n ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค:

  1. n8n ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ HTTP Request ๋…ธ๋“œ ๋˜๋Š” MCP ๊ด€๋ จ ์ปค๋ฎค๋‹ˆํ‹ฐ ๋…ธ๋“œ(์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. SSE ์—”๋“œํฌ์ธํŠธ URL์„ http://upbit_mcp_server:8001/sse๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • upbit_mcp_server: docker-compose.yml์— ์ •์˜๋œ ์„œ๋น„์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. Docker ๋‚ด๋ถ€ DNS๊ฐ€ ์ด ์ด๋ฆ„์„ ๊ณต์œ  ๋„คํŠธ์›Œํฌ ๋‚ด์˜ ์˜ฌ๋ฐ”๋ฅธ ์ปจํ…Œ์ด๋„ˆ IP๋กœ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค.
    • 8001: ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ์„œ๋ฒ„๊ฐ€ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ํฌํŠธ์ž…๋‹ˆ๋‹ค. (ํ˜ธ์ŠคํŠธ ํฌํŠธ์™€ ๋™์ผํ•˜๊ฒŒ ๋งคํ•‘๋œ ๊ฒฝ์šฐ)
    • /sse: FastMCP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ SSE ์ŠคํŠธ๋ฆผ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ฃจํŠธ ๊ฒฝ๋กœ(/)๋กœ ์š”์ฒญ ์‹œ 404 Not Found ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, /sse ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”.
    • ๋งŒ์•ฝ n8n์ด Docker ์™ธ๋ถ€(์˜ˆ: ๋กœ์ปฌ ๋จธ์‹ )์—์„œ ์‹คํ–‰๋˜๊ณ  MCP ์„œ๋ฒ„๋งŒ Docker๋กœ ์‹คํ–‰ ์ค‘์ด๋ผ๋ฉด, URL์€ http://localhost:8001/sse (๋˜๋Š” Docker ํ˜ธ์ŠคํŠธ์˜ IP์™€ ๋…ธ์ถœ๋œ ํฌํŠธ)๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: ํ˜„์žฌ FastMCP import ์˜ค๋ฅ˜๋กœ ์ธํ•ด ์„œ๋ฒ„๊ฐ€ ์ •์ƒ ์‹คํ–‰๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์šฐ์„ ์ ์œผ๋กœ ํ•ด๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰ (Docker ๋ฏธ์‚ฌ์šฉ, ์ง์ ‘ ํ…Œ์ŠคํŠธ์šฉ)

๊ฐœ๋ฐœ ๋˜๋Š” ์ง์ ‘ ํ…Œ์ŠคํŠธ ๋ชฉ์ ์œผ๋กœ Docker ์—†์ด ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

# uv๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™” ๋ฐ ์‹คํ–‰ (๊ถŒ์žฅ)
uv run python main.py

๋˜๋Š” FastMCP์˜ ๊ฐœ๋ฐœ ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (FastMCP < 1.0.0 ์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋˜ ๋ฐฉ์‹, ํ˜„์žฌ ๋ฒ„์ „์—์„œ๋Š” uv run ๋˜๋Š” ์ง์ ‘ ์‹คํ–‰ ๊ถŒ์žฅ):

# fastmcp dev main.py # ์ด ๋ฐฉ์‹์€ FastMCP ๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜: ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ์ง์ ‘ ์‹คํ–‰ ์‹œ, n8n ์ธ์Šคํ„ด์Šค๊ฐ€ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ํ˜ธ์ŠคํŠธ์™€ ํฌํŠธ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. n8n ์—ฐ๋™ ์‹œ์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ Docker๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํŽธ๋ฆฌํ•˜๊ณ  ์•ˆ์ •์ ์ž…๋‹ˆ๋‹ค.

LLM ์—์ด์ „ํŠธ ์—ฐ๋™ ๊ฐ€์ด๋“œ

์ด MCP ์„œ๋ฒ„๋Š” LLM(Large Language Model) ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ์™€ ํšจ๊ณผ์ ์œผ๋กœ ์—ฐ๋™๋˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ๋ณธ ์„œ๋ฒ„์˜ ๊ธฐ๋Šฅ์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ๊ฐ€์ด๋“œ๋ผ์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1. ํˆด(Tool) ์‚ฌ์šฉ ์ดํ•ด

  • ๋ชฉ์  ์ˆ™์ง€: ์œ„์— ์„ค๋ช…๋œ ๊ฐ ํˆด์˜ ๋ชฉ์ , ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ, ๋ฐ˜ํ™˜ ๊ฐ’์„ LLM์ด ์ •ํ™•ํžˆ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋‚˜ ๋ณ„๋„์˜ ํˆด ์‚ฌ์šฉ ๊ฐ€์ด๋“œ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด LLM์—๊ฒŒ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”์ถœ: ์‚ฌ์šฉ์ž์˜ ์ž์—ฐ์–ด ์งˆ๋ฌธ์—์„œ ๊ฐ ํˆด์— ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ •ํ™•ํžˆ ์ถ”์ถœํ•˜๋Š” ๋Šฅ๋ ฅ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, "๋น„ํŠธ์ฝ”์ธ ํ˜„์žฌ๊ฐ€ ์•Œ๋ ค์ค˜"์—์„œ get_ticker ํˆด์˜ symbol ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์œผ๋กœ "KRW-BTC"๋ฅผ ์ถ”๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ ์ ˆํ•œ ํˆด ์„ ํƒ: ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ ์˜๋„์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ํˆด์„ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, "๋น„ํŠธ์ฝ”์ธ ๊ฐ€๊ฒฉ"์€ get_ticker๋ฅผ, "๋น„ํŠธ์ฝ”์ธ ์ตœ๊ทผ ์ฒด๊ฒฐ ๊ธฐ๋ก"์€ get_trades๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ตฌ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ: ํˆด ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด (์˜ˆ: API ํ†ต์‹  ์‹คํŒจ, ์ž˜๋ชป๋œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ), ํˆด์€ ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ ๋‹ด์€ JSON ๊ฐ์ฒด(์˜ˆ: {\"error\": \"์—๋Ÿฌ ๋ฉ”์‹œ์ง€\"})๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. LLM์€ ์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์นœ์ ˆํ•˜๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์š”์ฒญํ•˜๊ฑฐ๋‚˜ ๋Œ€์•ˆ์ ์ธ ํ–‰๋™์„ ์ œ์•ˆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (๊ธฐ์กด UserError ๋ฐœ์ƒ ๋ฐฉ์‹์—์„œ ๋ณ€๊ฒฝ๋จ)

2. ํ”„๋กฌํ”„ํŠธ(Prompt) ํ™œ์šฉ

  • ์ œ๊ณต๋˜๋Š” ํ”„๋กฌํ”„ํŠธ๋“ค(explain_ticker, analyze_portfolio, order_help, trading_strategy)์€ LLM์ด ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹์„ ํ‘œ์ค€ํ™”ํ•˜๊ณ  ์งˆ์„ ๋†’์ด๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด, get_ticker๋กœ ์‹œ์„ธ ์ •๋ณด๋ฅผ ์–ป์€ ํ›„, explain_ticker ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋กœ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ๋ฆฌ์†Œ์Šค(Resource) ํ™œ์šฉ

  • market://list์™€ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ†ตํ•ด ๊ฑฐ๋ž˜ ๊ฐ€๋Šฅํ•œ ๋งˆ์ผ“ ๋ชฉ๋ก ๋“ฑ์˜ ๋™์ ์ธ ์ •๋ณด๋ฅผ ์–ป์–ด ํˆด ์‚ฌ์šฉ ์‹œ ์ •ํ™•ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ์ฐธ๊ณ  ์‚ฌํ•ญ

  • ๋กœ๊น…: ์ฃผ์š” ํ•จ์ˆ˜์˜ ์‹œ์ž‘, API ํ˜ธ์ถœ ์‹œ๋„, ์‘๋‹ต ๊ฒฐ๊ณผ, ์˜ค๋ฅ˜ ๋ฐœ์ƒ ๋“ฑ์˜ ์ƒํ™ฉ์— print(f\"DEBUG_TA: ...\", flush=True) ๋˜๋Š” print(f\"ERROR_TA: ...\", flush=True) ํ˜•ํƒœ์˜ ๋กœ๊ทธ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ํ„ฐ๋ฏธ๋„์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Docker ์‚ฌ์šฉ ์‹œ docker-compose logs -f upbit-mcp-server ๋ช…๋ น์œผ๋กœ ๋กœ๊ทธ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์„ธ์š”.
  • ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ: API ํ˜ธ์ถœ๊ณผ ๊ด€๋ จ๋œ ํˆด ํ•จ์ˆ˜๋“ค(get_ticker, technical_analysis ๋“ฑ)์€ async def๋กœ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ httpx.AsyncClient๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • EMA ๊ณ„์‚ฐ: technical_analysis์—์„œ MACD ๋“ฑ์˜ ์ง€ํ‘œ ๊ณ„์‚ฐ ์‹œ, ์ดˆ๊ธฐ์—๋Š” ๋‹จ์ˆœ ํ‰๊ท (SMA)์œผ๋กœ EMA๋ฅผ ๊ทผ์‚ฌํ–ˆ์ง€๋งŒ, ํ˜„์žฌ๋Š” ๋ณด๋‹ค ํ‘œ์ค€์ ์ธ EMA ๊ณ„์‚ฐ ๋ฐฉ์‹์„ ์ ์šฉํ•˜์—ฌ ์ •ํ™•๋„๋ฅผ ๋†’์˜€์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ด์Šˆ ๋ฐ ํ•ด๊ฒฐ ํ•„์š” ์‚ฌํ•ญ

โœ… ์ตœ๊ทผ ์™„๋ฃŒ๋œ ์ฃผ์š” ๊ธฐ๋Šฅ

  1. ์ฐจํŠธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹œ์Šคํ…œ ๊ตฌ์ถ• ์™„๋ฃŒ

    • tools/generate_chart_image.py ๊ตฌํ˜„
    • Matplotlib ๊ธฐ๋ฐ˜ ์บ”๋“ค์Šคํ‹ฑ/๋ผ์ธ/OHLC ์ฐจํŠธ ์ƒ์„ฑ
    • ๋‚ ์งœ ๋ฒ”์œ„ ์ง€์ • ๊ธฐ๋Šฅ (๊ณผ๊ฑฐ ํŠน์ • ๊ธฐ๊ฐ„ ์ฐจํŠธ ์ƒ์„ฑ ๊ฐ€๋Šฅ)
    • Nginx + SSL ๊ธฐ๋ฐ˜ ์›น ์„œ๋น™ (charts.resteful3.shop)
    • Docker ํ™˜๊ฒฝ ์™„์ „ ๊ตฌ์„ฑ
  2. ๋ฐฑํ…Œ์ŠคํŒ… ์‹œ์Šคํ…œ ์•ˆ์ •ํ™” ์™„๋ฃŒ

    • ๋ชจ๋“  ์ฃผ์š” ์ „๋žต (SMA, RSI, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ, MACD) ์ •์ƒ ์ž‘๋™
    • ์ •ํ™•ํ•œ ํฌํŠธํด๋ฆฌ์˜ค ์ถ”์  ๋ฐ ์†์ต ๊ณ„์‚ฐ
    • ์ž์—ฐ์–ด ์š”์ฒญ ์ฒ˜๋ฆฌ ํ”„๋กฌํ”„ํŠธ ์™„์„ฑ
  3. ๋ฐฑํ…Œ์ŠคํŒ… ์ฐจํŠธ ์‹œ๊ฐํ™” ๊ธฐ๋Šฅ ์™„์„ฑ

    • tools/generate_backtest_chart.py ๊ตฌํ˜„
    • 3๋‹จ ๊ตฌ์„ฑ ์ฐจํŠธ (๊ฐ€๊ฒฉ+๋งค๋งค์‹ ํ˜ธ, ํฌํŠธํด๋ฆฌ์˜ค ๊ฐ€์น˜ ๋ณ€ํ™”, ๊ฑฐ๋ž˜๋Ÿ‰+๊ฑฐ๋ž˜ ์‹œ์ )
    • ๋ฐฑํ…Œ์ŠคํŒ… ์‹คํ–‰ ์‹œ ์ž๋™ ์ฐจํŠธ ์ƒ์„ฑ ์˜ต์…˜ (generate_chart: bool = True)
    • ๋ชจ๋“  ๋งค๋งค ์‹ ํ˜ธ์™€ ํฌํŠธํด๋ฆฌ์˜ค ๋ณ€ํ™”๊ฐ€ ์ •ํ™•ํžˆ ์‹œ๊ฐํ™”๋จ
  4. ๋ฐฑํ…Œ์ŠคํŒ… ์‹œ์Šคํ…œ ์ฃผ์š” ๋ฒ„๊ทธ ์ˆ˜์ •

    • ๋งค๋„ ์ˆ˜๋Ÿ‰ ๊ธฐ๋ก ๋ฌธ์ œ ํ•ด๊ฒฐ: ๋ชจ๋“  ์ „๋žต์—์„œ ๋งค๋„ ์‹œ ์ˆ˜๋Ÿ‰์ด 0์œผ๋กœ ๊ธฐ๋ก๋˜๋˜ ๋ฌธ์ œ ์ˆ˜์ •
    • ํฌํŠธํด๋ฆฌ์˜ค ์š”์•ฝ ๋ˆ„๋ฝ ๋ฌธ์ œ ํ•ด๊ฒฐ: RSI, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ ์ „๋žต์—์„œ portfolio_summary ๊ณ„์‚ฐ ๋ˆ„๋ฝ ์ˆ˜์ •
    • enhance_trade_history ์˜ค๋ฅ˜ ํ•ด๊ฒฐ: 'cash_balance' ํ‚ค ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•˜๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ œ๊ฑฐ
    • MACD ์ „๋žต ์™„์ „ ์ˆ˜์ •: ๋งค๋„ ๋กœ์ง, ํฌํŠธํด๋ฆฌ์˜ค ์š”์•ฝ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ชจ๋‘ ์ •์ƒํ™”
    • ๋ชจ๋“  ๋ฐฑํ…Œ์ŠคํŒ… ์ „๋žต (SMA, RSI, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ, MACD, ๋ธŒ๋ ˆ์ดํฌ์•„์›ƒ)์ด ์™„์ „ํžˆ ์ •์ƒ ์ž‘๋™ ํ™•์ธ

๐Ÿšจ ๊ธด๊ธ‰ ์ˆ˜์ • ํ•„์š”

  1. FastMCP Import ์˜ค๋ฅ˜: main.py์—์„œ from mcp.server.fastmcp import FastMCP, Context ๋ผ์ธ์ด ๋ชจ๋“ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ
  2. ์˜์กด์„ฑ ๋ฒ„์ „ ๋ถˆ์ผ์น˜:
    • requirements.txt: fastmcp==1.0.0
    • pyproject.toml: fastmcp>=0.1.8

๐Ÿ“‹ ํ–ฅํ›„ ๊ฐœ์„  ๋ฐฉํ–ฅ (TODO)

๊ธฐ๋Šฅ ํ™•์žฅ
  • ๋” ๋งŽ์€ ๊ธฐ์ˆ ์  ์ง€ํ‘œ ์ถ”๊ฐ€ (์˜ˆ: Stochastic Oscillator, Ichimoku Cloud ๋“ฑ)
  • ์‹ค์‹œ๊ฐ„ ์›น์†Œ์ผ“ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์› (๋ณ„๋„ ํˆด ๋˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ)
  • ์‚ฌ์šฉ์ž๋ณ„ ์„ค์ • ์ €์žฅ ๊ธฐ๋Šฅ (์˜ˆ: ์„ ํ˜ธํ•˜๋Š” ๊ธฐ์ˆ ์  ์ง€ํ‘œ, ์•Œ๋ฆผ ์„ค์ • ๋“ฑ)
  • ํˆด ํŒŒ๋ผ๋ฏธํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๊ฐ•ํ™”
  • ๋” ๋‹ค์–‘ํ•œ ํ”„๋กฌํ”„ํŠธ ๋ฐ ๋ฆฌ์†Œ์Šค ์ถ”๊ฐ€
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ปค๋ฒ„๋ฆฌ์ง€ ํ™•๋Œ€
์ฐจํŠธ ๊ธฐ๋Šฅ ๊ฐœ์„ 
  • ๋” ๋งŽ์€ ์ฐจํŠธ ํƒ€์ž… ์ถ”๊ฐ€ (ํ—ค์ดํ‚จ ์•„์‹œ, ๋ Œ์ฝ” ์ฐจํŠธ ๋“ฑ)
  • ์ถ”๊ฐ€ ๊ธฐ์ˆ ์  ์ง€ํ‘œ ์˜ค๋ฒ„๋ ˆ์ด (RSI, MACD, ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ ๋“ฑ)
  • ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์ฐจํŠธ ์ง€์› (Plotly ๋“ฑ)
  • ์ฐจํŠธ ์Šคํƒ€์ผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์˜ต์…˜
  • ๋‹ค์ค‘ ๋งˆ์ผ“ ๋น„๊ต ์ฐจํŠธ

๋ผ์ด์„ ์Šค

MIT


โš ๏ธ ๋ฉด์ฑ… ์กฐํ•ญ (DISCLAIMER)

๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ๊ต์œก ๋ฐ ์—ฐ๊ตฌ ๋ชฉ์ ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

๐Ÿšจ ์ค‘์š”ํ•œ ๊ฒฝ๊ณ 

  1. ํˆฌ์ž ์†์‹ค์— ๋Œ€ํ•œ ์ฑ…์ž„ ๋ถ€์ธ

    • ๋ณธ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ํˆฌ์ž ์†์‹ค์— ๋Œ€ํ•ด ๊ฐœ๋ฐœ์ž, ๊ธฐ์—ฌ์ž, ๋ฐฐํฌ์ž๋Š” ์–ด๋– ํ•œ ์ฑ…์ž„๋„ ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • ์•”ํ˜ธํ™”ํ ํˆฌ์ž๋Š” ๋†’์€ ์œ„ํ—˜์„ ์ˆ˜๋ฐ˜ํ•˜๋ฉฐ, ํˆฌ์ž ์›๊ธˆ์˜ ์ „์•ก ์†์‹ค ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ์˜ ํ•œ๊ณ„

    • ๋ฐฑํ…Œ์ŠคํŒ… ๊ฒฐ๊ณผ๋Š” ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด๋ฉฐ, ๋ฏธ๋ž˜ ์ˆ˜์ต์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • ์‹ค์ œ ๊ฑฐ๋ž˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์Šฌ๋ฆฌํ”ผ์ง€, ์œ ๋™์„ฑ ๋ถ€์กฑ, ๊ฑฐ๋ž˜์†Œ ์žฅ์•  ๋“ฑ ๋ฐฑํ…Œ์ŠคํŒ…์—์„œ ๊ณ ๋ ค๋˜์ง€ ์•Š์€ ์š”์†Œ๋“ค์ด ์„ฑ๊ณผ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ์†Œํ”„ํŠธ์›จ์–ด ํ’ˆ์งˆ ๋ณด์ฆ ๋ถ€์ธ

    • ๋ณธ ์†Œํ”„ํŠธ์›จ์–ด๋Š” "์žˆ๋Š” ๊ทธ๋Œ€๋กœ(AS-IS)" ์ œ๊ณต๋˜๋ฉฐ, ๋ช…์‹œ์  ๋˜๋Š” ๋ฌต์‹œ์  ๋ณด์ฆ ์—†์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
    • ์†Œํ”„ํŠธ์›จ์–ด์˜ ์˜ค๋ฅ˜, ๋ฒ„๊ทธ, ๋ณด์•ˆ ์ทจ์•ฝ์ ์œผ๋กœ ์ธํ•œ ์†์‹ค์— ๋Œ€ํ•ด ์ฑ…์ž„์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  4. ์‚ฌ์šฉ์ž ์ฑ…์ž„

    • ๋ณธ ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ์™€ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
    • ์‹ค์ œ ์ž๊ธˆ์„ ํˆฌ์žํ•˜๊ธฐ ์ „์— ๋ชจ์˜ ๊ฑฐ๋ž˜๋‚˜ ์†Œ์•ก ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์‹œ์Šคํ…œ์„ ์ถฉ๋ถ„ํžˆ ์ดํ•ดํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
    • ํˆฌ์ž ๊ฒฐ์ •์€ ์ „์ ์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ์ฑ…์ž„์ด๋ฉฐ, ์ „๋ฌธ๊ฐ€์˜ ์กฐ์–ธ์„ ๊ตฌํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๐Ÿ“‹ ๊ถŒ์žฅ ์‚ฌํ•ญ

  • ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ๊ต์œก ๋ชฉ์ ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  • ์‹ค์ œ ํˆฌ์ž์— ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์ถฉ๋ถ„ํ•œ ๊ฒ€์ฆ๊ณผ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  • ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„ ๋‚ด์—์„œ๋งŒ ํˆฌ์žํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  • ํˆฌ์ž ์ „์— ์ „๋ฌธ๊ฐ€์˜ ์กฐ์–ธ์„ ๊ตฌํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ณธ ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์œ„์˜ ๋ฉด์ฑ… ์กฐํ•ญ์— ๋™์˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.