restful3/upbit-mcp-sse
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.
get_ticker
Retrieves current price information for a specific cryptocurrency market.
get_orderbook
Fetches real-time bid/ask order book information for a specific market.
get_trades
Retrieves the most recent trade details for a specific market.
get_accounts
Fetches the user's total account balance and asset information.
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_summary | KRW ์ ์ฒด ๋ง์ผ์ ํ์ฌ ์ํฉ์ ๋์ ์ผ๋ก ์์ฝํ์ฌ ์ ๊ณตํฉ๋๋ค. | 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_ticker | get_ticker ๋ก ์ป์ ์์ธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉ์์๊ฒ ์ค๋ช
ํ๊ธฐ ์ํ ํ
์คํธ๋ฅผ ์์ฑํฉ๋๋ค. |
analyze_portfolio | get_accounts ๋ก ์ป์ ๊ณ์ข ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ํฌํธํด๋ฆฌ์ค ๋ถ์์ ์์ฒญํ๋ ํ
์คํธ๋ฅผ ์์ฑํฉ๋๋ค. |
order_help | create_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" | |
MACD | MACD ์ (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_crossover | SMA ๊ต์ฐจ ์ ๋ต | ๋จ๊ธฐ/์ฅ๊ธฐ ์ด๋ํ๊ท ์ ์ ๊ณจ๋ ํฌ๋ก์ค/๋ฐ๋ํฌ๋ก์ค ๊ธฐ๋ฐ ๋งค๋งค | fast_period , slow_period |
rsi_oversold | RSI ๊ณผ๋งค๋/๊ณผ๋งค์ ์ ๋ต | RSI ์งํ์ ๊ณผ๋งค๋/๊ณผ๋งค์ ๊ตฌ๊ฐ ์ง์ ์ ๋งค๋งค | rsi_period , oversold_threshold , overbought_threshold |
bollinger_bands | ๋ณผ๋ฆฐ์ ๋ฐด๋ ์ ๋ต | ๋ณผ๋ฆฐ์ ๋ฐด๋ ๋ด ์๋์ ์์น ๊ธฐ๋ฐ ๋งค๋งค | period , std_dev , buy_threshold , sell_threshold |
macd_signal | MACD ์ ํธ์ ์ ๋ต | 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 | ๋ผ์ธ ์ฐจํธ (์ข ๊ฐ๋ง ํ์) | ||
ohlc | OHLC ๋ฐ ์ฐจํธ (์๊ณ ์ ์ข ํ์) | ||
์๊ฐ ๊ฐ๊ฒฉ | minute1 ~ minute240 | 1๋ถ๋ด๋ถํฐ 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) ํฌํจ ์ฌ๋ถ | โ ํฌํจ |
์ฐจํธ ์์ฑ ํ๋ก์ฐ
- ๋ฐ์ดํฐ ์์ง: Upbit API์์ ์ง์ ๋ ๋ง์ผ๊ณผ ์๊ฐ ๊ฐ๊ฒฉ์ ์บ๋ค ๋ฐ์ดํฐ ์กฐํ
- ๋ ์ง ํํฐ๋ง:
start_date
์end_date
๊ฐ ์ง์ ๋ ๊ฒฝ์ฐ ํด๋น ๋ฒ์์ ๋ฐ์ดํฐ๋ง ์ถ์ถ - ์ฐจํธ ์์ฑ: Matplotlib์ ์ฌ์ฉํ์ฌ ์๊ฐ์ ์ฐจํธ ์ด๋ฏธ์ง ์์ฑ
- ์บ๋ค์คํฑ/๋ผ์ธ/OHLC ์ฐจํธ
- ๊ฑฐ๋๋ ์๋ธ์ฐจํธ (์ ํ ์)
- ์ด๋ํ๊ท ์ ์ค๋ฒ๋ ์ด (์ ํ ์)
- ํ์ผ ์ ์ฅ:
/app/uploads/charts/
๋๋ ํ ๋ฆฌ์ PNG ํ์ผ๋ก ์ ์ฅ - 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 ์ ์ ํ์ผ ์๋น
์ฐจํธ ๊ธฐ๋ฅ์ ์ฅ์
- ์ฆ์ ์๊ฐํ: ๋ณต์กํ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ํ์ ๊ฐ๋ฅํ ์ฐจํธ๋ก ๋ณํ
- ์น ์ ๊ทผ์ฑ: ์์ฑ๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐ๋ก ์น์์ ํ์ธ ๊ฐ๋ฅ
- ์ ์ฐํ ์ค์ : ๋ค์ํ ์ฐจํธ ํ์ ๊ณผ ์๊ฐ ๊ฐ๊ฒฉ ์ง์
- ๋ ์ง ๋ฒ์: ํน์ ๊ธฐ๊ฐ์ ๊ณผ๊ฑฐ ๋ฐ์ดํฐ ์ฐจํธ ์์ฑ ๊ฐ๋ฅ
- ๊ธฐ์ ์ ๋ถ์: ์ด๋ํ๊ท ์ ๊ณผ ๊ฑฐ๋๋์ผ๋ก ์ถ๊ฐ ์ธ์ฌ์ดํธ ์ ๊ณต
์ํ ๊ฐ๋ฅํ ๊ธฐ๋ฅ ๋ชฉ๋ก (์ธ๋ถ)
์์ฅ ๋ฐ์ดํฐ ์กฐํ
- ํน์ ์ํธํํ์ ํ์ฌ ์์ธ(๊ฐ๊ฒฉ, ๋ณ๋๋ฅ ๋ฑ) ์กฐํ (
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 ํค๋ฅผ ๋ฐ๊ธ๋ฐ์์ผ ํฉ๋๋ค:
- Upbit์ ๊ณ์ ์ด ์๋ค๋ฉด ๋จผ์ ํ์๊ฐ์ ์ ์งํํฉ๋๋ค.
- Upbit ๊ฐ๋ฐ์ ์ผํฐ๋ก ์ด๋ํฉ๋๋ค.
- ์๋ก์ด API ํค๋ฅผ ์์ฑํฉ๋๋ค.
- API ํค์ ํ์ํ ๊ถํ(์กฐํ, ์ฃผ๋ฌธ, ์ถ๊ธ ๋ฑ)์ ์ ์ ํ ์ค์ ํฉ๋๋ค.
- ๋ฐ๊ธ๋ฐ์ API ํค(
UPBIT_ACCESS_KEY
,UPBIT_SECRET_KEY
)๋ฅผ ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์.env
ํ์ผ๋ก ์ ์ฅํฉ๋๋ค (์ค์น ์น์ ์ฐธ์กฐ).
์ค์น ๋ฐฉ๋ฒ
-
์ ์ฅ์ ๋ณต์ :
git clone <ํ์ฌ_ํ๋ก์ ํธ_์ ์ฅ์_URL> # ์ด ๋ถ๋ถ์ ์ค์ ์ ์ฅ์ URL๋ก ๋ณ๊ฒฝํด์ฃผ์ธ์. cd upbit-mcp-server
-
์์กด์ฑ ํจํค์ง ์ค์น (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
-
ํ๊ฒฝ ๋ณ์ ์ค์ : ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์
.env
ํ์ผ์ ์์ฑํ๊ณ , ๋ฐ๊ธ๋ฐ์ Upbit API ํค๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ ฅํฉ๋๋ค:UPBIT_ACCESS_KEY=์ฌ๊ธฐ์_๋ฐ๊ธ๋ฐ์_ACCESS_KEY๋ฅผ_์ ๋ ฅํ์ธ์ UPBIT_SECRET_KEY=์ฌ๊ธฐ์_๋ฐ๊ธ๋ฐ์_SECRET_KEY๋ฅผ_์ ๋ ฅํ์ธ์
์ฌ์ฉ ๋ฐฉ๋ฒ
์ด ์๋ฒ๋ n8n๊ณผ์ ์ํํ ์ฐ๋์ ์ํด Docker Compose๋ฅผ ์ฌ์ฉํ์ฌ ์คํํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
Docker Compose๋ฅผ ์ด์ฉํ ์คํ (n8n ์ฐ๋ ๊ถ์ฅ)
-
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
: ํ์ฌ ๋๋ ํ ๋ฆฌ๋ฅผ ์ปจํ ์ด๋ ๋ด๋ถ์ ๋ง์ดํธํ์ฌ, ์ด๋ฏธ์ง ์ฌ๋น๋ ์์ด ์ฝ๋ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ํ ์ ์๊ฒ ํฉ๋๋ค (๊ฐ๋ฐ ์ ์ ์ฉ).
-
์๋ฒ ์์:
docker-compose up -d --build
--build
์ต์ ์ Docker ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ๋ก ๋ค์ ๋น๋ํฉ๋๋ค. ์ฝ๋ ๋ณ๊ฒฝ์ฌํญ์ด ์์ ๋ ์ ์ฉํฉ๋๋ค. ์๋ฒ๋ฅผ ์ค์งํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค:docker-compose down
-
๋ก๊ทธ ํ์ธ: ์๋ฒ ๋ก๊ทธ๋ ๋ค์ ๋ช ๋ น์ผ๋ก ํ์ธํ ์ ์์ต๋๋ค:
docker-compose logs -f upbit-mcp-server
n8n ์ฐ๋
์ ์ค๋ช ๋๋ก Upbit MCP ์๋ฒ๊ฐ Docker Compose๋ฅผ ํตํด ์คํ๋๊ณ n8n ์ธ์คํด์ค์ ๋์ผํ Docker ๋คํธ์ํฌ์ ์ฐ๊ฒฐ๋์๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด n8n ์ํฌํ๋ก์ฐ๋ฅผ ์ค์ ํฉ๋๋ค:
- n8n ์ํฌํ๋ก์ฐ์์ HTTP Request ๋ ธ๋ ๋๋ MCP ๊ด๋ จ ์ปค๋ฎค๋ํฐ ๋ ธ๋(์ฌ์ฉ ๊ฐ๋ฅํ๋ค๋ฉด)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- 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 ๊ณ์ฐ ๋ฐฉ์์ ์ ์ฉํ์ฌ ์ ํ๋๋ฅผ ๋์์ต๋๋ค.
ํ์ฌ ์ด์ ๋ฐ ํด๊ฒฐ ํ์ ์ฌํญ
โ ์ต๊ทผ ์๋ฃ๋ ์ฃผ์ ๊ธฐ๋ฅ
-
์ฐจํธ ์ด๋ฏธ์ง ์์ฑ ์์คํ ๊ตฌ์ถ ์๋ฃ
tools/generate_chart_image.py
๊ตฌํ- Matplotlib ๊ธฐ๋ฐ ์บ๋ค์คํฑ/๋ผ์ธ/OHLC ์ฐจํธ ์์ฑ
- ๋ ์ง ๋ฒ์ ์ง์ ๊ธฐ๋ฅ (๊ณผ๊ฑฐ ํน์ ๊ธฐ๊ฐ ์ฐจํธ ์์ฑ ๊ฐ๋ฅ)
- Nginx + SSL ๊ธฐ๋ฐ ์น ์๋น (
charts.resteful3.shop
) - Docker ํ๊ฒฝ ์์ ๊ตฌ์ฑ
-
๋ฐฑํ ์คํ ์์คํ ์์ ํ ์๋ฃ
- ๋ชจ๋ ์ฃผ์ ์ ๋ต (SMA, RSI, ๋ณผ๋ฆฐ์ ๋ฐด๋, MACD) ์ ์ ์๋
- ์ ํํ ํฌํธํด๋ฆฌ์ค ์ถ์ ๋ฐ ์์ต ๊ณ์ฐ
- ์์ฐ์ด ์์ฒญ ์ฒ๋ฆฌ ํ๋กฌํํธ ์์ฑ
-
๋ฐฑํ ์คํ ์ฐจํธ ์๊ฐํ ๊ธฐ๋ฅ ์์ฑ
tools/generate_backtest_chart.py
๊ตฌํ- 3๋จ ๊ตฌ์ฑ ์ฐจํธ (๊ฐ๊ฒฉ+๋งค๋งค์ ํธ, ํฌํธํด๋ฆฌ์ค ๊ฐ์น ๋ณํ, ๊ฑฐ๋๋+๊ฑฐ๋ ์์ )
- ๋ฐฑํ
์คํ
์คํ ์ ์๋ ์ฐจํธ ์์ฑ ์ต์
(
generate_chart: bool = True
) - ๋ชจ๋ ๋งค๋งค ์ ํธ์ ํฌํธํด๋ฆฌ์ค ๋ณํ๊ฐ ์ ํํ ์๊ฐํ๋จ
-
๋ฐฑํ ์คํ ์์คํ ์ฃผ์ ๋ฒ๊ทธ ์์
- ๋งค๋ ์๋ ๊ธฐ๋ก ๋ฌธ์ ํด๊ฒฐ: ๋ชจ๋ ์ ๋ต์์ ๋งค๋ ์ ์๋์ด 0์ผ๋ก ๊ธฐ๋ก๋๋ ๋ฌธ์ ์์
- ํฌํธํด๋ฆฌ์ค ์์ฝ ๋๋ฝ ๋ฌธ์ ํด๊ฒฐ: RSI, ๋ณผ๋ฆฐ์ ๋ฐด๋ ์ ๋ต์์
portfolio_summary
๊ณ์ฐ ๋๋ฝ ์์ - enhance_trade_history ์ค๋ฅ ํด๊ฒฐ:
'cash_balance'
ํค ์ค๋ฅ๋ฅผ ์ ๋ฐํ๋ ํจ์ ํธ์ถ ์ ๊ฑฐ - MACD ์ ๋ต ์์ ์์ : ๋งค๋ ๋ก์ง, ํฌํธํด๋ฆฌ์ค ์์ฝ, ์๋ฌ ์ฒ๋ฆฌ ๋ชจ๋ ์ ์ํ
- ๋ชจ๋ ๋ฐฑํ ์คํ ์ ๋ต (SMA, RSI, ๋ณผ๋ฆฐ์ ๋ฐด๋, MACD, ๋ธ๋ ์ดํฌ์์)์ด ์์ ํ ์ ์ ์๋ ํ์ธ
๐จ ๊ธด๊ธ ์์ ํ์
- FastMCP Import ์ค๋ฅ:
main.py
์์from mcp.server.fastmcp import FastMCP, Context
๋ผ์ธ์ด ๋ชจ๋์ ์ฐพ์ ์ ์๋ ์ค๋ฅ ๋ฐ์ - ์์กด์ฑ ๋ฒ์ ๋ถ์ผ์น:
requirements.txt
:fastmcp==1.0.0
pyproject.toml
:fastmcp>=0.1.8
๐ ํฅํ ๊ฐ์ ๋ฐฉํฅ (TODO)
๊ธฐ๋ฅ ํ์ฅ
- ๋ ๋ง์ ๊ธฐ์ ์ ์งํ ์ถ๊ฐ (์: Stochastic Oscillator, Ichimoku Cloud ๋ฑ)
- ์ค์๊ฐ ์น์์ผ ๋ฐ์ดํฐ ์คํธ๋ฆฌ๋ฐ ์ง์ (๋ณ๋ ํด ๋๋ ๊ธฐ๋ฅ์ผ๋ก)
- ์ฌ์ฉ์๋ณ ์ค์ ์ ์ฅ ๊ธฐ๋ฅ (์: ์ ํธํ๋ ๊ธฐ์ ์ ์งํ, ์๋ฆผ ์ค์ ๋ฑ)
- ํด ํ๋ผ๋ฏธํฐ ์ ํจ์ฑ ๊ฒ์ฆ ๊ฐํ
- ๋ ๋ค์ํ ํ๋กฌํํธ ๋ฐ ๋ฆฌ์์ค ์ถ๊ฐ
- ํ ์คํธ ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ํ๋
์ฐจํธ ๊ธฐ๋ฅ ๊ฐ์
- ๋ ๋ง์ ์ฐจํธ ํ์ ์ถ๊ฐ (ํค์ดํจ ์์, ๋ ์ฝ ์ฐจํธ ๋ฑ)
- ์ถ๊ฐ ๊ธฐ์ ์ ์งํ ์ค๋ฒ๋ ์ด (RSI, MACD, ๋ณผ๋ฆฐ์ ๋ฐด๋ ๋ฑ)
- ์ธํฐ๋ํฐ๋ธ ์ฐจํธ ์ง์ (Plotly ๋ฑ)
- ์ฐจํธ ์คํ์ผ ์ปค์คํฐ๋ง์ด์ง ์ต์
- ๋ค์ค ๋ง์ผ ๋น๊ต ์ฐจํธ
๋ผ์ด์ ์ค
MIT
โ ๏ธ ๋ฉด์ฑ ์กฐํญ (DISCLAIMER)
๋ณธ ํ๋ก์ ํธ๋ ๊ต์ก ๋ฐ ์ฐ๊ตฌ ๋ชฉ์ ์ผ๋ก ์ ๊ณต๋ฉ๋๋ค.
๐จ ์ค์ํ ๊ฒฝ๊ณ
-
ํฌ์ ์์ค์ ๋ํ ์ฑ ์ ๋ถ์ธ
- ๋ณธ ์ํํธ์จ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ํ๋ ๋ชจ๋ ํฌ์ ์์ค์ ๋ํด ๊ฐ๋ฐ์, ๊ธฐ์ฌ์, ๋ฐฐํฌ์๋ ์ด๋ ํ ์ฑ ์๋ ์ง์ง ์์ต๋๋ค.
- ์ํธํํ ํฌ์๋ ๋์ ์ํ์ ์๋ฐํ๋ฉฐ, ํฌ์ ์๊ธ์ ์ ์ก ์์ค ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
-
๋ฐฑํ ์คํ ๊ฒฐ๊ณผ์ ํ๊ณ
- ๋ฐฑํ ์คํ ๊ฒฐ๊ณผ๋ ๊ณผ๊ฑฐ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์๋ฎฌ๋ ์ด์ ์ด๋ฉฐ, ๋ฏธ๋ ์์ต์ ๋ณด์ฅํ์ง ์์ต๋๋ค.
- ์ค์ ๊ฑฐ๋ ํ๊ฒฝ์์๋ ์ฌ๋ฆฌํผ์ง, ์ ๋์ฑ ๋ถ์กฑ, ๊ฑฐ๋์ ์ฅ์ ๋ฑ ๋ฐฑํ ์คํ ์์ ๊ณ ๋ ค๋์ง ์์ ์์๋ค์ด ์ฑ๊ณผ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
-
์ํํธ์จ์ด ํ์ง ๋ณด์ฆ ๋ถ์ธ
- ๋ณธ ์ํํธ์จ์ด๋ "์๋ ๊ทธ๋๋ก(AS-IS)" ์ ๊ณต๋๋ฉฐ, ๋ช ์์ ๋๋ ๋ฌต์์ ๋ณด์ฆ ์์ด ์ ๊ณต๋ฉ๋๋ค.
- ์ํํธ์จ์ด์ ์ค๋ฅ, ๋ฒ๊ทธ, ๋ณด์ ์ทจ์ฝ์ ์ผ๋ก ์ธํ ์์ค์ ๋ํด ์ฑ ์์ง์ง ์์ต๋๋ค.
-
์ฌ์ฉ์ ์ฑ ์
- ๋ณธ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ถฉ๋ถํ ํ ์คํธ์ ๊ฒ์ฆ์ ์ํํ์๊ธฐ ๋ฐ๋๋๋ค.
- ์ค์ ์๊ธ์ ํฌ์ํ๊ธฐ ์ ์ ๋ชจ์ ๊ฑฐ๋๋ ์์ก ํ ์คํธ๋ฅผ ํตํด ์์คํ ์ ์ถฉ๋ถํ ์ดํดํ์๊ธฐ ๋ฐ๋๋๋ค.
- ํฌ์ ๊ฒฐ์ ์ ์ ์ ์ผ๋ก ์ฌ์ฉ์์ ์ฑ ์์ด๋ฉฐ, ์ ๋ฌธ๊ฐ์ ์กฐ์ธ์ ๊ตฌํ์๊ธฐ ๋ฐ๋๋๋ค.
๐ ๊ถ์ฅ ์ฌํญ
- ๋ณธ ํ๋ก์ ํธ๋ ๊ต์ก ๋ชฉ์ ์ผ๋ก๋ง ์ฌ์ฉํ์๊ธฐ ๋ฐ๋๋๋ค.
- ์ค์ ํฌ์์ ์ฌ์ฉํ๊ธฐ ์ ์ ์ถฉ๋ถํ ๊ฒ์ฆ๊ณผ ํ ์คํธ๋ฅผ ์ํํ์๊ธฐ ๋ฐ๋๋๋ค.
- ๊ฐ๋นํ ์ ์๋ ๋ฒ์ ๋ด์์๋ง ํฌ์ํ์๊ธฐ ๋ฐ๋๋๋ค.
- ํฌ์ ์ ์ ์ ๋ฌธ๊ฐ์ ์กฐ์ธ์ ๊ตฌํ์๊ธฐ ๋ฐ๋๋๋ค.
๋ณธ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ์์ ๋ฉด์ฑ ์กฐํญ์ ๋์ํ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.