tardis-dev 12.7.9 → 13.1.2

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.
Files changed (150) hide show
  1. package/dist/consts.d.ts +4 -4
  2. package/dist/consts.d.ts.map +1 -1
  3. package/dist/consts.js +58 -4
  4. package/dist/consts.js.map +1 -1
  5. package/dist/handy.d.ts +2 -0
  6. package/dist/handy.d.ts.map +1 -1
  7. package/dist/handy.js +15 -1
  8. package/dist/handy.js.map +1 -1
  9. package/dist/mappers/ascendex.d.ts +1 -1
  10. package/dist/mappers/ascendex.d.ts.map +1 -1
  11. package/dist/mappers/ascendex.js +5 -0
  12. package/dist/mappers/ascendex.js.map +1 -1
  13. package/dist/mappers/binance.d.ts +1 -1
  14. package/dist/mappers/binance.d.ts.map +1 -1
  15. package/dist/mappers/binance.js +5 -11
  16. package/dist/mappers/binance.js.map +1 -1
  17. package/dist/mappers/binancedex.d.ts +1 -1
  18. package/dist/mappers/binancedex.d.ts.map +1 -1
  19. package/dist/mappers/binancedex.js +4 -0
  20. package/dist/mappers/binancedex.js.map +1 -1
  21. package/dist/mappers/binanceoptions.d.ts.map +1 -1
  22. package/dist/mappers/binanceoptions.js +3 -0
  23. package/dist/mappers/binanceoptions.js.map +1 -1
  24. package/dist/mappers/bitfinex.d.ts +1 -1
  25. package/dist/mappers/bitfinex.d.ts.map +1 -1
  26. package/dist/mappers/bitfinex.js +5 -0
  27. package/dist/mappers/bitfinex.js.map +1 -1
  28. package/dist/mappers/bitflyer.d.ts +1 -1
  29. package/dist/mappers/bitflyer.d.ts.map +1 -1
  30. package/dist/mappers/bitflyer.js +3 -0
  31. package/dist/mappers/bitflyer.js.map +1 -1
  32. package/dist/mappers/bitmex.d.ts +1 -1
  33. package/dist/mappers/bitmex.d.ts.map +1 -1
  34. package/dist/mappers/bitmex.js +5 -0
  35. package/dist/mappers/bitmex.js.map +1 -1
  36. package/dist/mappers/bitstamp.d.ts.map +1 -1
  37. package/dist/mappers/bitstamp.js +3 -8
  38. package/dist/mappers/bitstamp.js.map +1 -1
  39. package/dist/mappers/bybit.d.ts.map +1 -1
  40. package/dist/mappers/bybit.js +5 -0
  41. package/dist/mappers/bybit.js.map +1 -1
  42. package/dist/mappers/coinbase.d.ts.map +1 -1
  43. package/dist/mappers/coinbase.js +3 -0
  44. package/dist/mappers/coinbase.js.map +1 -1
  45. package/dist/mappers/coinflex.d.ts +1 -1
  46. package/dist/mappers/coinflex.d.ts.map +1 -1
  47. package/dist/mappers/coinflex.js +4 -0
  48. package/dist/mappers/coinflex.js.map +1 -1
  49. package/dist/mappers/cryptofacilities.d.ts +1 -1
  50. package/dist/mappers/cryptofacilities.d.ts.map +1 -1
  51. package/dist/mappers/cryptofacilities.js +6 -0
  52. package/dist/mappers/cryptofacilities.js.map +1 -1
  53. package/dist/mappers/delta.d.ts +1 -1
  54. package/dist/mappers/delta.d.ts.map +1 -1
  55. package/dist/mappers/delta.js +4 -0
  56. package/dist/mappers/delta.js.map +1 -1
  57. package/dist/mappers/deribit.d.ts +1 -1
  58. package/dist/mappers/deribit.d.ts.map +1 -1
  59. package/dist/mappers/deribit.js +6 -0
  60. package/dist/mappers/deribit.js.map +1 -1
  61. package/dist/mappers/dydx.d.ts +1 -1
  62. package/dist/mappers/dydx.d.ts.map +1 -1
  63. package/dist/mappers/dydx.js +4 -0
  64. package/dist/mappers/dydx.js.map +1 -1
  65. package/dist/mappers/ftx.d.ts +1 -1
  66. package/dist/mappers/ftx.d.ts.map +1 -1
  67. package/dist/mappers/ftx.js +5 -0
  68. package/dist/mappers/ftx.js.map +1 -1
  69. package/dist/mappers/gateio.d.ts.map +1 -1
  70. package/dist/mappers/gateio.js +3 -0
  71. package/dist/mappers/gateio.js.map +1 -1
  72. package/dist/mappers/gateiofutures.d.ts +1 -1
  73. package/dist/mappers/gateiofutures.d.ts.map +1 -1
  74. package/dist/mappers/gateiofutures.js +4 -0
  75. package/dist/mappers/gateiofutures.js.map +1 -1
  76. package/dist/mappers/gemini.d.ts.map +1 -1
  77. package/dist/mappers/gemini.js +3 -0
  78. package/dist/mappers/gemini.js.map +1 -1
  79. package/dist/mappers/hitbtc.d.ts.map +1 -1
  80. package/dist/mappers/hitbtc.js +3 -0
  81. package/dist/mappers/hitbtc.js.map +1 -1
  82. package/dist/mappers/huobi.d.ts +2 -2
  83. package/dist/mappers/huobi.d.ts.map +1 -1
  84. package/dist/mappers/huobi.js +3 -1
  85. package/dist/mappers/huobi.js.map +1 -1
  86. package/dist/mappers/index.d.ts +3 -3
  87. package/dist/mappers/index.d.ts.map +1 -1
  88. package/dist/mappers/index.js +43 -23
  89. package/dist/mappers/index.js.map +1 -1
  90. package/dist/mappers/kraken.d.ts.map +1 -1
  91. package/dist/mappers/kraken.js +3 -0
  92. package/dist/mappers/kraken.js.map +1 -1
  93. package/dist/mappers/okex.d.ts +245 -1
  94. package/dist/mappers/okex.d.ts.map +1 -1
  95. package/dist/mappers/okex.js +396 -1
  96. package/dist/mappers/okex.js.map +1 -1
  97. package/dist/mappers/poloniex.d.ts.map +1 -1
  98. package/dist/mappers/poloniex.js +3 -0
  99. package/dist/mappers/poloniex.js.map +1 -1
  100. package/dist/mappers/serum.d.ts +1 -1
  101. package/dist/mappers/serum.d.ts.map +1 -1
  102. package/dist/mappers/serum.js +12 -3
  103. package/dist/mappers/serum.js.map +1 -1
  104. package/dist/mappers/upbit.d.ts +1 -1
  105. package/dist/mappers/upbit.d.ts.map +1 -1
  106. package/dist/mappers/upbit.js +3 -0
  107. package/dist/mappers/upbit.js.map +1 -1
  108. package/dist/realtimefeeds/okex.d.ts +4 -2
  109. package/dist/realtimefeeds/okex.d.ts.map +1 -1
  110. package/dist/realtimefeeds/okex.js +38 -10
  111. package/dist/realtimefeeds/okex.js.map +1 -1
  112. package/dist/replay.d.ts.map +1 -1
  113. package/dist/replay.js +2 -6
  114. package/dist/replay.js.map +1 -1
  115. package/dist/stream.d.ts.map +1 -1
  116. package/dist/stream.js +2 -6
  117. package/dist/stream.js.map +1 -1
  118. package/package.json +13 -13
  119. package/src/consts.ts +62 -4
  120. package/src/handy.ts +14 -0
  121. package/src/mappers/ascendex.ts +6 -1
  122. package/src/mappers/binance.ts +2 -9
  123. package/src/mappers/binancedex.ts +6 -1
  124. package/src/mappers/binanceoptions.ts +7 -1
  125. package/src/mappers/bitfinex.ts +10 -1
  126. package/src/mappers/bitflyer.ts +8 -2
  127. package/src/mappers/bitmex.ts +12 -2
  128. package/src/mappers/bitstamp.ts +1 -7
  129. package/src/mappers/bybit.ts +9 -0
  130. package/src/mappers/coinbase.ts +7 -1
  131. package/src/mappers/coinflex.ts +8 -1
  132. package/src/mappers/cryptofacilities.ts +12 -1
  133. package/src/mappers/delta.ts +8 -1
  134. package/src/mappers/deribit.ts +14 -2
  135. package/src/mappers/dydx.ts +8 -1
  136. package/src/mappers/ftx.ts +12 -2
  137. package/src/mappers/gateio.ts +5 -0
  138. package/src/mappers/gateiofutures.ts +8 -1
  139. package/src/mappers/gemini.ts +5 -0
  140. package/src/mappers/hitbtc.ts +5 -0
  141. package/src/mappers/huobi.ts +6 -2
  142. package/src/mappers/index.ts +77 -24
  143. package/src/mappers/kraken.ts +7 -1
  144. package/src/mappers/okex.ts +591 -2
  145. package/src/mappers/poloniex.ts +5 -0
  146. package/src/mappers/serum.ts +17 -5
  147. package/src/mappers/upbit.ts +6 -1
  148. package/src/realtimefeeds/okex.ts +42 -10
  149. package/src/replay.ts +2 -7
  150. package/src/stream.ts +3 -7
