tardis-dev 13.19.1 → 13.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/consts.ts CHANGED
@@ -24,6 +24,7 @@ export const EXCHANGES = [
24
24
  'poloniex',
25
25
  'bybit',
26
26
  'bybit-spot',
27
+ 'bybit-options',
27
28
  'phemex',
28
29
  'delta',
29
30
  'ftx-us',
@@ -336,7 +337,29 @@ const BINANCE_OPTIONS_CHANNELS = ['TRADE', 'TICKER', 'DEPTH100', 'INDEX'] as con
336
337
 
337
338
  const PHEMEX_CHANNELS = ['book', 'orderbook_p', 'trades', 'trades_p', 'market24h', 'spot_market24h', 'perp_market24h_pack_p'] as const
338
339
 
339
- const BYBIT_CHANNELS = ['trade', 'instrument_info', 'orderBookL2_25', 'insurance', 'orderBook_200', 'liquidation'] as const
340
+ const BYBIT_CHANNELS = [
341
+ 'trade',
342
+ 'instrument_info',
343
+ 'orderBookL2_25',
344
+ 'insurance',
345
+ 'orderBook_200',
346
+ 'liquidation',
347
+ 'trade',
348
+ 'instrument_info',
349
+ 'orderBookL2_25',
350
+ 'insurance',
351
+ 'orderBook_200',
352
+ 'liquidation',
353
+ 'long_short_ratio',
354
+ 'orderbook.1',
355
+ 'orderbook.50',
356
+ 'orderbook.500',
357
+ 'publicTrade',
358
+ 'tickers',
359
+ 'liquidation'
360
+ ] as const
361
+
362
+ const BYBIT_OPTIONS_CHANNELS = ['orderbook.25', 'orderbook.100', 'publicTrade', 'tickers']
340
363
 
341
364
  const HITBTC_CHANNELS = ['updateTrades', 'snapshotTrades', 'snapshotOrderbook', 'updateOrderbook'] as const
342
365
 
@@ -392,7 +415,7 @@ const MANGO_CHANNELS = [
392
415
 
393
416
  const HUOBI_DM_OPTIONS_CHANNELS = ['trade', 'detail', 'depth', 'bbo', 'open_interest', 'option_market_index', 'option_index'] as const
394
417
 
395
- const BYBIT_SPOT_CHANNELS = ['trade', 'bookTicker', 'depth']
418
+ const BYBIT_SPOT_CHANNELS = ['trade', 'bookTicker', 'depth', 'orderbook.1', 'orderbook.50', 'publicTrade', 'tickers', 'lt']
396
419
 
397
420
  const CRYPTO_COM_CHANNELS = ['trade', 'book', 'ticker', 'settlement', 'index', 'mark', 'funding']
398
421
 
@@ -445,6 +468,7 @@ export const EXCHANGE_CHANNELS_INFO = {
445
468
  'huobi-dm-linear-swap': HUOBI_DM_LINEAR_SWAP_CHANNELS,
446
469
  bybit: BYBIT_CHANNELS,
447
470
  'bybit-spot': BYBIT_SPOT_CHANNELS,
471
+ 'bybit-options': BYBIT_OPTIONS_CHANNELS,
448
472
  okcoin: OKCOIN_CHANNELS,
449
473
  hitbtc: HITBTC_CHANNELS,
450
474
  coinflex: COINFLEX_CHANNELS,
@@ -1,7 +1,317 @@
1
- import { upperCaseSymbols } from '../handy'
2
- import { BookChange, DerivativeTicker, Exchange, Liquidation, Trade } from '../types'
1
+ import { asNumberIfValid, upperCaseSymbols } from '../handy'
2
+ import { BookChange, BookTicker, DerivativeTicker, Exchange, Liquidation, OptionSummary, Trade } from '../types'
3
3
  import { Mapper, PendingTickerInfoHelper } from './mapper'
4
4
 
5
+ // v5 https://bybit-exchange.github.io/docs/v5/ws/connect
6
+
7
+ export class BybitV5TradesMapper implements Mapper<'bybit' | 'bybit-spot' | 'bybit-options', Trade> {
8
+ constructor(private readonly _exchange: Exchange) {}
9
+
10
+ canHandle(message: BybitV5Trade) {
11
+ if (message.topic === undefined) {
12
+ return false
13
+ }
14
+
15
+ return message.topic.startsWith('publicTrade.')
16
+ }
17
+
18
+ getFilters(symbols?: string[]) {
19
+ symbols = upperCaseSymbols(symbols)
20
+
21
+ return [
22
+ {
23
+ channel: 'publicTrade',
24
+ symbols
25
+ } as const
26
+ ]
27
+ }
28
+
29
+ *map(message: BybitV5Trade, localTimestamp: Date): IterableIterator<Trade> {
30
+ for (const trade of message.data) {
31
+ yield {
32
+ type: 'trade',
33
+ symbol: trade.s,
34
+ exchange: this._exchange,
35
+ id: trade.i,
36
+ price: Number(trade.p),
37
+ amount: Number(trade.v),
38
+ side: trade.S == 'Buy' ? 'buy' : trade.S === 'Sell' ? 'sell' : 'unknown',
39
+ timestamp: new Date(trade.T),
40
+ localTimestamp
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ export class BybitV5BookChangeMapper implements Mapper<'bybit' | 'bybit-spot' | 'bybit-options', BookChange> {
47
+ constructor(protected readonly _exchange: Exchange, private readonly _depth: number) {}
48
+
49
+ canHandle(message: BybitV5OrderBookMessage) {
50
+ if (message.topic === undefined) {
51
+ return false
52
+ }
53
+ return message.topic.startsWith(`orderbook.${this._depth}.`)
54
+ }
55
+
56
+ getFilters(symbols?: string[]) {
57
+ symbols = upperCaseSymbols(symbols)
58
+ return [
59
+ {
60
+ channel: `orderbook.${this._depth}`,
61
+ symbols
62
+ } as const
63
+ ]
64
+ }
65
+
66
+ *map(message: BybitV5OrderBookMessage, localTimestamp: Date) {
67
+ yield {
68
+ type: 'book_change',
69
+ symbol: message.data.s,
70
+ exchange: this._exchange,
71
+ isSnapshot: message.type === 'snapshot',
72
+ bids: message.data.b.map(this._mapBookLevel),
73
+ asks: message.data.a.map(this._mapBookLevel),
74
+ timestamp: new Date(message.ts),
75
+ localTimestamp
76
+ } as const
77
+ }
78
+
79
+ private _mapBookLevel(level: [string, string]) {
80
+ return { price: Number(level[0]), amount: Number(level[1]) }
81
+ }
82
+ }
83
+
84
+ export class BybitV5BookTickerMapper implements Mapper<'bybit' | 'bybit-spot', BookTicker> {
85
+ private _snapshots: {
86
+ [key: string]: {
87
+ askAmount: number | undefined
88
+ askPrice: number | undefined
89
+ bidPrice: number | undefined
90
+ bidAmount: number | undefined
91
+ }
92
+ } = {}
93
+
94
+ constructor(protected readonly _exchange: Exchange) {}
95
+
96
+ canHandle(message: BybitV5OrderBookMessage) {
97
+ if (message.topic === undefined) {
98
+ return false
99
+ }
100
+ return message.topic.startsWith(`orderbook.1.`)
101
+ }
102
+
103
+ getFilters(symbols?: string[]) {
104
+ symbols = upperCaseSymbols(symbols)
105
+ return [
106
+ {
107
+ channel: 'orderbook.1',
108
+ symbols
109
+ } as const
110
+ ]
111
+ }
112
+
113
+ *map(message: BybitV5OrderBookMessage, localTimestamp: Date) {
114
+ const bestAsk = message.data.a[0]
115
+ const bestBid = message.data.b[0]
116
+
117
+ if (message.type === 'snapshot') {
118
+ this._snapshots[message.data.s] = {
119
+ askAmount: bestAsk !== undefined ? Number(bestAsk[1]) : undefined,
120
+ askPrice: bestAsk !== undefined ? Number(bestAsk[0]) : undefined,
121
+ bidPrice: bestBid !== undefined ? Number(bestBid[0]) : undefined,
122
+ bidAmount: bestBid !== undefined ? Number(bestBid[1]) : undefined
123
+ }
124
+ }
125
+
126
+ const matchingSnapshot = this._snapshots[message.data.s]
127
+ if (!matchingSnapshot) {
128
+ return
129
+ }
130
+
131
+ const bookTicker: BookTicker = {
132
+ type: 'book_ticker',
133
+ symbol: message.data.s,
134
+ exchange: this._exchange,
135
+ askAmount: bestAsk !== undefined ? Number(bestAsk[1]) : matchingSnapshot.askAmount,
136
+ askPrice: bestAsk !== undefined ? Number(bestAsk[0]) : matchingSnapshot.askPrice,
137
+ bidPrice: bestBid !== undefined ? Number(bestBid[0]) : matchingSnapshot.bidPrice,
138
+ bidAmount: bestBid !== undefined ? Number(bestBid[1]) : matchingSnapshot.bidAmount,
139
+ timestamp: new Date(message.ts),
140
+ localTimestamp: localTimestamp
141
+ }
142
+
143
+ yield bookTicker
144
+ }
145
+ }
146
+
147
+ export class BybitV5DerivativeTickerMapper implements Mapper<'bybit', DerivativeTicker> {
148
+ private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
149
+
150
+ canHandle(message: BybitV5DerivTickerMessage) {
151
+ if (message.topic === undefined) {
152
+ return false
153
+ }
154
+
155
+ return message.topic.startsWith('tickers.')
156
+ }
157
+
158
+ getFilters(symbols?: string[]) {
159
+ symbols = upperCaseSymbols(symbols)
160
+
161
+ return [
162
+ {
163
+ channel: 'tickers',
164
+ symbols
165
+ } as const
166
+ ]
167
+ }
168
+
169
+ *map(message: BybitV5DerivTickerMessage, localTimestamp: Date): IterableIterator<DerivativeTicker> {
170
+ const instrumentInfo = message.data
171
+
172
+ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(instrumentInfo.symbol, 'bybit')
173
+
174
+ if (instrumentInfo.fundingRate !== undefined && instrumentInfo.fundingRate !== '') {
175
+ pendingTickerInfo.updateFundingRate(Number(instrumentInfo.fundingRate))
176
+ }
177
+
178
+ if (instrumentInfo.nextFundingTime !== undefined && instrumentInfo.nextFundingTime !== '') {
179
+ pendingTickerInfo.updateFundingTimestamp(new Date(Number(instrumentInfo.nextFundingTime)))
180
+ }
181
+
182
+ if (instrumentInfo.indexPrice !== undefined && instrumentInfo.indexPrice !== '') {
183
+ pendingTickerInfo.updateIndexPrice(Number(instrumentInfo.indexPrice))
184
+ }
185
+
186
+ if (instrumentInfo.markPrice !== undefined && instrumentInfo.markPrice !== '') {
187
+ pendingTickerInfo.updateMarkPrice(Number(instrumentInfo.markPrice))
188
+ }
189
+
190
+ if (instrumentInfo.openInterest !== undefined && instrumentInfo.openInterest !== '') {
191
+ pendingTickerInfo.updateOpenInterest(Number(instrumentInfo.openInterest))
192
+ }
193
+
194
+ if (instrumentInfo.lastPrice !== undefined && instrumentInfo.lastPrice !== '') {
195
+ pendingTickerInfo.updateLastPrice(Number(instrumentInfo.lastPrice))
196
+ }
197
+
198
+ pendingTickerInfo.updateTimestamp(new Date(message.ts))
199
+
200
+ if (pendingTickerInfo.hasChanged()) {
201
+ yield pendingTickerInfo.getSnapshot(localTimestamp)
202
+ }
203
+ }
204
+ }
205
+
206
+ export class BybitV5LiquidationsMapper implements Mapper<'bybit', Liquidation> {
207
+ constructor(private readonly _exchange: Exchange) {}
208
+ canHandle(message: BybitV5LiquidationMessage) {
209
+ if (message.topic === undefined) {
210
+ return false
211
+ }
212
+
213
+ return message.topic.startsWith('liquidation.')
214
+ }
215
+
216
+ getFilters(symbols?: string[]) {
217
+ symbols = upperCaseSymbols(symbols)
218
+
219
+ return [
220
+ {
221
+ channel: 'liquidation',
222
+ symbols
223
+ } as const
224
+ ]
225
+ }
226
+
227
+ *map(message: BybitV5LiquidationMessage, localTimestamp: Date): IterableIterator<Liquidation> {
228
+ // from bybit telegram: When "side":"Buy", a long position was liquidated. Will fix the docs.
229
+
230
+ const bybitLiquidation = message.data
231
+ const liquidation: Liquidation = {
232
+ type: 'liquidation',
233
+ symbol: bybitLiquidation.symbol,
234
+ exchange: this._exchange,
235
+ id: undefined,
236
+ price: Number(bybitLiquidation.price),
237
+ amount: Number(bybitLiquidation.size),
238
+ side: bybitLiquidation.side == 'Buy' ? 'sell' : 'buy',
239
+ timestamp: new Date(message.ts),
240
+ localTimestamp
241
+ }
242
+
243
+ yield liquidation
244
+ }
245
+ }
246
+
247
+ export class BybitV5OptionSummaryMapper implements Mapper<'bybit-options', OptionSummary> {
248
+ canHandle(message: BybitV5OptionTickerMessage) {
249
+ if (message.topic === undefined) {
250
+ return false
251
+ }
252
+
253
+ return message.topic.startsWith('tickers.')
254
+ }
255
+
256
+ getFilters(symbols?: string[]) {
257
+ symbols = upperCaseSymbols(symbols)
258
+
259
+ return [
260
+ {
261
+ channel: 'tickers',
262
+ symbols
263
+ } as const
264
+ ]
265
+ }
266
+
267
+ *map(message: BybitV5OptionTickerMessage, localTimestamp: Date) {
268
+ const symbolParts = message.data.symbol.split('-')
269
+
270
+ const isPut = symbolParts[3] === 'P'
271
+
272
+ const strikePrice = Number(symbolParts[2])
273
+
274
+ const expirationDate = new Date(symbolParts[1] + 'Z')
275
+ expirationDate.setUTCHours(8)
276
+
277
+ const optionSummary: OptionSummary = {
278
+ type: 'option_summary',
279
+ symbol: message.data.symbol,
280
+ exchange: 'bybit-options',
281
+ optionType: isPut ? 'put' : 'call',
282
+ strikePrice,
283
+ expirationDate,
284
+
285
+ bestBidPrice: asNumberIfValid(message.data.bidPrice),
286
+ bestBidAmount: asNumberIfValid(message.data.bidSize),
287
+ bestBidIV: asNumberIfValid(message.data.bidIv),
288
+
289
+ bestAskPrice: asNumberIfValid(message.data.askPrice),
290
+ bestAskAmount: asNumberIfValid(message.data.askSize),
291
+ bestAskIV: asNumberIfValid(message.data.askIv),
292
+
293
+ lastPrice: asNumberIfValid(message.data.lastPrice),
294
+ openInterest: asNumberIfValid(message.data.openInterest),
295
+
296
+ markPrice: asNumberIfValid(message.data.markPrice),
297
+ markIV: asNumberIfValid(message.data.markPriceIv),
298
+
299
+ delta: asNumberIfValid(message.data.delta),
300
+ gamma: asNumberIfValid(message.data.gamma),
301
+ vega: asNumberIfValid(message.data.vega),
302
+ theta: asNumberIfValid(message.data.theta),
303
+ rho: undefined,
304
+
305
+ underlyingPrice: asNumberIfValid(message.data.underlyingPrice),
306
+ underlyingIndex: '',
307
+ timestamp: new Date(message.ts),
308
+ localTimestamp: localTimestamp
309
+ }
310
+
311
+ yield optionSummary
312
+ }
313
+ }
314
+
5
315
  // https://github.com/bybit-exchange/bybit-official-api-docs/blob/master/en/websocket.md
6
316
 
7
317
  export class BybitTradesMapper implements Mapper<'bybit', Trade> {
@@ -96,9 +406,6 @@ export class BybitBookChangeMapper implements Mapper<'bybit', BookChange> {
96
406
  : message.data
97
407
  : [...message.data.delete, ...message.data.update, ...message.data.insert]
98
408
 
99
- // TODO: test instrument info
100
- // TODO: test liquidations?
101
-
102
409
  const timestampBybit = message.timestamp_e6 !== undefined ? Number(message.timestamp_e6) : Number(message.timestampE6)
103
410
  const timestamp = new Date(timestampBybit / 1000)
104
411
  timestamp.μs = timestampBybit % 1000
@@ -276,6 +583,122 @@ export class BybitLiquidationsMapper implements Mapper<'bybit', Liquidation> {
276
583
  }
277
584
  }
278
585
 
586
+ type BybitV5Trade =
587
+ | {
588
+ topic: 'publicTrade.LTCUSDT'
589
+ type: 'snapshot'
590
+ ts: 1680688979985
591
+ data: [
592
+ {
593
+ T: 1680688979983
594
+ s: 'LTCUSDT'
595
+ S: 'Buy'
596
+ v: '0.4'
597
+ p: '94.53'
598
+ L: 'ZeroMinusTick'
599
+ i: '4c7b6bdc-b4a3-5716-9c7b-bbe01dc7072f'
600
+ BT: false
601
+ }
602
+ ]
603
+ }
604
+ | {
605
+ topic: 'publicTrade.BTCUSDC'
606
+ ts: 1680688980000
607
+ type: 'snapshot'
608
+ data: [{ i: '2240000000041223438'; T: 1680688979998; p: '28528.98'; v: '0.00433'; S: 'Buy'; s: 'BTCUSDC'; BT: false }]
609
+ }
610
+ | {
611
+ id: 'publicTrade.BTC-3414637898-1680652922102'
612
+ topic: 'publicTrade.BTC'
613
+ ts: 1680652922102
614
+ data: [
615
+ { p: '985'; v: '0.01'; i: '0404c393-8419-5bac-95c3-5fea28404754'; T: 1680652922081; BT: false; s: 'BTC-28APR23-29500-C'; S: 'Sell' }
616
+ ]
617
+ type: 'snapshot'
618
+ }
619
+
620
+ type BybitV5OrderBookMessage = {
621
+ topic: 'orderbook.50.LTCUSD'
622
+ type: 'snapshot' | 'delta'
623
+ ts: 1680673822478
624
+ data: {
625
+ s: string
626
+ b: [string, string][]
627
+ a: [string, string][]
628
+ u: 11802648
629
+ seq: 941860281
630
+ }
631
+ }
632
+
633
+ type BybitV5DerivTickerMessage = {
634
+ topic: 'tickers.BTCUSD'
635
+ type: 'snapshot' | 'delta'
636
+ data: {
637
+ symbol: string
638
+ lastPrice?: string
639
+
640
+ markPrice?: string
641
+ indexPrice?: string
642
+ openInterest?: string
643
+ openInterestValue?: string
644
+ nextFundingTime?: string
645
+ fundingRate?: string
646
+ bid1Price?: string
647
+ bid1Size?: string
648
+ ask1Price?: string
649
+ ask1Size?: string
650
+ }
651
+ cs: 20856433578
652
+ ts: 1680673822577
653
+ }
654
+
655
+ type BybitV5LiquidationMessage = {
656
+ data: {
657
+ price: '0.03803'
658
+ side: 'Buy'
659
+ size: '1637'
660
+ symbol: 'GALAUSDT'
661
+ updatedTime: 1673251091822
662
+ }
663
+ topic: 'liquidation.GALAUSDT'
664
+ ts: 1673251091822
665
+ type: 'snapshot'
666
+ }
667
+
668
+ type BybitV5OptionTickerMessage = {
669
+ id: 'tickers.ETH-30JUN23-200-P-3164908233-1680652859919'
670
+ topic: 'tickers.ETH-30JUN23-200-P'
671
+ ts: 1680652859919
672
+ data: {
673
+ symbol: 'ETH-30JUN23-200-P'
674
+ bidPrice: '0.1'
675
+ bidSize: '5'
676
+ bidIv: '1.4744'
677
+ askPrice: '0'
678
+ askSize: '0'
679
+ askIv: '0'
680
+ lastPrice: '1'
681
+ highPrice24h: '0'
682
+ lowPrice24h: '0'
683
+ markPrice: '0.2548522'
684
+ indexPrice: '1871.27'
685
+ markPriceIv: '1.5991'
686
+ underlyingPrice: '1886.16'
687
+ openInterest: '231.5'
688
+ turnover24h: '0'
689
+ volume24h: '0'
690
+ totalVolume: '232'
691
+ totalTurnover: '362305'
692
+ delta: '-0.00052953'
693
+ gamma: '0.00000128'
694
+ vega: '0.01719155'
695
+ theta: '-0.0159208'
696
+ predictedDeliveryPrice: '0'
697
+ change24h: '0'
698
+ }
699
+ type: 'snapshot'
700
+ }
701
+
279
702
  type BybitDataMessage = {
280
703
  topic: string
281
704
  }
@@ -29,7 +29,18 @@ import {
29
29
  import { BitnomialBookChangMapper, bitnomialTradesMapper } from './bitnomial'
30
30
  import { BitstampBookChangeMapper, bitstampTradesMapper } from './bitstamp'
31
31
  import { BlockchainComBookChangeMapper, BlockchainComTradesMapper } from './blockchaincom'
32
- import { BybitBookChangeMapper, BybitDerivativeTickerMapper, BybitLiquidationsMapper, BybitTradesMapper } from './bybit'
32
+ import {
33
+ BybitBookChangeMapper,
34
+ BybitDerivativeTickerMapper,
35
+ BybitLiquidationsMapper,
36
+ BybitTradesMapper,
37
+ BybitV5BookChangeMapper,
38
+ BybitV5BookTickerMapper,
39
+ BybitV5DerivativeTickerMapper,
40
+ BybitV5LiquidationsMapper,
41
+ BybitV5OptionSummaryMapper,
42
+ BybitV5TradesMapper
43
+ } from './bybit'
33
44
  import { BybitSpotBookChangeMapper, BybitSpotBookTickerMapper, BybitSpotTradesMapper } from './bybitspot'
34
45
  import { CoinbaseBookChangMapper, coinbaseBookTickerMapper, coinbaseTradesMapper } from './coinbase'
35
46
  import { coinflexBookChangeMapper, CoinflexDerivativeTickerMapper, coinflexTradesMapper } from './coinflex'
@@ -136,6 +147,12 @@ const shouldIgnoreBookSnapshotOverlap = (date: Date) => {
136
147
  return isRealTime(date) === false
137
148
  }
138
149
 
150
+ const BYBIT_V5_API_SWITCH_DATE = new Date('2023-04-05T00:00:00.000Z')
151
+
152
+ const shouldUseBybitV5Mappers = (localTimestamp: Date) => {
153
+ return isRealTime(localTimestamp) || localTimestamp.valueOf() >= BYBIT_V5_API_SWITCH_DATE.valueOf()
154
+ }
155
+
139
156
  const tradesMappers = {
140
157
  bitmex: () => bitmexTradesMapper,
141
158
  binance: () => new BinanceTradesMapper('binance'),
@@ -172,7 +189,8 @@ const tradesMappers = {
172
189
  'huobi-dm-swap': () => new HuobiTradesMapper('huobi-dm-swap'),
173
190
  'huobi-dm-linear-swap': () => new HuobiTradesMapper('huobi-dm-linear-swap'),
174
191
  'huobi-dm-options': () => new HuobiTradesMapper('huobi-dm-options'),
175
- bybit: () => new BybitTradesMapper('bybit'),
192
+ bybit: (localTimestamp: Date) =>
193
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5TradesMapper('bybit') : new BybitTradesMapper('bybit'),
176
194
  okcoin: () => new OkexTradesMapper('okcoin', 'spot'),
177
195
  hitbtc: () => hitBtcTradesMapper,
178
196
  phemex: () => phemexTradesMapper,
@@ -189,13 +207,15 @@ const tradesMappers = {
189
207
  serum: () => new SerumTradesMapper('serum'),
190
208
  'star-atlas': () => new SerumTradesMapper('star-atlas'),
191
209
  mango: () => new SerumTradesMapper('mango'),
192
- 'bybit-spot': () => new BybitSpotTradesMapper('bybit-spot'),
210
+ 'bybit-spot': (localTimestamp: Date) =>
211
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5TradesMapper('bybit-spot') : new BybitSpotTradesMapper('bybit-spot'),
193
212
  'crypto-com': () => new CryptoComTradesMapper('crypto-com'),
194
213
  'crypto-com-derivatives': () => new CryptoComTradesMapper('crypto-com-derivatives'),
195
214
  kucoin: () => new KucoinTradesMapper('kucoin'),
196
215
  bitnomial: () => bitnomialTradesMapper,
197
216
  'woo-x': () => wooxTradesMapper,
198
- 'blockchain-com': () => new BlockchainComTradesMapper()
217
+ 'blockchain-com': () => new BlockchainComTradesMapper(),
218
+ 'bybit-options': () => new BybitV5TradesMapper('bybit-options')
199
219
  }
200
220
 
201
221
  const bookChangeMappers = {
@@ -247,8 +267,10 @@ const bookChangeMappers = {
247
267
  'huobi-dm-swap': () => new HuobiBookChangeMapper('huobi-dm-swap'),
248
268
  'huobi-dm-linear-swap': () => new HuobiBookChangeMapper('huobi-dm-linear-swap'),
249
269
  'huobi-dm-options': () => new HuobiBookChangeMapper('huobi-dm-options'),
250
- 'bybit-spot': () => new BybitSpotBookChangeMapper('bybit-spot'),
251
- bybit: () => new BybitBookChangeMapper('bybit', false),
270
+ 'bybit-spot': (localTimestamp: Date) =>
271
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5BookChangeMapper('bybit-spot', 50) : new BybitSpotBookChangeMapper('bybit-spot'),
272
+ bybit: (localTimestamp: Date) =>
273
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5BookChangeMapper('bybit', 50) : new BybitBookChangeMapper('bybit', false),
252
274
  okcoin: (localTimestamp: Date) =>
253
275
  new OkexBookChangeMapper('okcoin', 'spot', localTimestamp.valueOf() >= new Date('2020-02-13').valueOf()),
254
276
  hitbtc: () => hitBtcBookChangeMapper,
@@ -271,7 +293,8 @@ const bookChangeMappers = {
271
293
  kucoin: (localTimestamp: Date) => new KucoinBookChangeMapper('kucoin', isRealTime(localTimestamp) === false),
272
294
  bitnomial: () => new BitnomialBookChangMapper(),
273
295
  'woo-x': () => new WooxBookChangeMapper(),
274
- 'blockchain-com': () => new BlockchainComBookChangeMapper()
296
+ 'blockchain-com': () => new BlockchainComBookChangeMapper(),
297
+ 'bybit-options': () => new BybitV5BookChangeMapper('bybit-options', 25)
275
298
  }
276
299
 
277
300
  const derivativeTickersMappers = {
@@ -289,7 +312,8 @@ const derivativeTickersMappers = {
289
312
  'okex-swap': (localTimestamp: Date) =>
290
313
  shouldUseOkexV5Mappers(localTimestamp) ? new OkexV5DerivativeTickerMapper('okex-swap') : new OkexDerivativeTickerMapper('okex-swap'),
291
314
 
292
- bybit: () => new BybitDerivativeTickerMapper(),
315
+ bybit: (localTimestamp: Date) =>
316
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5DerivativeTickerMapper() : new BybitDerivativeTickerMapper(),
293
317
  phemex: () => new PhemexDerivativeTickerMapper(),
294
318
  ftx: () => new FTXDerivativeTickerMapper('ftx'),
295
319
  delta: (localTimestamp: Date) => new DeltaDerivativeTickerMapper(localTimestamp.valueOf() >= new Date('2020-10-14').valueOf()),
@@ -310,7 +334,8 @@ const optionsSummaryMappers = {
310
334
  'okex-options': (localTimestamp: Date) =>
311
335
  shouldUseOkexV5Mappers(localTimestamp) ? new OkexV5OptionSummaryMapper() : new OkexOptionSummaryMapper(),
312
336
  'binance-options': () => new BinanceOptionSummaryMapper(),
313
- 'huobi-dm-options': () => new HuobiOptionsSummaryMapper()
337
+ 'huobi-dm-options': () => new HuobiOptionsSummaryMapper(),
338
+ 'bybit-options': () => new BybitV5OptionSummaryMapper()
314
339
  }
315
340
 
316
341
  const liquidationsMappers = {
@@ -324,7 +349,8 @@ const liquidationsMappers = {
324
349
  'huobi-dm': () => new HuobiLiquidationsMapper('huobi-dm'),
325
350
  'huobi-dm-swap': () => new HuobiLiquidationsMapper('huobi-dm-swap'),
326
351
  'huobi-dm-linear-swap': () => new HuobiLiquidationsMapper('huobi-dm-linear-swap'),
327
- bybit: () => new BybitLiquidationsMapper('bybit'),
352
+ bybit: (localTimestamp: Date) =>
353
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5LiquidationsMapper('bybit') : new BybitLiquidationsMapper('bybit'),
328
354
  'okex-futures': (localTimestamp: Date) =>
329
355
  shouldUseOkexV5Mappers(localTimestamp)
330
356
  ? new OkexV5LiquidationsMapper('okex-futures')
@@ -379,12 +405,14 @@ const bookTickersMappers = {
379
405
  'star-atlas': () => new SerumBookTickerMapper('star-atlas'),
380
406
  mango: () => new SerumBookTickerMapper('mango'),
381
407
  'gate-io-futures': () => new GateIOFuturesBookTickerMapper('gate-io-futures'),
382
- 'bybit-spot': () => new BybitSpotBookTickerMapper('bybit-spot'),
408
+ 'bybit-spot': (localTimestamp: Date) =>
409
+ shouldUseBybitV5Mappers(localTimestamp) ? new BybitV5BookTickerMapper('bybit-spot') : new BybitSpotBookTickerMapper('bybit-spot'),
383
410
  'crypto-com': () => new CryptoComBookTickerMapper('crypto-com'),
384
411
  'crypto-com-derivatives': () => new CryptoComBookTickerMapper('crypto-com-derivatives'),
385
412
  kucoin: () => new KucoinBookTickerMapper('kucoin'),
386
413
  'woo-x': () => new WooxBookTickerMapper(),
387
- delta: () => new DeltaBookTickerMapper()
414
+ delta: () => new DeltaBookTickerMapper(),
415
+ bybit: () => new BybitV5BookTickerMapper('bybit')
388
416
  }
389
417
 
390
418
  export const normalizeTrades = <T extends keyof typeof tradesMappers>(exchange: T, localTimestamp: Date): Mapper<T, Trade> => {