We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jon-fox/agentic-investor'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""yfinance API helper functions."""
import logging
import sys
from typing import Literal
import pandas as pd
import yfinance as yf
from tenacity import (
retry,
stop_after_attempt,
wait_exponential,
retry_if_exception,
after_log,
)
from yfinance.exceptions import YFRateLimitError
# Setup logging
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[logging.StreamHandler(sys.stderr)],
)
def api_retry(func):
"""Unified retry decorator for API calls (yfinance and HTTP).
Retries on:
- YFRateLimitError
- HTTP 5xx errors
- Network/connection issues
- Rate limiting (429)
"""
return retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=2.0, min=2.0, max=30.0),
retry=retry_if_exception(
lambda e: isinstance(e, YFRateLimitError)
or (hasattr(e, "status_code") and getattr(e, "status_code", 0) >= 500)
or any(
term in str(e).lower()
for term in [
"rate limit",
"too many requests",
"temporarily blocked",
"timeout",
"connection",
"network",
"temporary",
"5",
"429",
"502",
"503",
"504",
]
)
),
after=after_log(logger, logging.WARNING),
)(func)
@api_retry
def yf_call(ticker: str, method: str, *args, **kwargs):
"""Generic yfinance API call with retry logic.
Args:
ticker: Stock ticker symbol
method: Method name to call on yf.Ticker object
*args: Positional arguments to pass to the method
**kwargs: Keyword arguments to pass to the method
Returns:
Result of the yfinance method call
"""
t = yf.Ticker(ticker)
return getattr(t, method)(*args, **kwargs)
def get_options_chain(
ticker: str, expiry: str, option_type: Literal["C", "P"] | None = None
) -> pd.DataFrame:
"""Get options chain with optional filtering by type.
Args:
ticker: Stock ticker symbol
expiry: Expiration date
option_type: Option type - "C" for calls, "P" for puts, None for both
Returns:
DataFrame with options chain data
"""
chain = yf_call(ticker, "option_chain", expiry)
if option_type == "C":
return chain.calls
elif option_type == "P":
return chain.puts
return pd.concat([chain.calls, chain.puts], ignore_index=True)