Spaces:
Sleeping
Sleeping
| # hl_indicators_server.py | |
| """ | |
| FastMCP server exposing Hyperliquid indicator tools. | |
| This server provides a unified interface to compute common trading indicators | |
| directly from Hyperliquid testnet market data via the `candles_snapshot` API. | |
| Available tools: | |
| - ema β Exponential Moving Average | |
| - macd β Moving Average Convergence Divergence | |
| - stoch_rsi β Stochastic RSI | |
| - adl β Accumulation / Distribution Line | |
| - obv β On-Balance Volume | |
| - atr_adx β Average True Range / Directional Index / ADX | |
| - bbands β Bollinger Bands | |
| - mfi β Money Flow Index | |
| - vwap β Volume-Weighted Average Price | |
| - volume β Raw trading volume | |
| - bundle β Compute multiple indicators in one call | |
| Run: | |
| python hl_indicators_server.py | |
| """ | |
| from __future__ import annotations | |
| from typing import List, Optional, Literal, Dict, Any | |
| from mcp.server.fastmcp import FastMCP | |
| import hl_indicators as hi | |
| Interval = Literal["1m", "5m", "15m", "1h", "4h", "1d"] | |
| mcp = FastMCP("hl_indicators_server") | |
| # ------------------ Health check ------------------ # | |
| async def ping() -> str: | |
| """Check if the MCP server is online and responding.""" | |
| return "pong" | |
| # ------------------ Indicator tools ------------------ # | |
| async def ema( | |
| name: str, | |
| interval: Interval = "1h", | |
| periods: Optional[List[int]] = None, | |
| lookback: Optional[int] = None, | |
| limit: int = 600, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Compute Exponential Moving Averages (EMA). | |
| Args: | |
| name: Coin name (e.g. "BTC", "ETH", "HYPE"). | |
| interval: Candle interval ("1m", "5m", "15m", "1h", "4h", "1d"). | |
| periods: List of EMA window lengths (e.g. [20, 200]). | |
| lookback: Optional shorthand for a single EMA (e.g. 36). | |
| limit: Number of candles to fetch from the API. | |
| Notes: | |
| - `limit` controls how many data points are retrieved; it should be at | |
| least 2β3Γ the largest EMA period for accurate results. | |
| - The function automatically uses Hyperliquid testnet data. | |
| Returns: | |
| A dictionary containing EMA series for each period and the most recent values. | |
| """ | |
| if periods is None and lookback is not None: | |
| periods = [lookback] | |
| return hi.get_ema(name=name, periods=periods, interval=interval, limit=limit, testnet=False) | |
| async def macd( | |
| name: str, | |
| interval: Interval = "1h", | |
| fast: int = 12, | |
| slow: int = 26, | |
| signal: int = 9, | |
| limit: int = 600, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Compute the Moving Average Convergence Divergence (MACD). | |
| Args: | |
| name: Coin name (e.g. "BTC"). | |
| interval: Candle interval. | |
| fast: Period for the fast EMA (default: 12). | |
| slow: Period for the slow EMA (default: 26). | |
| signal: Period for the MACD signal line (default: 9). | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary with MACD line, signal line, histogram, and last computed values. | |
| """ | |
| return hi.get_macd(name=name, fast=fast, slow=slow, signal=signal, interval=interval, limit=limit, testnet=False) | |
| async def stoch_rsi( | |
| name: str, | |
| interval: Interval = "1h", | |
| rsi_length: int = 14, | |
| stoch_length: int = 14, | |
| k_smooth: int = 3, | |
| d_smooth: int = 3, | |
| limit: int = 600, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Compute the Stochastic RSI oscillator (%K and %D). | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| rsi_length: Period for RSI computation (default: 14). | |
| stoch_length: Period for Stochastic window (default: 14). | |
| k_smooth: Smoothing factor for %K (default: 3). | |
| d_smooth: Smoothing factor for %D (default: 3). | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary containing %K, %D, and the raw StochRSI values. | |
| """ | |
| return hi.get_stoch_rsi( | |
| name=name, | |
| rsi_length=rsi_length, | |
| stoch_length=stoch_length, | |
| k_smooth=k_smooth, | |
| d_smooth=d_smooth, | |
| interval=interval, | |
| limit=limit, | |
| testnet=False, | |
| ) | |
| async def adl(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Compute the Accumulation/Distribution Line (ADL). | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary containing the ADL time series and the latest ADL value. | |
| """ | |
| return hi.get_adl(name=name, interval=interval, limit=limit, testnet=False) | |
| async def obv(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Compute the On-Balance Volume (OBV). | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| limit: Number of candles to fetch. | |
| Returns: | |
| OBV values accumulated over time and the latest OBV. | |
| """ | |
| return hi.get_obv(name=name, interval=interval, limit=limit, testnet=False) | |
| async def atr_adx(name: str, interval: Interval = "1h", period: int = 14, limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Compute volatility and directional indicators: ATR, +DI, -DI, and ADX. | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| period: Lookback for smoothing (default: 14). | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary with ATR, +DI, -DI, and ADX values. | |
| """ | |
| return hi.get_atr_adx(name=name, period=period, interval=interval, limit=limit, testnet=False) | |
| async def bbands( | |
| name: str, | |
| interval: Interval = "1h", | |
| period: int = 20, | |
| std_mult: float = 2.0, | |
| limit: int = 600, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Compute Bollinger Bands (basis, upper/lower bands, %b, bandwidth). | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| period: Window for SMA (default: 20). | |
| std_mult: Standard deviation multiplier (default: 2.0). | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary with band series and the most recent band values. | |
| """ | |
| return hi.get_bbands(name=name, period=period, std_mult=std_mult, interval=interval, limit=limit, testnet=False) | |
| async def mfi(name: str, interval: Interval = "1h", period: int = 14, limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Compute the Money Flow Index (MFI), a volume-weighted momentum oscillator. | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| period: Rolling window (default: 14). | |
| limit: Number of candles to fetch. | |
| Returns: | |
| A dictionary containing MFI series and the most recent value. | |
| """ | |
| return hi.get_mfi(name=name, period=period, interval=interval, limit=limit, testnet=False) | |
| async def vwap(name: str, interval: Interval = "1h", daily_reset: bool = False, limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Compute the Volume-Weighted Average Price (VWAP). | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| daily_reset: If True, VWAP resets each trading day. | |
| limit: Number of candles to fetch. | |
| Returns: | |
| VWAP time series and the last computed VWAP value. | |
| """ | |
| return hi.get_vwap(name=name, daily_reset=daily_reset, interval=interval, limit=limit, testnet=False) | |
| async def volume(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]: | |
| """ | |
| Retrieve the raw trading volume per candle. | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| limit: Number of candles to fetch. | |
| Returns: | |
| Volume values for each candle and the latest volume. | |
| """ | |
| return hi.get_volume(name=name, interval=interval, limit=limit, testnet=False) | |
| async def bundle( | |
| name: str, | |
| interval: Interval = "1h", | |
| limit: int = 600, | |
| include: Optional[List[str]] = None, | |
| ema_periods: Optional[List[int]] = None, | |
| macd_fast: int = 12, | |
| macd_slow: int = 26, | |
| macd_signal: int = 9, | |
| stoch_rsi_len: int = 14, | |
| stoch_len: int = 14, | |
| k_smooth: int = 3, | |
| d_smooth: int = 3, | |
| bb_period: int = 20, | |
| bb_std: float = 2.0, | |
| mfi_period: int = 14, | |
| vwap_daily_reset: bool = False, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Compute multiple indicators in a single request. | |
| Args: | |
| name: Coin name. | |
| interval: Candle interval. | |
| limit: Number of candles to fetch. | |
| include: List of indicators to include. Default includes all: | |
| ["ema","macd","stoch_rsi","adl","obv","atr_adx","bbands","mfi","vwap","volume"] | |
| ema_periods: EMA periods (default: [20, 200]). | |
| macd_fast / macd_slow / macd_signal: MACD configuration. | |
| stoch_rsi_len / stoch_len / k_smooth / d_smooth: StochRSI configuration. | |
| bb_period / bb_std: Bollinger Band configuration. | |
| mfi_period: Money Flow Index lookback. | |
| vwap_daily_reset: Whether VWAP resets daily. | |
| Returns: | |
| A combined dictionary with all requested indicators. | |
| """ | |
| return hi.get_bundle( | |
| name=name, | |
| interval=interval, | |
| limit=limit, | |
| testnet=False, | |
| include=include or ("ema","macd","stoch_rsi","adl","obv","atr_adx","bbands","mfi","vwap","volume"), | |
| ema_periods=ema_periods, | |
| macd_fast=macd_fast, | |
| macd_slow=macd_slow, | |
| macd_signal=macd_signal, | |
| stoch_rsi_len=stoch_rsi_len, | |
| stoch_len=stoch_len, | |
| k_smooth=k_smooth, | |
| d_smooth=d_smooth, | |
| bb_period=bb_period, | |
| bb_std=bb_std, | |
| mfi_period=mfi_period, | |
| vwap_daily_reset=vwap_daily_reset, | |
| ) | |
| # ------------------ Entry point ------------------ # | |
| if __name__ == "__main__": | |
| mcp.run(transport='stdio') | |