Stock_MCP 업데이트 : 특정 날짜 조회 추가 (260220)

WonTerry·2026년 2월 20일

MCP

목록 보기
20/23

특정 날짜의 종가를 조회할 수 있도록 date 필드를 선택적으로 입력받는 로직을 추가했다.

날짜가 입력되면 해당 날짜의 데이터를, 입력되지 않으면 최신 종가를 가져오도록 구성했다. yfinance에서 특정 날짜 데이터를 가져올 때는 start와 end 범위를 지정하는 방식이 가장 안정적이다.


💡 주요 변경 사항
입력 구조 확장:

StockRequest 클래스에 date 필드를 추가했다.
Optional을 사용하여 날짜 없이 호출해도 기존처럼 최신가를 가져오도록 하위 호환성을 유지했다.


💡 날짜 처리 로직 (history 활용):

yf.Ticker.history(start=..., end=...)를 사용했다.

중요: yfinance에서 end 날짜는 포함되지 않으므로, 입력받은 날짜의 데이터를 얻기 위해 target_date부터 target_date + 1일까지의 범위를 지정했다.

예외 상황 안내:

사용자가 주말(토, 일)이나 시장 휴장일을 입력하면 데이터프레임(df)이 비어 있게 된다. 이 경우 "주말이나 공휴일인지 확인해달라"는 친절한 메시지를 출력하도록 했다.


📝 사용 예시 (LLM 호출 시)
"삼성전자(005930) 오늘 가격 알려줘" → date 없이 호출

"삼성전자 2024년 1월 2일 종가가 얼마였어?" → symbol="005930", date="2024-01-02"로 호출


Stock_MCP.py

from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from typing import Optional
import yfinance as yf
from datetime import datetime, timedelta

class StockRequest(BaseModel):
    symbol: str = Field(description="종목 코드 (예: 005930, AAPL)")
    date: Optional[str] = Field(default=None, description="조회할 날짜 (YYYY-MM-DD 형식, 미입력 시 최신 종가)")

mcp = FastMCP("stock_mcp")

@mcp.tool()
def get_stock_price(input: StockRequest) -> str:
    """
    yfinance를 사용하여 한국/해외 주식의 가격을 조회합니다.
    특정 날짜(YYYY-MM-DD)를 입력하면 해당 날짜의 종가를 반환합니다.
    """
    code = input.symbol.strip().upper()
    target_date = input.date
    
    # 1. 티커 후보군 생성 (재시도 전략)
    if code.endswith(".KS") or code.endswith(".KQ"):
        candidate_tickers = [code]
    elif code.isdigit() and len(code) == 6:
        candidate_tickers = [f"{code}.KS", f"{code}.KQ"]
    else:
        candidate_tickers = [code]

    last_exception = None

    for ticker in candidate_tickers:
        try:
            stock = yf.Ticker(ticker)
            
            if target_date:
                # 특정 날짜 조회 로직
                # yfinance history는 end 날짜를 포함하지 않으므로 +1일을 해줍니다.
                start_dt = datetime.strptime(target_date, "%Y-%m-%d")
                end_dt = start_dt + timedelta(days=1)
                
                df = stock.history(start=start_dt.strftime("%Y-%m-%d"), 
                                   end=end_dt.strftime("%Y-%m-%d"))
                
                if not df.empty:
                    price = df["Close"].iloc[0]
                    date_str = df.index[0].strftime("%Y-%m-%d")
                    return f"[{date_str}] {ticker}의 종가는 {price:,.2f}원(또는 해당 통화)입니다."
                else:
                    # 해당 날짜에 데이터가 없는 경우 (주말, 휴장일 등) 다음 티커 시도 전 체크
                    continue
            else:
                # 최신 가격 조회 로직 (기존 로직 유지)
                df = stock.history(period="1d")
                if not df.empty:
                    price = df["Close"].iloc[-1]
                    date_str = df.index[-1].strftime("%Y-%m-%d")
                    return f"[최신: {date_str}] {ticker}의 가격은 {price:,.2f}원입니다."
                continue

        except Exception as e:
            last_exception = e
            continue

    msg = f"'{code}'에 대한 정보를 찾을 수 없습니다."
    if target_date:
        msg += f" (날짜: {target_date} - 주말이나 공휴일인지 확인해주세요.)"
    return f"오류: {msg} (상세: {last_exception})"

if __name__ == "__main__":
    mcp.run()
profile
Hello, I'm Terry! 👋 Enjoy every moment of your life! 🌱 My current interests are Signal processing, Machine learning, Python, Database, LLM & RAG, MCP & ADK, Multi-Agents, Physical AI, ROS2...

0개의 댓글