interactive_trading_bot / hl_indicators_server.py
samsonleegh's picture
Upload 10 files
80fa9cc verified
# 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 ------------------ #
@mcp.tool()
async def ping() -> str:
"""Check if the MCP server is online and responding."""
return "pong"
# ------------------ Indicator tools ------------------ #
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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,
)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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)
@mcp.tool()
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')