forked from github/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata-collector-code.py
More file actions
174 lines (148 loc) · 7.52 KB
/
Copy pathdata-collector-code.py
File metadata and controls
174 lines (148 loc) · 7.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# data_collector.py
import asyncio
import json
import websockets
import aiohttp
import time
from datetime import datetime
from database import CryptoDatabase
class DataCollector:
def __init__(self, config_path="config/api_config.json"):
"""Inicializador del recolector de datos de criptomonedas"""
self.db = CryptoDatabase()
self.active_streams = {}
self.api_keys = {}
self.exchanges = []
self.load_config(config_path)
def load_config(self, config_path):
"""Carga la configuración de APIs desde un archivo JSON"""
with open(config_path, 'r') as file:
config = json.load(file)
self.api_keys = config.get('api_keys', {})
self.exchanges = config.get('exchanges', [])
async def initialize_streams(self):
"""Inicializa los streams de datos para todos los exchanges configurados"""
tasks = []
for exchange in self.exchanges:
if exchange == 'binance':
tasks.append(self.connect_binance())
elif exchange == 'coinbase':
tasks.append(self.connect_coinbase())
# Agregar más exchanges según sea necesario
await asyncio.gather(*tasks)
async def connect_binance(self):
"""Establece conexión con WebSocket de Binance para datos en tiempo real"""
uri = "wss://stream.binance.com:9443/ws/!ticker@arr"
async with websockets.connect(uri) as websocket:
self.active_streams['binance'] = websocket
while True:
try:
response = await websocket.recv()
data = json.loads(response)
# Procesamiento de los datos recibidos
for ticker in data:
symbol = ticker['s']
if symbol.endswith('USDT'): # Filtramos pares con USDT
crypto = symbol[:-4] # Eliminamos 'USDT' del final
price = float(ticker['c']) # Precio actual
timestamp = int(time.time() * 1000)
# Almacenamos en la base de datos
await self.db.store_price_data({
'exchange': 'binance',
'symbol': crypto,
'price': price,
'timestamp': timestamp,
'volume_24h': float(ticker['v']),
'change_24h': float(ticker['p'])
})
except Exception as e:
print(f"Error en Binance WebSocket: {e}")
# Reconexión tras error
await asyncio.sleep(5)
return await self.connect_binance()
async def connect_coinbase(self):
"""Establece conexión con la API de Coinbase para datos en tiempo real"""
uri = "wss://ws-feed.pro.coinbase.com"
# Configuración de la suscripción
subscription = {
"type": "subscribe",
"channels": [{"name": "ticker", "product_ids": ["BTC-USD", "ETH-USD", "SOL-USD"]}]
}
async with websockets.connect(uri) as websocket:
self.active_streams['coinbase'] = websocket
# Enviar mensaje de suscripción
await websocket.send(json.dumps(subscription))
while True:
try:
response = await websocket.recv()
data = json.loads(response)
if data.get('type') == 'ticker':
product_id = data.get('product_id', '')
if '-USD' in product_id:
crypto = product_id.split('-')[0]
price = float(data.get('price', 0))
timestamp = int(datetime.fromisoformat(data.get('time').replace('Z', '+00:00')).timestamp() * 1000)
# Almacenamos en la base de datos
await self.db.store_price_data({
'exchange': 'coinbase',
'symbol': crypto,
'price': price,
'timestamp': timestamp,
'volume_24h': float(data.get('volume_24h', 0)),
'change_24h': 0 # Coinbase no proporciona este dato directamente
})
except Exception as e:
print(f"Error en Coinbase WebSocket: {e}")
# Reconexión tras error
await asyncio.sleep(5)
return await self.connect_coinbase()
async def fetch_rest_data(self):
"""Obtiene datos adicionales a través de APIs REST para exchanges que no soportan WebSockets"""
while True:
for exchange in self.exchanges:
if exchange == 'kraken':
await self.fetch_kraken_data()
# Agregar más exchanges según sea necesario
# Actualizamos cada 30 segundos para APIs REST
await asyncio.sleep(30)
async def fetch_kraken_data(self):
"""Obtiene datos de precios desde la API REST de Kraken"""
url = "https://api.kraken.com/0/public/Ticker"
params = {"pair": "BTCUSD,ETHUSD,SOLUSD"}
async with aiohttp.ClientSession() as session:
try:
async with session.get(url, params=params) as response:
if response.status == 200:
data = await response.json()
result = data.get('result', {})
# Mapeamos los pares de Kraken a símbolos estándar
mapping = {
'XXBTZUSD': 'BTC',
'XETHZUSD': 'ETH',
'SOLUSD': 'SOL'
}
for pair, info in result.items():
if pair in mapping:
crypto = mapping[pair]
price = float(info['c'][0]) # Precio actual
timestamp = int(time.time() * 1000)
# Almacenamos en la base de datos
await self.db.store_price_data({
'exchange': 'kraken',
'symbol': crypto,
'price': price,
'timestamp': timestamp,
'volume_24h': float(info['v'][1]), # Volumen 24h
'change_24h': 0 # Calcularlo manualmente si es necesario
})
except Exception as e:
print(f"Error obteniendo datos de Kraken: {e}")
async def run(self):
"""Ejecuta todos los recolectores de datos en paralelo"""
await asyncio.gather(
self.initialize_streams(),
self.fetch_rest_data()
)
if __name__ == "__main__":
collector = DataCollector()
asyncio.run(collector.run())