Лет 7 назад, имел опыт написания терминала для Московской биржи. Часть команды увлекалась алгоритмической торговлей, в том числе и я. Однако никогда не воспринимал это дело, как реальный источник дохода, хотя были в этом небольшие успехи. Понятно, что конкурировать с банками и различными фондами, с их командами математиков и программистов сложно и проще реализоваться в других областях.
Сейчас на слуху криптовалюты, появилось огромное количество бирж. Исходя из предположения, что на разнице курсов на разных биржах, можно заработать, решил изучить возможность создания арбитражного робота. А в основном, чтобы начать изучать python на реальном примере. Итак, приступим.
В первую очередь требуется обнаружить валютные пары, по которым возможна арбитражная торговля. Нам нужны пары, у которых в первом приближении, идет активная торговля, и цены на разных биржах расходятся и сходятся.
Навскидку план работы должен быть такой:
- Создание базы данных, где будут храниться цены валютных пар.
- Сервер который будет сохранять данные в базу.
- Первичный анализ.
Исходники доступны по ссылке arb_analysis.
Создание базы данных
Для того чтобы хранить данные, понадобится 3 таблицы.
В этой таблице будет храниться список бирж.
CREATE TABLE `exchange` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
Список криптовалютных пар.
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);
Таблица со сделками, также здесь будет храниться информация, по данным из биржевого стакана.
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);
Получение данных с бирж
Для удобного доступа к биржам есть опенсорсный проект ccxt. С помощью которого возможно в едином стиле обращаться к различным биржам. Однако оказалось, что не все так радужно, по ряду бирж информацию не получалось доставать, и некоторые методы не работали.
В файле create_markets.py происходит инициализация, получаем список криптовалютных пар, по биржам. При этом используется метод load_markets(), который возвращает список пар для биржи.
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)
Далее в файле ex_data_saver.py, запускаем сохранение изменение цен для пар:
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)
Асинхронное получение тиков для конкретной пары, происходит с помощью метода ccxt fetchTickers().
async def fetch_ticker(exchanges, name):
item = exchanges[name]
try:
ticker = await item.fetchTickers()
return {name:ticker}
Предварительный анализ данных
Прежде всего интересно на каких биржах и по каким парам, происходит самая активная торговля, нас интересуют ликвидные пары. Для этого нужно подсчитать количество сделок с группировкой по биржам и конкретным парам. В итоге мы получим пары, по которым идет активная торговля.
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;
С помощью SQL запросов, можно находить различные закономерности и отсеивать данные, однако для детального анализа, требуется создание тестового робота, работающего на накопленных с различных бирж данными.
Следующая статья будет посвящена этого робота. И тестового сервера — эмулирующего работу реальной биржи.В тестовый сервер хочу заложить следующие моменты:
- Задержки.
- Проскальзывание.
- Комиссии.
Автор: evgeny_not_007