samsonleegh commited on
Commit
75465af
·
verified ·
1 Parent(s): 80cbced

Update hl_indicators_server.py

Browse files
Files changed (1) hide show
  1. hl_indicators_server.py +325 -0
hl_indicators_server.py CHANGED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # hl_indicators_server.py
2
+ """
3
+ FastMCP server exposing Hyperliquid indicator tools.
4
+
5
+ This server provides a unified interface to compute common trading indicators
6
+ directly from Hyperliquid testnet market data via the `candles_snapshot` API.
7
+
8
+ Available tools:
9
+ - ema → Exponential Moving Average
10
+ - macd → Moving Average Convergence Divergence
11
+ - stoch_rsi → Stochastic RSI
12
+ - adl → Accumulation / Distribution Line
13
+ - obv → On-Balance Volume
14
+ - atr_adx → Average True Range / Directional Index / ADX
15
+ - bbands → Bollinger Bands
16
+ - mfi → Money Flow Index
17
+ - vwap → Volume-Weighted Average Price
18
+ - volume → Raw trading volume
19
+ - bundle → Compute multiple indicators in one call
20
+
21
+ Run:
22
+ python hl_indicators_server.py
23
+ """
24
+
25
+ from __future__ import annotations
26
+ from typing import List, Optional, Literal, Dict, Any
27
+
28
+ from mcp.server.fastmcp import FastMCP
29
+ import hl_indicators as hi
30
+
31
+ Interval = Literal["1m", "5m", "15m", "1h", "4h", "1d"]
32
+
33
+ mcp = FastMCP("hl_indicators_server")
34
+
35
+
36
+ # ------------------ Health check ------------------ #
37
+
38
+ @mcp.tool()
39
+ async def ping() -> str:
40
+ """Check if the MCP server is online and responding."""
41
+ return "pong"
42
+
43
+
44
+ # ------------------ Indicator tools ------------------ #
45
+
46
+ @mcp.tool()
47
+ async def ema(
48
+ name: str,
49
+ interval: Interval = "1h",
50
+ periods: Optional[List[int]] = None,
51
+ lookback: Optional[int] = None,
52
+ limit: int = 600,
53
+ ) -> Dict[str, Any]:
54
+ """
55
+ Compute Exponential Moving Averages (EMA).
56
+
57
+ Args:
58
+ name: Coin name (e.g. "BTC", "ETH", "HYPE").
59
+ interval: Candle interval ("1m", "5m", "15m", "1h", "4h", "1d").
60
+ periods: List of EMA window lengths (e.g. [20, 200]).
61
+ lookback: Optional shorthand for a single EMA (e.g. 36).
62
+ limit: Number of candles to fetch from the API.
63
+
64
+ Notes:
65
+ - `limit` controls how many data points are retrieved; it should be at
66
+ least 2–3× the largest EMA period for accurate results.
67
+ - The function automatically uses Hyperliquid testnet data.
68
+
69
+ Returns:
70
+ A dictionary containing EMA series for each period and the most recent values.
71
+ """
72
+ if periods is None and lookback is not None:
73
+ periods = [lookback]
74
+ return hi.get_ema(name=name, periods=periods, interval=interval, limit=limit, testnet=False)
75
+
76
+
77
+ @mcp.tool()
78
+ async def macd(
79
+ name: str,
80
+ interval: Interval = "1h",
81
+ fast: int = 12,
82
+ slow: int = 26,
83
+ signal: int = 9,
84
+ limit: int = 600,
85
+ ) -> Dict[str, Any]:
86
+ """
87
+ Compute the Moving Average Convergence Divergence (MACD).
88
+
89
+ Args:
90
+ name: Coin name (e.g. "BTC").
91
+ interval: Candle interval.
92
+ fast: Period for the fast EMA (default: 12).
93
+ slow: Period for the slow EMA (default: 26).
94
+ signal: Period for the MACD signal line (default: 9).
95
+ limit: Number of candles to fetch.
96
+
97
+ Returns:
98
+ A dictionary with MACD line, signal line, histogram, and last computed values.
99
+ """
100
+ return hi.get_macd(name=name, fast=fast, slow=slow, signal=signal, interval=interval, limit=limit, testnet=False)
101
+
102
+
103
+ @mcp.tool()
104
+ async def stoch_rsi(
105
+ name: str,
106
+ interval: Interval = "1h",
107
+ rsi_length: int = 14,
108
+ stoch_length: int = 14,
109
+ k_smooth: int = 3,
110
+ d_smooth: int = 3,
111
+ limit: int = 600,
112
+ ) -> Dict[str, Any]:
113
+ """
114
+ Compute the Stochastic RSI oscillator (%K and %D).
115
+
116
+ Args:
117
+ name: Coin name.
118
+ interval: Candle interval.
119
+ rsi_length: Period for RSI computation (default: 14).
120
+ stoch_length: Period for Stochastic window (default: 14).
121
+ k_smooth: Smoothing factor for %K (default: 3).
122
+ d_smooth: Smoothing factor for %D (default: 3).
123
+ limit: Number of candles to fetch.
124
+
125
+ Returns:
126
+ A dictionary containing %K, %D, and the raw StochRSI values.
127
+ """
128
+ return hi.get_stoch_rsi(
129
+ name=name,
130
+ rsi_length=rsi_length,
131
+ stoch_length=stoch_length,
132
+ k_smooth=k_smooth,
133
+ d_smooth=d_smooth,
134
+ interval=interval,
135
+ limit=limit,
136
+ testnet=False,
137
+ )
138
+
139
+
140
+ @mcp.tool()
141
+ async def adl(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]:
142
+ """
143
+ Compute the Accumulation/Distribution Line (ADL).
144
+
145
+ Args:
146
+ name: Coin name.
147
+ interval: Candle interval.
148
+ limit: Number of candles to fetch.
149
+
150
+ Returns:
151
+ A dictionary containing the ADL time series and the latest ADL value.
152
+ """
153
+ return hi.get_adl(name=name, interval=interval, limit=limit, testnet=False)
154
+
155
+
156
+ @mcp.tool()
157
+ async def obv(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]:
158
+ """
159
+ Compute the On-Balance Volume (OBV).
160
+
161
+ Args:
162
+ name: Coin name.
163
+ interval: Candle interval.
164
+ limit: Number of candles to fetch.
165
+
166
+ Returns:
167
+ OBV values accumulated over time and the latest OBV.
168
+ """
169
+ return hi.get_obv(name=name, interval=interval, limit=limit, testnet=False)
170
+
171
+
172
+ @mcp.tool()
173
+ async def atr_adx(name: str, interval: Interval = "1h", period: int = 14, limit: int = 600) -> Dict[str, Any]:
174
+ """
175
+ Compute volatility and directional indicators: ATR, +DI, -DI, and ADX.
176
+
177
+ Args:
178
+ name: Coin name.
179
+ interval: Candle interval.
180
+ period: Lookback for smoothing (default: 14).
181
+ limit: Number of candles to fetch.
182
+
183
+ Returns:
184
+ A dictionary with ATR, +DI, -DI, and ADX values.
185
+ """
186
+ return hi.get_atr_adx(name=name, period=period, interval=interval, limit=limit, testnet=False)
187
+
188
+
189
+ @mcp.tool()
190
+ async def bbands(
191
+ name: str,
192
+ interval: Interval = "1h",
193
+ period: int = 20,
194
+ std_mult: float = 2.0,
195
+ limit: int = 600,
196
+ ) -> Dict[str, Any]:
197
+ """
198
+ Compute Bollinger Bands (basis, upper/lower bands, %b, bandwidth).
199
+
200
+ Args:
201
+ name: Coin name.
202
+ interval: Candle interval.
203
+ period: Window for SMA (default: 20).
204
+ std_mult: Standard deviation multiplier (default: 2.0).
205
+ limit: Number of candles to fetch.
206
+
207
+ Returns:
208
+ A dictionary with band series and the most recent band values.
209
+ """
210
+ return hi.get_bbands(name=name, period=period, std_mult=std_mult, interval=interval, limit=limit, testnet=False)
211
+
212
+
213
+ @mcp.tool()
214
+ async def mfi(name: str, interval: Interval = "1h", period: int = 14, limit: int = 600) -> Dict[str, Any]:
215
+ """
216
+ Compute the Money Flow Index (MFI), a volume-weighted momentum oscillator.
217
+
218
+ Args:
219
+ name: Coin name.
220
+ interval: Candle interval.
221
+ period: Rolling window (default: 14).
222
+ limit: Number of candles to fetch.
223
+
224
+ Returns:
225
+ A dictionary containing MFI series and the most recent value.
226
+ """
227
+ return hi.get_mfi(name=name, period=period, interval=interval, limit=limit, testnet=False)
228
+
229
+
230
+ @mcp.tool()
231
+ async def vwap(name: str, interval: Interval = "1h", daily_reset: bool = False, limit: int = 600) -> Dict[str, Any]:
232
+ """
233
+ Compute the Volume-Weighted Average Price (VWAP).
234
+
235
+ Args:
236
+ name: Coin name.
237
+ interval: Candle interval.
238
+ daily_reset: If True, VWAP resets each trading day.
239
+ limit: Number of candles to fetch.
240
+
241
+ Returns:
242
+ VWAP time series and the last computed VWAP value.
243
+ """
244
+ return hi.get_vwap(name=name, daily_reset=daily_reset, interval=interval, limit=limit, testnet=False)
245
+
246
+
247
+ @mcp.tool()
248
+ async def volume(name: str, interval: Interval = "1h", limit: int = 600) -> Dict[str, Any]:
249
+ """
250
+ Retrieve the raw trading volume per candle.
251
+
252
+ Args:
253
+ name: Coin name.
254
+ interval: Candle interval.
255
+ limit: Number of candles to fetch.
256
+
257
+ Returns:
258
+ Volume values for each candle and the latest volume.
259
+ """
260
+ return hi.get_volume(name=name, interval=interval, limit=limit, testnet=False)
261
+
262
+
263
+ @mcp.tool()
264
+ async def bundle(
265
+ name: str,
266
+ interval: Interval = "1h",
267
+ limit: int = 600,
268
+ include: Optional[List[str]] = None,
269
+ ema_periods: Optional[List[int]] = None,
270
+ macd_fast: int = 12,
271
+ macd_slow: int = 26,
272
+ macd_signal: int = 9,
273
+ stoch_rsi_len: int = 14,
274
+ stoch_len: int = 14,
275
+ k_smooth: int = 3,
276
+ d_smooth: int = 3,
277
+ bb_period: int = 20,
278
+ bb_std: float = 2.0,
279
+ mfi_period: int = 14,
280
+ vwap_daily_reset: bool = False,
281
+ ) -> Dict[str, Any]:
282
+ """
283
+ Compute multiple indicators in a single request.
284
+
285
+ Args:
286
+ name: Coin name.
287
+ interval: Candle interval.
288
+ limit: Number of candles to fetch.
289
+ include: List of indicators to include. Default includes all:
290
+ ["ema","macd","stoch_rsi","adl","obv","atr_adx","bbands","mfi","vwap","volume"]
291
+ ema_periods: EMA periods (default: [20, 200]).
292
+ macd_fast / macd_slow / macd_signal: MACD configuration.
293
+ stoch_rsi_len / stoch_len / k_smooth / d_smooth: StochRSI configuration.
294
+ bb_period / bb_std: Bollinger Band configuration.
295
+ mfi_period: Money Flow Index lookback.
296
+ vwap_daily_reset: Whether VWAP resets daily.
297
+
298
+ Returns:
299
+ A combined dictionary with all requested indicators.
300
+ """
301
+ return hi.get_bundle(
302
+ name=name,
303
+ interval=interval,
304
+ limit=limit,
305
+ testnet=False,
306
+ include=include or ("ema","macd","stoch_rsi","adl","obv","atr_adx","bbands","mfi","vwap","volume"),
307
+ ema_periods=ema_periods,
308
+ macd_fast=macd_fast,
309
+ macd_slow=macd_slow,
310
+ macd_signal=macd_signal,
311
+ stoch_rsi_len=stoch_rsi_len,
312
+ stoch_len=stoch_len,
313
+ k_smooth=k_smooth,
314
+ d_smooth=d_smooth,
315
+ bb_period=bb_period,
316
+ bb_std=bb_std,
317
+ mfi_period=mfi_period,
318
+ vwap_daily_reset=vwap_daily_reset,
319
+ )
320
+
321
+
322
+ # ------------------ Entry point ------------------ #
323
+
324
+ if __name__ == "__main__":
325
+ mcp.run(transport='stdio')