import { Bitmex } from '@dripjs/exchanges' ; import { Bar , BarRequest , Depth , OrderSide , Pair , Ticker , Transaction } from '@dripjs/types' ; import { BigNumber } from 'bignumber.js' ; import * as moment from 'moment' ; import { Observable , zip } from 'rxjs' ; import { map } from 'rxjs/operators' ; import { Intel } from '../intel' ; export class BitmexSpy extends Intel { readonly name = 'bitmex' ; private readonly rest : Bitmex . Rest ; private readonly ws : Bitmex . Websocket ; private symbols : Pair [ ] = [ ] ; constructor ( config ) { super ( ) ; this . rest = new Bitmex . Rest ( config ) ; this . ws = new Bitmex . Websocket ( config ) ; } destory ( ) { this . ws . destroy ( ) ; } async getSymbols ( ) { if ( this . symbols . length === 0 ) { const res = await this . rest . fetchInstrument ( ) ; if ( ! res . error ) { this . symbols = res . instruments . map ( ( o ) => { return { exchange : 'bitmex' , name : o . symbol , baseAsset : o . rootSymbol , quoteAsset : o . quoteCurrency , amountPrecision : o . lotSize , pricePrecision : new BigNumber ( o . tickSize ) . dp ( ) , minOrderAmount : 0 , maxOrderAmount : 0 , minOrderPrice : 0 , maxOrderPrice : 0 , isEnabled : true , } ; } ) ; } else { throw new Error ( res . error . message ) ; } } return this . symbols ; } async getSymbol ( symbol ) { if ( this . symbols . length === 0 ) { await this . getSymbols ( ) ; } return this . symbols . find ( ( o ) => o . name === symbol ) ; } getTicker$ ( symbol ) { const trade$ = this . ws . trade$ ( symbol ) ; const quote$ = this . ws . quote$ ( symbol ) ; return zip ( trade$ , quote$ ) . pipe ( map ( ( res ) => { return { ask : res [ 1 ] . askPrice , bid : res [ 1 ] . bidPrice , high : 0 , low : 0 , last : res [ 0 ] . price , volume : res [ 0 ] . amount , time : res [ 0 ] . timestamp , } ; } ) ) ; } stopTicker ( symbol ? ) { this . ws . stopTrade ( symbol ) ; this . ws . stopQuote ( symbol ) ; } async getBars ( request ) { const resolutions = Object . values ( Bitmex . Resolution ) ; if ( ! resolutions . includes ( request . resolution ) ) { throw new Error ( `${ request . resolution } is not supported,${ this . name } only allows resolution: ${ resolutions }` ) ; } const res = await this . rest . fetchBar ( { symbol : request . symbol , binSize : request . resolution as Bitmex . Resolution , startTime : moment ( request . start ) . toISOString ( ) , endTime : moment ( request . end ) . toISOString ( ) , } ) ; let bars = [ ] ; if ( res . bars . length > 0 ) { bars = res . bars . map ( ( o ) => { return { time : moment ( o . timestamp ) . unix ( ) * 1000 , open : o . open , high : o . high , low : o . low , close : o . close , volume : o . volume , } ; } ) ; } return bars ; } getDepth$ ( symbol ) { return this . ws . orderbook$ ( symbol ) . pipe ( map ( ( res ) => { return < Depth > { asks : res . asks . map ( ( o ) => o . map ( Number ) ) , bids : res . bids . map ( ( o ) => o . map ( Number ) ) , } ; } ) ) ; } stopDepth ( symbol ? ) { this . ws . stopOrderbook ( symbol ) ; } getTransaction$ ( symbol ) { return this . ws . trade$ ( symbol ) . pipe ( map ( ( res ) => { return { time : res . timestamp , side : res . side === Bitmex . OrderSide . Buy ? OrderSide . Buy : OrderSide . Sell , price : res . price , amount : res . amount , } ; } ) ) ; } stopTransaction ( symbol ? ) { this . ws . stopTrade ( symbol ) ; } }