working version, before optimalization

This commit is contained in:
2026-01-06 09:47:49 +01:00
parent c29dc2c8ac
commit a166d33012
36 changed files with 5394 additions and 901 deletions

View File

@ -0,0 +1,171 @@
import json
import time
import requests
import math
import os
from datetime import datetime
from statistics import mean, stdev
# --- Configuration ---
COINS = ["ETH"]
# Mapping of label to number of 1-minute periods
PERIODS_CONFIG = {
"37m": 37,
"3h": 3 * 60, # 180 minutes
"12h": 12 * 60, # 720 minutes
"24h": 24 * 60 # 1440 minutes
}
MA_PERIODS = [33, 44, 88, 144]
STD_DEV_MULTIPLIER = 1.6 # Standard deviation multiplier for bands
OUTPUT_FILE = os.path.join("market_data", "indicators.json")
API_URL = "https://api.hyperliquid.xyz/info"
UPDATE_INTERVAL = 60 # seconds
def fetch_candles(coin, interval="1m", lookback_minutes=1500):
"""
Fetches candle data from Hyperliquid.
We need at least enough candles for the longest period (1440).
Requesting slightly more to be safe.
"""
# Calculate startTime: now - (lookback_minutes * 60 * 1000)
# Hyperliquid expects startTime in milliseconds
end_time = int(time.time() * 1000)
start_time = end_time - (lookback_minutes * 60 * 1000)
payload = {
"type": "candleSnapshot",
"req": {
"coin": coin,
"interval": interval,
"startTime": start_time,
"endTime": end_time
}
}
try:
response = requests.post(API_URL, json=payload, timeout=10)
response.raise_for_status()
data = response.json()
# Data format is typically a list of dicts:
# {'t': 170..., 'T': 170..., 's': 'ETH', 'i': '1m', 'o': '...', 'c': '...', 'h': '...', 'l': '...', 'v': '...', 'n': ...}
# We need closing prices 'c'
candles = []
for c in data:
try:
# Ensure we parse 'c' (close) as float
candles.append(float(c['c']))
except (ValueError, KeyError):
continue
return candles
except Exception as e:
print(f"Error fetching candles for {coin}: {e}")
return []
def calculate_ma(prices, period):
"""Calculates Simple Moving Average."""
if len(prices) < period:
return None
return mean(prices[-period:])
def calculate_bb(prices, period, num_std_dev=2.0):
"""
Calculates Bollinger Bands for the LAST 'period' items in prices.
Returns {mid, upper, lower} or None if insufficient data.
"""
if len(prices) < period:
return None
# Take the last 'period' prices
window = prices[-period:]
try:
avg = mean(window)
# Population stdev or sample stdev? Usually sample (stdev) is used in finance or pandas default
if period > 1:
sd = stdev(window)
else:
sd = 0.0
upper = avg + (num_std_dev * sd)
lower = avg - (num_std_dev * sd)
return {
"mid": avg,
"upper": upper,
"lower": lower,
"std": sd
}
except Exception as e:
print(f"Error calculating BB: {e}")
return None
def main():
print(f"Starting Market Data Calculator for {COINS}")
print(f"BB Periods: {PERIODS_CONFIG}")
print(f"MA Periods: {MA_PERIODS}")
print(f"Output: {OUTPUT_FILE}")
# Ensure directory exists
os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)
while True:
try:
results = {
"last_updated": datetime.now().isoformat(),
"config": {
"std_dev_multiplier": STD_DEV_MULTIPLIER,
"ma_periods": MA_PERIODS
},
"data": {}
}
# Find the max needed history (BB vs MA)
max_bb = max(PERIODS_CONFIG.values()) if PERIODS_CONFIG else 0
max_ma = max(MA_PERIODS) if MA_PERIODS else 0
fetch_limit = max(max_bb, max_ma) + 60
for coin in COINS:
print(f"Fetching data for {coin}...", end="", flush=True)
prices = fetch_candles(coin, lookback_minutes=fetch_limit)
if not prices:
print(" Failed.")
continue
print(f" Got {len(prices)} candles.", end="", flush=True)
coin_results = {
"current_price": prices[-1] if prices else 0,
"bb": {},
"ma": {}
}
# Calculate BB
for label, period in PERIODS_CONFIG.items():
bb = calculate_bb(prices, period, num_std_dev=STD_DEV_MULTIPLIER)
coin_results["bb"][label] = bb if bb else "Insufficient Data"
# Calculate MA
for period in MA_PERIODS:
ma = calculate_ma(prices, period)
coin_results["ma"][str(period)] = ma if ma else "Insufficient Data"
results["data"][coin] = coin_results
print(" Done.")
# Save to file
with open(OUTPUT_FILE, 'w') as f:
json.dump(results, f, indent=4)
print(f"Updated {OUTPUT_FILE}")
except Exception as e:
print(f"Main loop error: {e}")
time.sleep(UPDATE_INTERVAL)
if __name__ == "__main__":
main()