Edoruin commited on
Commit
380b4bf
·
1 Parent(s): 0b2c13d

first commit

Browse files
Files changed (5) hide show
  1. .gitattributes +0 -35
  2. Dockerfile +15 -0
  3. README.md +74 -5
  4. app.py +136 -0
  5. requirements.txt +7 -0
.gitattributes DELETED
@@ -1,35 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+ FROM python:3.11-slim
3
+
4
+ RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
5
+
6
+ WORKDIR /app
7
+
8
+ COPY requirements.txt ./
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ COPY . ./
12
+
13
+ EXPOSE 7860
14
+
15
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "app:app"]
README.md CHANGED
@@ -1,11 +1,80 @@
1
  ---
2
  title: RapidAgentClient
3
- emoji: 🏃
4
- colorFrom: red
5
- colorTo: red
6
  sdk: docker
 
7
  pinned: false
8
- short_description: Microservice of RapidQuant for get AI assistant for crypto
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: RapidAgentClient
3
+ emoji: 🤖
4
+ colorFrom: purple
5
+ colorTo: blue
6
  sdk: docker
7
+ app_port: 7860
8
  pinned: false
 
9
  ---
10
 
11
+ # 🤖 RapidAgentClient - AI Analysis API
12
+
13
+ API de análisis de mercado con IA. Diseñado para ser consumido por RapidQuant.
14
+
15
+ ## 📡 Endpoints
16
+
17
+ | Método | Endpoint | Descripción |
18
+ |--------|----------|-------------|
19
+ | GET | `/` | Estado del servicio |
20
+ | GET | `/health` | Health check |
21
+ | POST | `/analyze` | Análisis de mercado |
22
+
23
+ ## 📥 Uso
24
+
25
+ ### Request
26
+ ```bash
27
+ curl -X POST https://tu-usuario-RapidAgentClient.huggingface.space/analyze \
28
+ -H "Content-Type: application/json" \
29
+ -d '{"symbol": "BTC"}'
30
+ ```
31
+
32
+ ### Response
33
+ ```json
34
+ {
35
+ "success": true,
36
+ "data": {
37
+ "symbol": "BTC",
38
+ "price_data": {
39
+ "price": 50000,
40
+ "change_24h": 2.5,
41
+ "market_cap": 1000000000000
42
+ },
43
+ "tech_data": {
44
+ "rsi": 65,
45
+ "trend": "bullish"
46
+ },
47
+ "analysis": "..."
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## 🔧 Configuración
53
+
54
+ ### Variables de Entorno
55
+ - `HF_TOKEN`: Token de HuggingFace (opcional, para IA avanzada)
56
+
57
+ ## 🔍 Verificar Conexión (Terminal)
58
+
59
+ ```bash
60
+ # Estado del servicio
61
+ curl https://tu-usuario-RapidAgentClient.huggingface.space/
62
+
63
+ # Health check
64
+ curl https://tu-usuario-RapidAgentClient.huggingface.space/health
65
+
66
+ # Análisis de prueba
67
+ curl -X POST https://tu-usuario-RapidAgentClient.huggingface.space/analyze \
68
+ -H "Content-Type: application/json" \
69
+ -d '{"symbol": "ETH"}'
70
+ ```
71
+
72
+ ## 📊 Datos que Retorna
73
+
74
+ - **price_data**: Precio, cambio 24h/7d/30d, market cap, rank
75
+ - **tech_data**: RSI, MA7, MA20, tendencia, volatilidad
76
+ - **analysis**: Señal de trading (comprar/vender/mantener)
77
+
78
+ ## 🔗 Consumido por
79
+
80
+ - **RapidQuant** - Frontend principal
app.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ RapidAgentClient - API Terminal
4
+ API para análisis de mercado. Diseñado para ser consumido por otros Spaces.
5
+ """
6
+
7
+ from flask import Flask, request, jsonify
8
+ import os
9
+ import requests
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+
14
+ import yfinance as yf
15
+ import pandas as pd
16
+ import numpy as np
17
+
18
+ app = Flask(__name__)
19
+
20
+ HF_TOKEN = os.getenv("HF_TOKEN", "")
21
+
22
+ COINGECKO_API = "https://api.coingecko.com/api/v3"
23
+
24
+ SYMBOL_MAP = {
25
+ 'BTC': 'bitcoin', 'ETH': 'ethereum', 'SOL': 'solana',
26
+ 'ADA': 'cardano', 'DOT': 'polkadot', 'AVAX': 'avalanche-2',
27
+ 'MATIC': 'matic-network', 'LINK': 'chainlink', 'XRP': 'ripple',
28
+ 'DOGE': 'dogecoin', 'BNB': 'binancecoin', 'LTC': 'litecoin',
29
+ }
30
+
31
+ @app.route("/", methods=["GET"])
32
+ def index():
33
+ return jsonify({"success": True, "message": "RapidAgentClient API running"})
34
+
35
+ @app.route("/health", methods=["GET"])
36
+ def health():
37
+ return jsonify({"success": True, "status": "healthy"})
38
+
39
+ @app.route("/analyze", methods=["POST"])
40
+ def analyze():
41
+ data = request.get_json()
42
+ symbol = data.get("symbol", "BTC").upper()
43
+
44
+ price_data = get_price_data(symbol)
45
+ tech_data = get_technical_data(symbol)
46
+
47
+ analysis = generate_analysis(symbol, price_data, tech_data)
48
+
49
+ return jsonify({
50
+ "success": True,
51
+ "data": {
52
+ "symbol": symbol,
53
+ "price_data": price_data,
54
+ "tech_data": tech_data,
55
+ "analysis": analysis
56
+ }
57
+ })
58
+
59
+ def get_price_data(symbol):
60
+ try:
61
+ coin_id = SYMBOL_MAP.get(symbol, symbol.lower())
62
+ url = f"{COINGECKO_API}/coins/{coin_id}"
63
+ params = {'localization': 'false', 'tickers': 'false', 'community_data': 'false', 'developer_data': 'false', 'sparkline': 'false'}
64
+ response = requests.get(url, params=params, timeout=15)
65
+ if response.status_code == 200:
66
+ data = response.json()
67
+ return {
68
+ 'success': True,
69
+ 'price': data.get('market_data', {}).get('current_price', {}).get('usd', 0),
70
+ 'change_24h': data.get('market_data', {}).get('price_change_percentage_24h', 0),
71
+ 'change_7d': data.get('market_data', {}).get('price_change_percentage_7d', 0),
72
+ 'change_30d': data.get('market_data', {}).get('price_change_percentage_30d', 0),
73
+ 'market_cap': data.get('market_data', {}).get('market_cap', {}).get('usd', 0),
74
+ 'volume_24h': data.get('market_data', {}).get('total_volume', {}).get('usd', 0),
75
+ 'rank': data.get('market_cap_rank', 0),
76
+ }
77
+ except:
78
+ pass
79
+ return {'success': False}
80
+
81
+ def get_technical_data(symbol):
82
+ try:
83
+ ticker = yf.Ticker(f"{symbol}-USD")
84
+ hist = ticker.history(period="1mo")
85
+ if hist.empty:
86
+ return {'success': False}
87
+
88
+ current_price = hist['Close'].iloc[-1]
89
+ hist['MA7'] = hist['Close'].rolling(window=7).mean()
90
+ hist['MA20'] = hist['Close'].rolling(window=20).mean()
91
+
92
+ delta = hist['Close'].diff()
93
+ gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
94
+ loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
95
+ rs = gain / loss
96
+ hist['RSI'] = 100 - (100 / (1 + rs))
97
+
98
+ volatility = hist['Close'].pct_change().std() * 100
99
+
100
+ return {
101
+ 'success': True,
102
+ 'price': float(current_price),
103
+ 'rsi': float(hist['RSI'].iloc[-1]) if not pd.isna(hist['RSI'].iloc[-1]) else 50.0,
104
+ 'ma7': float(hist['MA7'].iloc[-1]) if not pd.isna(hist['MA7'].iloc[-1]) else float(current_price),
105
+ 'ma20': float(hist['MA20'].iloc[-1]) if not pd.isna(hist['MA20'].iloc[-1]) else float(current_price),
106
+ 'volatility': float(volatility * 100),
107
+ 'trend': 'bullish' if current_price > hist['MA7'].iloc[-1] else 'bearish' if current_price < hist['MA7'].iloc[-1] else 'neutral',
108
+ }
109
+ except:
110
+ return {'success': False}
111
+
112
+ def generate_analysis(symbol, price_data, tech_data):
113
+ rsi = tech_data.get('rsi', 50)
114
+ trend = tech_data.get('trend', 'neutral')
115
+ change_24h = price_data.get('change_24h', 0)
116
+
117
+ if rsi > 70:
118
+ signal = "vender"
119
+ risk = "alto"
120
+ elif rsi < 30:
121
+ signal = "comprar"
122
+ risk = "medio"
123
+ elif trend == "bullish" and change_24h > 0:
124
+ signal = "comprar"
125
+ risk = "bajo"
126
+ elif trend == "bearish" and change_24h < 0:
127
+ signal = "vender"
128
+ risk = "medio"
129
+ else:
130
+ signal = "mantener"
131
+ risk = "bajo"
132
+
133
+ return f'{{"tendencia": "{trend}", "senal": "{signal}", "riesgo": "{risk}", "accion": "Considerar {signal} {symbol}"}}'
134
+
135
+ if __name__ == "__main__":
136
+ app.run(host="0.0.0.0", port=7860)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ flask>=3.0.0
2
+ yfinance>=0.2.36
3
+ pandas>=2.1.0
4
+ numpy>=1.26.0
5
+ requests>=2.31.0
6
+ python-dotenv>=1.0.0
7
+ gunicorn>=21.0.0