Skip to main content
Glama
j840425

MCP Trading Quantitative Analysis Server

by j840425
client.py7.84 kB
""" Alpha Vantage API client for market data """ import requests import pandas as pd from datetime import datetime, timedelta from typing import Dict, Optional, Any import time from ..config import Config class AlphaVantageClient: """Client for Alpha Vantage API""" def __init__(self): self.api_key = Config.ALPHA_VANTAGE_API_KEY self.base_url = Config.ALPHA_VANTAGE_BASE_URL self.last_request_time = 0 self.rate_limit_delay = 60 / Config.ALPHA_VANTAGE_RATE_LIMIT # seconds between requests def _rate_limit(self): """Implement rate limiting""" current_time = time.time() time_since_last_request = current_time - self.last_request_time if time_since_last_request < self.rate_limit_delay: time.sleep(self.rate_limit_delay - time_since_last_request) self.last_request_time = time.time() def _make_request(self, params: Dict[str, str]) -> Dict[str, Any]: """Make API request with rate limiting""" self._rate_limit() params['apikey'] = self.api_key try: response = requests.get(self.base_url, params=params, timeout=30) response.raise_for_status() data = response.json() # Check for API errors if "Error Message" in data: raise ValueError(f"Alpha Vantage API Error: {data['Error Message']}") if "Note" in data: raise ValueError(f"Alpha Vantage Rate Limit: {data['Note']}") return data except requests.exceptions.RequestException as e: raise ConnectionError(f"Failed to connect to Alpha Vantage: {str(e)}") def get_current_price(self, symbol: str) -> Dict[str, Any]: """ Get current price for a symbol Args: symbol: Stock ticker (e.g., "AAPL") or forex pair (e.g., "EUR/USD") Returns: Dictionary with current price information """ # Check if it's a forex pair if '/' in symbol: from_currency, to_currency = symbol.split('/') params = { 'function': 'CURRENCY_EXCHANGE_RATE', 'from_currency': from_currency, 'to_currency': to_currency } data = self._make_request(params) if "Realtime Currency Exchange Rate" not in data: raise ValueError(f"No data found for {symbol}") rate_data = data["Realtime Currency Exchange Rate"] return { 'symbol': symbol, 'price': float(rate_data['5. Exchange Rate']), 'timestamp': rate_data['6. Last Refreshed'], 'from_currency': rate_data['1. From_Currency Code'], 'to_currency': rate_data['3. To_Currency Code'], 'bid_price': float(rate_data.get('8. Bid Price', 0)), 'ask_price': float(rate_data.get('9. Ask Price', 0)) } else: # Stock symbol params = { 'function': 'GLOBAL_QUOTE', 'symbol': symbol } data = self._make_request(params) if "Global Quote" not in data or not data["Global Quote"]: raise ValueError(f"No data found for {symbol}") quote = data["Global Quote"] return { 'symbol': quote['01. symbol'], 'price': float(quote['05. price']), 'timestamp': quote['07. latest trading day'], 'change': float(quote['09. change']), 'change_percent': quote['10. change percent'], 'volume': int(quote['06. volume']), 'open': float(quote['02. open']), 'high': float(quote['03. high']), 'low': float(quote['04. low']), 'previous_close': float(quote['08. previous close']) } def get_historical_data( self, symbol: str, start_date: str, end_date: str, interval: str = 'daily' ) -> pd.DataFrame: """ Get historical OHLCV data Args: symbol: Stock ticker start_date: Start date (YYYY-MM-DD) end_date: End date (YYYY-MM-DD) interval: Time interval (1min, 5min, 15min, 30min, 60min, daily, weekly, monthly) Returns: DataFrame with OHLCV data """ interval_map = { '1min': 'TIME_SERIES_INTRADAY', '5min': 'TIME_SERIES_INTRADAY', '15min': 'TIME_SERIES_INTRADAY', '30min': 'TIME_SERIES_INTRADAY', '60min': 'TIME_SERIES_INTRADAY', 'daily': 'TIME_SERIES_DAILY', 'weekly': 'TIME_SERIES_WEEKLY', 'monthly': 'TIME_SERIES_MONTHLY' } if interval not in interval_map: raise ValueError(f"Invalid interval: {interval}") function = interval_map[interval] params = { 'function': function, 'symbol': symbol, 'outputsize': 'full' } # Add interval parameter for intraday data if 'INTRADAY' in function: params['interval'] = interval data = self._make_request(params) # Find the time series key time_series_key = None for key in data.keys(): if 'Time Series' in key: time_series_key = key break if not time_series_key: raise ValueError(f"No time series data found for {symbol}") time_series = data[time_series_key] # Convert to DataFrame df = pd.DataFrame.from_dict(time_series, orient='index') df.index = pd.to_datetime(df.index) df = df.sort_index() # Rename columns column_map = { '1. open': 'Open', '2. high': 'High', '3. low': 'Low', '4. close': 'Close', '5. volume': 'Volume' } df = df.rename(columns=column_map) # Convert to numeric for col in df.columns: df[col] = pd.to_numeric(df[col]) # Filter by date range start = pd.to_datetime(start_date) end = pd.to_datetime(end_date) df = df[(df.index >= start) & (df.index <= end)] return df def get_quote_info(self, symbol: str) -> Dict[str, Any]: """ Get comprehensive quote information Args: symbol: Stock ticker Returns: Dictionary with comprehensive quote information """ # Get current quote current_quote = self.get_current_price(symbol) # Get company overview params = { 'function': 'OVERVIEW', 'symbol': symbol } try: overview = self._make_request(params) # Combine data result = { **current_quote, 'company_name': overview.get('Name', 'N/A'), 'description': overview.get('Description', 'N/A'), 'sector': overview.get('Sector', 'N/A'), 'industry': overview.get('Industry', 'N/A'), 'market_cap': overview.get('MarketCapitalization', 'N/A'), 'pe_ratio': overview.get('PERatio', 'N/A'), 'eps': overview.get('EPS', 'N/A'), 'dividend_yield': overview.get('DividendYield', 'N/A'), '52_week_high': overview.get('52WeekHigh', 'N/A'), '52_week_low': overview.get('52WeekLow', 'N/A'), 'beta': overview.get('Beta', 'N/A') } return result except Exception as e: # If overview fails, just return current quote return current_quote

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/j840425/MCP_trading'

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