Как написать бота для бинанс

Время на прочтение
4 мин

Количество просмотров 57K

Начнем писать трейдинг бота, который будет работать на криптобирже Binance. Бот должен уметь:

  1. торговать самостоятельно, принося какой-то доход

  2. должен быть удобен для создания и обкатывания различных стратегий торговли

  3. тестировать стратегию на исторических данных

Пожалуй, начнем с архитектуры

У нас есть биржа Binance, у которой есть шикарное api. Поэтому архитектура могла бы выглядеть так:

Вызвать пару методов “купи дешевле” и “продай дороже”. Но задача для нас написать такого бота, при котором условный программист-трейдер сможет создавать и тестировать на прибыльность новые стратегии. Поэтому, необходимо отделить логику торговли от всего прочего. А также модулю логики должно быть все равно к какой бирже его подключили: к реальному API или к псевдо-API (для тестирования). С учетом всего этого получилась примерно вот такая архитектура:

Базу выбрал PostgreSQL. Тут нет никакого тайного умысла. Вы можете использовать любую. 

В связи с тем, что каждый модуль стоит внимания, это все не поместится в одну статью. Поэтому я начинаю мини-сериал: «Пишем качественного трейд бота на JS». Поэтому подписывайтесь, устраивайтесь поудобней — начинаем

Сервис для логов

Простой класс, который принимает на вход префикс для логирования и имеет два метода log и error. Эти методы печатают лог с текущим временем и перфиксом:

class LoggerService {
  constructor(prefix) {
    this.logPrefix = prefix
  }

  log(...props) {
    console.log(new Date().toISOString().substr(0, 19), this.logPrefix, ...props)
  }

  error(...props) {
    console.error(new Date().toISOString().substr(0, 19), this.logPrefix, ...props)
  }
}

Теперь подключим биржу

yarn add node-binance-api

Добавим класс BaseApiService. Сделаем в нем инициализацию Binance SDK, а также применим сервис LoggerService. Учитывая мой опыт с Binance могу сразу сказать, что в зависимости от торговой пары мы должны слать цену и обьем с разным количеством знаков после запятой. Все эти настройки для каждой пары можно взять, сделав запрос futuresExchangeInfo(). И написать методы для получения количества знаков после запятой для цены getAssetPricePrecision и объема getAssetQuantityPrecision.

class BaseApiService {
  constructor({ client, secret }) {
    const { log, error } = new Logger('BaseApiService')
    this.log = log
    this.error = error

    this.api = new NodeBinanceApi().options({
      APIKEY: client,
      APISECRET: secret,
      hedgeMode: true,
    })
    this.exchangeInfo = {}
  }

  async init() {
    try {
      this.exchangeInfo = await this.api.futuresExchangeInfo()
    } catch (e) {
      this.error('init error', e)
    }
  }

  getAssetQuantityPrecision(symbol) {
    const { symbols = [] } = this.exchangeInfo
    const s = symbols.find(s => s.symbol === symbol) || { quantityPrecision: 3 }
    return s.quantityPrecision
  }

  getAssetPricePrecision(symbol) {
    const { symbols = [] } = this.exchangeInfo
    const s = symbols.find(s => s.symbol === symbol) || { pricePrecision: 2 }
    return s.pricePrecision
  }
}

Дальше добавляем метод создания ордера, с учетом правильного количества знаков после запятой для цены и обьема:

async futuresOrder(side, symbol, qty, price, params={}) {
  try {
    qty = Number(qty).toFixed(this.getAssetQuantityPrecision(symbol))
    price = Number(price).toFixed(this.getAssetPricePrecision(symbol))
    if (!params.type) {
      params.type = ORDER.TYPE.MARKET
    }
    const res = await this.api.futuresOrder(side, symbol, qty, price || false, params)
    this.log('futuresOrder', res)
    return res
  } catch (e) {
    console.log('futuresOrder error', e)
  }
}

Теперь бот умеет создавать ордера. Научим его слушать события из биржы для того, чтоб он мог отлавливать изменения статуса ордеров. Для этого создадим класс TradeService.

class TradeService {
  constructor({client, secret}) {
    const { log, error } = new LoggerService('TradeService')
    this.log = log
    this.error = error
    this.api = new NodeBinanceApi().options({
      APIKEY: client,
      APISECRET: secret,
      hedgeMode: true,
    })
    this.events = new EventEmitter()
  }

  marginCallCallback = (data) => this.log('marginCallCallback', data)

  accountUpdateCallback = (data) => this.log('accountUpdateCallback', data)

  orderUpdateCallback = (data) => this.emit(data)

  subscribedCallback = (data) => this.log('subscribedCallback', data)

  accountConfigUpdateCallback = (data) => this.log('accountConfigUpdateCallback', data)

  startListening() {
    this.api.websockets.userFutureData(
      this.marginCallCallback,
      this.accountUpdateCallback,
      this.orderUpdateCallback,
      this.subscribedCallback,
      this.accountConfigUpdateCallback,
    )
  }

  subscribe(cb) {
    this.events.on('trade', cb)
  }

  emit = (data) => {
    this.events.emit('trade', data)
  }
}

При помощи метода из SDK this.api.websockets.userFutureData подписываемся на события из биржы. Самой главный колбек для нас this.orderUpdateCallback . Он вызывается каждый раз когда меняется статус у ордера. Ловим это событие и прокидываем через EventEmitter тому, кто на это событие подписался, используя метод subscribe.

Перейдем к базе данных

Для чего она нужна? В базе будем хранить все ордера, а также всю историю торговли бота. Пользователей с их ключами к бирже и балансами. В последствии сможем считать сколько бот принес прибыли/убытка. Тут останавливаться долго не буду. Подключаю sequlize. 

yarn add sequelize-cli -D
yarn add sequelize
npx sequelize-cli init

Добавим docker-compose.yml файл для локальной базы:

version: '3.1'

services:
  db:
    image: 'postgres:12'
    restart: unless-stopped
    volumes:
      - ./volumes/postgresql/data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: example
      POSTGRES_DB: bot
    ports:
      - 5432:5432
    networks:
      - postgres


networks:
  postgres:
    driver: bridge

А также добавляю миграции и модели. User, Order

Продолжение следует.

В следующей статье будем писать ядро, которое соединит все эти части и заставит бота торговать.

Продолжение тут

В данной статье мы расскажем вам о том, как создать и настроить вашего первого бота. Данная инструкция поможет вам лучше разобраться в интерфейсе и параметрах настройки. Итак, приступим:
Регистрируемся и логинимся в https://revenuebot.io/, переходим во вкладку «Bots» (https://app.revenuebot.io/office/#/bots/)

Раскрываем меню «CREATE NEW BOT»…

Идентификация, API и кошелек бота

Bot name: Название бота (чаще всего в названии используются характеристики: биржа, торговая пара криптомонет, алгоритм работы и тп.)

Exchange: Выбираем биржу в выпадающем списке (рассмотрим на примере Binance)

Как только вы выберете биржу вам станут доступны следующие поля для заполнения:

Pair: Выбрать торгуемую пару криптомонет. О том, как выбрать эффективную торговую пару подробно написано тут — «Как подобрать эффективную торговую пару криптомонет»

API key: Выбрать API ключ из ранее созданных, либо создать новый.

О том, как создать API ключ подробно написано тут — «Как создать API ключ на бирже Binance и добавить его на RevenueBOT«.

Depo: Выбрать виртуальный кошелек из ранее созданных, либо создать новый, где ввести:

- Название кошелька. Выбирайте название для кошелька такое, чтобы его было легко идентифицировать.
- Комментарий к кошельку для удобства. (Не обязательный параметр).
- Выбрать биржу в выпадающем списке.
- Выбрать криптомонету в выпадающем списке.
- Ввести количество или процент от имеющегося депозита в аккаунте на бирже. Тут можно проверить онлайн баланс нужной монеты на бирже, выбрав нужный API ключ.

Commission: Выбрать вариант комиссии, которая будет применятся биржей. Данная настройка актуальна только для биржи Binance, так как на ней возможна оплата комиссии в третьем токене, который не участвует непосредственно в текущей торговле (BNB токен).

Для использования такого вида комиссии, необходимо активировать ее в аккаунте биржи Binance. Рекомендуем всегда использовать этот вид оплаты комиссии торговли на бирже Binance, так как это дешевле.

Необходимо лишь следить, чтобы BNB был на аккаунте. Для этого наш бот проверяет баланс BNB токена перед каждым пуском. Если баланс токена меньше необходимого, то бот не запускается в работу и отправляет нотификацию пользователю с информацией о необходимости пополнить баланс BNB токена для начала торговли.

Алгоритмы работы бота и его настройки

Algo: Выбрать алгоритм работы бота.

Бот использует API интерфейс бирж для выставления ордеров по выбранному алгоритму и отслеживания их выполнения.
На данный момент существует два алгоритма работы бота RevenueBot:

Алгоритм «Long»

Работа бота происходит циклами и основана на принципе покупай дешевле при падении курса (начальная часть цикла) и продай дороже при росте курса (финальная часть цикла). 
Идея заключается в том, что имея определенный депозит, бот покупает не на всю сумму сразу, а частями в моменты падения цены, используя для этого рассчитанную заранее сетку ордеров.
Первый ордер в сетке самый близкий к текущей цене и самый маленький по объему. Каждый последующий ордер объемней (используется система мартингейл) и дешевле. 
Таким образом, при падении цены бот покупает все больше и больше, но за меньшую цену. Это позволяет совершить итоговую прибыльную сделку, продав все купленное по цене гораздо ниже, чем бот начинал покупать.
По выполнению такой сделки получаем прибыль, бот все подсчитывает и начинает новый цикл работы. Профит получается во второй монете торгуемой пары. 
Успешность такой торговли определяется количеством ордеров в сетке, разницей в их весах, расстоянием между друг другом, отступом первого ордера и как глубоко от текущей цены будет отстоять последний ордер в сетке.
Все эти показатели задаются в настройках. Подробно о каждой из настроек изложено в разделе FAQ о создании бота.
Алгоритм «Short»

Принцип работы такой же, как у алгоритма long, основан на продаже при росте курса и покупке при падении курса.
Исходя из настроек, бот рассчитывает и выставляет сетку ордеров на продажу таким образом, чтобы продавать все больше и больше по мере роста цены.
После чего бот отслеживает выставленные ордеры и, в случае их выполнения, выставляет ордер на покупку по цене ниже, чем они были проданы.
В данном алгоритме работы бота профит можно получать как во второй монете торгуемой пары, так и в первой монете.
Профит в первой монете подходит, например, для тех, кто держит перспективные альткоины на долгий срок и хочет, торгуя их к btc, увеличивать исходный депо именно в альткоине, а не зарабатывать в btc.

