Всем доброго времени суток!
Меня зовут Илья и сегодня я хочу вам немного рассказать о своем хобби — криптовалютном алго-трейдинге. Скоро будет год, как меня настигла мысль написать торгового робота, который бы минимизировал человеческий фактор торговли (торгующие люди наверняка знают, что такое каждые пять минут обновлять баланс и зачастую делать какие-то поспешные, и потому неверные, торговые решения). Потому было решено переложить все на робота, удалить приложения по просмотру курсов с телефона и начать спать спокойно. Потратив много времени на написание чего-то более или менее работающего, хочу дать читателю маленькое overview, с чего стоит начинать на этом веселом (и нервном) поприще, как алготрейдинг. Этот гайд не является призывом начинать торговлю, не содержит советов по инвестированию, преследуются исключительно образовательные цели.
Как вы можете видеть из заголовка, тот робот, которого мы с вами напишем, будет работать на бирже BitMEX. Выбор объясняется очень просто — там есть плечи вплоть до 100. И наш робот будет работать с маржой.
Для тех, кто не понял о чем я говорю. Маржинальная торговля это торговля с кредитным плечом. [1] Что такое кредитное плечо?
Кредитное плечо — это отношение Вашего депозита к лоту, с которым Вы работаете. Т.е. имея на депозите 100$, Вы можете совершить сделку с лотом в 10 000, и тогда оно будет равно 1 к 100. Если же Вы выставите лот в 5 000, то кредитное плечо будет 1 к 50 и т.д. [2]
Итак, я надеюсь, что у читающего это есть базовые знания о торговле на бирже, к примеру, что такое OHLCV свечи (a.k.a. японские свечки), что бывают разные временные промежутки их представления и т.д.
Ну что, приступим к нашему маленькому приключения в страну алгоритмической маржинальной торговли?
Я любитель top-down коммуникации и поэтому я для начала расскажу, что я собираюсь сделать, а потом мы приступим к реализации. Глобально есть две важные вещи, которые надо сделать для запуска робота: разработать стратегию принятия решения (при каких условиях покупать) и разработать логику поверх принятого решения (сколько и как покупать).
Стратегия принятия решение (
Логика поверх решения нашего индикатора будет простой: если индикатор сказал покупать, то мы купим, если продавать, то мы продадим. Торговать будем фиксированным количеством денег с фиксированным плечом.
Первое с чего мы начнем, это установка нужных библиотек. Для начала нам нужен клиент биржи, его берем тут.
После установки всех нужных библиотек предлагаю читателю зарегистрироваться на https://testnet.bitmex.com — это копия биржи BitMEX, но там вы торгуете не реальным деньгами, а виртуальными. Очень удобно использовать для отладки роботов перед запуском на реальной бирже. После регистрации создаем себе ключи и создаем клиент биржи:
client = bitmex.bitmex(
test=True,
api_key="YOUR_KEY",
api_secret="YOUR_SECRET"
)
Обратите внимание на параметр test. Он выставлен в true, что означает, что мы будем торговать на тестовой бирже. Этот пост не будет про использование API биржи, все возникающие вопросы по нему вы можете перенаправить в API explorer, благо он у них очень удобный.
Следующим шагом нам надо получить данных для использования их на MACD индикаторе. Мы получим 100 свечей с разрешением в 1 час.
ohlcv_candles = pd.DataFrame(client.Trade.Trade_getBucketed(
binSize=self.timeframe,
symbol='XBTUSD',
count=100,
reverse=True
).result()[0])
Теперь у нас есть датафрейм со свечками, давайте применим индикатор.
macd, signal, hist = talib.MACD(ohlcv_candles.close.values,
fastperiod = 8,
slowperiod = 28,
signalperiod = 9)
Я выбрал такие параметры немного поигравшись со стратегией и ее бэктестом на Trading View. Вот примеры картинок с точками входа/выхода стратегии на графике и сколько денег она заработала. Но учтите, это стратегия тестировалась без плеча.
Итак, получив индикатор, давайте поймем, как на его основе принимать решение. Ну тут все просто. Когда гистограмма пересекает нулевое значение снизу вверх, то это является сигналом к покупке, и наоборот.
#sell
if hist[-2] > 0 and hist[-1] < 0:
return -1
#buy
if hist[-2] < 0 and hist[-1] > 0:
return 1
#do nothing
else:
return 0
Все очень просто и понятно. Давайте оформим это в один класс, который назовем стратегией.
class Strategy():
def __init__(self, client, timeframe='5m'):
self.client = client
self.timeframe = timeframe
def predict(self):
ohlcv_candles = pd.DataFrame(self.client.Trade.Trade_getBucketed(
binSize="1h",
symbol='XBTUSD',
count=100,
reverse=True
).result()[0])
macd, signal, hist = talib.MACD(ohlcv_candles.close.values,
fastperiod = 8,
slowperiod = 28,
signalperiod = 9)
#sell
if hist[-2] > 0 and hist[-1] < 0:
return -1
#buy
if hist[-2] < 0 and hist[-1] > 0:
return 1
#do nothing
else:
return 0
Теперь давайте напишем исполнителя наших решений. Логика простая — стратегия сказала нам покупать, значит мы покупаем. Приведу код торговца сразу, в нем ничего сложного нет:
class Trader():
def __init__(self, client, strategy, money_to_trade=100, leverage=5):
self.client = client
self.strategy = strategy
self.money_to_trade = money_to_trade
self.leverage = leverage
def execute_trade(self):
prediction = self.strategy.predict()
print(f"Last prediction: {prediction}")
try:
if prediction == -1:
response = self.client.Order.Order_new(
symbol="XBTUSD",
side="Sell",
orderQty=self.money_to_trade * self.leverage,
).result()
if prediction == 1:
response = self.client.Order.Order_new(
symbol="XBTUSD",
side="Buy",
orderQty=self.money_to_trade * self.leverage,
).result()
except Exception:
print("Something goes wrong!")
return
Маленький нюанс — для упрощения себе жизни, ордера здесь исполняются не по выставленной заранее цене, а по рыночной. В случае с BitMEX это хорошо по двум причинам:
- Возвращается комиссия за выставление ордера
- Не нужно запариваться с отдельным исполнителем цены, который в общем случае должен защищать от падений биржи, передвигать выставленный ордер в случае задержки исполнения, и т.д. и т.п.
Теперь логика принятия решения у нас есть, логика исполнения решений у нас есть, осталось это все дело скомпоновать. Нам нужно запускать процесс торговли раз в выбранный нами временной период, в данном случае это был 1 час. Я сделаю это с костылем во имя быстроты написания, но лучше это делать, к примеру, через cron.
time_to_wait_new_trade = 60*60 #sec
strategy = Strategy(client, timeframe='1h')
trader = Trader(client, strategy)
while True:
if round(time.time()) % time_to_wait_new_trade == 0:
trader.execute_trade()
time.sleep(10)
Ну вот, теперь это дело можно оформить в один скрипт и смело запускать, но только на тестовой бирже! На реальной бирже этого делать не советую, ибо можно потерять деньги. Данный скрипт своей целью ставил показать, что начать легко, и сделал более умный
Juputer тетрадку с кодом я выложил в свой репозиторий, если кому-то интересно просмотреть — you are welcome!
- https://ru.wikipedia.org/wiki/Маржинальная_торговля
- https://www.fxclub.org/faq/chto-takoe-kreditnoe-plecho/"
- https://ru.wikipedia.org/wiki/Индикатор_MACD
Автор: Илья Кротов