En Solana, en esta pista donde se generan miles de transacciones por segundo, si intentas escuchar todas las actualizaciones de cuentas de la red, tu robot rápidamente se verá abrumado por el masivo ruido de datos. Las limitaciones de ancho de banda de los nodos RPC, la presión de procesamiento del CPU y la latencia de la red pueden destruir instantáneamente las oportunidades de arbitraje.
El buscador eficiente nunca "escucha a ciegas". Utilizan una estrategia llamada "Monitoreo Impulsado por Inventario": primero construyen un índice global del fondo de liquidez de la red de manera offline, filtran un "grupo de candidatos a arbitraje" de alto valor y luego realizan suscripciones precisas.
Este artículo desglosará cómo construir este sistema de Inventario de alto rendimiento.
1. Concepto central: reducir el campo de batalla, enfocar el punto de victoria
1.1 ¿Por qué construir un Inventario?
Los DEX (intercambios descentralizados) en Solana, como Raydium y Orca, tienen miles de pools de liquidez. Pero para estrategias de arbitraje, solo aquellos pares de trading que existen simultáneamente en múltiples protocolos (por ejemplo, SOL/USDC, que tiene un pool en Raydium y también en Orca) tienen espacio para arbitraje atómico.
La tarea del Inventario es:
Arranque en frío agregado: obtener la lista completa de pools desde las API de cada DEX.
Cálculo de intersecciones: encontrar pares de trading de tokens superpuestos.
Filtrado de lista blanca: eliminar pools zombie y pools de baja liquidez, generar una 'lista blanca de seguimiento'.
1.2 Inventario impulsado vs. impulsado por totalidades
Impulsado por totalidades: suscribirse a todos los registros y buscar oportunidades para luego consultar la tabla. La ventaja es su amplio alcance, la desventaja es una latencia extremadamente alta y un manejo de datos redundantes.
Impulsado por inventario: solo se suscriben las actualizaciones de cuentas en la lista blanca. La ventaja es una respuesta extremadamente rápida y un ahorro de recursos RPC, siendo la opción preferida para arbitraje de alta frecuencia.
2. Arquitectura técnica: máquina de estados de alta concurrencia basada en Rust
En el motor de ejecución de Rust, el módulo de Inventario está diseñado como un singleton de alta concurrencia y seguro para hilos, compartido entre múltiples módulos de estrategia.
2.1 Estructura de datos clave: DashMap y Arc
Dado que el procesamiento de datos de Solana es paralelo y multihilo, el Inventario debe manejar frecuencias de lectura y escritura extremadamente altas:
DashMap: esta es una tabla hash concurrente de alto rendimiento. En comparación con HashMap estándar + Mutex, reduce la granularidad del bloqueo al nivel de fragmentos (Shard), evitando la competencia de bloqueo global durante el análisis de estado de alta frecuencia.
Arc (Contador de Referencia Atómico): se utiliza para compartir de manera segura la dirección de memoria del Inventario entre diferentes tareas de Tokio (como tareas de escucha, tareas de precios, tareas de ejecución), logrando un acceso a datos sin copias.
2.2 Lógica de jerarquía de índices
El sistema mantiene dos niveles de índice:
Índice Global de Pools: registra el mapeo de direcciones de pools a metadatos de tokens (Mint, Decimales, Vault).
Mapa de Pares de Arbitraje: registra 'pares de arbitraje candidatos'. Por ejemplo, ingresa la dirección Mint de SOL y devuelve inmediatamente su información asociada en el pool A de Raydium y el pool B de Orca.
3. Implementación del algoritmo: intersección rápida O(N+M)O(N+M)
El núcleo de construir una lista blanca de arbitraje es 'encontrar la intersección'.
Escanear protocolo A (Raydium): almacenar todas las pools en una tabla hash temporal según Token_A -> Pool_Address.
Escanear protocolo B (Orca): recorrer su lista de pools, si se encuentra el mismo Token_A en la tabla hash del protocolo A, se dispara una oportunidad de arbitraje potencial.
Generar lista de seguimiento: agregar simultáneamente las direcciones de los dos pools que se activaron a la 'lista de seguimiento'.
Complejidad temporal: solo se requieren dos escaneos lineales, incluso frente a decenas de miles de pools, se puede completar el arranque en milisegundos.
4. Puntos de optimización de rendimiento: velocidad desde los detalles de ingeniería
4.1 Caché de API y tolerancia a fallos
La API oficial de protocolos como Raydium a menudo no es lo suficientemente estable. Hemos incorporado un caché persistente local en la implementación del proyecto.
Al arrancar en frío, priorizar la lectura del pools_cache.json local.
Solicitudes asíncronas en segundo plano para actualizar la caché de la API.
Esto garantiza que incluso en entornos de red extremos, el robot pueda reanudar su trabajo de inmediato.
4.2 Límite de suscripción y fragmentación
La mayoría de los nodos RPC tienen un límite en la cantidad de conexiones accountSubscribe por única conexión (por ejemplo, entre 50 y 100).
El Inventario automáticamente ordena la lista de seguimiento según la 'calidez de los pools (volumen/TVL)', priorizando la suscripción a los Top N pools con mayor potencial de ganancias, o distribuyendo las suscripciones a múltiples nodos RPC a través de balanceo de carga.
5. Demostración del prototipo del algoritmo (implementación lógica en Python)
Aunque utilizamos Rust en el entorno de producción, la lógica subyacente se puede expresar claramente mediante el siguiente ejemplo en Python:
from dataclasses import dataclass
from typing import Dict, List, Set
@dataclass(frozen=True)
class PoolMetadata:
address: str
token_mint: str
def build_arbitrage_radar(ray_pools: List[PoolMetadata], orca_pools: List[PoolMetadata]):
# 1. Construir índice de Raydium (Token -> Pool)
ray_index = {p.token_mint: p.address for p in ray_pools}
arbitrage_watchlist = []
# 2. Escanear Orca para encontrar intersecciones
for o_pool in orca_pools:
if o_pool.token_mint in ray_index:
# Descubrir superposición: ese token tiene liquidez en ambos DEX
arbitrage_watchlist.append({
"token": o_pool.token_mint,
"raydium_pool": ray_index[o_pool.token_mint],
"orca_pool": o_pool.address
})
return arbitrage_watchlist
# Mostrar datos de prueba
ray_list = [PoolMetadata("RAY_SOL_POOL", "SOL_MINT"), PoolMetadata("RAY_BONK_POOL", "BONK_MINT")]
orca_list = [PoolMetadata("ORCA_SOL_POOL", "SOL_MINT"), PoolMetadata("ORCA_WIF_POOL", "WIF_MINT")]
watchlist = build_arbitrage_radar(ray_list, orca_list)
print(f"[*] Se encontraron {len(watchlist)} rutas de arbitraje potenciales")
# La salida incluirá rutas de SOL porque ambos DEX tienen pools de SOL
6. Resumen: el radar ha sido activado
El módulo de Inventario es el 'filtro' de todo el sistema MEV, que filtra el ruido de toda la red y deja solo los objetivos que brillan con la luz de las ganancias.
Sin Inventario: tu robot procesa miles de mensajes inválidos sin rumbo.
Con Inventario: tu robot solo se enfoca en esos pocos pools que cambian frecuentemente, listo para accionar en cualquier momento.
Avance del siguiente paso
Con la lista blanca, el siguiente paso es cómo capturar en tiempo real los cambios en estas cuentas. En el próximo artículo, abordaremos el módulo Scout y cómo implementar la escucha y el análisis de datos a nivel de submilisegundos mediante el protocolo gRPC/WebSocket.
Este artículo fue escrito por Levi.eth, enfocado en prácticas de ingeniería de alto rendimiento en el ecosistema de Solana.