Mari mulai menulis bot perdagangan yang akan berjalan di bursa kripto Binance. Bot harus dapat:
berdagang sendiri, menghasilkan semacam penghasilan
harus nyaman untuk membuat dan meluncurkan berbagai strategi perdagangan
menguji strategi pada data historis
Mari kita mulai dengan arsitektur
Kami memiliki pertukaran Binance yang memiliki api yang luar biasa. Oleh karena itu, arsitekturnya dapat terlihat seperti ini:
Panggil beberapa metode "beli lebih murah" dan "jual lebih mahal". Tetapi tugas kami adalah menulis bot di mana seorang programmer-trader bersyarat dapat membuat dan menguji strategi baru untuk profitabilitas. Oleh karena itu, perlu untuk memisahkan logika perdagangan dari yang lainnya. Dan juga modul logika seharusnya tidak peduli dengan pertukaran mana yang terhubung: ke API nyata atau ke API semu (untuk pengujian). Mempertimbangkan semua ini, kami mendapatkan sesuatu seperti arsitektur ini:
Basis dipilih oleh PostgreSQL. Tidak ada niat rahasia di sini. Anda dapat menggunakan apa saja.
Karena kenyataan bahwa setiap modul patut Anda perhatikan, semua ini tidak akan muat dalam satu artikel. Oleh karena itu, saya memulai seri mini: "Menulis bot perdagangan berkualitas tinggi di JS". Karena itu, berlangganan, buat diri Anda nyaman - mari kita mulai
Layanan untuk log
, 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
Bersambung.
Pada artikel berikutnya, kami akan menulis inti yang akan menghubungkan semua bagian ini dan melakukan perdagangan bot.