@hummingbot/skills 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/package.json +28 -0
- package/skills/candles-feed/SKILL.md +259 -0
- package/skills/candles-feed/scripts/calculate_indicator.sh +359 -0
- package/skills/candles-feed/scripts/get_candles.sh +158 -0
- package/skills/candles-feed/scripts/get_funding_rate.sh +112 -0
- package/skills/candles-feed/scripts/get_price.sh +86 -0
- package/skills/candles-feed/scripts/list_candle_connectors.sh +47 -0
- package/skills/executor-creator/SKILL.md +212 -0
- package/skills/executor-creator/scripts/clear_position.sh +54 -0
- package/skills/executor-creator/scripts/create_executor.sh +92 -0
- package/skills/executor-creator/scripts/get_executor.sh +37 -0
- package/skills/executor-creator/scripts/get_executor_schema.sh +37 -0
- package/skills/executor-creator/scripts/get_executors_summary.sh +30 -0
- package/skills/executor-creator/scripts/get_position.sh +44 -0
- package/skills/executor-creator/scripts/get_positions.sh +30 -0
- package/skills/executor-creator/scripts/list_executor_types.sh +30 -0
- package/skills/executor-creator/scripts/list_executors.sh +52 -0
- package/skills/executor-creator/scripts/setup_executor.sh +197 -0
- package/skills/executor-creator/scripts/stop_executor.sh +54 -0
- package/skills/hummingbot-api-setup/SKILL.md +308 -0
- package/skills/hummingbot-api-setup/references/original_setup.sh +628 -0
- package/skills/hummingbot-api-setup/scripts/check_prerequisites.sh +92 -0
- package/skills/hummingbot-api-setup/scripts/deploy_full_stack.sh +151 -0
- package/skills/hummingbot-api-setup/scripts/health_check.sh +100 -0
- package/skills/hummingbot-api-setup/scripts/step1_detect_system.sh +88 -0
- package/skills/hummingbot-api-setup/scripts/step2_check_dependencies.sh +81 -0
- package/skills/keys-manager/SKILL.md +132 -0
- package/skills/keys-manager/scripts/add_credentials.sh +106 -0
- package/skills/keys-manager/scripts/get_connector_config.sh +67 -0
- package/skills/keys-manager/scripts/list_account_credentials.sh +82 -0
- package/skills/keys-manager/scripts/list_connectors.sh +64 -0
- package/skills/keys-manager/scripts/remove_credentials.sh +79 -0
- package/skills/keys-manager/scripts/setup_connector.sh +214 -0
- package/skills.json +137 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Hummingbot Skills
|
|
2
|
+
|
|
3
|
+
AI agent skills for [Hummingbot](https://hummingbot.org) algorithmic trading infrastructure.
|
|
4
|
+
|
|
5
|
+
Built on the [Agent Skills](https://agentskills.io) open standard.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx skills add hummingbot/skills
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install a specific skill:
|
|
14
|
+
```bash
|
|
15
|
+
npx skills add hummingbot/skills --skill executor-creator
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
After installing, ask your AI agent:
|
|
21
|
+
|
|
22
|
+
- "Create a BTC position with 2% stop loss and 4% take profit"
|
|
23
|
+
- "Show me the RSI for ETH on Binance"
|
|
24
|
+
- "Add my Binance API keys"
|
|
25
|
+
- "Set up Hummingbot with Docker"
|
|
26
|
+
|
|
27
|
+
## Available Skills
|
|
28
|
+
|
|
29
|
+
| Skill | Description |
|
|
30
|
+
|-------|-------------|
|
|
31
|
+
| [hummingbot-api-setup](./skills/hummingbot-api-setup/) | Deploy Hummingbot infrastructure (Docker, API, Gateway) |
|
|
32
|
+
| [keys-manager](./skills/keys-manager/) | Manage exchange API credentials |
|
|
33
|
+
| [executor-creator](./skills/executor-creator/) | Create trading executors (position, grid, DCA, TWAP) |
|
|
34
|
+
| [candles-feed](./skills/candles-feed/) | Fetch market data and technical indicators |
|
|
35
|
+
|
|
36
|
+
## Prerequisites
|
|
37
|
+
|
|
38
|
+
Skills interact with the Hummingbot API server:
|
|
39
|
+
- **URL**: `http://localhost:8000`
|
|
40
|
+
- **Credentials**: `admin:admin`
|
|
41
|
+
- **Docs**: `http://localhost:8000/docs`
|
|
42
|
+
|
|
43
|
+
Use the `hummingbot-api-setup` skill to deploy the API server.
|
|
44
|
+
|
|
45
|
+
## Repository Structure
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
hummingbot/skills/
|
|
49
|
+
├── skills/ # Skill definitions
|
|
50
|
+
│ ├── hummingbot-api-setup/ # Infrastructure setup
|
|
51
|
+
│ │ ├── SKILL.md
|
|
52
|
+
│ │ └── scripts/
|
|
53
|
+
│ ├── keys-manager/ # API credentials
|
|
54
|
+
│ ├── executor-creator/ # Trading executors
|
|
55
|
+
│ └── candles-feed/ # Market data
|
|
56
|
+
└── skills.json # Skill metadata (for webapp)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Links
|
|
60
|
+
|
|
61
|
+
- [Hummingbot](https://hummingbot.org)
|
|
62
|
+
- [skills.sh](https://skills.sh)
|
|
63
|
+
- [Agent Skills Spec](https://agentskills.io)
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hummingbot/skills",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI agent skills for Hummingbot algorithmic trading infrastructure",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hummingbot",
|
|
7
|
+
"trading",
|
|
8
|
+
"crypto",
|
|
9
|
+
"ai-agent",
|
|
10
|
+
"skills",
|
|
11
|
+
"algorithmic-trading"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://skills.hummingbot.org",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/hummingbot/skills.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "Apache-2.0",
|
|
19
|
+
"author": "Hummingbot Foundation <dev@hummingbot.org>",
|
|
20
|
+
"files": [
|
|
21
|
+
"skills/",
|
|
22
|
+
"skills.json",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: candles-feed
|
|
3
|
+
description: Fetch market data (OHLCV candles) and calculate technical indicators (RSI, EMA, MACD, Bollinger Bands) from exchanges via Hummingbot API. Use this skill when the user needs price data, candlestick charts, or technical analysis.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Hummingbot Candles Skill
|
|
8
|
+
|
|
9
|
+
This skill fetches candlestick (OHLCV) data from exchanges and calculates technical indicators. It provides the data foundation for strategy development and market analysis.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- Hummingbot API server must be running (use the setup skill)
|
|
14
|
+
- Exchange connector must support candle data
|
|
15
|
+
|
|
16
|
+
## Capabilities
|
|
17
|
+
|
|
18
|
+
### 1. Get Available Connectors
|
|
19
|
+
|
|
20
|
+
List exchanges that support candle data:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
./scripts/list_candle_connectors.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Fetch Candles
|
|
27
|
+
|
|
28
|
+
Get OHLCV data for a trading pair:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
./scripts/get_candles.sh \
|
|
32
|
+
--connector binance \
|
|
33
|
+
--pair BTC-USDT \
|
|
34
|
+
--interval 1h \
|
|
35
|
+
--days 30
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Supported intervals: `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`, `1w`
|
|
39
|
+
|
|
40
|
+
### 3. Calculate Indicators
|
|
41
|
+
|
|
42
|
+
Calculate technical indicators on candle data:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# RSI (Relative Strength Index)
|
|
46
|
+
./scripts/calculate_indicator.sh \
|
|
47
|
+
--connector binance \
|
|
48
|
+
--pair BTC-USDT \
|
|
49
|
+
--indicator rsi \
|
|
50
|
+
--period 14
|
|
51
|
+
|
|
52
|
+
# EMA (Exponential Moving Average)
|
|
53
|
+
./scripts/calculate_indicator.sh \
|
|
54
|
+
--connector binance \
|
|
55
|
+
--pair BTC-USDT \
|
|
56
|
+
--indicator ema \
|
|
57
|
+
--period 20
|
|
58
|
+
|
|
59
|
+
# MACD (Moving Average Convergence Divergence)
|
|
60
|
+
./scripts/calculate_indicator.sh \
|
|
61
|
+
--connector binance \
|
|
62
|
+
--pair BTC-USDT \
|
|
63
|
+
--indicator macd \
|
|
64
|
+
--fast 12 \
|
|
65
|
+
--slow 26 \
|
|
66
|
+
--signal 9
|
|
67
|
+
|
|
68
|
+
# Bollinger Bands
|
|
69
|
+
./scripts/calculate_indicator.sh \
|
|
70
|
+
--connector binance \
|
|
71
|
+
--pair BTC-USDT \
|
|
72
|
+
--indicator bb \
|
|
73
|
+
--period 20 \
|
|
74
|
+
--std 2
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 4. Get Current Price
|
|
78
|
+
|
|
79
|
+
Get the latest price for trading pairs:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
./scripts/get_price.sh \
|
|
83
|
+
--connector binance \
|
|
84
|
+
--pairs "BTC-USDT,ETH-USDT"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 5. Get Funding Rate (Perpetuals)
|
|
88
|
+
|
|
89
|
+
Get funding rate for perpetual contracts:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
./scripts/get_funding_rate.sh \
|
|
93
|
+
--connector binance_perpetual \
|
|
94
|
+
--pair BTC-USDT
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Supported Indicators
|
|
98
|
+
|
|
99
|
+
| Indicator | Code | Parameters | Description |
|
|
100
|
+
|-----------|------|------------|-------------|
|
|
101
|
+
| RSI | `rsi` | period | Relative Strength Index |
|
|
102
|
+
| EMA | `ema` | period | Exponential Moving Average |
|
|
103
|
+
| SMA | `sma` | period | Simple Moving Average |
|
|
104
|
+
| MACD | `macd` | fast, slow, signal | Moving Average Convergence Divergence |
|
|
105
|
+
| Bollinger Bands | `bb` | period, std | Volatility bands |
|
|
106
|
+
| ATR | `atr` | period | Average True Range |
|
|
107
|
+
| VWAP | `vwap` | - | Volume Weighted Average Price |
|
|
108
|
+
| Stochastic | `stoch` | k_period, d_period | Stochastic Oscillator |
|
|
109
|
+
|
|
110
|
+
## Candle Data Format
|
|
111
|
+
|
|
112
|
+
Returned candle data includes:
|
|
113
|
+
|
|
114
|
+
| Field | Type | Description |
|
|
115
|
+
|-------|------|-------------|
|
|
116
|
+
| `timestamp` | int | Unix timestamp (ms) |
|
|
117
|
+
| `open` | float | Opening price |
|
|
118
|
+
| `high` | float | Highest price |
|
|
119
|
+
| `low` | float | Lowest price |
|
|
120
|
+
| `close` | float | Closing price |
|
|
121
|
+
| `volume` | float | Trading volume |
|
|
122
|
+
|
|
123
|
+
Example output:
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"candles": [
|
|
127
|
+
{
|
|
128
|
+
"timestamp": 1706400000000,
|
|
129
|
+
"open": 42150.5,
|
|
130
|
+
"high": 42300.0,
|
|
131
|
+
"low": 42100.0,
|
|
132
|
+
"close": 42250.0,
|
|
133
|
+
"volume": 1250.5
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"interval": "1h",
|
|
137
|
+
"total_candles": 720
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Indicator Output
|
|
142
|
+
|
|
143
|
+
### RSI Output
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"indicator": "rsi",
|
|
147
|
+
"period": 14,
|
|
148
|
+
"current_value": 65.5,
|
|
149
|
+
"signal": "neutral",
|
|
150
|
+
"interpretation": {
|
|
151
|
+
"overbought": 70,
|
|
152
|
+
"oversold": 30,
|
|
153
|
+
"description": "RSI at 65.5 indicates slightly bullish momentum"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### MACD Output
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"indicator": "macd",
|
|
162
|
+
"current_values": {
|
|
163
|
+
"macd_line": 125.5,
|
|
164
|
+
"signal_line": 110.2,
|
|
165
|
+
"histogram": 15.3
|
|
166
|
+
},
|
|
167
|
+
"signal": "bullish",
|
|
168
|
+
"interpretation": "MACD above signal line, positive momentum"
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Bollinger Bands Output
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"indicator": "bb",
|
|
176
|
+
"period": 20,
|
|
177
|
+
"std": 2,
|
|
178
|
+
"current_values": {
|
|
179
|
+
"upper": 43500.0,
|
|
180
|
+
"middle": 42000.0,
|
|
181
|
+
"lower": 40500.0,
|
|
182
|
+
"current_price": 42250.0
|
|
183
|
+
},
|
|
184
|
+
"position": "middle",
|
|
185
|
+
"bandwidth": 0.071
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Workflow: Market Analysis
|
|
190
|
+
|
|
191
|
+
1. **Check available connectors**
|
|
192
|
+
```bash
|
|
193
|
+
./scripts/list_candle_connectors.sh
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
2. **Fetch candle data**
|
|
197
|
+
```bash
|
|
198
|
+
./scripts/get_candles.sh --connector binance --pair BTC-USDT --interval 4h --days 30
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
3. **Calculate indicators**
|
|
202
|
+
```bash
|
|
203
|
+
# Get RSI
|
|
204
|
+
./scripts/calculate_indicator.sh --connector binance --pair BTC-USDT --indicator rsi --period 14
|
|
205
|
+
|
|
206
|
+
# Get EMA crossover
|
|
207
|
+
./scripts/calculate_indicator.sh --connector binance --pair BTC-USDT --indicator ema --period 20
|
|
208
|
+
./scripts/calculate_indicator.sh --connector binance --pair BTC-USDT --indicator ema --period 50
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
4. **Interpret signals**
|
|
212
|
+
- RSI > 70: Overbought, potential sell signal
|
|
213
|
+
- RSI < 30: Oversold, potential buy signal
|
|
214
|
+
- EMA(20) > EMA(50): Bullish trend
|
|
215
|
+
- EMA(20) < EMA(50): Bearish trend
|
|
216
|
+
|
|
217
|
+
## API Endpoints Used
|
|
218
|
+
|
|
219
|
+
All requests go to `http://localhost:8000` with Basic Auth (`admin:admin`):
|
|
220
|
+
|
|
221
|
+
| Endpoint | Method | Description |
|
|
222
|
+
|----------|--------|-------------|
|
|
223
|
+
| `/market-data/available-candle-connectors` | GET | List connectors with candle support |
|
|
224
|
+
| `/market-data/historical-candles` | POST | Fetch bulk historical OHLCV data |
|
|
225
|
+
| `/market-data/candles` | POST | Fetch real-time OHLCV data |
|
|
226
|
+
| `/market-data/prices` | POST | Get current prices |
|
|
227
|
+
| `/market-data/funding-info` | POST | Get funding rates |
|
|
228
|
+
|
|
229
|
+
## Data Fetching Strategy
|
|
230
|
+
|
|
231
|
+
Scripts use a dual-fetch approach for comprehensive data:
|
|
232
|
+
1. **Historical candles** - Bulk data from `/market-data/historical-candles`
|
|
233
|
+
2. **Real-time candles** - Latest data from `/market-data/candles`
|
|
234
|
+
3. **Merge** - Deduplicate by timestamp, real-time overrides historical
|
|
235
|
+
|
|
236
|
+
## Environment Variables
|
|
237
|
+
|
|
238
|
+
| Variable | Default | Description |
|
|
239
|
+
|----------|---------|-------------|
|
|
240
|
+
| `API_URL` | `http://localhost:8000` | API base URL |
|
|
241
|
+
| `API_USER` | `admin` | API username |
|
|
242
|
+
| `API_PASS` | `admin` | API password |
|
|
243
|
+
|
|
244
|
+
## Error Handling
|
|
245
|
+
|
|
246
|
+
| Error | Cause | Solution |
|
|
247
|
+
|-------|-------|----------|
|
|
248
|
+
| "Connector not supported" | Exchange doesn't support candles | Use list_candle_connectors |
|
|
249
|
+
| "Invalid interval" | Unsupported interval format | Use 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w |
|
|
250
|
+
| "Rate limited" | Too many requests | Wait and retry |
|
|
251
|
+
| "Invalid trading pair" | Pair not available | Check exchange for valid pairs |
|
|
252
|
+
|
|
253
|
+
## Notes
|
|
254
|
+
|
|
255
|
+
- Candle data is fetched directly from exchanges via the Hummingbot API
|
|
256
|
+
- Indicators are calculated locally using the fetched candle data
|
|
257
|
+
- Historical data availability varies by exchange (typically 30-90 days)
|
|
258
|
+
- For real-time data, consider shorter intervals (1m, 5m)
|
|
259
|
+
- For trend analysis, use longer intervals (4h, 1d)
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Calculate technical indicators on candle data
|
|
3
|
+
# Usage: ./calculate_indicator.sh --connector CONNECTOR --pair PAIR --indicator INDICATOR [--period PERIOD] [options]
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
API_URL="${API_URL:-http://localhost:8000}"
|
|
8
|
+
API_USER="${API_USER:-admin}"
|
|
9
|
+
API_PASS="${API_PASS:-admin}"
|
|
10
|
+
CONNECTOR=""
|
|
11
|
+
TRADING_PAIR=""
|
|
12
|
+
INDICATOR=""
|
|
13
|
+
PERIOD=14
|
|
14
|
+
INTERVAL="1h"
|
|
15
|
+
DAYS=30
|
|
16
|
+
# MACD specific
|
|
17
|
+
FAST=12
|
|
18
|
+
SLOW=26
|
|
19
|
+
SIGNAL=9
|
|
20
|
+
# BB specific
|
|
21
|
+
STD=2
|
|
22
|
+
|
|
23
|
+
# Parse arguments
|
|
24
|
+
while [[ $# -gt 0 ]]; do
|
|
25
|
+
case $1 in
|
|
26
|
+
--connector)
|
|
27
|
+
CONNECTOR="$2"
|
|
28
|
+
shift 2
|
|
29
|
+
;;
|
|
30
|
+
--pair)
|
|
31
|
+
TRADING_PAIR="$2"
|
|
32
|
+
shift 2
|
|
33
|
+
;;
|
|
34
|
+
--indicator)
|
|
35
|
+
INDICATOR="$2"
|
|
36
|
+
shift 2
|
|
37
|
+
;;
|
|
38
|
+
--period)
|
|
39
|
+
PERIOD="$2"
|
|
40
|
+
shift 2
|
|
41
|
+
;;
|
|
42
|
+
--interval)
|
|
43
|
+
INTERVAL="$2"
|
|
44
|
+
shift 2
|
|
45
|
+
;;
|
|
46
|
+
--days)
|
|
47
|
+
DAYS="$2"
|
|
48
|
+
shift 2
|
|
49
|
+
;;
|
|
50
|
+
--fast)
|
|
51
|
+
FAST="$2"
|
|
52
|
+
shift 2
|
|
53
|
+
;;
|
|
54
|
+
--slow)
|
|
55
|
+
SLOW="$2"
|
|
56
|
+
shift 2
|
|
57
|
+
;;
|
|
58
|
+
--signal)
|
|
59
|
+
SIGNAL="$2"
|
|
60
|
+
shift 2
|
|
61
|
+
;;
|
|
62
|
+
--std)
|
|
63
|
+
STD="$2"
|
|
64
|
+
shift 2
|
|
65
|
+
;;
|
|
66
|
+
--api-url)
|
|
67
|
+
API_URL="$2"
|
|
68
|
+
shift 2
|
|
69
|
+
;;
|
|
70
|
+
--api-user)
|
|
71
|
+
API_USER="$2"
|
|
72
|
+
shift 2
|
|
73
|
+
;;
|
|
74
|
+
--api-pass)
|
|
75
|
+
API_PASS="$2"
|
|
76
|
+
shift 2
|
|
77
|
+
;;
|
|
78
|
+
*)
|
|
79
|
+
shift
|
|
80
|
+
;;
|
|
81
|
+
esac
|
|
82
|
+
done
|
|
83
|
+
|
|
84
|
+
# Validate required arguments
|
|
85
|
+
if [ -z "$CONNECTOR" ]; then
|
|
86
|
+
echo '{"error": "connector is required. Use --connector CONNECTOR_NAME"}'
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if [ -z "$TRADING_PAIR" ]; then
|
|
91
|
+
echo '{"error": "trading pair is required. Use --pair TRADING_PAIR"}'
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
if [ -z "$INDICATOR" ]; then
|
|
96
|
+
echo '{"error": "indicator is required. Use --indicator [rsi|ema|sma|macd|bb|atr]"}'
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Calculate max records needed
|
|
101
|
+
case "$INTERVAL" in
|
|
102
|
+
*m)
|
|
103
|
+
MINUTES=${INTERVAL%m}
|
|
104
|
+
MAX_RECORDS=$((1440 * DAYS / MINUTES))
|
|
105
|
+
;;
|
|
106
|
+
*h)
|
|
107
|
+
HOURS=${INTERVAL%h}
|
|
108
|
+
MAX_RECORDS=$((24 * DAYS / HOURS))
|
|
109
|
+
;;
|
|
110
|
+
*d)
|
|
111
|
+
MAX_RECORDS=$DAYS
|
|
112
|
+
;;
|
|
113
|
+
*)
|
|
114
|
+
MAX_RECORDS=$((24 * DAYS))
|
|
115
|
+
;;
|
|
116
|
+
esac
|
|
117
|
+
|
|
118
|
+
# Calculate timestamps for historical fetch
|
|
119
|
+
END_TIME=$(date +%s)
|
|
120
|
+
START_TIME=$((END_TIME - DAYS * 24 * 3600))
|
|
121
|
+
|
|
122
|
+
# Fetch historical candles
|
|
123
|
+
HISTORICAL=$(curl -s -u "$API_USER:$API_PASS" \
|
|
124
|
+
-X POST "$API_URL/market-data/historical-candles" \
|
|
125
|
+
-H "Content-Type: application/json" \
|
|
126
|
+
-d "{\"connector_name\": \"$CONNECTOR\", \"trading_pair\": \"$TRADING_PAIR\", \"interval\": \"$INTERVAL\", \"start_time\": $START_TIME, \"end_time\": $END_TIME}" 2>/dev/null || echo "[]")
|
|
127
|
+
|
|
128
|
+
# Fetch real-time candles
|
|
129
|
+
REALTIME=$(curl -s -u "$API_USER:$API_PASS" \
|
|
130
|
+
-X POST "$API_URL/market-data/candles" \
|
|
131
|
+
-H "Content-Type: application/json" \
|
|
132
|
+
-d "{\"connector_name\": \"$CONNECTOR\", \"trading_pair\": \"$TRADING_PAIR\", \"interval\": \"$INTERVAL\", \"max_records\": 100}" 2>/dev/null || echo "[]")
|
|
133
|
+
|
|
134
|
+
# Merge and deduplicate by timestamp
|
|
135
|
+
CANDLES=$(echo "$HISTORICAL $REALTIME" | jq -s '.[0] + .[1] | group_by(.timestamp) | map(.[0]) | sort_by(.timestamp)')
|
|
136
|
+
|
|
137
|
+
if echo "$CANDLES" | jq -e '.detail' > /dev/null 2>&1; then
|
|
138
|
+
echo "{\"error\": \"Failed to fetch candles\", \"detail\": $CANDLES}"
|
|
139
|
+
exit 1
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# Extract close prices (compact JSON to avoid newline issues in heredoc)
|
|
143
|
+
CLOSES=$(echo "$CANDLES" | jq -c '[.[].close]')
|
|
144
|
+
HIGHS=$(echo "$CANDLES" | jq -c '[.[].high]')
|
|
145
|
+
LOWS=$(echo "$CANDLES" | jq -c '[.[].low]')
|
|
146
|
+
VOLUMES=$(echo "$CANDLES" | jq -c '[.[].volume]')
|
|
147
|
+
TOTAL=$(echo "$CANDLES" | jq 'length')
|
|
148
|
+
|
|
149
|
+
# Calculate indicator using Python (for accurate calculations)
|
|
150
|
+
calculate_with_python() {
|
|
151
|
+
python3 << PYTHON_SCRIPT
|
|
152
|
+
import json
|
|
153
|
+
import sys
|
|
154
|
+
|
|
155
|
+
closes = json.loads('$CLOSES')
|
|
156
|
+
highs = json.loads('$HIGHS')
|
|
157
|
+
lows = json.loads('$LOWS')
|
|
158
|
+
volumes = json.loads('$VOLUMES')
|
|
159
|
+
indicator = '$INDICATOR'
|
|
160
|
+
period = int('$PERIOD')
|
|
161
|
+
fast = int('$FAST')
|
|
162
|
+
slow = int('$SLOW')
|
|
163
|
+
signal_period = int('$SIGNAL')
|
|
164
|
+
std_dev = float('$STD')
|
|
165
|
+
|
|
166
|
+
def sma(data, period):
|
|
167
|
+
if len(data) < period:
|
|
168
|
+
return None
|
|
169
|
+
return sum(data[-period:]) / period
|
|
170
|
+
|
|
171
|
+
def ema(data, period):
|
|
172
|
+
if len(data) < period:
|
|
173
|
+
return None
|
|
174
|
+
multiplier = 2 / (period + 1)
|
|
175
|
+
ema_val = sum(data[:period]) / period
|
|
176
|
+
for price in data[period:]:
|
|
177
|
+
ema_val = (price - ema_val) * multiplier + ema_val
|
|
178
|
+
return ema_val
|
|
179
|
+
|
|
180
|
+
def rsi(data, period):
|
|
181
|
+
if len(data) < period + 1:
|
|
182
|
+
return None
|
|
183
|
+
gains = []
|
|
184
|
+
losses = []
|
|
185
|
+
for i in range(1, len(data)):
|
|
186
|
+
change = data[i] - data[i-1]
|
|
187
|
+
if change > 0:
|
|
188
|
+
gains.append(change)
|
|
189
|
+
losses.append(0)
|
|
190
|
+
else:
|
|
191
|
+
gains.append(0)
|
|
192
|
+
losses.append(abs(change))
|
|
193
|
+
|
|
194
|
+
avg_gain = sum(gains[-period:]) / period
|
|
195
|
+
avg_loss = sum(losses[-period:]) / period
|
|
196
|
+
|
|
197
|
+
if avg_loss == 0:
|
|
198
|
+
return 100
|
|
199
|
+
rs = avg_gain / avg_loss
|
|
200
|
+
return 100 - (100 / (1 + rs))
|
|
201
|
+
|
|
202
|
+
def macd(data, fast_period, slow_period, signal_period):
|
|
203
|
+
if len(data) < slow_period:
|
|
204
|
+
return None, None, None
|
|
205
|
+
fast_ema = ema(data, fast_period)
|
|
206
|
+
slow_ema = ema(data, slow_period)
|
|
207
|
+
macd_line = fast_ema - slow_ema
|
|
208
|
+
|
|
209
|
+
# Calculate signal line (EMA of MACD)
|
|
210
|
+
macd_values = []
|
|
211
|
+
for i in range(slow_period, len(data)):
|
|
212
|
+
subset = data[:i+1]
|
|
213
|
+
f = ema(subset, fast_period)
|
|
214
|
+
s = ema(subset, slow_period)
|
|
215
|
+
macd_values.append(f - s)
|
|
216
|
+
|
|
217
|
+
signal_line = ema(macd_values, signal_period) if len(macd_values) >= signal_period else macd_line
|
|
218
|
+
histogram = macd_line - signal_line
|
|
219
|
+
|
|
220
|
+
return macd_line, signal_line, histogram
|
|
221
|
+
|
|
222
|
+
def bollinger_bands(data, period, std_multiplier):
|
|
223
|
+
if len(data) < period:
|
|
224
|
+
return None, None, None
|
|
225
|
+
middle = sma(data, period)
|
|
226
|
+
variance = sum((x - middle) ** 2 for x in data[-period:]) / period
|
|
227
|
+
std = variance ** 0.5
|
|
228
|
+
upper = middle + (std_multiplier * std)
|
|
229
|
+
lower = middle - (std_multiplier * std)
|
|
230
|
+
return upper, middle, lower
|
|
231
|
+
|
|
232
|
+
def atr(highs, lows, closes, period):
|
|
233
|
+
if len(closes) < period + 1:
|
|
234
|
+
return None
|
|
235
|
+
tr_values = []
|
|
236
|
+
for i in range(1, len(closes)):
|
|
237
|
+
hl = highs[i] - lows[i]
|
|
238
|
+
hc = abs(highs[i] - closes[i-1])
|
|
239
|
+
lc = abs(lows[i] - closes[i-1])
|
|
240
|
+
tr_values.append(max(hl, hc, lc))
|
|
241
|
+
return sum(tr_values[-period:]) / period
|
|
242
|
+
|
|
243
|
+
result = {}
|
|
244
|
+
current_price = closes[-1] if closes else 0
|
|
245
|
+
|
|
246
|
+
if indicator == 'rsi':
|
|
247
|
+
value = rsi(closes, period)
|
|
248
|
+
if value is not None:
|
|
249
|
+
if value > 70:
|
|
250
|
+
sig = 'overbought'
|
|
251
|
+
elif value < 30:
|
|
252
|
+
sig = 'oversold'
|
|
253
|
+
else:
|
|
254
|
+
sig = 'neutral'
|
|
255
|
+
result = {
|
|
256
|
+
'indicator': 'rsi',
|
|
257
|
+
'period': period,
|
|
258
|
+
'current_value': round(value, 2),
|
|
259
|
+
'signal': sig,
|
|
260
|
+
'interpretation': {
|
|
261
|
+
'overbought_threshold': 70,
|
|
262
|
+
'oversold_threshold': 30,
|
|
263
|
+
'description': f'RSI at {round(value, 2)} indicates {sig} conditions'
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
elif indicator == 'ema':
|
|
268
|
+
value = ema(closes, period)
|
|
269
|
+
if value is not None:
|
|
270
|
+
trend = 'bullish' if current_price > value else 'bearish'
|
|
271
|
+
result = {
|
|
272
|
+
'indicator': 'ema',
|
|
273
|
+
'period': period,
|
|
274
|
+
'current_value': round(value, 2),
|
|
275
|
+
'current_price': round(current_price, 2),
|
|
276
|
+
'signal': trend,
|
|
277
|
+
'distance_pct': round((current_price - value) / value * 100, 2)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
elif indicator == 'sma':
|
|
281
|
+
value = sma(closes, period)
|
|
282
|
+
if value is not None:
|
|
283
|
+
trend = 'bullish' if current_price > value else 'bearish'
|
|
284
|
+
result = {
|
|
285
|
+
'indicator': 'sma',
|
|
286
|
+
'period': period,
|
|
287
|
+
'current_value': round(value, 2),
|
|
288
|
+
'current_price': round(current_price, 2),
|
|
289
|
+
'signal': trend,
|
|
290
|
+
'distance_pct': round((current_price - value) / value * 100, 2)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
elif indicator == 'macd':
|
|
294
|
+
macd_line, signal_line, histogram = macd(closes, fast, slow, signal_period)
|
|
295
|
+
if macd_line is not None:
|
|
296
|
+
sig = 'bullish' if histogram > 0 else 'bearish'
|
|
297
|
+
result = {
|
|
298
|
+
'indicator': 'macd',
|
|
299
|
+
'parameters': {'fast': fast, 'slow': slow, 'signal': signal_period},
|
|
300
|
+
'current_values': {
|
|
301
|
+
'macd_line': round(macd_line, 4),
|
|
302
|
+
'signal_line': round(signal_line, 4),
|
|
303
|
+
'histogram': round(histogram, 4)
|
|
304
|
+
},
|
|
305
|
+
'signal': sig,
|
|
306
|
+
'interpretation': f'MACD {"above" if histogram > 0 else "below"} signal line, {sig} momentum'
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
elif indicator == 'bb':
|
|
310
|
+
upper, middle, lower = bollinger_bands(closes, period, std_dev)
|
|
311
|
+
if upper is not None:
|
|
312
|
+
bandwidth = (upper - lower) / middle
|
|
313
|
+
if current_price > upper:
|
|
314
|
+
position = 'above_upper'
|
|
315
|
+
elif current_price < lower:
|
|
316
|
+
position = 'below_lower'
|
|
317
|
+
else:
|
|
318
|
+
position = 'middle'
|
|
319
|
+
result = {
|
|
320
|
+
'indicator': 'bb',
|
|
321
|
+
'period': period,
|
|
322
|
+
'std': std_dev,
|
|
323
|
+
'current_values': {
|
|
324
|
+
'upper': round(upper, 2),
|
|
325
|
+
'middle': round(middle, 2),
|
|
326
|
+
'lower': round(lower, 2),
|
|
327
|
+
'current_price': round(current_price, 2)
|
|
328
|
+
},
|
|
329
|
+
'position': position,
|
|
330
|
+
'bandwidth': round(bandwidth, 4)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
elif indicator == 'atr':
|
|
334
|
+
value = atr(highs, lows, closes, period)
|
|
335
|
+
if value is not None:
|
|
336
|
+
atr_pct = (value / current_price) * 100
|
|
337
|
+
result = {
|
|
338
|
+
'indicator': 'atr',
|
|
339
|
+
'period': period,
|
|
340
|
+
'current_value': round(value, 4),
|
|
341
|
+
'current_price': round(current_price, 2),
|
|
342
|
+
'atr_percent': round(atr_pct, 2),
|
|
343
|
+
'interpretation': f'ATR of {round(value, 4)} ({round(atr_pct, 2)}% of price) indicates {"high" if atr_pct > 3 else "normal"} volatility'
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
else:
|
|
347
|
+
result = {'error': f'Unknown indicator: {indicator}'}
|
|
348
|
+
|
|
349
|
+
result['connector'] = '$CONNECTOR'
|
|
350
|
+
result['trading_pair'] = '$TRADING_PAIR'
|
|
351
|
+
result['interval'] = '$INTERVAL'
|
|
352
|
+
result['candles_used'] = len(closes)
|
|
353
|
+
|
|
354
|
+
print(json.dumps(result, indent=2))
|
|
355
|
+
PYTHON_SCRIPT
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Run calculation
|
|
359
|
+
calculate_with_python
|