μΆμΈμΆμ’ ν¬μ λ°©λ²λ‘ μ κΈ°λ°μΌλ‘ ν MCP(Model Context Protocol) μλ²μ λλ€. μ£Όμ μμ₯ λΆμ, λ§€λ§€ μμ νλ¨, ν¬νΈν΄λ¦¬μ€ κ΄λ¦¬λ₯Ό μν μ’ ν©μ μΈ ν¬μ λꡬλ₯Ό μ 곡ν©λλ€.
Trend Following MCP Serverλ λ€μκ³Ό κ°μ ν΅μ¬ κΈ°λ₯μ μ 곡ν©λλ€:
- π μ£Όμ μ 보 μμ§: μ€μκ° μ£Όκ°, μ¬λ¬΄μ ν, λ΄μ€ λ°μ΄ν°
- π κΈ°μ μ λΆμ: μ΄λνκ· , RSI, MACD, λ³Όλ¦°μ λ°΄λ λ±
- π― λ§€λ§€ μμ μ νΈ: μΆμΈ μΆμ’ μ λ΅ κΈ°λ° λ§€μ/λ§€λ μμ νλ¨
- π ν¬νΈν΄λ¦¬μ€ κ΄λ¦¬: μμ° λ°°λΆ, 리μ€ν¬ κ΄λ¦¬, μ±κ³Ό μΆμ
- π€ AI κΈ°λ° λΆμ: λ¨Έμ λ¬λμ νμ©ν μμ₯ μμΈ‘ λ° μ΅μ ν
get_stock_info
: μ€μκ° μ£Όκ° λ°μ΄ν° μμ§ λ° κΈ°μ μ 보 μ‘°νscreen_stocks
: κΈ°μ μ /κΈ°λ³Έμ 쑰건μ λ°λ₯Έ μ£Όμ μ€ν¬λ¦¬λ- κΈ°μ μ¬λ¬΄μ ν λΆμ (μμ΅κ³μ°μ, μ¬λ¬΄μνν, νκΈνλ¦ν)
- λ΄μ€ λ° μ΄λ²€νΈ λͺ¨λν°λ§
- μΉν°λ³ μμ₯ λν₯ λΆμ
analyze_technical
: μ’ ν©μ μΈ κΈ°μ μ λΆμ μν- μ΄λνκ· μ λΆμ (20μΌ, 50μΌ, 200μΌ SMA/EMA)
- λͺ¨λ©ν μ§ν (RSI, MACD, μ€ν μΊμ€ν±)
- λ³λμ± μ§ν (λ³Όλ¦°μ λ°΄λ, ATR)
- κ±°λλ λΆμ (OBV, κ±°λλ κ°μ€ νκ· )
- μΆμΈ λ°©ν₯ λ° κ°λ λΆμ
generate_signal
: μΆμΈ μΆμ’ λ§€λ§€ μμ νλ¨backtest_signals
: μ λ΅ λ°±ν μ€ν λ° μ±κ³Ό λΆμ- 리μ€ν¬ κ΄λ¦¬ λ° μμ λ§€ μ€μ
- ν¬μ§μ μ¬μ΄μ§ μ΅μ ν
- μ νΈ μ λ’°λ λ° κ°λ κ³μ°
manage_portfolio
: ν¬νΈν΄λ¦¬μ€ λΆμ, μ΅μ ν, 리밸λ°μ±analyze_risk
: ν¬νΈν΄λ¦¬μ€ 리μ€ν¬ λΆμ (VaR, CVaR)- μμ° λ°°λΆ μ΅μ ν
- 리μ€ν¬ λλΉ μμ΅λ₯ λΆμ
- μ±κ³Ό μΆμ λ° λ¦¬ν¬ν
TradeMonster/
βββ src/
β βββ mcp/ # MCP μλ² ν΅μ¬
β β βββ server.py # MCP μλ² λ©μΈ
β β βββ schemas.py # λ°μ΄ν° μ€ν€λ§ (Pydantic λͺ¨λΈ)
β β βββ tools/ # MCP λꡬλ€
β β βββ stock_info.py # μ£Όμ μ 보 λꡬ
β β βββ technical.py # κΈ°μ μ λΆμ λꡬ
β β βββ signals.py # λ§€λ§€ μ νΈ λꡬ
β β βββ portfolio.py # ν¬νΈν΄λ¦¬μ€ κ΄λ¦¬ λꡬ
β βββ analysis/ # λΆμ μμ§
β β βββ trend_analysis.py # μΆμΈ λΆμ μμ§
β β βββ momentum.py # λͺ¨λ©ν
λΆμ (ꡬν μμ )
β β βββ volatility.py # λ³λμ± λΆμ (ꡬν μμ )
β βββ utils/ # μ νΈλ¦¬ν°
β β βββ config.py # μ€μ κ΄λ¦¬ (Pydantic κΈ°λ°)
β β βββ logger.py # λ‘κΉ
μμ€ν
β βββ main.py # λ©μΈ μ€ν νμΌ
βββ tests/ # ν
μ€νΈ νμΌλ€
β βββ test_mcp_server.py # MCP μλ² ν
μ€νΈ
βββ pyproject.toml # νλ‘μ νΈ μ€μ (μ
λ°μ΄νΈλ¨)
βββ README.md # νλ‘μ νΈ λ¬Έμ
βββ env.example # νκ²½ λ³μ μμ
βββ LICENSE # MIT λΌμ΄μ μ€
- μΆμΈ νμΈ: μ₯κΈ° μ΄λνκ· μ μ κΈ°μ€μΌλ‘ μμΉ/νλ½ μΆμΈ νλ¨
- λͺ¨λ©ν νμ©: RSI, MACD λ± λͺ¨λ©ν μ§νλ‘ κ°λ μΈ‘μ
- λ³λμ± κ΄λ¦¬: λ³Όλ¦°μ λ°΄λ, ATRλ‘ λ³λμ± κΈ°λ° μ§μ /μ²μ°
- 리μ€ν¬ μ μ΄: μμ λ§€, μ΅μ λ§€, ν¬μ§μ μ¬μ΄μ§μΌλ‘ 리μ€ν¬ κ΄λ¦¬
- λ§€μ 쑰건: μμΉ μΆμΈ + λͺ¨λ©ν μμΉ + λ³λμ± νλ
- λ§€λ 쑰건: νλ½ μΆμΈ + λͺ¨λ©ν νλ½ + μ§μ§μ μ΄ν
- νλ© μ‘°κ±΄: μΆμΈ μ§μ + 리μ€ν¬ κ΄λ¦¬ λ²μ λ΄
# κ°λ ₯ν λ§€μ μ νΈ
if (trend_direction == "up" and
current_price > sma_20 > sma_50 > sma_200 and
rsi < 70 and # κ³Όλ§€μ μλ
macd > macd_signal and
price_position < 0.8): # λ³Όλ¦°μ μλ¨ λ°΄λ μ΄ν
signal_type = "strong_buy"
# μ μ₯μ ν΄λ‘
git clone https://github.com/yourusername/TradeMonster.git
cd TradeMonster
# κ°μνκ²½ μμ± λ° νμ±ν
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# μμ‘΄μ± μ€μΉ
pip install -e .
# .env νμΌ μμ±
cp env.example .env
# API ν€ μ€μ (μ νμ¬ν - yfinanceλ κΈ°λ³Έμ μΌλ‘ API ν€κ° νμ μμ)
YAHOO_FINANCE_API_KEY=your_api_key
ALPHA_VANTAGE_API_KEY=your_alpha_vantage_api_key
# λ©μΈ μ€ν νμΌλ‘ μ€ν
python src/main.py
# λλ μ§μ MCP μλ² μ€ν
python -m src.mcp.server --dev
# λλ κ°λ° λͺ¨λ
python -m src.mcp.server --dev --stdio
# μ 체 ν
μ€νΈ μ€ν
pytest tests/
# νΉμ ν
μ€νΈ μ€ν
pytest tests/test_mcp_server.py -v
# Apple μ£Όμ μ 보 μ‘°ν
stock_info = await session.call_tool("get_stock_info", {
"symbol": "AAPL",
"include_financials": True,
"include_news": True
})
# κΈ°μ μ μ§ν λΆμ
analysis = await session.call_tool("analyze_technical", {
"symbol": "AAPL",
"period": "1y",
"indicators": ["sma", "rsi", "macd", "bollinger"]
})
# μΆμΈμΆμ’
λ§€λ§€ μ νΈ
signal = await session.call_tool("generate_signal", {
"symbol": "AAPL",
"strategy": "trend_following",
"risk_level": "moderate"
})
# ν¬νΈν΄λ¦¬μ€ λΆμ
portfolio = await session.call_tool("manage_portfolio", {
"action": "analyze",
"portfolio": [
{"symbol": "AAPL", "shares": 100, "cost_basis": 150.0},
{"symbol": "GOOGL", "shares": 50, "cost_basis": 2800.0}
]
})
# ν¬νΈν΄λ¦¬μ€ 리μ€ν¬ λΆμ
risk_analysis = await session.call_tool("analyze_risk", {
"portfolio": portfolio_data,
"confidence_level": 0.95
})
# src/mcp/tools/new_tool.py
from mcp import Tool
from typing import Dict, Any
class NewTool(Tool):
name = "new_tool"
description = "μλ‘μ΄ λꡬ μ€λͺ
"
async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
# λꡬ λ‘μ§ κ΅¬ν
return {"result": "success"}
# src/utils/config.pyμμ μ€μ μΆκ°
class Config(BaseSettings):
new_setting: str = Field(default="default_value", description="μλ‘μ΄ μ€μ ")
from src.utils.logger import get_logger
logger = get_logger(__name__)
logger.info("μ 보 λ©μμ§")
logger.error("μλ¬ λ©μμ§")
- μΉλ₯ : 65% μ΄μ λͺ©ν
- μ€ν λΉμ¨: 1.5 μ΄μ λͺ©ν
- μ΅λ λν: 15% μ΄ν λͺ©ν
- μ°κ° μμ΅λ₯ : 20% μ΄μ λͺ©ν
- ATR κΈ°λ° μμ λ§€: λ³λμ±μ λ°λ₯Έ λμ μμ λ§€ μ€μ
- ν¬μ§μ μ¬μ΄μ§: μ λ’°λμ 리μ€ν¬ μμ€μ λ°λ₯Έ ν¬μ§μ ν¬κΈ° μ‘°μ
- ν¬νΈν΄λ¦¬μ€ λ€κ°ν: μμ° κ° μκ΄κ΄κ³λ₯Ό κ³ λ €ν λ°°λΆ
- VaR/CVaR λΆμ: ν¬νΈν΄λ¦¬μ€ 리μ€ν¬ μΈ‘μ
# 보μμ (Conservative)
stop_loss_multiplier = 2.0
position_size = 0.05 # 5%
# μ€κ° (Moderate) - κΈ°λ³Έκ°
stop_loss_multiplier = 1.5
position_size = 0.1 # 10%
# 곡격μ (Aggressive)
stop_loss_multiplier = 1.0
position_size = 0.15 # 15%
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
- Python 3.13+ μ¬μ©
- Type hints νμ
- Pydantic λͺ¨λΈ μ¬μ©
- Async/await ν¨ν΄ μ¬μ©
- ν μ€νΈ μ½λ μμ±
μ΄ νλ‘μ νΈλ MIT λΌμ΄μ μ€ νμ λ°°ν¬λ©λλ€. μμΈν λ΄μ©μ LICENSE νμΌμ μ°Έμ‘°νμΈμ.
μ΄ νλ‘μ νΈλ κ΅μ‘ λ° μ°κ΅¬ λͺ©μ μΌλ‘ μ μλμμ΅λλ€. μ€μ ν¬μμ μ¬μ©νκΈ° μ μ μΆ©λΆν κ²μ¦κ³Ό ν μ€νΈλ₯Ό κ±°μ³μΌ ν©λλ€. ν¬μ μμ€μ λν μ± μμ μ¬μ©μμκ² μμ΅λλ€.
μ€μ: μ΄ λꡬλ ν¬μ μ‘°μΈμ΄ μλλλ€. λͺ¨λ ν¬μ κ²°μ μ λ³ΈμΈμ νλ¨μ λ°λΌ μ΄λ£¨μ΄μ ΈμΌ ν©λλ€.
νλ‘μ νΈμ λν λ¬Έμμ¬νμ΄λ μ μμ¬νμ΄ μμΌμλ©΄ μ΄μλ₯Ό μμ±ν΄ μ£ΌμΈμ.
ν¨κ» λ λμ ν¬μ λꡬλ₯Ό λ§λ€μ΄κ°μ! π