Cara menulis penghasilan pasif: Menulis bot perdagangan berkualitas di JS (bagian 1)

Mari mulai menulis bot perdagangan yang akan berjalan di bursa kripto Binance. Bot harus dapat:





  1. berdagang sendiri, menghasilkan semacam penghasilan





  2. harus nyaman untuk membuat dan meluncurkan berbagai strategi perdagangan





  3. 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.








All Articles