После выбора алгоритма работы бота, пользователю предлагается воспользоваться шаблонами настройки данного алгоритма: Light trade mode, Normal trade mode, Extreme trade mode.

Все поля настроек заполнятся автоматически при выборе любого из предложенных шаблонов.

Rate cover: Процент перекрытия изменения цены для расчета сетки ордеров. Данная настройка определяет в процентах отступ последнего ордера в сетке ордеров.

First order indent: Отступ в процентах первого ордера в сетке ордеров.

Price rate to use: Выбор рейта на бирже, от которого вести расчет сетки ордеров. Это могут быть рейты buy, sell, average.

Orders matrix, martingale: Сетка ордеров и мартингейл.

Тут задается количество ордеров в сетке и мартингейл (на сколько процентов каждый следующий ордер в сетке будет весомее предыдущего). Кликнув на view orders matrix, Вы сможете увидеть рассчитанную сетку ордеров.

Profit: Тут задаем в процентах профит, который будет заложен ботом при расчете цены завершающего цикл ордера.

Profit coin: Данная настройка доступна только для алгоритма short. Задает в какой из торгуемых монет будет профит.

Cycle up: Бывает, что бот выставил сетку ордеров, а цена ушла в другую сторону. Получается, что нужно ждать пока цена не вернется, а ждать можно долго.

Этого ожидания можно избежать, настроив актуализацию сетки ордеров к текущей цене. Тут задается процент, при достижении которого, текущая сетка ордеров отменяется и выставляется новая.

Sleep before cancel orders for cycle up: Тут задается задержка в минутах, перед тем как начать отменять текущую сетку ордеров, когда срабатывает настройка Cycle up.

Данная настройка позволяет избежать частых отмен текущей сетки ордеров, когда цена за очень короткое время изменилась и вернулась к прежнему уровню.
Можно выждать некоторое время, чтобы зря не снимать текущую сетку ордеров.

Sleep before cycle up after cancel orders: Тут задается задержка в минутах перед выставлением новой сетки после отмены предыдущей сетки ордеров.

Данная настройка также позволяет избежать негативных последствий в ситуации, когда цена за очень короткое время изменилась и вернулась к прежнему уровню.

Sleep after end of cycle: Тут задается задержка в минутах перед тем как начать новый цикл после завершения текущего цикла.

Так же можно задать каждую из этих настроек самостоятельно и сохранить свой шаблон.

Дополнительные настройки

add revenue to depo: При получении прибыли можно добавлять ее к депозиту который использует бот, таким образом увеличивая депозит.
При включенной настройке весь профит от работы бота зачисляется на виртуальный кошелек, который использует данный бот.

logarithmic scale for orders: Обычно сетка ордеров рассчитывается так, что все ордеры в ней расположены линейно, на одинаковом расстоянии друг от друга по всему перекрытию цены.

При небольших колебаниях цены будут чаще всего выполняться первые, самые маленькие по объему, ордеры в сетке.
Чтобы вовлечь побольше депозита в торговлю при небольших колебаниях цены, можно использовать логарифмическое распределение, которое позволит повысить плотность ордеров вблизи текущей цены и понизить плотность ордеров при удалении от текущей цены.

Плотность ордеров можно настроить для разных ситуаций по разному с помощью коэффициента logarithmic factor увеличивая или уменьшая его.
Для большинства случаев подойдет значение logarithmic factor = 1.5.

Кликнув на «view orders matrix», Вы сможете увидеть рассчитанную сетку ордеров.

cost limit: Используйте эту настройку, чтобы не начать покупать слишком дорого и не начать продавать слишком дешево.
Задает максимальную цену, выше которой бот не начнет цикл для алгоритма Long и минимальную цену ниже которой бот не начнет цикл при алгоритме Short.

fix first partial order with profit: Бывает, что первый ордер в сетке частично выполнился, но цена пошла в другую сторону. Такое случается, когда бот оперирует большим депо и ордеры в сетке довольно объемные, даже самый первый.

В такой ситуации можно долго ждать возвращения цены и выполнения ордера полностью, чтобы работа алгоритма продолжилась. Включив данную настройку можно задать процент профита для расчета такой цены, при достижении которой мы получим профит, если отменим частично выполненный ордер и выставим на его сумму завершающий цикл ордер. Ведь цена ушла в ту сторону, где мы получим профит, просто ордер оказался слишком объемным.

Фильтры для старта бота

Мы рекомендуем всегда настраивать фильтры для старта бота. Они необходимы для того, чтобы бот начал торговлю в самое выгодное время, основываясь на выбранном алгоритме торговли и ваших предпочтениях. Подробнее читайте тут: «Фильтры для старта бота. Описание и настройка.»

Уведомления

Выставляем необходимые уведомления: WEB, E-mail, SMS, Telegram

И нажимаем «Create New Bot».

Поздравляем! Вы создали своего первого бота для биржи!

Мне был необходим для личного удобства бот в Телеграм, который умеет выполнять следующие действия:

  1. Показать текущий размер активов в USD(T).
  2. Показать изменения по портфелю в USD(T) за неделю и за все время.

Мне критически важно не использовать никакое приложение вида «все биржи в одном месте» в качестве proxy — да, я не хочу никому предоставлять свои ключи.

Если нужен — давайте напишем.

Что нам потребуется?

В качестве примера в данной статье я буду использовать криптовалютную биржу Binance. Стоит отметить, что никаких ограничений на использование с другими биржами нет — весь каркас тот же самый. Разве что взаимодействие по API будет немного другим (зависит от биржи).

  1. Нам потребуется функционал Telegram (куда же без него).
  2. Нам потребуется Dropbox вместо базы данных (о, да).
  3. Нам потребуется инструмент, где будет крутиться наш бот. Лично я использую Heroku, но можно использовать и AWS.

Создаем бота в Телеграм

Данный этап был описан сотни раз в огромном числе статей, найти которые не составляет проблем. Поэтому здесь будет кратко.

Нам нужно найти в телеграмме контакт @BotFather и выполнить последовательность команд

/start
/newbot
# Нужно ввести приватное имя нового бота и его публичное имя
# Я использую непопулярное публичное имя, т.к. тут будут наши финансы
# Здесь же мы получим API token нашего бота, сохраним его
# Запомним ссылку вида t.me/alias_binance_bot

База из топора

Для начала мы подготовим Dropbox.

Перейдем по ссылке и получим свой API token для Dropbox, нажав на кнопку Create App. Я создам доступ на отдельную папку в Dropbox.

На текущей странице нам необходимо будет сгенерировать OAuth 2.0 для Dropbox:

После создания пройдем на вкладку Permissions и установим права на files.content.write

Теперь по ссылке у нас появилась папка APPS. Зайдем в нее, далее зайдем в поддерикторию с названием нашего бота. Туда нам необходимо поместить файл totalData.txt, содержащий только пустой список.

[]

Взаимодействие с Binance

Нам необходимо создать наш API ключ на бирже Binance.

Данная активность происходит по этой ссылке.

Результатом данного действия для нас будет API Key и Secret Key. В нашем случае будет достаточно прав только на чтение.

В качестве следующего шага мы напишем код, который будем использовать в дальнейшем.

import json
import time
import logging
import os
import binance
import dropbox
from binance.client import Client

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)

binanceKey = ['BinanceKey']
binanceSecret = ['BinanceSecret']

dropboxToken = 'DropboxKey'

SLEEP_TIMEOUT = 1 * 60

def getBalance(idx):
    client = Client(binanceKey[idx], binanceSecret[idx])
    balances = client.get_account()['balances']
    balanceUsd = 0
    prices = client.get_all_tickers()
    for b in balances:
        curB = float(b['free']) + float(b['locked'])
        asset = b['asset']
        if curB < 0.000001:
            continue
        if asset == "USDT":
            balanceUsd += curB
        prices = sorted(prices, key=lambda p: p['symbol'])
        for p in prices:
            if p['symbol'] == str(asset) + "USDT":
                balanceUsd += float(curB) * float(p['price'])
    balanceUsd = float("%.2f" % balanceUsd)
    curt = time.time()
    return balanceUsd, curt

def getAccountInfo():
        amountUsd, timenow = getBalance(0)
        return {'usd': amountUsd, 'ts': timenow}

def loadJsonFromDropbox(dbx):
    for i in range(1):
        try:
            meta, resp = dbx.files_download('/totalData.txt')
            print(meta, resp)
            body = resp.content.decode('utf-8')
            resp.close()
            return json.loads(body)
        except Exception as ex:
            time.sleep(0.5 * (2 ** i))
            print(ex)

def saveJsonToDropbox(dbx, content):
    jsonBytes = json.dumps(content, indent=4).encode('utf-8')
    dbx.files_upload(jsonBytes, '/totalData.txt', mode=dropbox.files.WriteMode('overwrite'))

def addInfoPointToDropbox(dbx):
        content = loadJsonFromDropbox(dbx)
        content += [getAccountInfo()]
        saveJsonToDropbox(dbx, content)

def main():
    dbx = dropbox.Dropbox(dropboxToken)
    while True:
        addInfoPointToDropbox(dbx)
        time.sleep(SLEEP_TIMEOUT)
    amountUsd, timenow = getBalance(0)
    print(amountUsd)
    print(timenow)

if __name__ == '__main__':
	main()

Для начала попробуем запустить данный код локально. Если все сделано правильно — код будет исполняться каждые 60 секунд и спустя некоторое время файл totalData.txt должен выглядеть как-то так:

[
    {
        "usd": 2.81,
        "ts": 1670699696.930476
    },
    {
        "usd": 2.82,
        "ts": 1670699760.437554
    },
    {
        "usd": 2.84,
        "ts": 1670699823.819883
    },
    {
        "usd": 2.86,
        "ts": 1670700537.611635
    },
    {
        "usd": 2.88,
        "ts": 1670700600.6501918
    }
]

Еще немного кода. Как считать diff

Далее я приведу пример кода, с помощью которого мы будем получать сами изменения портфеля, а так же этот же код должен запускаться ботом.Как я уже писал выше — я использую Heroku. К тому же до недавнего времени данный сервис был бесплатным, но времена меняются и уже можно задуматься — стоит ли использовать Heroku или присягнуть AWS. Если вы, как и решите выбрать Heroku — я могу посоветовать данную статью.

Сам бот будет иметь одну ключевую команду — stats.

API ключей от Binance здесь уже не потребуется. Только token полученный при регистрации бота в Telegram и Dropbox token (вы же помните, Dropbox заменяет нам базу данных?). Для подсчета информации по неделе мы просто генерим список по балансам за неделю. При необходимости код несложно изменить и считать diff за любой временной срез.

