[JavaScript, Node.JS, Криптовалюты] Как написать пассивный доход: Пишем качественного трейд бота на JS (часть 1)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Начнем писать трейдинг бота, который будет работать на криптобирже Binance. Бот должен уметь:
- торговать самостоятельно, принося какой-то доход
- должен быть удобен для создания и обкатывания различных стратегий торговли
- тестировать стратегию на исторических данных
Пожалуй, начнем с архитектурыУ нас есть биржа 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Продолжение следует. В следующей статье будем писать ядро, которое соединит все эти части и заставит бота торговать.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, JavaScript, HTML, Видеоконференцсвязь] Как мы интрегрировали Agora SDK в проект
- [Java] Кросс-браузерное тестирование в Selenium (перевод)
- [JavaScript, Программирование, Angular] Кастомные операторы RxJS (перевод)
- [PHP, JavaScript] Браузерные Push-уведомления на Javascript и PHP
- [JavaScript, VueJS, TypeScript] Из Vue 2 на Vue 3 – Migration Helper
- [JavaScript] @teqfw/di
- [Информационная безопасность, Криптография, JavaScript, Node.JS, Криптовалюты] Поиск коллизий в SHA-256 на платформе Node.js при помощи Bitcoin Hasher
- [Хакатоны] Подведены итоги Tech Monsters Night
- [Программирование, Java] Optional.stream() (перевод)
- [Криптография, Open source, Python, Программирование] Как использовать Python для проверки протокола Signal (перевод)
Теги для поиска: #_javascript, #_node.js, #_kriptovaljuty (Криптовалюты), #_binance, #_cryptocurrency, #_java, #_node, #_javascript, #_node.js, #_kriptovaljuty (
Криптовалюты
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 10:05
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Начнем писать трейдинг бота, который будет работать на криптобирже Binance. Бот должен уметь:
Вызвать пару методов “купи дешевле” и “продай дороже”. Но задача для нас написать такого бота, при котором условный программист-трейдер сможет создавать и тестировать на прибыльность новые стратегии. Поэтому, необходимо отделить логику торговли от всего прочего. А также модулю логики должно быть все равно к какой бирже его подключили: к реальному 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
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) } } 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) } } yarn add sequelize-cli -D
yarn add sequelize npx sequelize-cli init 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 =========== Источник: habr.com =========== Похожие новости:
Криптовалюты ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 10:05
Часовой пояс: UTC + 5