@@ -1,7 +1,584 @@
1
- import { asNumberIfValid } from '../handy'
2
- import { BookChange, DerivativeTicker, Exchange, Trade, OptionSummary, Liquidation, BookTicker } 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 Okex API mappers
6
+ // https://www.okex.com/docs-v5/en/#websocket-api-public-channel-trades-channel
7
+
8
+ export class OkexV5TradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
9
+ constructor(private readonly _exchange: Exchange) {}
10
+
11
+ canHandle(message: any) {
12
+ if (message.event !== undefined || message.arg === undefined) {
13
+ return false
14
+ }
15
+ return message.arg.channel === 'trades'
16
+ }
17
+
18
+ getFilters(symbols?: string[]) {
19
+ symbols = upperCaseSymbols(symbols)
20
+
21
+ return [
22
+ {
23
+ channel: `trades` as const,
24
+ symbols
25
+ }
26
+ ]
27
+ }
28
+
29
+ *map(okexTradesMessage: OkexV5TradeMessage, localTimestamp: Date): IterableIterator<Trade> {
30
+ for (const okexTrade of okexTradesMessage.data) {
31
+ yield {
32
+ type: 'trade',
33
+ symbol: okexTrade.instId,
34
+ exchange: this._exchange,
35
+ id: okexTrade.tradeId,
36
+ price: Number(okexTrade.px),
37
+ amount: Number(okexTrade.sz),
38
+ side: okexTrade.side === 'buy' ? 'buy' : 'sell',
39
+ timestamp: new Date(Number(okexTrade.ts)),
40
+ localTimestamp: localTimestamp
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ const mapV5BookLevel = (level: OkexV5BookLevel) => {
47
+ const price = Number(level[0])
48
+ const amount = Number(level[1])
49
+
50
+ return { price, amount }
51
+ }
52
+
53
+ export class OkexV5BookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange> {
54
+ constructor(private readonly _exchange: Exchange) {}
55
+
56
+ canHandle(message: any) {
57
+ if (message.event !== undefined || message.arg === undefined) {
58
+ return false
59
+ }
60
+ return message.arg.channel === 'books-l2-tbt'
61
+ }
62
+
63
+ getFilters(symbols?: string[]) {
64
+ symbols = upperCaseSymbols(symbols)
65
+
66
+ return [
67
+ {
68
+ channel: `books-l2-tbt` as const,
69
+ symbols
70
+ }
71
+ ]
72
+ }
73
+
74
+ *map(okexDepthDataMessage: OkexV5BookMessage, localTimestamp: Date): IterableIterator<BookChange> {
75
+ for (const message of okexDepthDataMessage.data) {
76
+ if (okexDepthDataMessage.action === 'update' && message.bids.length === 0 && message.asks.length === 0) {
77
+ continue
78
+ }
79
+
80
+ const timestamp = new Date(Number(message.ts))
81
+
82
+ if (timestamp.valueOf() === 0) {
83
+ continue
84
+ }
85
+
86
+ yield {
87
+ type: 'book_change',
88
+ symbol: okexDepthDataMessage.arg.instId,
89
+ exchange: this._exchange,
90
+ isSnapshot: okexDepthDataMessage.action === 'snapshot',
91
+ bids: message.bids.map(mapV5BookLevel),
92
+ asks: message.asks.map(mapV5BookLevel),
93
+ timestamp,
94
+ localTimestamp: localTimestamp
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ export class OkexV5BookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker> {
101
+ constructor(private readonly _exchange: Exchange) {}
102
+
103
+ canHandle(message: any) {
104
+ if (message.event !== undefined || message.arg === undefined) {
105
+ return false
106
+ }
107
+ return message.arg.channel === 'tickers'
108
+ }
109
+
110
+ getFilters(symbols?: string[]) {
111
+ symbols = upperCaseSymbols(symbols)
112
+
113
+ return [
114
+ {
115
+ channel: `tickers` as const,
116
+ symbols
117
+ }
118
+ ]
119
+ }
120
+
121
+ *map(message: OkexV5TickerMessage, localTimestamp: Date): IterableIterator<BookTicker> {
122
+ for (const okexTicker of message.data) {
123
+ const ticker: BookTicker = {
124
+ type: 'book_ticker',
125
+ symbol: okexTicker.instId,
126
+ exchange: this._exchange,
127
+
128
+ askAmount: asNumberIfValid(okexTicker.askSz),
129
+ askPrice: asNumberIfValid(okexTicker.askPx),
130
+
131
+ bidPrice: asNumberIfValid(okexTicker.bidPx),
132
+ bidAmount: asNumberIfValid(okexTicker.bidSz),
133
+ timestamp: new Date(Number(okexTicker.ts)),
134
+ localTimestamp: localTimestamp
135
+ }
136
+
137
+ yield ticker
138
+ }
139
+ }
140
+ }
141
+
142
+ export class OkexV5DerivativeTickerMapper implements Mapper<'okex-futures' | 'okex-swap', DerivativeTicker> {
143
+ private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
144
+ private readonly _indexPrices = new Map<string, number>()
145
+
146
+ private _futuresChannels = ['tickers', 'open-interest', 'mark-price', 'index-tickers'] as const
147
+
148
+ private _swapChannels = ['tickers', 'open-interest', 'mark-price', 'index-tickers', 'funding-rate'] as const
149
+
150
+ constructor(private readonly _exchange: Exchange) {}
151
+
152
+ canHandle(message: any) {
153
+ const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
154
+
155
+ if (message.event !== undefined || message.arg === undefined) {
156
+ return false
157
+ }
158
+
159
+ return channels.includes(message.arg.channel)
160
+ }
161
+
162
+ getFilters(symbols?: string[]) {
163
+ symbols = upperCaseSymbols(symbols)
164
+
165
+ const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
166
+ return channels.map((channel) => {
167
+ if (channel === 'index-tickers') {
168
+ const indexes =
169
+ symbols !== undefined
170
+ ? symbols.map((s) => {
171
+ const symbolParts = s.split('-')
172
+ return `${symbolParts[0]}-${symbolParts[1]}`
173
+ })
174
+ : undefined
175
+ return {
176
+ channel,
177
+ symbols: indexes
178
+ }
179
+ }
180
+
181
+ return {
182
+ channel,
183
+ symbols
184
+ }
185
+ })
186
+ }
187
+
188
+ *map(
189
+ message: OkexV5TickerMessage | OkexV5OpenInterestMessage | OkexV5MarkPriceMessage | OkexV5IndexTickerMessage | OkexV5FundingRateMessage,
190
+ localTimestamp: Date
191
+ ): IterableIterator<DerivativeTicker> {
192
+ if (message.arg.channel === 'index-tickers') {
193
+ for (const dataMessage of message.data) {
194
+ const indexTickerMessage = dataMessage as OkexV5IndexTickerMessage['data'][0]
195
+
196
+ const lastIndexPrice = Number(indexTickerMessage.idxPx)
197
+ if (lastIndexPrice > 0) {
198
+ this._indexPrices.set(indexTickerMessage.instId, lastIndexPrice)
199
+ }
200
+ }
201
+
202
+ return
203
+ }
204
+
205
+ for (const dataMessage of message.data) {
206
+ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(dataMessage.instId, this._exchange)
207
+ const symbolParts = dataMessage.instId.split('-')
208
+ const indexSymbol = `${symbolParts[0]}-${symbolParts[1]}`
209
+
210
+ const indexPrice = this._indexPrices.get(indexSymbol)
211
+
212
+ if (indexPrice !== undefined) {
213
+ pendingTickerInfo.updateIndexPrice(indexPrice)
214
+ }
215
+
216
+ if (message.arg.channel === 'mark-price') {
217
+ const markPriceMessage = dataMessage as OkexV5MarkPriceMessage['data'][0]
218
+
219
+ const markPrice = Number(markPriceMessage.markPx)
220
+ if (markPrice > 0) {
221
+ pendingTickerInfo.updateMarkPrice(markPrice)
222
+ pendingTickerInfo.updateTimestamp(new Date(Number(markPriceMessage.ts)))
223
+ }
224
+ }
225
+
226
+ if (message.arg.channel === 'open-interest') {
227
+ const openInterestMessage = dataMessage as OkexV5OpenInterestMessage['data'][0]
228
+
229
+ const openInterest = Number(openInterestMessage.oi)
230
+ if (openInterest > 0) {
231
+ pendingTickerInfo.updateOpenInterest(openInterest)
232
+ pendingTickerInfo.updateTimestamp(new Date(Number(openInterestMessage.ts)))
233
+ }
234
+ }
235
+
236
+ if (message.arg.channel === 'funding-rate') {
237
+ const fundingRateMessage = dataMessage as OkexV5FundingRateMessage['data'][0]
238
+
239
+ pendingTickerInfo.updateFundingRate(Number(fundingRateMessage.fundingRate))
240
+ //
241
+ pendingTickerInfo.updateFundingTimestamp(new Date(Number(fundingRateMessage.fundingTime)))
242
+
243
+ if (fundingRateMessage.nextFundingRate !== undefined) {
244
+ pendingTickerInfo.updatePredictedFundingRate(Number(fundingRateMessage.nextFundingRate))
245
+ }
246
+ }
247
+
248
+ if (message.arg.channel === 'tickers') {
249
+ const tickerMessage = dataMessage as OkexV5TickerMessage['data'][0]
250
+
251
+ const lastPrice = Number(tickerMessage.last)
252
+
253
+ if (lastPrice > 0) {
254
+ pendingTickerInfo.updateLastPrice(lastPrice)
255
+ pendingTickerInfo.updateTimestamp(new Date(Number(tickerMessage.ts)))
256
+ }
257
+ }
258
+
259
+ if (pendingTickerInfo.hasChanged()) {
260
+ yield pendingTickerInfo.getSnapshot(localTimestamp)
261
+ }
262
+ }
263
+ }
264
+ }
265
+
266
+ export class OkexV5LiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidation> {
267
+ constructor(private readonly _exchange: Exchange) {}
268
+
269
+ canHandle(message: any) {
270
+ if (message.event !== undefined || message.arg === undefined) {
271
+ return false
272
+ }
273
+ return message.arg.channel === 'liquidations'
274
+ }
275
+
276
+ getFilters(symbols?: string[]) {
277
+ symbols = upperCaseSymbols(symbols)
278
+
279
+ return [
280
+ {
281
+ channel: 'liquidations',
282
+ symbols
283
+ } as any
284
+ ]
285
+ }
286
+
287
+ *map(okexLiquidationMessage: OkexV5LiquidationMessage, localTimestamp: Date): IterableIterator<Liquidation> {
288
+ for (const okexLiquidation of okexLiquidationMessage.data) {
289
+ const liquidation: Liquidation = {
290
+ type: 'liquidation',
291
+ symbol: okexLiquidationMessage.arg.instId,
292
+ exchange: this._exchange,
293
+ id: undefined,
294
+ price: Number(okexLiquidation.bkPx),
295
+ amount: Number(okexLiquidation.sz),
296
+ side: okexLiquidation.side === 'buy' ? 'buy' : 'sell',
297
+ timestamp: new Date(Number(okexLiquidation.ts)),
298
+ localTimestamp: localTimestamp
299
+ }
300
+ yield liquidation
301
+ }
302
+ }
303
+ }
304
+
305
+ export class OkexV5OptionSummaryMapper implements Mapper<'okex-options', OptionSummary> {
306
+ private readonly _indexPrices = new Map<string, number>()
307
+ private readonly _openInterests = new Map<string, number>()
308
+ private readonly _markPrices = new Map<string, number>()
309
+
310
+ private readonly _tickers = new Map<string, OkexV5TickerMessage['data'][0]>()
311
+ private readonly expiration_regex = /(\d{2})(\d{2})(\d{2})/
312
+
313
+ canHandle(message: any) {
314
+ if (message.event !== undefined || message.arg === undefined) {
315
+ return false
316
+ }
317
+ return (
318
+ message.arg.channel === 'opt-summary' ||
319
+ message.arg.channel === 'index-tickers' ||
320
+ message.arg.channel === 'tickers' ||
321
+ message.arg.channel === 'open-interest' ||
322
+ message.arg.channel === 'mark-price'
323
+ )
324
+ }
325
+
326
+ getFilters(symbols?: string[]) {
327
+ symbols = upperCaseSymbols(symbols)
328
+
329
+ const indexes =
330
+ symbols !== undefined
331
+ ? symbols.map((s) => {
332
+ const symbolParts = s.split('-')
333
+ return `${symbolParts[0]}-${symbolParts[1]}`
334
+ })
335
+ : undefined
336
+
337
+ return [
338
+ {
339
+ channel: `opt-summary`,
340
+ symbols: [] as string[]
341
+ } as const,
342
+ {
343
+ channel: `index-tickers`,
344
+ symbols: indexes
345
+ } as const,
346
+ {
347
+ channel: `tickers`,
348
+ symbols: symbols
349
+ } as const,
350
+ {
351
+ channel: `open-interest`,
352
+ symbols: symbols
353
+ } as const,
354
+ {
355
+ channel: `mark-price`,
356
+ symbols: symbols
357
+ } as const
358
+ ]
359
+ }
360
+
361
+ *map(
362
+ message: OkexV5SummaryMessage | OkexV5IndexTickerMessage | OkexV5TickerMessage | OkexV5OpenInterestMessage | OkexV5MarkPriceMessage,
363
+ localTimestamp: Date
364
+ ): IterableIterator<OptionSummary> | undefined {
365
+ if (message.arg.channel === 'index-tickers') {
366
+ for (const dataMessage of message.data) {
367
+ const indexTickerMessage = dataMessage as OkexV5IndexTickerMessage['data'][0]
368
+
369
+ const lastIndexPrice = asNumberIfValid(indexTickerMessage.idxPx)
370
+ if (lastIndexPrice !== undefined) {
371
+ this._indexPrices.set(indexTickerMessage.instId, lastIndexPrice)
372
+ }
373
+ }
374
+ return
375
+ }
376
+
377
+ if (message.arg.channel === 'open-interest') {
378
+ for (const dataMessage of message.data) {
379
+ const openInterestMessage = dataMessage as OkexV5OpenInterestMessage['data'][0]
380
+
381
+ const openInterestValue = asNumberIfValid(openInterestMessage.oi)
382
+ if (openInterestValue !== undefined) {
383
+ this._openInterests.set(openInterestMessage.instId, openInterestValue)
384
+ }
385
+ }
386
+ return
387
+ }
388
+
389
+ if (message.arg.channel === 'mark-price') {
390
+ for (const dataMessage of message.data) {
391
+ const markPriceMessage = dataMessage as OkexV5MarkPriceMessage['data'][0]
392
+
393
+ const markPrice = asNumberIfValid(markPriceMessage.markPx)
394
+ if (markPrice !== undefined) {
395
+ this._markPrices.set(markPriceMessage.instId, markPrice)
396
+ }
397
+ }
398
+ return
399
+ }
400
+
401
+ if (message.arg.channel === 'tickers') {
402
+ for (const dataMessage of message.data) {
403
+ const tickerMessage = dataMessage as OkexV5TickerMessage['data'][0]
404
+
405
+ this._tickers.set(tickerMessage.instId, tickerMessage)
406
+ }
407
+ return
408
+ }
409
+
410
+ if (message.arg.channel === 'opt-summary') {
411
+ for (const dataMessage of message.data) {
412
+ const summary = dataMessage as OkexV5SummaryMessage['data'][0]
413
+
414
+ const symbolParts = summary.instId.split('-')
415
+ const isPut = symbolParts[4] === 'P'
416
+ const strikePrice = Number(symbolParts[3])
417
+
418
+ var dateArray = this.expiration_regex.exec(symbolParts[2])!
419
+
420
+ const expirationDate = new Date(Date.UTC(+('20' + dateArray[1]), +dateArray[2] - 1, +dateArray[3], 8, 0, 0, 0))
421
+ const lastUnderlyingPrice = this._indexPrices.get(summary.uly)
422
+
423
+ const lastOpenInterest = this._openInterests.get(summary.instId)
424
+
425
+ const lastMarkPrice = this._markPrices.get(summary.instId)
426
+
427
+ const lastTickerInfo = this._tickers.get(summary.instId)
428
+
429
+ const optionSummary: OptionSummary = {
430
+ type: 'option_summary',
431
+ symbol: summary.instId,
432
+ exchange: 'okex-options',
433
+ optionType: isPut ? 'put' : 'call',
434
+ strikePrice,
435
+ expirationDate,
436
+
437
+ bestBidPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.bidPx) : undefined,
438
+ bestBidAmount: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.bidSz) : undefined,
439
+ bestBidIV: asNumberIfValid(summary.bidVol),
440
+
441
+ bestAskPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.askPx) : undefined,
442
+ bestAskAmount: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.askSz) : undefined,
443
+ bestAskIV: asNumberIfValid(summary.askVol),
444
+
445
+ lastPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.last) : undefined,
446
+ openInterest: lastOpenInterest,
447
+
448
+ markPrice: lastMarkPrice,
449
+ markIV: asNumberIfValid(summary.markVol),
450
+
451
+ delta: asNumberIfValid(summary.delta),
452
+ gamma: asNumberIfValid(summary.gamma),
453
+ vega: asNumberIfValid(summary.vega),
454
+ theta: asNumberIfValid(summary.theta),
455
+ rho: undefined,
456
+
457
+ underlyingPrice: lastUnderlyingPrice,
458
+ underlyingIndex: summary.uly,
459
+
460
+ timestamp: new Date(Number(summary.ts)),
461
+ localTimestamp: localTimestamp
462
+ }
463
+
464
+ yield optionSummary
465
+ }
466
+ }
467
+ }
468
+ }
469
+
470
+ type OkexV5TradeMessage = {
471
+ arg: { channel: 'trades'; instId: 'CRV-USDT' }
472
+ data: [{ instId: 'CRV-USDT'; tradeId: '21300150'; px: '3.973'; sz: '13.491146'; side: 'buy'; ts: '1639999319938' }]
473
+ }
474
+
475
+ type OkexV5BookLevel = [string, string, string, string]
476
+
477
+ type OkexV5BookMessage =
478
+ | {
479
+ arg: { channel: 'books-l2-tbt'; instId: string }
480
+ action: 'snapshot'
481
+ data: [
482
+ {
483
+ asks: OkexV5BookLevel[]
484
+ bids: OkexV5BookLevel[]
485
+ ts: string
486
+ }
487
+ ]
488
+ }
489
+ | {
490
+ arg: { channel: 'books-l2-tbt'; instId: string }
491
+ action: 'update'
492
+ data: [{ asks: OkexV5BookLevel[]; bids: OkexV5BookLevel[]; ts: string }]
493
+ }
494
+
495
+ type OkexV5TickerMessage = {
496
+ arg: { channel: 'tickers'; instId: string }
497
+ data: [
498
+ {
499
+ instType: 'SPOT'
500
+ instId: 'ACT-USDT'
501
+ last: '0.00718'
502
+ lastSz: '8052.117146'
503
+ askPx: '0.0072'
504
+ askSz: '54969.407534'
505
+ bidPx: '0.00713'
506
+ bidSz: '4092.326'
507
+ open24h: '0.00717'
508
+ high24h: '0.00722'
509
+ low24h: '0.00696'
510
+ sodUtc0: '0.00714'
511
+ sodUtc8: '0.00721'
512
+ volCcy24h: '278377.765301'
513
+ vol24h: '39168761.49997'
514
+ ts: '1639999318686'
515
+ }
516
+ ]
517
+ }
518
+
519
+ type OkexV5OpenInterestMessage = {
520
+ arg: { channel: 'open-interest'; instId: string }
521
+ data: [{ instId: 'FIL-USDT-220325'; instType: 'FUTURES'; oi: '236870'; oiCcy: '23687'; ts: '1640131202886' }]
522
+ }
523
+
524
+ type OkexV5MarkPriceMessage = {
525
+ arg: { channel: 'mark-price'; instId: string }
526
+ data: [{ instId: 'FIL-USDT-220325'; instType: 'FUTURES'; markPx: '36.232'; ts: '1640131204676' }]
527
+ }
528
+
529
+ type OkexV5IndexTickerMessage = {
530
+ arg: { channel: 'index-tickers'; instId: string }
531
+ data: [
532
+ {
533
+ instId: 'FIL-USDT'
534
+ idxPx: '35.583'
535
+ open24h: '34.558'
536
+ high24h: '35.862'
537
+ low24h: '34.529'
538
+ sodUtc0: '35.309'
539
+ sodUtc8: '34.83'
540
+ ts: '1640140200581'
541
+ }
542
+ ]
543
+ }
544
+
545
+ type OkexV5FundingRateMessage = {
546
+ arg: { channel: 'funding-rate'; instId: string }
547
+ data: [{ fundingRate: '0.00048105'; fundingTime: '1640131200000'; instId: string; instType: 'SWAP'; nextFundingRate: '0.00114' }]
548
+ }
549
+
550
+ type OkexV5LiquidationMessage = {
551
+ arg: { channel: 'liquidations'; instId: 'BTC-USDT-211231'; generated: true }
552
+ data: [{ bkLoss: '0'; bkPx: '49674.2'; ccy: ''; posSide: 'short'; side: 'buy'; sz: '40'; ts: '1640140211925' }]
553
+ }
554
+
555
+ type OkexV5SummaryMessage = {
556
+ arg: { channel: 'opt-summary'; uly: 'ETH-USD' }
557
+ data: [
558
+ {
559
+ instType: 'OPTION'
560
+ instId: 'ETH-USD-211222-4000-C'
561
+ uly: 'ETH-USD'
562
+ delta: '0.1975745164'
563
+ gamma: '4.7290833601'
564
+ vega: '0.0002005415'
565
+ theta: '-0.004262964'
566
+ lever: '162.472613953'
567
+ markVol: '0.7794507758'
568
+ bidVol: '0.7421960156'
569
+ askVol: '0.8203208593'
570
+ realVol: ''
571
+ deltaBS: '0.2038286081'
572
+ gammaBS: '0.0013437829'
573
+ thetaBS: '-16.4798150221'
574
+ vegaBS: '0.7647227087'
575
+ ts: '1640001659301'
576
+ }
577
+ ]
578
+ }
579
+
580
+ //---
581
+ //V3 Okex API mappers
5
582
  // https://www.okex.com/docs/en/#ws_swap-README
6
583
 
7
584
  export class OkexTradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
@@ -12,6 +589,8 @@ export class OkexTradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
12
589
  }
13
590
 
14
591
  getFilters(symbols?: string[]) {
592
+ symbols = upperCaseSymbols(symbols)
593
+
15
594
  return [
16
595
  {
17
596
  channel: `${this._market}/trade` as const,
@@ -60,6 +639,8 @@ export class OkexBookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange>
60
639
  }
61
640
 
62
641
  getFilters(symbols?: string[]) {
642
+ symbols = upperCaseSymbols(symbols)
643
+
63
644
  if (this._canUseTickByTickChannel) {
64
645
  return [
65
646
  {
@@ -124,6 +705,8 @@ export class OkexDerivativeTickerMapper implements Mapper<'okex-futures' | 'okex
124
705
  }
125
706
 
126
707
  getFilters(symbols?: string[]) {
708
+ symbols = upperCaseSymbols(symbols)
709
+
127
710
  const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
128
711
  return channels.map((channel) => {
129
712
  return {
@@ -180,6 +763,8 @@ export class OkexOptionSummaryMapper implements Mapper<'okex-options', OptionSum
180
763
  }
181
764
 
182
765
  getFilters(symbols?: string[]) {
766
+ symbols = upperCaseSymbols(symbols)
767
+
183
768
  const indexes =
184
769
  symbols !== undefined
185
770
  ? symbols.map((s) => {
@@ -269,6 +854,8 @@ export class OkexLiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidatio
269
854
  }
270
855
 
271
856
  getFilters(symbols?: string[]) {
857
+ symbols = upperCaseSymbols(symbols)
858
+
272
859
  return [
273
860
  {
274
861
  channel: `${this._market}/liquidation`,
@@ -303,6 +890,8 @@ export class OkexBookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker>
303
890
  }
304
891
 
305
892
  getFilters(symbols?: string[]) {
893
+ symbols = upperCaseSymbols(symbols)
894
+
306
895
  return [
307
896
  {
308
897
  channel: `${this._market}/ticker`,
@@ -1,3 +1,4 @@
1
+ import { upperCaseSymbols } from '../handy'
1
2
  import { BookChange, Trade } from '../types'
2
3
  import { Mapper } from './mapper'
3
4
 
@@ -19,6 +20,8 @@ export class PoloniexTradesMapper implements Mapper<'poloniex', Trade> {
19
20
  }
20
21
 
21
22
  getFilters(symbols?: string[]) {
23
+ symbols = upperCaseSymbols(symbols)
24
+
22
25
  return [
23
26
  {
24
27
  channel: 'price_aggregated_book',
@@ -89,6 +92,8 @@ export class PoloniexBookChangeMapper implements Mapper<'poloniex', BookChange>
89
92
  }
90
93
 
91
94
  getFilters(symbols?: string[]) {
95
+ symbols = upperCaseSymbols(symbols)
96
+
92
97
  return [
93
98
  {
94
99
  channel: 'price_aggregated_book',