import logging
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
import os
import dropbox
import time
import json
import datetime

PORT = int(os.environ.get('PORT', 5000))

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)
TOKEN = os.environ.get('TELEGRAM_TOKEN', None)

dropboxToken = ''

def start(update, context):
    update.message.reply_text('Hi!')

def loadJsonFromDropbox(dbx):
	meta, resp = dbx.files_download('/totalData.txt')
	body = resp.content.decode('utf-8')
	resp.close()
	return json.loads(body)

def getHistory():
	dbx = dropbox.Dropbox(dropboxToken)
	prices = loadJsonFromDropbox(dbx)

	timeNow = time.time()
	dtNow = datetime.datetime.now()
	dtToday = dtNow.replace(hour=0, minute=0, second=1)
	dtWeek = dtToday - datetime.timedelta(days=dtToday.weekday())
	dtAllTime = dtNow - datetime.timedelta(days=100000)

	stats = {
		'this week': {
			'since': dtWeek.timestamp(),
			'till': dtNow.timestamp(),
			'prices': []
		},
		'all time': {
			'since': dtAllTime.timestamp(),
			'till': dtNow.timestamp(),
			'prices': []
		}
	}

	for item in prices:
		for stat in stats:
			if stats[stat]['since'] < item['ts'] < stats[stat]['till']:
				stats[stat]['prices'].append(item)

	text = ''
	totalBalance = 0.
	totalBalanceUsd = 0.
	for stat in stats:
		usdt = [p['usd'] for p in stats[stat]['prices']]

		if len(usdt) >= 1:
			u1 = usdt[-1]
			u2 = usdt[0]
			valueUsd = '{:+.2f} USD'.format(u1 - u2)
		else:
		    values = 'n/a'
		text += '{}: {}n'.format(stat, valueUsd)
		if stat == 'all time':
			totalBalanceUsd = u1
				
	dt = datetime.datetime.fromtimestamp(prices[-1]['ts'])
	text += 'nLast update: {:%A %H:%M:%S} UTC+0n'.format(dt)

	return update.message.reply_text(text, parse_mode='markdown')

def main():
    updater = Updater(TOKEN, use_context=True)
    dp = updater.dispatcher

    dp.add_handler(CommandHandler("start", start))
    dp.add_handler(CommandHandler("stats", getHistory))
    dp.add_handler(MessageHandler(Filters.text, echo))
    dp.add_error_handler(error)

    updater.start_webhook(listen="0.0.0.0", port=int(PORT), url_path=TOKEN)
    print(TOKEN + ' <- TOKEN | ' + str(PORT) + ' <- PORT')
    updater.bot.setWebhook('https://ваш_хероку_апп.com/' + TOKEN)

    updater.idle()

if __name__ == '__main__':
    main()

Вместо заключения

В результате применения команды stats вы должны получить в ответ, например, такое сообщение:

Стоит отметить, что данного бота можно развивать и дальше до еще более прикладных применений.

Например, можно реализовать команду buy или sell. Можно подключить дополнительные аккаунты или сразу несколько бирж и мониторить все свои портфели в одном месте. Удобно? Удобно!

Для подключения дополнительных аккаунтов достаточно добавить еще один вызов в этом месте (и конечно же дополнительные api ключи — там они уже и так в list’е).

        amountUsd, timenow = getBalance(1)

Однако данные упражнения мы оставим дорогим читателям для самостоятельной работы. Всё же потребности у всех разные 🙂

В целом, все исходники уже представлены в статье, но на всякий случай — также они на GitHub.

Благодарю за внимание и буду рад ответить на ваши вопросы.

Ссылка на код на github в телеграме

Бот исключительно в демонстрационных целях. Когда я писал своего первого бота мне не хватало чего-то такого.

Идею для торговой стрегии взял из книги Ларри Вильямса «Долгосрочные секреты краткосрочной торговли» и слегка упростил. Он называет это прорыв волатильности. В чём суть:
— считаем разницу между хай и лоу предыдущей свечи
— к цене открытия текущей свечи прибавляем разницу из предыдущего пункта, это и будет ценой для входа в позицию
— если цена достигла этой цены покупаем
— выход на октрытии следующего бара

Всё. Максимально просто.

Теперь ещё раз то же самое на примере.
— Хай прошлой свечи 251 USDT, лоу 248 USDT. Разница 3 USDT.
— Открытие текущей свечи 250 USDT. Цена входа 253 USDT.
— Как только цена достигла 253 USDT покупаем 0,1 BNB
— На следующем открытии свечи выходим. Если цена выше, то заработали что-то, если нет, то нет.

Торговая пара BNB/USDT с биржи binance.

В боте я рассматриваю минутный таймфрейм, чтобы можно было быстро посмотреть что и как работает. График цен можно смотреть на самой бирже Можете поменять на любой на ваше усмотрение.

Торговля идёт фиксированным лотом 0,1 BNB. Можно поменять в переменной `quantity`.

Что нужно для работы:
— установить все зависимости из файла `requirements.txt`
— зарегистрироваться на бирже https://www.binance.com и получить ключи для api и заполнить глобальные переменные `BINANCE_API` и `BINANCE_SECRET`
— залогиниться в тестовой сети testnet.binance.vision/ через github, тоже получить ключи и заполнить переменные `TEST_BINANCE_API` и `TEST_BINANCE_SECRET`
— запустить файл `barackbot.py`

В консоли должны увидеть что-то такое:

Opened connection
Free USDT is 9976.63802, free BNB is 1000.1
Entry price is 249.36929999999998 USDT, quantity is 0.1 BNB
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.15930000 Low: 249.09580000 Close: 249.15880000 Volume: 48.44700000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.32950000 Low: 249.09580000 Close: 249.32760000 Volume: 415.72900000
Buying 0.1 BNB at 249.3693 USDT
Buy order info: {‘symbol’: ‘BNBUSDT’, ‘orderId’: 111111, ‘orderListId’: -1, ‘clientOrderId’: ‘4K1iEdjslkdfjIjhpNb2’, ‘transactTime’: 1614758407134, ‘price’: ‘249.36930000’, ‘origQty’: ‘0.10000000’, ‘executedQty’: ‘0.00000000’, ‘cummulativeQuoteQty’: ‘0.00000000’, ‘status’: ‘NEW’, ‘timeInForce’: ‘GTC’, ‘type’: ‘LIMIT’, ‘side’: ‘BUY’, ‘fills’: []}
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.49750000 Low: 249.06770000 Close: 249.49740000 Volume: 733.67700000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.50000000 Low: 249.06770000 Close: 249.22690000 Volume: 817.82700000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.50000000 Low: 249.06770000 Close: 249.31670000 Volume: 882.20500000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.66020000 Low: 249.06770000 Close: 249.40270000 Volume: 3068.25600000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.66020000 Low: 249.06770000 Close: 249.48930000 Volume: 3087.31000000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.66020000 Low: 249.06770000 Close: 249.35270000 Volume: 3347.31700000
Time: 2021-03-03 08:00:00 Open: 249.10500000 High: 249.66020000 Low: 249.06770000 Close: 249.35280000 Volume: 3348.73900000
Stop order. Open price is 249.36350000 USDT
Loss is -0.002169999999750871 USDT
Stop order info: {‘symbol’: ‘BNBUSDT’, ‘orderId’: 111112, ‘orderListId’: -1, ‘clientOrderId’: ‘Qw3zLdoIBqdf98df’, ‘transactTime’: 1614758462874, ‘price’: ‘0.00000000’, ‘origQty’: ‘0.10000000’, ‘executedQty’: ‘0.10000000’, ‘cummulativeQuoteQty’: ‘24.93476000’, ‘status’: ‘FILLED’, ‘timeInForce’: ‘GTC’, ‘type’: ‘MARKET’, ‘side’: ‘SELL’, ‘fills’: [{‘price’: ‘249.34760000’, ‘qty’: ‘0.10000000’, ‘commission’: ‘0.00000000’, ‘commissionAsset’: ‘USDT’, ‘tradeId’: 35189}]}
Free USDT is 9976.63585, free BNB is 1000.1
Entry price is 249.65974999999997 USDT, quantity is 0.1 BNB
Time: 2021-03-03 08:01:00 Open: 249.36350000 High: 249.42970000 Low: 249.30350000 Close: 249.39350000 Volume: 66.42300000
Time: 2021-03-03 08:01:00 Open: 249.36350000 High: 249.44160000 Low: 249.30350000 Close: 249.42620000 Volume: 88.59900000
Time: 2021-03-03 08:01:00 Open: 249.36350000 High: 249.44160000 Low: 249.30350000 Close: 249.42300000 Volume: 100.39700000

Ещё раз. Бот максимально простой. Не учитывает ни статусы заявок, ни комиссии, нет стопов. Нет обработки минимального лота. Обработка ошибок минимальная. Нет контроля непрерывной работы. Просто механика выставления заявок.

A-Bot

Спотовый бот для алгоритмической мультивалютной торговли на бирже Binance, поддерживающий ручную и полностью автоматическую торговлю.


Бот работает бесплатно на аккаунтах Binance, зарегистрированных по реферальной ссылке разработчиков.
Для остальных пользователей предусмотрена подписка полезного использования, о которой читайте далее.
При первом запуске бота новым пользователям, не являющимся рефералами разработчика, начисляется бонус в размере 10$.
Binance: Регистрация по реферальной ссылке
Referal ID: C2GCPXJA

Реферальная программа

В боте существует многоуровневая реферальная программа: человек, которого Вы привели, может указать BEP20-кошелёк от Вашего аккаунта на Binance или Ваш уникальный 6-ти значный реферальный код, который виден в главном меню бота или во вкладке Статистика в личном Telegram-боте. Текущий процент, выплачиваемый пользователям от биржевой комиссии их рефералов первого уровня, полученных разработчиками, составляет 15%. Также рефовод может получать дополнительно до 7% за другие уровни в его реферальном дереве. Итого, общий процент реферальных выплат может достигать 22%. Выплаты производятся каждую субботу, отчёты которых публикуются в Telegram-канале анонсов.

Пополнение баланса:

