Sistema de arbitraje para principiantes, parte 1

Hace unos 7 años, tenía experiencia escribiendo un terminal para la Bolsa de Moscú. Parte del equipo era aficionado al comercio algorítmico, incluido yo mismo. Sin embargo, nunca percibió este negocio como una fuente real de ingresos, aunque hubo poco éxito en esto. Está claro que competir con bancos y diversos fondos, con sus equipos de matemáticos y programadores, es difícil y fácil de implementar en otras áreas.

Ahora que se escuchan las criptomonedas, han aparecido una gran cantidad de intercambios. Basado en el supuesto de que es posible ganar dinero con la diferencia en los tipos de cambio en diferentes intercambios, decidí estudiar la posibilidad de crear un robot de arbitraje. Pero básicamente, comenzar a aprender Python con un ejemplo real. Entonces comencemos.

En primer lugar, es necesario detectar pares de divisas para los cuales es posible el comercio de arbitraje. Necesitamos pares que, en una primera aproximación, se negocien activamente, y los precios en diferentes intercambios divergen y convergen.

Por casualidad, el plan de trabajo debería ser así:

  • Creación de una base de datos donde se almacenarán los precios de los pares de divisas.
  • Un servidor que guardará datos en la base de datos.
  • Análisis primario

Las fuentes están disponibles en arb_analysis .

Creación de base de datos.


Para almacenar datos, necesita 3 tablas.

Esta tabla almacenará una lista de intercambios.

CREATE TABLE `exchange` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM; 

Lista de pares de criptomonedas.

 CREATE TABLE `market` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(50) NOT NULL, `id_exchange` int(11) NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM; CREATE INDEX id_exchange ON market (id_exchange); 

Una tabla con las transacciones, la información también se almacenará aquí, de acuerdo con los datos del vidrio de la bolsa de valores.

 CREATE TABLE `ticker` ( `id` int(11) NOT NULL AUTO_INCREMENT, `id_market` int(5) NOT NULL, `local_time` int(9) NOT NULL, `timestamp` int(9) NOT NULL, `last` DECIMAL (11,11) NOT NULL, `low` DECIMAL (11,11), `high` DECIMAL (11,11), `bid` DECIMAL (11,11), `ask` DECIMAL (11,11), PRIMARY KEY (id) ) ENGINE=MyISAM; CREATE INDEX id_market ON ticker (id_market); 

Obtener datos de intercambios


Para un acceso conveniente a los intercambios hay un proyecto de código abierto ccxt. Con la ayuda de la cual es posible aplicar a diferentes intercambios en un solo estilo. Sin embargo, resultó que no todo era tan color de rosa, para varios intercambios, no se pudo obtener información y algunos métodos no funcionaron.

En el archivo create_markets.py, se produce la inicialización, obtenemos una lista de pares de criptomonedas, por intercambio. En este caso, se utiliza el método load_markets (), que devuelve una lista de pares para el intercambio.

 name_exchange = ["acx", "binance", "bitfinex", "bitfinex2", "wex"] def create_exchange_and_market_in_db(): exchanges = {} for id in name_exchange: exchange = getattr(ccxt, id) exchanges[id] = exchange() id_exchage = db_helper.insert_exchage_to_db(exchanges[id],cnx,cursor) markets = exchanges[id].load_markets() for mark in markets: id_market = db_helper.insert_market_to_db( id_exchage, mark, cnx,cursor) 

A continuación, en el archivo ex_data_saver.py, comenzamos a guardar el cambio en los precios de los pares:

 def save(): markets = db_helper.get_data_exch() exchanges = {} for id in name_exchange: exchange = getattr(ccxt, id) #isHas = exchange.hasFetchTickers #if isHas: exchanges[id] = exchange({ 'enableRateLimit': True, # or .enableRateLimit = True later }) cnx = db_helper.CreateConnection() cursor = cnx.cursor() loop = asyncio.get_event_loop() while True: start_time = time.time() input_coroutines = [fetch_ticker(exchanges, name) for name in exchanges] exch_tickers = loop.run_until_complete(asyncio.gather(*input_coroutines, return_exceptions=True)) count_exchange = 0 delta = time.time() - start_time for tickers in exch_tickers: if tickers is not None: count_exchange+=1 inserted_start = time.time() db_helper.insert_tick(markets,exch_tickers,cnx,cursor) inserted_time = time.time() print(count_exchange," ", delta, ' ', inserted_start - inserted_time) 

La recepción asíncrona de ticks para un par específico ocurre usando el método ccxt fetchTickers ().

 async def fetch_ticker(exchanges, name): item = exchanges[name] try: ticker = await item.fetchTickers() return {name:ticker} 

Análisis de datos preliminares.


En primer lugar, es interesante en qué intercambios y en qué pares tiene lugar la negociación más activa, estamos interesados ​​en pares líquidos. Para hacer esto, debe calcular el número de transacciones agrupadas por intercambios y pares específicos. Como resultado, obtenemos pares que operan activamente.

 SELECT ex.name as exchange_name, m.name as market_name, count(*) as count_deals FROM exchange ex LEFT JOIN market m ON m.id_exchange = ex.id LEFT JOIN ticker t ON t.id_market =m.id GROUP BY ex.id, t.id_market ORDER BY m.name HAVING count_deals > 10000; 

Usando consultas SQL, puede encontrar varios patrones y filtrar datos, sin embargo, para un análisis detallado, necesita crear un robot de prueba que funcione con los datos acumulados de varios intercambios.

El próximo artículo estará dedicado a la creación de este robot. Y el servidor de prueba - emulando el trabajo de un intercambio real. Quiero establecer los siguientes puntos en el servidor de prueba:

  • Retrasos
  • Deslizamiento
  • Comisiones

Source: https://habr.com/ru/post/es436062/


All Articles