Spaces:
Running
Running
Manual changes saved
Browse files
app.py
CHANGED
|
@@ -1,76 +1,115 @@
|
|
| 1 |
-
```python
|
| 2 |
from flask import Flask, jsonify
|
| 3 |
-
import requests
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
app = Flask(__name__)
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
@app.route("/api/data")
|
| 8 |
def get_data():
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
btc, eth = {}
|
| 15 |
|
| 16 |
-
#
|
| 17 |
data = {
|
| 18 |
-
"phi_score":
|
| 19 |
-
"volx":
|
| 20 |
-
"momx":
|
| 21 |
-
"fbs":
|
| 22 |
-
"lpi":
|
| 23 |
-
|
| 24 |
-
"btc": {
|
| 25 |
-
"price": float(btc.get("lastPrice", 67000)),
|
| 26 |
-
"change_24h": float(btc.get("priceChangePercent", -2.3)),
|
| 27 |
-
"dominance": 52.1,
|
| 28 |
-
"funding_rate": 0.0001,
|
| 29 |
-
"open_interest": 13_000_000_000,
|
| 30 |
-
"liquidations": 5_800_000,
|
| 31 |
-
"price_history": [random.uniform(60000, 68000) for _ in range(24)]
|
| 32 |
-
},
|
| 33 |
-
"eth": {
|
| 34 |
-
"price": float(eth.get("lastPrice", 3400)),
|
| 35 |
-
"change_24h": float(eth.get("priceChangePercent", 1.8)),
|
| 36 |
-
"dominance": 18.2,
|
| 37 |
-
"funding_rate": 0.0002,
|
| 38 |
-
"open_interest": 8_500_000_000,
|
| 39 |
-
"liquidations": 2_900_000,
|
| 40 |
-
"price_history": [random.uniform(3200, 3600) for _ in range(24)]
|
| 41 |
-
},
|
| 42 |
|
| 43 |
-
"
|
| 44 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
"top_gainers": [
|
| 47 |
-
{"symbol": "SOLUSDT", "price": 148.5, "change":
|
| 48 |
-
{"symbol": "AVAXUSDT", "price": 33.8, "change":
|
| 49 |
-
{"symbol": "LINKUSDT", "price": 12.9, "change":
|
| 50 |
],
|
| 51 |
"top_losers": [
|
| 52 |
-
{"symbol": "DOGEUSDT", "price": 0.123, "change": -
|
| 53 |
-
{"symbol": "PEPEUSDT", "price": 0.000012, "change": -1.
|
| 54 |
],
|
| 55 |
|
| 56 |
"funding_rates": {
|
| 57 |
-
"Binance":
|
| 58 |
-
"OKX":
|
| 59 |
-
"Bybit": 0.
|
| 60 |
-
"Deribit":
|
| 61 |
-
"Bitget":
|
| 62 |
},
|
| 63 |
"open_interest": {
|
| 64 |
-
"btc_history": [
|
| 65 |
-
"eth_history": [
|
| 66 |
},
|
| 67 |
"liquidations": {
|
| 68 |
-
"longs": [
|
| 69 |
-
"shorts": [
|
| 70 |
}
|
| 71 |
}
|
|
|
|
| 72 |
return jsonify(data)
|
| 73 |
|
| 74 |
if __name__ == "__main__":
|
| 75 |
app.run(host="0.0.0.0", port=7860)
|
| 76 |
-
```
|
|
|
|
|
|
|
| 1 |
from flask import Flask, jsonify
|
| 2 |
+
import requests
|
| 3 |
+
import math
|
| 4 |
+
import statistics
|
| 5 |
+
import time
|
| 6 |
|
| 7 |
app = Flask(__name__)
|
| 8 |
|
| 9 |
+
# Helper: safe fetch with timeout
|
| 10 |
+
def fetch_json(url):
|
| 11 |
+
try:
|
| 12 |
+
r = requests.get(url, timeout=5)
|
| 13 |
+
r.raise_for_status()
|
| 14 |
+
return r.json()
|
| 15 |
+
except Exception as e:
|
| 16 |
+
print("Fetch error:", e)
|
| 17 |
+
return {}
|
| 18 |
+
|
| 19 |
+
# Compute PHI components
|
| 20 |
+
def compute_phi_metrics(symbol):
|
| 21 |
+
# Binance endpoints
|
| 22 |
+
ticker = fetch_json(f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}")
|
| 23 |
+
klines = fetch_json(f"https://api.binance.com/api/v3/klines?symbol={symbol}&interval=1h&limit=100")
|
| 24 |
+
funding = fetch_json(f"https://fapi.binance.com/fapi/v1/fundingRate?symbol={symbol}&limit=1")
|
| 25 |
+
oi = fetch_json(f"https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}")
|
| 26 |
+
|
| 27 |
+
# Price data
|
| 28 |
+
try:
|
| 29 |
+
closes = [float(k[4]) for k in klines]
|
| 30 |
+
returns = [math.log(closes[i]/closes[i-1]) for i in range(1, len(closes))]
|
| 31 |
+
volx = min(100, statistics.pstdev(returns) * 5000)
|
| 32 |
+
momx = max(0, min(100, ((closes[-1] - closes[0]) / closes[0]) * 200))
|
| 33 |
+
except Exception:
|
| 34 |
+
volx = momx = 0
|
| 35 |
+
|
| 36 |
+
# Funding bias (FBS) and leverage pressure (LPI)
|
| 37 |
+
try:
|
| 38 |
+
fbs = float(funding[0]["fundingRate"]) * 10000
|
| 39 |
+
except Exception:
|
| 40 |
+
fbs = 0
|
| 41 |
+
try:
|
| 42 |
+
lpi = min(100, float(oi.get("openInterest", 0)) / 1e8)
|
| 43 |
+
except Exception:
|
| 44 |
+
lpi = 0
|
| 45 |
+
|
| 46 |
+
# PHI calculation
|
| 47 |
+
phi_score = round(0.4 * momx + 0.3 * volx + 0.2 * abs(fbs) + 0.1 * lpi, 1)
|
| 48 |
+
|
| 49 |
+
return {
|
| 50 |
+
"symbol": symbol,
|
| 51 |
+
"price": float(ticker.get("lastPrice", 0)),
|
| 52 |
+
"change_24h": float(ticker.get("priceChangePercent", 0)),
|
| 53 |
+
"funding_rate": fbs / 10000,
|
| 54 |
+
"open_interest": float(oi.get("openInterest", 0)),
|
| 55 |
+
"volx": volx,
|
| 56 |
+
"momx": momx,
|
| 57 |
+
"lpi": lpi,
|
| 58 |
+
"phi_score": phi_score,
|
| 59 |
+
"price_history": closes[-24:] if len(klines) >= 24 else [],
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
@app.route("/api/data")
|
| 63 |
def get_data():
|
| 64 |
+
btc = compute_phi_metrics("BTCUSDT")
|
| 65 |
+
eth = compute_phi_metrics("ETHUSDT")
|
| 66 |
+
|
| 67 |
+
# Weighted average PHI
|
| 68 |
+
phi_score = round((btc["phi_score"] * 0.6 + eth["phi_score"] * 0.4), 1)
|
|
|
|
| 69 |
|
| 70 |
+
# Global derived data
|
| 71 |
data = {
|
| 72 |
+
"phi_score": phi_score,
|
| 73 |
+
"volx": round((btc["volx"] + eth["volx"]) / 2, 1),
|
| 74 |
+
"momx": round((btc["momx"] + eth["momx"]) / 200, 2), # normalize to 0–1 scale
|
| 75 |
+
"fbs": round((btc["funding_rate"] + eth["funding_rate"]) / 2, 6),
|
| 76 |
+
"lpi": round((btc["lpi"] + eth["lpi"]) / 2, 1),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
+
"btc": btc,
|
| 79 |
+
"eth": eth,
|
| 80 |
+
|
| 81 |
+
# Realistic placeholders (to be expanded later)
|
| 82 |
+
"long_short_ratio": 1.05,
|
| 83 |
+
"fear_greed": {"value": 55, "label": "Neutral"},
|
| 84 |
|
| 85 |
"top_gainers": [
|
| 86 |
+
{"symbol": "SOLUSDT", "price": 148.5, "change": 3.2},
|
| 87 |
+
{"symbol": "AVAXUSDT", "price": 33.8, "change": 2.1},
|
| 88 |
+
{"symbol": "LINKUSDT", "price": 12.9, "change": 1.4}
|
| 89 |
],
|
| 90 |
"top_losers": [
|
| 91 |
+
{"symbol": "DOGEUSDT", "price": 0.123, "change": -1.2},
|
| 92 |
+
{"symbol": "PEPEUSDT", "price": 0.000012, "change": -1.0}
|
| 93 |
],
|
| 94 |
|
| 95 |
"funding_rates": {
|
| 96 |
+
"Binance": btc["funding_rate"],
|
| 97 |
+
"OKX": eth["funding_rate"] * 1.1,
|
| 98 |
+
"Bybit": eth["funding_rate"] * 0.9,
|
| 99 |
+
"Deribit": eth["funding_rate"] * 0.8,
|
| 100 |
+
"Bitget": eth["funding_rate"] * 1.2
|
| 101 |
},
|
| 102 |
"open_interest": {
|
| 103 |
+
"btc_history": [btc["open_interest"] * (0.95 + 0.1 * math.sin(i)) for i in range(7)],
|
| 104 |
+
"eth_history": [eth["open_interest"] * (0.96 + 0.08 * math.cos(i)) for i in range(7)]
|
| 105 |
},
|
| 106 |
"liquidations": {
|
| 107 |
+
"longs": [abs(math.sin(i)) * 8_000_000 for i in range(8)],
|
| 108 |
+
"shorts": [abs(math.cos(i)) * 7_000_000 for i in range(8)]
|
| 109 |
}
|
| 110 |
}
|
| 111 |
+
|
| 112 |
return jsonify(data)
|
| 113 |
|
| 114 |
if __name__ == "__main__":
|
| 115 |
app.run(host="0.0.0.0", port=7860)
|
|
|