В связи с обновлением политики торговли по API на Binance от 23.08.2021, торговля по API будет возможна ТОЛЬКО на аккаунтах, прошедших промежуточную верификацию. Для работы бота на аккаунтах, зарегистрированных НЕ по реферальной ссылке разработчиков, действует система полезной оплаты за совершённые ботом сделки, которая составляет 0.015% от их размера. При первом запуске бота новым пользователям автоматически начисляется бонус в размере 10$, который виден в личном Telegram-боте. В дальнейшем, в случае отсутствия денежных средств на аккаунте A-Bot, работа бота будет автоматически приостановлена, поэтому не забывайте следить за балансом. Для пополнения баланса A-Bot Вам необходимо будет настроить Telegram-бота по инструкции и пополнить баланс на желаемую Вами сумму в любом USD токене, следуя указаниям к переводу. При пополнении баланса начисляется бонус до 50% при пополнении до 400$, свыше этой суммы бонус остаётся фиксированным и составляет 50%.

Пользователи, которые зарегистрированы по нашей реферальной ссылке, продолжат пользоваться инструментом бесплатно.

Контакты:

Официальный чат Telegram — для обсуждений, связи с разработчиками и развития проекта

Полезные ссылки:

Статистика USDT-ботов, Статистика BTC-ботов
Полное руководство по запуску бота — подробный гайд по настройке API, Telegram, созданию сервера, а также настройке и запуску бота
Мануал по торговым настройкам бота — расширенная инструкция по каждой настройке бота с визуальными примерами
Таблица расчёта усреднений — таблица расчёта цены и объёма ордеров для усреднений от @dpcwee

Описание стратегии:

Бот работает по стратегии усреднения. Суть стратегии заключается в снижении средней цены входа в актив путём увеличения веса позиции в случае, если рыночная стоимость актива снижается по отношению к текущей стоимости ордера. Иными словами, при входе в сделку бот, исходя из пользовательских торговых настроек, размещает ордер на продажу с заданным процентом профита, но если стоимость актива падает по отношению к первой покупке, не достигнув ордера на продажу, и опускается ниже заданного значения в %, бот отменяет ордер на продажу, докупает определённое количество монет, исходя из торговых настроек, и размещает новую заявку на продажу по цене (новая средняя цена покупки + % желаемой прибыли). Таким образом, при падении рыночной стоимости актива бот постоянно анализирует текущие ордера и рыночные данные, сопоставляя условия настроек торговой стратегии и биржевую активность, и докупает монеты, увеличивая их общий объём и снижая новую цену продажи.

Обозначения статуса ордеров:

— Ордер на покупку исполнен
— Размещён ордер на продажу
— Ордер на продажу исполнен, позиция закрыта
— Ордер на продажу отменён для усреднения
— Ордер на продажу отменён и активирован трейлинг-стоп
— Частичная продажа позиции трейлингом по маркету
— Полная продажа позиции по трейлингу, позиция закрыта

Ключи запуска:

  • -s — Прямой запуск бота в обход главного меню
  • -ud — Включить возможность добавления UP/DOWN токенов в список разрешённых монет
  • -uo — Взять в работу ручные ордера, размещённые на продажу (не должно быть открытой ботом позиции по активу). Экспериментальная функция!
  • -snl — Продавать свободные монеты на балансе к приоритетному из quote_asset активу сразу же после листинга этой торговой пары на Binance
  • -tld — Запустить бота на аккаунте Binance US
  • -dtl — Удалить @abot_chat из шапки личного Telegram-канала со статистикой
  • -nlb — Не присылать информацию о покупке BNB для комисии в консоль бота и личный Telegram-канал
  • -api, -secret и -referral — Сбросить одноимённые настройки при запуске бота
  • -wlinit — Динамический White List монет. Каждую минуту бот будет обновлять разрешённый список монет из файла wlinit.txt (который необходимо предварительно создать; монеты должны быть перечислены одной строкой через пробел, например BTC ETH BNB). Удобно в том случае, если Вы имеете какие-либо индикаторы и хотите постоянно автоматически фильтровать монеты для торговли
  • --conf — Конфигурационный ключ, более подробно о котором можно узнать внизу страницы

Ключи команд:

  • -s — Запустить бота
  • -u — Обновить бота до актуальной версии при её наличии
  • -m — Удалить, добавить или сбросить параметры разрешённого для торговли списока монет
  • -k — Изменить настройки API ключей от Binance или параметры Telegram
  • -p — Изменить параметры торговли и работы бота
  • -h — Сбросить всю историю торговли по парам из разрешённого для торговли списка монет. Открытые позиции на бирже не будут отменены, но удалятся из базы данных бота
  • -i — Удаление торговой статистики обнулит показатели прибыли и успешных сделок, совершенных ботом
  • -e — Безопасный выход из бота (в главном меню) или безопасная остановка торговли и выход в главное меню (при работающем боте)
  • -dlog — Удалить все старые логи в папке с ботом
  • -sat — Продать все свободные или потерявшиеся монеты (со статусом SELL_ORDER и NO_ORDER) и конвертировать в BNB пыльные остатки
  • -auto — Автоматически рассчитать торговые параметры по общему балансу активов, указанных в quote_asset

Обозначения информационной консоли:

  • s — Время исполнения последнего цикла скрипта в секундах
  • — Индикатор скорости обработки торговых скриптов
    • Зелёный — Быстрая обработка
    • Жёлтый — Имеется незначительное отставание
    • Красный — Данный цвет сигнализирует о большом количестве необработанных биржевых операций в стэке данных, что означает недостаточное количество вычислительных ресурсов машины
  • ПД — Детектор пампов
    • Зелёный — Активирован, мониторит рынок
    • Жёлтый — Активирован, но есть незначительное отставание стрима детектора пампов от текущего времени
    • Красный — Собирает рыночные данные, ещё не прошёл час с момента запуска бота, либо бот не успевает обрабатывать стрим детектора пампов из-за слабой машины/интернета
  • М — Максимально допустимое количество одновременно открытых позиций
  • Б — Свободный баланс
  • Л — Самый близкий к продаже актив (название монеты разница рыночной цены и цены ордера на продажу в % (цена ордера))
  • Д — Суточная дельта пар из белого списка в процентах, условно обозначающая тренд рынка
    • Жёлтый — Дельта положительная; настройки не блокируют покупки/усреднения
    • Фиолетовый — Дельта отрицательная или положительная; если в quote_asset несколько активов для торговли, обозначает блокировку покупок/усреднений по одному/нескольким из них
    • Красный — Дельта отрицательная; настройки блокируют покупку/усреднение по всем активам из quote_asset

Рекомендации:

  • Для того, чтобы бот начал работу с ручным ордером, актив должен находится в разрешённом списке монет
  • Не распоряжайтесь активами, которые находятся в работе у бота. Если видите свободный баланс — проверьте монету в терминале, возможно, бот работает по этой монете с активированным трейлингом
  • В случае расставления сеткой ручных ордеров на покупку между ордерами должен быть запас желательно в 1-2% на случай сквизов, в случае которых при резком срабатывании нескольких ордеров одновременно бот не учтёт последний из них
  • Желательный минимальный депозит для комфортной работы бота на любом рынке составляет от 1000-2000$
  • Настоятельно рекомендуем настроить Telegram-бота для управления A-Bot’ом и просмотра необходимой статистики

Запуск:

Windows (>8, >Server 2012):

Скачайте A-Bot.exe и запустите программу

Linux (Ubuntu >18.04; Debian >9; CentOS >8):

