Skip to main content
Glama

get_technical_summary

Analyzes technical indicators like RSI, MACD, and moving averages to generate Buy, Sell, or Neutral trading signals for financial symbols.

Instructions

Performs a technical analysis summary (RSI, MACD, Moving Averages). Returns a 'Buy', 'Sell', or 'Neutral' signal based on aggregated indicators.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
symbolYes

Implementation Reference

  • The core handler function for the 'get_technical_summary' tool. Downloads 2y historical data using yfinance, computes RSI(14), MACD, SMA50, SMA200. Generates a score-based signal (STRONG BUY to STRONG SELL) with detailed reasons.
    def get_technical_summary(symbol: str) -> str:
        """
        Performs a technical analysis summary (RSI, MACD, Moving Averages).
        Returns a 'Buy', 'Sell', or 'Neutral' signal based on aggregated indicators.
        """
        try:
            # Need enough data for 200 SMA
            df = yf.download(symbol, period="2y", progress=False)
            if df.empty:
                return f"No data found for {symbol}"
                
            # Handle MultiIndex if present
            # yfinance structure: columns are (Price, Ticker)
            if isinstance(df.columns, pd.MultiIndex):
                # If we have a MultiIndex, we want the 'Close' level, and then the specific ticker
                # But usually df['Close'] gives us the Close column(s).
                pass 
                
            close = df['Close']
            if isinstance(close, pd.DataFrame):
                # If multiple tickers or just weird structure, take the first column
                close = close.iloc[:, 0]
                
            # 1. RSI
            rsi = ta.rsi(close, length=14)
            if rsi is None or rsi.empty:
                return f"Not enough data to calculate RSI for {symbol}"
            current_rsi = rsi.iloc[-1]
            
            # 2. MACD
            macd = ta.macd(close)
            if macd is None or macd.empty:
                return f"Not enough data to calculate MACD for {symbol}"
            
            # MACD_12_26_9, MACDh_12_26_9 (hist), MACDs_12_26_9 (signal)
            # Column names depend on pandas_ta version/settings, but usually standard
            macd_line = macd.iloc[-1, 0] # First column is usually MACD line
            macd_signal = macd.iloc[-1, 2] # Third column is usually Signal line
            
            # 3. Moving Averages
            sma_50 = ta.sma(close, length=50)
            sma_200 = ta.sma(close, length=200)
            
            if sma_50 is None or sma_50.empty:
                return "Not enough data for SMA 50"
            if sma_200 is None or sma_200.empty:
                # Fallback if 200 SMA not available (e.g. IPO recently)
                sma_200_val = 0
                has_200 = False
            else:
                sma_200_val = sma_200.iloc[-1]
                has_200 = True
                
            sma_50_val = sma_50.iloc[-1]
            current_price = close.iloc[-1]
            
            # Scoring Logic
            score = 0
            reasons = []
            
            # RSI Logic
            if current_rsi < 30:
                score += 1
                reasons.append(f"RSI is Oversold ({current_rsi:.2f})")
            elif current_rsi > 70:
                score -= 1
                reasons.append(f"RSI is Overbought ({current_rsi:.2f})")
            else:
                reasons.append(f"RSI is Neutral ({current_rsi:.2f})")
                
            # MACD Logic
            if macd_line > macd_signal:
                score += 1
                reasons.append("MACD Bullish Crossover")
            else:
                score -= 1
                reasons.append("MACD Bearish Crossover")
                
            # Trend Logic
            if current_price > sma_50_val:
                score += 1
                reasons.append("Price above 50 SMA (Bullish Trend)")
            else:
                score -= 1
                reasons.append("Price below 50 SMA (Bearish Trend)")
                
            if has_200:
                if current_price > sma_200_val:
                    score += 1
                    reasons.append("Price above 200 SMA (Long-term Bullish)")
                else:
                    score -= 1
                    reasons.append("Price below 200 SMA (Long-term Bearish)")
            else:
                reasons.append("200 SMA not available (Insufficient history)")
                
            # Final Verdict
            if score >= 2:
                signal = "STRONG BUY"
            elif score == 1:
                signal = "BUY"
            elif score == 0:
                signal = "NEUTRAL"
            elif score == -1:
                signal = "SELL"
            else:
                signal = "STRONG SELL"
                
            return (f"Technical Summary for {symbol}:\n"
                    f"Signal: {signal} (Score: {score})\n"
                    f"Price: ${current_price:.2f}\n"
                    f"--------------------------------\n"
                    f"Analysis:\n" + "\n".join([f"- {r}" for r in reasons]))
                    
        except Exception as e:
            return f"Error performing technical analysis: {str(e)}"
  • server.py:390-393 (registration)
    Registers the get_technical_summary tool (along with compute_indicators and rolling_stats) as an MCP tool using the register_tools helper function, which applies @mcp.tool() decorator.
    register_tools(
        [compute_indicators, rolling_stats, get_technical_summary],
        "Feature Engineering"
    )
  • server.py:16-16 (registration)
    Import statement bringing the get_technical_summary function into the MCP server module for registration.
    from tools.feature_engineering import compute_indicators, rolling_stats, get_technical_summary

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/N-lia/MonteWalk'

If you have feedback or need assistance with the MCP directory API, please join our Discord server