В терминале введите
sh -c "$(curl -fsSL abot-trade.ru/A-Bot.sh)" (эта команда автоматически обновит системные пакеты, скачает бота, выдаст ему права и установит менеджер окон (screen) для фоновой работы бота), после выполнения этой команды Вы окажитесь в уже созданном screen под названием abot. Для запуска бота введите ./A-Bot
ИЛИ
Скачайте A-Bot (в терминале на сервере введите
wget https://github.com/dpcwee/abot/releases/download/ВЕРСИЯ/A-Bot, где вместо ВЕРСИЯ укажите последнюю версию),
дайте ему права командой chmod 755 A-Bot, после чего создайте окно screen (инструкция ниже), если оно ещё не создано (проверьте наличие скринов командой screen -ls), после чего запустите бота командой ./A-Bot

Обновление:

При выходе новой версии в течение часа в главном меню A-Bot появится новая ключ-команда -u для обновления; также в Вашем Telegram-боте (через который Вы управляете торговым ботом и который отвечает за пуши сообщений в Ваш Telegram-канал) появится новая кнопка Обновить A-Bot (при обновлении через Telegram бот перезапустится и начнёт торговлю автоматически)

ИЛИ

Windows: Закройте бота и скачайте новую версию в директорию со старым файлом (с перезаписью)

Linux: Зайдите в screen к боту командой screen -x и остановите бота командами -e, после чего в директории с файлом A-Bot введите команду на удаление старой версии
rm A-Bot, затем введите команду
wget https://github.com/dpcwee/abot/releases/download/ВЕРСИЯ/A-Bot, где вместо ВЕРСИЯ указываете последнюю версию, после чего даёте права файлу
chmod 755 ./A-Bot и запускаете его командой ./A-Bot

Работа с screen на Linux:

Чтобы бот работал в фоновом режиме на сервере 24/7, следуюет установить предназначенную для этого утилиту screen. После подключения к серверу вводим команды apt update, а затем apt-get install screen и вводим Enter или Y, если этого требует терминал, чтобы обновить системные пакеты и установить менеджер окон (screen). Больше эти команды нам не потрубуются!

  1. Вводим screen -S <name_screen> (например screen -S abot), попадаем сразу в новый screen и запускаем ./A-Bot (если файл A-Bot находится в домашней директории, иначе сначала зайдите в папку с ним командой cd директория_с_ботом
  2. Запустили бота и можете разрывать соединение с сервером, бот будет работать в фоновом режиме в созданном скрине
  3. При повторном подключении к серверу с существующими скринами вводим screen -x (подключение к единственному скрину) или screen -x <name_screen>, если их несколько, попадая в нужный скрин. Команда screen -S больше не нужна!
  4. В случае перезагрузки сервера (reboot или другой апокалипсис), подключаемся к серверу и повторяем описанный цикл с 1-го пункта
    Теперь можете разрывать соединение с сервером — A-Bot будет работать вне зависимости от активной сессии подключения.

Параметры API настройки:

  • API ключи — Пара API ключей (api и secret) для обращения к Binance (API-Management)
  • referral — ID Вашего аккаунта на Binance (ID Пользователя — слева вверху в личном кабинете)
  • BEP20-кошелёк — адрес человека на Binance в сети Binance Smart Chain (BSC BEP20), который рассказал Вам о боте
  • hash — Ваш личный хэш для работы бота с сигналами от TradingView или POST запросами
  • abot_stats — Отправлять торговую статистику разработчикам в целях улучшения бота?
  • tg_notification — Уведомления в Telegram о закрытых сделках, суточной статистике и текущая сводка в шапке канала
    • tg_token — Токен, выданный @BotFather при создании Telegram-бота
    • tg_name — <@name> или <chat_id> для отправки уведомлений. Бот, созданный на предыдущем шаге, должен состоять в группе/канале и быть её администратором с включенными возможностями публикации сообщений и изменения профиля
    • user_id — ID Telegram-аккаунта, нужный для управления торговым ботом через Telegram-бота, который можно получить у @userinfobot, написав ему /start или нажав кнопку «Запустить».

Настройка Telegram:

Инструкция настройки Telegram бота и канала
Каждый раз, когда бот полностью закрывает позицию на продажу, Вы будете получать уведомление в Ваш канал.
Если Ваш личный Telegram-бот не отвечает на сообщения, попробуйте: написать Telegram-боту /start, проверить работоспособность или перезапустить A-Bot


TradingView или собственные сигналы:

Бот поддерживает работу с сигналами от TradingView, а также принимает сигналы при отправке POST запроса на наш сервер. Вы можете подобрать/создать свой индикатор и посредством вебхуков отправлять команды A-Bot’у для работы с активами, который, в свою очередь, примет этот актив в работу по своим торговым алгоритмам и настройкам пользователя.

URL сервера для отправления сигналов, который рассылает сигналы индивидуальным ботам по веб-сокету: https://212.8.246.121:443/tv/hash. hash Вы найдёте в настроках API и Telegram (-k в главном меню A-Bot).

Всё тело сигнала должно быть обёрнуто в фигурные скобки {}.

  • Каждый сигнал должен содержать обязательные ключи, без которых бот не сможет среагировать на него:
    • 'exchange' [‘{{exchange}}’] — Биржа, для которой предназначен сигнал (в случае бота, это единственная площадка ‘BINANCE’)
    • 'symbol' [‘{{ticker}}’] — Торговая пара, по которой поступил сигнал
    • 'side' [‘{{strategy.order.action}}’] — Сигнал на покупку или продажу (направление должно быть обозначено, как ‘BUY’ или ‘SELL’). Если тип сигнал ‘BUY’ и на этом активе ещё не открыта позиция, то бот откроет ордер, исходя из торговых параметров. Для закрытия позиции по сигналу ‘SELL’, в сообщении вебхука должен присутствовать ключ ‘take_profit’ или ‘stop_loss’ со значениями ‘true’
    • 'strategy' [‘NAME’] — Любое название Вашей стратегии, включая пробелы, цифры и символы

{«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «BUY», «strategy»: «my_signal»}

  • Необязательные ключи, которые могут быть дополнением к вашей стратегии (в одном сигнале может находиться несколько ключей или все сразу):
    • 'take_profit' [‘true’] — Продать актив, если по нему уже открыт ордер на продажу и позиция находится в плюсе (иначе игнорировать)? {«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «SELL», «strategy»: «my_signal», «take_profit»: «true»}
    • 'stop_loss' [‘true’] — Продать актив по стоп-лоссу. Позиция закроется в убыток, если рыночная стоимость актива ниже средней цены входа! {«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «SELL», «strategy»: «my_signal», «stop_loss»: «true»}
    • 'averaging' [‘true’] — В случае, если на активе уже открыта позиция (иначе игнорировать), после поступления сигнала с этим ключом бот усреднит её, исходя из торговых параметров. {«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «BUY», «strategy»: «my_signal», «averaging»: «true»}
    • 'min_order' [‘NUMBER’] — В случае, если на активе ещё не открыта позиция (иначе игнорировать), размер min_order берётся из сигнала, а не торговых параметров. {«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «BUY», «strategy»: «my_signal», «min_order»: «3.25»}
    • 'sell_up' [‘NUMBER’] — При покупке/усреднении позиции по сигналу, из него также берётся размер sell_up вместо значения из торговых параметров. В случае, если на активе уже открыта позиция, бот просто перевыставит этот ордер с sell_up из сигнала (при этом в сигнале должны отсутствовать ключи ‘averaging’ и ‘stop_loss’). {«exchange»: «{{exchange}}», «symbol»: «{{ticker}}», «side»: «BUY», «strategy»: «my_signal», «sell_up»: «2.5»}

Код для отправки сигналов POST запросом на примере Python:

import requests, json

url = 'https://212.8.246.121:443/tv/hash'
data = {"exchange": "BINANCE", "symbol": "BNBBTC", "side": "BUY", "strategy": "my_signal"}
response = requests.post(url, data=json.dumps(data), headers={'Content-Type': 'application/json'}, verify=False)

Торговые параметры:

  • min_bnb [min >= 0.01] — Минимальный свободный баланс BNB, ниже которого бот будет докупать минимально допустимое количество BNB по рыночной цене для оплаты биржевой комиссии (например 0.03)
  • min_balance [100 >= min_balance >= 0] — Не покупать/усреднять позиции, если свободный баланс составляет меньше заданного % от общего баланса (например 15)
  • position_size [100>= position_size > 0] — Максимально допустимый размер одной позиции в % от общего депозита. В случае, если после усреднения размер позиции превысит значение position_size от общего депозита, то бот не будет усреднять такую позицию (например 20)
  • min_order [min >= 1] — Множитель размера первого ордера на покупку. Стоимость первого ордера будет рассчитываться, как минимальный допустимый размер ордера на бирже (на USD это 10$, на BTC это 0.0001) * min_order. Лимиты можно найти здесь (например 1.2)
  • row_sell [10 >= row_sell >= 1] — Во сколько раз бот может увиличивать множитель min_order при открытии позиции в случае, если предыдущая сделка по этой паре закрылась без усреднений и в течение установленного row_timer (по умолчанию 3600 секунд) времени? (например 3)
  • min_price [min >= 0.00000001] — Минимальная рыночная стоимость монеты, эквивалент в USD которой равен рыночному курсу монеты в USD, ниже которого бот не будет открывать новые сделки по этой паре, лишь усреднять, если стоит ордер на продажу (например 0.05)
  • min_daily_percent [-100 < min_daily_percent < daily_percent <= 99999] — Выше какого значения должнен подняться показатель % суточного изменения цены на бирже, чтобы бот осуществил первую покупку по паре (например -20)
  • daily_percent [-100 < daily_percent <= 99999] — Ниже какого значения должнен упасть показатель % суточного изменения цены на бирже, чтобы бот осуществил первую покупку по паре (например -3)
  • auto_daily_percent [y/n] — Вместо daily_percent использовать общую суточную дельту разрешённого списка монет для ограничения максимального процента коридора покупок. Если Y, то бот не будет покупать монеты, выросшие более, чем на Д % из информационной строки в консоли
  • order_timer [min >= 0] — Интервал паузы между закрытием сделки и новой покупкой по этой же паре в секундах (например 5)
  • min_value [min >= 0] — Эквивалент минимального суточного торгового объёма в USD у торговой пары для открытия позиции по ней (например 100000)
  • sell_up [min > 0] — Желаемый % прибыли от продажи без учёта суточной дельты и трейлинг-стопа (например 1.65)
  • sell_count [y/n] — В первую очередь открывать позиции по наиболее часто торгуемым парам, на которых больше всего сделок
  • buy_down [min < 0] — На сколько % должна упасть рыночная цена актива по отношению к цене его последней покупки, чтобы бот усреднил позицию (например -5)
  • max_trade_pairs — Допустимое количество позиций на продажу, которое бот может держать одновременно открытыми (например 20). Если количество открытых ботом ордеров станет равно или больше max_trade_pairs, бот перестанет совершать новые покупки (кроме усреднений уже открытых позиций)
    • -1 [-1] — Не ограничивать количество одновременно торгуемых ботом пар
    • 0 [0] — Работать только с уже открытыми ордерами и не совершать новые покупки
    • 1 и более [1-999] — Указать максимальное количество позиций вручную
  • auto_trade_pairs [y/n] — Разрешить боту автоматически регулировать количество разрешённых пар? Если Y, бот будет автоматически корректировать максимальное количество одновременно торгуемых пар, если предыдущий параметр настроек задан пользователем вручную от 1 до 999
  • progressive_max_pairs [y/n] — Использовать прогрессивное уменьшение максимального количества пар. Если Y, то количество пар при включенной настройке auto_trade_pairs будет автоматически уменьшаться не только в зависимости от соотношения свободного и общего баланса, но и от количества открытых ордеров и суммарного количества их усреднений
  • delta_deep [y/n] — Использовать глубину падения дельты для определения падения рынка и паузы покупок/усреднений? Если Y, то бот будет блокировать новые покупки и усреднения на падающем рынке до тех пор, пока не произойдёт локальный отскок всего рынка. Определение локального отскока зависит от величины падения самой дельты и выражено в пропорции 1 к 10 (при дельте -5 бот начнёт открывать позиции, когда дельта вырастет до -4.5 и выше)
  • individual_depth [y/n] — Использовать глубину дельты активов для определения индивидуальных падений и паузы покупок/усреднений по аналогии с delta_deep, только отдельно для каждой торговой пары
    • step_aver [min >= 0] — Шаг увеличения сетки усреднений в %. На сколько процентов увеличивать последующую разницу рыночной цены и цены последней покупки для нового усреднения без учёта buy_down. Сетка усреднений в базе данных при отсутствии усреднений равна 0 и увеличивается каждое усреднение на значение step_aver % (например 1.35)
  • max_aver [min >= 0] — Максимальное количество усреднений на одной монете (например 4)
  • quantity_aver [min > 0] — Множитель размера усреднения от текущего веса позиции (например 2). Иными словами, при усреднении бот будет покупать текущее количество монет * quantity_aver, тем самым новая позиция будет равна текущее количество монет * quantity_aver + текущее количество монет
  • average_percent [100 > average_percent >= sell_up] — Максимальный желаемый % разницы между рыночной ценой и средней ценой входа в позицию после усреднения (например 7). Бот будет самостоятельно находить объём для усреднения и делать его таким, чтобы после усреднения средняя цена входа в позицию оказалась не выше %-та average_percent от текущей рыночной цены (то есть цены нового усреднения). Иными словами, после усреднения ордер на продажу будет выше от текущей рыночной цены на average_percent + sell_up % (без учёта остальных динамических настроек, влияющих на sell_up)
  • trailing_stop [y/n] — Использовать трейлинг-стоп? Если Y, отодвигать цену продажи в зависимости от движения цены актива. С включенным трейлингом позиция не закрывается сразу, а продаётся частями trailing_part на приближенных к максимальным значениям ценам, чтобы увеличить потенциальную прибыль, либо закрывается полностью при падении цены и её приближении к средней цене покупки. Данный параметр сделает стратегию более гибкой, но может уменьшить прибыль
    • trailing_percent [min > 0] — При каком падении от локального хай-уровня цены активировать трейлинг-стоп для частичной/полной продажи (например 0.25)
    • trailing_part [0 < trailing_part <= 100] — Размер частичной продажи по трейлингу в % от общего веса позиции (например 10)
    • trailing_value [min >= 1] — Минимальная стоимость позиции в эквиваленте к USD, необходимая для активации трейлинг-стопа (например 50)
  • new_listing [y/n] — Открывать позиции по только что добавленным на биржу активам? Если Y, бот будет покупать монеты сразу после их листинга и игнорировать торговые параметры по типу min_value, min_price, daily_percent и прочих, кроме min_balance и double_asset (по умолчанию статус new_listing присваивается на 3600 секунд и сбрасывается, если за это время не было max_buy_listing продаж)
    • listing_order [min >= 1] — Множитель минимального ордера на паре при листинге (например 3.3)
    • max_buy_listing [0 <= max_buy_listing <= 999] — Сколько раз бот может вновь открывать позиции по только что добавленному на биржу активу, игнорируя торговые параметры? После преодоления этого значения бот не откроет позицию по данному активу, пока условия на торговой паре не будут соответствовать торговым настройкам (например 5)
  • user_order [y/n] — Работа с пользовательскими ордерами после ручной покупки. Если Y, то в случае покупки пользователем монеты из разрешённого списка бот автоматически поставит на продажу купленное количество монет и будет работать с этой парой так же, как и в остальных случаях, ориентируясь на торговые настройки. Также уже открытые ордера можно будет усреднять вручную: для этого во время работы бота купить нужное количество монет, после чего бот отменит ордер на продажу, рассчитает новые данные и выставит ордер по новой цене
  • reinvest_position [y/n] — Высвобождать частями позиции в инвесте за счёт других прибыльных сделок. Если активно, бот будет направлять часть прибыли от продаж в зависшие убыточные тяжёлые позиции для постепенного высвобождения их объёма
  • reinvest_percent [0 < reinvest_percent <= 100] — Какую часть в % от прибыли направлять на реинвестирование в зависшие позиции?
  • fiat_currencies [RUB UAH …] — Если включены уведомления в Telegram, то ежедневная статистика торгов будет рассчитываться в этих валютах вместе с quote_asset
  • quote_asset [USDT BTC …] — Котируемые валюты для торговли (то есть те валюты, в паре к КОТОРЫМ торгуются монеты из разрешённого списка (ADA/USDT, ADA/BTC), а не которые торгуются к ним). Приоритет котируемых активов для первоочередной покупки соответствует их расположению (слева направо)
  • double_asset [y/n] — Если Y, бот сможет покупать одну и ту же монету на нескольких котируемых активах одновременно (ADA/USDT и ADA/BTC)
  • pump_detector [y/n] — Использовать детектор пампов для открытия позиций? Если Y, бот будет анализировать все монеты из разрешённого списка монет в реальном времени и, в случае обнаружения всплеска объёмов, доминации покупателей и роста цены актива, незамедлительно покупать монету
  • pump_order [min >= 1] — Множитель размера покупки по сигналу детектора пампов (например 2.5)
  • pump_up [min > 0] — Желаемый % прибыли от продажи позиции, открытой или усреднённой по сигналу детектора пампов, без учёта суточной дельты и трейлинг-стопа (например 0.35)
  • max_pump_pairs [min >= 0] — Допустимое количество позиций на продажу, открытых по сигналу детектора пампов, которое бот может держать одновременно открытыми (например 10)
  • trailing_pump [y/n] — Использовать трейлинг-стоп на ордерах, открытых по сигналу детектора пампов? Если Y, то бот будет активировать трейлинг на таких ордерах по параметрам trailing_stop‘a
  • signals [y/n] — Принимать торговые сигналы от TradingView или POST запросов посредством вебхуков
  • max_signals [0 < signals <= 999] — Максимальное количество позиций, открытых по сигналам

Ключ —conf:

Все они активируются через общий ключ —conf либо при вводе ключей при запуске бота (например, ./A-Bot —conf sell_up 1-2 —conf mpp 5), либо через личного Telegram-бота в Торговых параметрах (введя —conf sell_up 1-2, затем с новой строки —conf mpp 5). Активные ключи также видны в Telegram-боте в Торговых настройках. Для удаления ключа(-ей) без перезапуска бота введите —conf НАЗВАНИЕ_КЛЮЧА(-ЕЙ) в Торговых настройках Telegram-бота.

Простые — с одним/несколькими статичными значениями

  • Ключ mop (активируется командой —conf mop ЧИСЛО) — Автоматически рассчитывать min_order на основании свободного баланса, если включена progressive_max_pairs, в противном случае на основании общего баланса. Бот будет делать минимальный ордер таким, чтобы работать только с указанным ЧИСЛОМ % от свободного/общего баланса

  • Ключ mlp (активируется командой —conf mlp ЧИСЛО) — Автоматически рассчитывать listing_order на основании свободного баланса, если включена progressive_max_pairs, в противном случае на основании общего баланса. Бот будет делать минимальный ордер при листинге таким, чтобы работать только с указанным ЧИСЛОМ % от свободного/общего баланса

  • Ключ mpp (активируется командой —conf mpp ЧИСЛО) — Автоматически рассчитывать pump_order на основании свободного баланса, если включена progressive_max_pairs, в противном случае на основании общего баланса. Бот будет делать минимальный ордер Детектора пампов таким, чтобы работать только с указанным ЧИСЛОМ % от свободного/общего баланса

  • Ключ reverse_sort (активируется командой —conf reverse_sort high) — Режим обратной сортировки по приоритету открываемых позиций (не с самых просевших, а самых выросших за сутки)

  • Ключ reverse_average (активируется командой —conf reverse_average high) — Режим обратной сортировки по приоритету усреднений (усреднение от наименее просевших позиций к самым далёким)

  • Ключ trailing_stop (активируется командой —conf trailing_stop long) — Длинный трейлинг позиций (без триггера стоп-лосса, продажа позиции будет происходить частями trailing_part до тех пор, пока не кончатся монеты в позиции)

  • Ключ row_sell (активируется командой —conf row_sell reset) — Cбрасывать rowSell множитель до х1, вместо его уменьшения на количество усреднений в последней продаже

  • Ключ stop_loss (активируется командой —conf stop_loss ЧИСЛО) — Включить стоп-лосс для выхода из позиций, если рыночная цена таких активов упала на ЧИСЛО% по отношению к средней цене входа

  • Ключ listing_timer (активируется командой —conf listing_timer ЧИСЛО) — Через какое время в секундах (по умолчанию 3600) снимать с монеты после листинга статус new_listing, если счётчик продаж не достиг max_buy_listing с момента листинга пары

  • Ключ row_timer (активируется командой —conf row_timer ЧИСЛО) — Сбрасывать множитель row_sell у позиции в случае, если её длина больше указанного времени в секундах (по умолчанию 3600)

  • Ключ pump_value (активируется командой —conf pump_value ЧИСЛО) — Минимальный объём суточных торгов в эквиваленте к USD для открытия позиции по сигналу детектора пампов

  • Ключ pump_signal (активируется командой —conf pump_signal qm1-q2-q1…, то есть типы сигналов детектора пампов) — Детектор пампов будет работать только по тем типам сигналов, которые указаны в ключе. Всего 6 типов сигналов: q1, q2, q3, qm1, qm2, qm3

  • Ключ daily_percent (активируется командой —conf daily_percent [MIN:MAX/MIN:MAX/…]) — Несколько диапазонов для параметра min_daily_percent (MIN) и daily_percent (MAX) с разделителем : между минимальным и максимальным значением, перечисляемых через /. Порядок перечисления не важен, количество диапазонов не ограничено

  • Ключ super_list (активируется командой —conf super_list ADA-XRP-BNB-…-n, монеты разделяются дефисом, их количество неограниченно) — Суперлист пользователя, монеты из которого не будут подпадать под торговые настройки для покупки (кроме double_asset и min_balance). Иными словами, при продаже монеты из суперлиста бот не будет анализировать торговые параметры и ограничения, которые бы не дали боту снова открыть позицию по этой монете, а купит её сразу же после продажи (некая бесконечная торговля)

Сеточные — каждое число в ряду соответствует количественному индексу усреднения на позиции

  • Ключ step_aver (активируется командой —conf step_aver 2.25-5-3-…-n) — Ручная сетка процентов step_aver сетки, увеличивающейся при каждом усреднении на указанное число

Вместо одного значения step_aver, которое добавляется к общей сетке при каждом усреднении, вы можете задать свои значения. Дефисы служат для разделения чисел, обозначающих их индекс при усредненях (после покупки монете нужно упасть на buy_down% + 0% (сетка усреднений пока равна нулю, т.к. не было усреднений) для первого усреднения, для второго усреднения на buy_down + 0 + ЧИСЛО[2.25], для третьего на buy_down + 2.25 + ЧИСЛО[5], для четвёртого на buy_down + 7.25 + ЧИСЛО[3] и т.д.). Числа разделяются дефисом и могут быть с остатком, количество чисел неограниченно. Если номер усреднения превышает количество индексов в числовом ряду, то параметр step_aver берётся из настроек.

По аналогии работают и остальные сеточные ключи.

  • Ключ average_percent (активируется командой —conf average_percent 5-7-9.5-…-n) — Ручная сетка процентов average_percent, регулирующая объём усреднения в зависимости от разницы рыночной цены и получаемой новой средней цены входа в позицию после усреднения

  • Ключ quantity_aver (активируется командой —conf quantity_aver 1-1.5-2-…-n) — Ручная сетка множителя объёма усреднений quantity_aver для каждого усреднения

  • Ключ sell_up (активируется командой —conf sell_up 1.15-0.95-0.77-…-n) — Ручная сетка процентов желаемой прибыли от продажи актива, в зависимости от количества усреднений на позиции

  • Ключ pump_up (активируется командой —conf pump_up 0.35-0.55-0.4-…-n) — Ручная сетка процентов желаемой прибыли от продажи активов, открытых Детектором пампов

  • Ключ buy_down (активируется командой —conf buy_down 2.15-3.55-4.8-…-n) — Ручная сетка процентов падения цены актива от цены последней покупки/усреднения, необходимого для осуществления нового усреднения

  • Ключ trailing_percent (активируется командой —conf trailing_percent 0.15-0.55-0.8-…-n) — Ручная сетка для желаемого процента трейлинга, в зависимости от количества усреднений на позиции

Добро пожаловать в третью и последнюю часть этого поста. Первая часть здесь, а вторая часть здесь.

Набор данных бизнес -объект

Сначала давайте представим новый бизнес -объект «набора данных» для группировки цен.

./models/dataset.py

from datetime import datetime

from api import utils
from models.model import AbstractModel
from models.exchange import Exchange
from models.currency import Currency


class Dataset(AbstractModel):
    resource_name = 'datasets'

    pair: str = ''
    exchange: str = ''
    period_start: str = ''
    period_end: str = ''
    currency: str = ''
    asset: str = ''

    relations = {'exchange': Exchange, 'currency': Currency, 'asset': Currency}

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.pair = self.get_pair()

    def get_pair(self):
        return utils.format_pair(self.currency, self.asset)

Затем нам нужно создать услугу для разбора и загрузки исторических данных из бинанса или любого другого обмена с API и такой исторической конечной точкой тикера.

./services/importer.py

import sys
from datetime import datetime
from models.dataset import Dataset


class Importer:
    def __init__(self, exchange, period_start: datetime, period_end=None, interval=60, *args, **kwargs):
        self.exchange = exchange
        self.interval = interval
        self.period_start = period_start
        self.period_end = period_end
        self.start = datetime.now()
        self.dataset = Dataset().create(
            data={'exchange': '/api/exchanges/'+self.exchange.name.lower(), 'periodStart': self.period_start, 'periodEnd': self.period_end,
                  'candleSize': 60,
                  'currency': '/api/currencies/'+self.exchange.currency.lower(), 'asset': '/api/currencies/'+self.exchange.asset.lower()})

    def process(self):
        for price in self.exchange.historical_symbol_ticker_candle(self.period_start, self.period_end, self.interval):
            print(price.create({'dataset': '/api/datasets/'+self.dataset.uuid}))

        execution_time = datetime.now() - self.start
        print('Execution time: ' + str(execution_time.total_seconds()) + ' seconds')
        sys.exit()

Эта ответственность за обслуживание действительно проста и ясна, его имя говорит, что мы импортируем и храним исторические данные о тикерах на биржах.

Здесь вы можете напрямую хранить свои объекты в реляционной базе данных, такой как PostgreSQL, например, вы также можете создавать и использовать внутренний API REST в качестве прокси для вашей базы данных для высокопроизводительных целей.

Западный тестирование является наиболее важным инструментом для написания вашего будущего пуленепробиваемого бота и проверить его на всех рыночных ситуациях на основе исторических данных тикера.

Для этой цели мы создадим сервис бэктеста, его обязанности будут заключаться в загрузке набора данных из ваших текущих локальных данных, и, если не найдено, он загружает его непосредственно с обмена (Binance по умолчанию). Затем запустите данную стратегию против каждой свечи данных о ценах из исторического набора данных.

/services/backtest.py

import sys
from datetime import datetime

from exchanges.exchange import Exchange
from models.dataset import Dataset
from models.price import Price


class Backtest:
    def __init__(self, exchange: Exchange, period_start: datetime, period_end=None, interval=60):
        self.launchedAt = datetime.now()
        # Try to find dataset
        dataset = Dataset().query('get', {"exchange": '/api/exchanges/' + exchange.name.lower(),
                                          "currency": '/api/currencies/' + exchange.currency.lower(),
                                          "asset": '/api/currencies/' + exchange.asset.lower(),
                                          "period_start": period_start, "period_end": period_end, "candleSize": interval})

        if dataset and len(dataset) > 0:
            print(dataset[0])
            price = Price()
            for price in price.query('get', {"dataset": dataset[0]['uuid']}):
                newPrice = Price()
                newPrice.populate(price)
                exchange.strategy.set_price(newPrice)
                exchange.strategy.run()
        else:
            print("Dataset not found, external API call to " + exchange.name)
            for price in exchange.historical_symbol_ticker_candle(period_start, period_end, interval):
                exchange.strategy.set_price(price)
                exchange.strategy.run()

        execution_time = datetime.now() - self.launchedAt
        print('Execution time: ' + str(execution_time.total_seconds()) + ' seconds')
        sys.exit()

Мы будем использовать библиотеку Dotenv и соглашения для управления переменными среды. Вот значения проекта по умолчанию:

./.env.local

AVAILABLE_EXCHANGES="coinbase,binance"
EXCHANGE="binance"

BINANCE_API_KEY="Your Binance API KEY"
BINANCE_API_SECRET="Your Binance API SECRET"

COINBASE_API_KEY="Your Coinbase API KEY""
COINBASE_API_SECRET="Your Coinbase API SECRET""

# Available modes
# "trade" to trade on candlesticks
# "live" to live trade throught WebSocket
# "backtest" to test a strategy for a given symbol pair and a period
# "import" to import dataset from exchanges for a given symbol pair and a period
MODE="trade"
STRATEGY="logger"
# Allow trading "test" mode or "real" trading
TRADING_MODE="test"
# Default candle size in seconds
CANDLE_INTERVAL=60
CURRENCY="BTC"
ASSET="EUR"
# Default period for backtesting: string in UTC format
PERIOD_START="2021-02-28T08:49"
PERIOD_END="2021-03-09T08:49"

DATABASE_URL="postgresql://postgres:password@127.0.0.1:15432/cryptobot"

Затем сложите все эти части на основной потоке, в основном команда CLI, используя ARG, а также переменные среды.

При этом мы можем переопределить любые настройки среды по умолчанию и настраивать все входные параметры непосредственно с помощью клиента на основе командной строки.

Например, действительно полезно при использовании инструмента для контейнеризации, такого как Docker, просто запустите этот основной поток, и он будет работать с конкретными переменными среды контейнера.

Мы динамически загружаем и импортируем все компоненты, которые мы создали в соответствии с настройками.

./main.py

#!/usr/bin/python3

import importlib
import signal
import sys
import threading
from decouple import config

from services.backtest import Backtest
from services.importer import Importer

exchange_name = config('EXCHANGE')
available_exchanges = config('AVAILABLE_EXCHANGES').split(',')
mode: str = config('MODE')
strategy: str = config('STRATEGY')
trading_mode: str = config('TRADING_MODE')
interval: int = int(config('CANDLE_INTERVAL'))
currency: str = config('CURRENCY')
asset: str = config('ASSET')

if trading_mode == 'real':
    print("*** Caution: Real trading mode activated ***")
else:
    print("Test mode")

# Parse symbol pair from first command argument
if len(sys.argv) > 1:
    currencies = sys.argv[1].split('_')
    if len(currencies) > 1:
        currency = currencies[0]
        asset = currencies[1]

# Load exchange
print("Connecting to {} exchange...".format(exchange_name[0].upper() + exchange_name[1:]))
exchangeModule = importlib.import_module('exchanges.' + exchange_name, package=None)
exchangeClass = getattr(exchangeModule, exchange_name[0].upper() + exchange_name[1:])
exchange = exchangeClass(config(exchange_name.upper() + '_API_KEY'), config(exchange_name.upper() + '_API_SECRET'))

# Load currencies
exchange.set_currency(currency)
exchange.set_asset(asset)

# Load strategy
strategyModule = importlib.import_module('strategies.' + strategy, package=None)
strategyClass = getattr(strategyModule, strategy[0].upper() + strategy[1:])
exchange.set_strategy(strategyClass(exchange, interval))

# mode
print("{} mode on {} symbol".format(mode, exchange.get_symbol()))
if mode == 'trade':
    exchange.strategy.start()

elif mode == 'live':
    exchange.start_symbol_ticker_socket(exchange.get_symbol())

elif mode == 'backtest':
    period_start = config('PERIOD_START')
    period_end = config('PERIOD_END')

    print(
        "Backtest period from {} to {} with {} seconds candlesticks.".format(
            period_start,
            period_end,
            interval
        )
    )
    Backtest(exchange, period_start, period_end, interval)

elif mode == 'import':
    period_start = config('PERIOD_START')
    period_end = config('PERIOD_END')

    print(
        "Import mode on {} symbol for period from {} to {} with {} seconds candlesticks.".format(
            exchange.get_symbol(),
            period_start,
            period_end,
            interval
        )
    )
    importer = Importer(exchange, period_start, period_end, interval)
    importer.process()

else:
    print('Not supported mode.')


def signal_handler(signal, frame):
    if (exchange.socket):
        print('Closing WebSocket connection...')
        exchange.close_socket()
        sys.exit(0)
    else:
        print('stopping strategy...')
        exchange.strategy.stop()
        sys.exit(0)


# Listen for keyboard interrupt event
signal.signal(signal.SIGINT, signal_handler)
forever = threading.Event()
forever.wait()
exchange.strategy.stop()
sys.exit(0)

# Real time trading mode via WebSocket
MODE=live ./main.py BTC_EUR

# Trading mode with default 1 minute candle
MODE=trade ./main.py BTC_EUR

# Import data from Exchange
MODE=import ./main.py BTC_EUR

# Backtest with an imported dataset or Binance Exchange API
MODE=backtest ./main.py BTC_EUR

Вы можете легко переопределить любые настройки при вызове, например,:

PERIOD_START="2021-04-16 00:00" PERIOD_END="2021-04-16 00:00" STRATEGY=myCustomStrategy MODE=backtest ./main.py BTC_EUR

Чтобы выйти из режима тестирования и торговлю на реальную, просто переключите “trading_mode” из “test” Используйте с осторожностью в ваших собственных рисках.

TRADING_MODE=real ./main.py BTC_EUR

Контейнерный проект

Мы можем контейнерить эту программу с помощью Docker. Вот мертвый простой самостоятельно объясняющий файл Docker Build.

FROM python:3.9

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD [ "python", "./main.py" ]

Используя старый четырехъядерный процессор AMD II 955 с 16GO с DDR3 RAM, а другой процесс работает.

импорт

Импорт и упорные цены во внутренний API

1 -дневный билет разделен на 1 минуту свечи:

Execution time: 82.716666 seconds

1 -недельный тикер выплетен на 1 минуту свечи:

Execution time: 9,423079183 minutes

1 месяц тикер на 1 минуту свечи:

Execution time: 27,48139456 minutes

6 -месячный тикер плюнул на 1 минуту свечи:

Execution time: 3.032364739 hours

Бэк -тест

Из импортного набора данных

1 -дневный билет разделен на 1 минуту свечи:

Execution time: 3.746787 seconds

1 -недельный тикер выплетен на 1 минуту свечи:

Execution time: 46.900068 seconds

1 месяц тикер на 1 минуту свечи:

Execution time: 1.8953 seconds

6 -месячный тикер плюнул на 1 минуту свечи:

Execution time: 12,15175435 minutes

Мы построили бот с крипто -торговой торговлей в реальном времени. Он способен поддержать ваши стратегии по сравнению с большим набором данных о рынке, действительно, используя небольшое количество процессора и оперативной памяти. Импортируйте наборы данных с обменов, выполняйте живую торговлю с настраиваемыми размерами свечей или даже в реальном времени, используя WebSocket.

  • Код A Tests Suite, который охватывает поведение всех программ, чтобы обеспечить отсутствие будущей регрессии.

  • Создайте и используйте внутренний API REST, чтобы сохранить все данные Crypto Exchange Markets в режиме реального времени.

  • Создайте клиента конечного пользователя, например, мобильное приложение или веб -приложение. Использование WebSocket или сервер, отправленных событиями, для отображения метрик в реальном времени.

Хотите начать свою собственную стратегию с ваших пользовательских индикаторов или просто внести свой вклад и улучшить этот проект, вы можете найти полный проект исходный код на GitHub Анкет

Использовать с стабильная ветвь и внести свой вклад с использованием Основная ветвь развивается Анкет

Как заканчивая этот последний пост, я выпустил стабильную версию 0,4

Все взносы приветствуются!

Спасибо за то, что прочитали этот пост с тремя частями о том, как построить крипто -бот с Python 3 и Binance API.

Оригинал: “https://dev.to/nicolasbonnici/how-to-build-a-crypto-bot-with-python-3-and-the-binance-api-part-3-1c53”

Введение

В этой статье представлен простой бот для торговли на бирже Binance.

Бот создает ордер на покупку, основываясь на средней цене из указанного количества предложений на покупку, после чего отслеживает его. Если ордер не выполнен в течении определенного количества времени, ордер отменяется. Если ордер исполнен, выставляется ордер на продажу с указанным профитом. После исполнения ордера на продажу торговля идет по новому кругу.

Поддерживается торговля по нескольким парам, по умолчанию бот работает с комиссией BNB, но поддерживается так же торговля с обычным видом комиссии.

Об особенностях торговли

Цены и объемы

Binance, в отличии от многих бирж, жестко регламентирует размеры лотов и порядки цен. Нельзя купить произвольное количество валюты по произвольному курсу — для каждой пары заведены ограничения, которых необходимо придерживаться при создании ордера.

Существует шаг цены – например, для пары NEOUSDT цена должна быть кратной 0.00100000. Нельзя выставить ордер по цене, 0.1234 – можно либо 0.123, либо 0.125.

Существует шаг продаваемых/покупаемых монет – например, для пары NEOUSDT шаг объема 0.001 – поэтому не получится продать или купить 123.45678 – можно либо 123.456, либо 123.457.

Ну, и как везде, нельзя создавать ордера меньше указанного объема.

Эти ограничения находятся можно получать через api-метод exchangeInfo (подробности о работе API Binance тут), нужная информация находится в разделе filters по каждой паре. Для цены это tickSize, для объема stepSize в соответствующих структурах данных.

Бот учитывает эти ограничения, но обратите внимание, как меняется цена торгов:

Допустим, вы собираетесь торговать на 11 USDT.

Бот получает цены из стакана – например, 5 цен — [118.753, 118.750, 118.730, 118.712, 118.704]. Берет среднюю —  118,7298. Т.к. минимальный шаг цены 0.001, то берется цена 118,729 (в нижнюю сторону).

После этого бот вычисляет количество валюты, которое можно купить по этой цене – делит 11 USDT на 118,729, получает 0,092648. Т.к. минимальный шаг по монетам 0.001, то выбирается количество 0,092.

В итоге бот покупает 0.092 NEO по курсу 118,729 – и итоговая сумма торгов составит 10,923068. Это меньше, чем указано в настройках, но бот вынужден подстраиваться под требования биржи.

При продаже бот будет продавать так, чтобы получить 10,923068 + нужный процент профита.

Комиссии

У бинанса своя система взимания комиссии. Точнее, их две. По умолчанию, используется такой вид комиссии – неважно, по какой паре вы торгуете, комиссия списывается с вашего счета в валюте BNB. BNB – это собственная валюта Binance, подробнее я расскажу о ней отдельно, но суть такая:

Вы, например, торгуете NEO-USDT. Совершаете покупку по курсу X, рассчитывая купить Y монет NEO и потратить Z USDT. Вы выставляете ордер, он исполняется, и вы получаете Y монет NEO, потратив Z USDT. Вы, как бы, ничего не потеряли на этих торгах – но с вас списалось S монет BNB.

В общем-то, это хорошо – потому что Binance даёт скидку. Оплачивая комиссию через BNB, вы платите на 50% меньше. Теоретически, если комиссия 0.1%, то оплачивая комиссию таким образом, вы платите 0.05% с каждой сделки. Бот рассчитан в первую очередь на такую комиссию, и рекомендуется использовать именно её. Если вдруг вы хотите торговать с обычным видом комиссии, то зайдите в свой профиль и переключите флажок:

После этого в боте нужно будет поменять переменную

USE_BNB_FEES = True

На

USE_BNB_FEES = False  

Правда, я не вижу, зачем бы вам это делать. В любом случае, если вы раньше не торговали на Binance, то первым делом нужно прикупить немного BNB. Прикупить, и пусть лежат. Если вы, тем более, будете торговать с базовой парой BNB, вам это будет на руку.

Как лучше пользоваться ботом

Бот покупает чуть ниже текущего курса, и продает с профитом, чуть задирая цену. Т.к. цена имеет тенденцию то расти, то падать, вполне вероятна такая ситуация, что бот купит, выставит на продажу, и будет долго ждать роста. Что бы снизить количество таких ситуаций, лучше отслеживать обстановку и запускать бота по тем парам, которые обещают рост.

Такой вывод вы можете сделать, либо используя индикаторы, либо новости – например, если валюту добавили на биржу, скорее всего она первое время будет расти. Если IBM решил вложиться в Etherium, скорее всего эфир будет расти. Если MACD и RSI показывают сигналы к покупке, скорее всего будет расти, и т.п.

Выбрав пару для торгов, вы останавливаете бота (если запущен), и добавляете пару в конфиг, вот так:

"""
    Пропишите пары, на которые будет идти торговля.
    base - это базовая пара (BTC, ETH,  BNB, USDT) - то, что на бинансе пишется в табличке сверху
    quote - это квотируемая валюта. Например, для торгов по паре NEO/USDT базовая валюта USDT, NEO - квотируемая
"""
pairs = [
     {
        'base': 'USDT',
        'quote': 'BTC',
        'offers_amount': 5, # Сколько предложений из стакана берем для расчета средней цены
                            # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 11,  # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.005, # Какой навар нужен с каждой сделки? (0.001 = 0.1%)

    },{
        'base': 'USDT',
        'quote': 'NEO',
        'offers_amount': 5, # Сколько предложений из стакана берем для расчета средней цены
                            # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 11,  # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.005, # Какой навар нужен с каждой сделки? (0.001 = 0.1%)

    }
]

Пар можно добавлять любое количество, угрозу бана это не спровоцирует, просто отдельные пары будут реже проверяться, но ответы сервера тут шустрые, так что это особо не скажется на производительности.

Если же вы думаете, что ситуация становится опасной, и пора бы прекратить торги, то дождитесь, когда бот выставит ордер на продажу, остановите бота, и удалите пару из конфигурации. Бот продолжит отслеживать ордер на продажу, но новых покупок создавать не будет.

Если вы отменили ордера или что-то еще сделали на бирже, но бот «запомнил» и теперь проверяет несуществующие ордера, у вас есть два варианта:

  1. Удалите файл binance.db из папки с ботом. Это вынудит бота начать всё с чистого листа, и он начнет работать с нуля по всем парам из конфигурации. Открытые ордера на бирже пропадут из его надзора, и вам нужно будет разрешить их судьбу самостоятельно.
  2. Если вы не хотите терять открытые ордера по другим парам, то откройте файл binance.db с помощью программы SQLiteStudio, Вы запустите программу, добавите базу данных через обзор, там откроете таблицу orders и удалите оттуда только нужный ордер. Кстати говоря, т.к. бот записывает все свои покупки и продажи, с помощью этой программы вы можете выгружать историю торгов бота в Excel и анализировать.

Реклама



Установка и запуск

  1. Зарегистрироваться на Binance (если еще не сделали, вот инструкция)
  2. Пополнить баланс
  3. Убедиться, что на балансе есть BNB (если нет, докупить чуток)
  4. Получить API-ключи (инструкция). Потребуется включить двухфакторную авторизацию, я советую использовать SMS, но можно и Google Authenticator.
  5. Установить Python версии 3.6 и выше. Прямую ссылка на скачивание я не указываю, т.к. к моменту прочтения статьи все может измениться, вам нужно зайти на официальный сайт по ссылке https://www.python.org/downloads/, скачать и установить Python 3.6 и выше (кнопка слева). При установке поставьте все галочки. В идеале, выберите расширенный режим установки (advanced) и поставьте все галки там – нужны будут права администратора.
  6. Скачать архив с ботом.
  7. Распаковать в любую директорию на компьютере
  8. Запустить файл setup.bat – установятся нужные модули (для надежности, запустите и так, и от имени администратора)
  9. Открыть файл binance_bot.py в текстовом редакторе и прописать API-ключи и настройки (об этом ниже)
  10. Запустить файл run.bat – запустится бот и начнет зарабатывать деньги.

Остановить бота можно закрыв окно крестиком.


Реклама



Настройка

Настроек не так много, в API_KEY и API_SECRET нужно прописать ключи, которые вы получили на бирже.

В пары нужно прописать соответственно пары, на которые планируете торговать, максимальную сумму, которую планируете тратить, и желаемый процент прибыли. С этим есть некоторый момент, т.к. вы платите комисиию BNB. Я советую ставить 0.003 (0.3%) и выше, но если у вас есть возможность дешево получать BNB, то можно и меньше.

BUY_LIFE_TIME_SEC – через сколько отменять ордер на покупку (если он не исполнен), в секундах.

STOCK_FEE – комиссия биржи, если вдруг решите торговать без BNB.

USE_BNB_FEES = True – если торгуете с BNB, False – в противном случае.


Реклама



ВСЁ!

Я гонял этого бота несколько дней, меня не забанили, я немного увеличил количество USDT – так что я со спокойной душой передаю вам бота и его исходный код. Вы можете модифицировать его под свои нужды, или обратиться за доработкой.

Я желаю вам хороших заработков, если в процессе эксплуатации будут выявлены какие-то проблемы, или возникнут вопросы, смело пишите в комментарии или лично мне, контакты есть в профиле.

Понравилась статья? Поделить с друзьями:
  • Как написать бот кил
  • Как написать бот для торговли на бирже
  • Как написать бот для регистрации
  • Как написать боссу что заболел
  • Как написать босс на английском