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.
- package/dist/consts.d.ts +4 -4
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +58 -4
- package/dist/consts.js.map +1 -1
- package/dist/handy.d.ts +2 -0
- package/dist/handy.d.ts.map +1 -1
- package/dist/handy.js +15 -1
- package/dist/handy.js.map +1 -1
- package/dist/mappers/ascendex.d.ts +1 -1
- package/dist/mappers/ascendex.d.ts.map +1 -1
- package/dist/mappers/ascendex.js +5 -0
- package/dist/mappers/ascendex.js.map +1 -1
- package/dist/mappers/binance.d.ts +1 -1
- package/dist/mappers/binance.d.ts.map +1 -1
- package/dist/mappers/binance.js +5 -11
- package/dist/mappers/binance.js.map +1 -1
- package/dist/mappers/binancedex.d.ts +1 -1
- package/dist/mappers/binancedex.d.ts.map +1 -1
- package/dist/mappers/binancedex.js +4 -0
- package/dist/mappers/binancedex.js.map +1 -1
- package/dist/mappers/binanceoptions.d.ts.map +1 -1
- package/dist/mappers/binanceoptions.js +3 -0
- package/dist/mappers/binanceoptions.js.map +1 -1
- package/dist/mappers/bitfinex.d.ts +1 -1
- package/dist/mappers/bitfinex.d.ts.map +1 -1
- package/dist/mappers/bitfinex.js +5 -0
- package/dist/mappers/bitfinex.js.map +1 -1
- package/dist/mappers/bitflyer.d.ts +1 -1
- package/dist/mappers/bitflyer.d.ts.map +1 -1
- package/dist/mappers/bitflyer.js +3 -0
- package/dist/mappers/bitflyer.js.map +1 -1
- package/dist/mappers/bitmex.d.ts +1 -1
- package/dist/mappers/bitmex.d.ts.map +1 -1
- package/dist/mappers/bitmex.js +5 -0
- package/dist/mappers/bitmex.js.map +1 -1
- package/dist/mappers/bitstamp.d.ts.map +1 -1
- package/dist/mappers/bitstamp.js +3 -8
- package/dist/mappers/bitstamp.js.map +1 -1
- package/dist/mappers/bybit.d.ts.map +1 -1
- package/dist/mappers/bybit.js +5 -0
- package/dist/mappers/bybit.js.map +1 -1
- package/dist/mappers/coinbase.d.ts.map +1 -1
- package/dist/mappers/coinbase.js +3 -0
- package/dist/mappers/coinbase.js.map +1 -1
- package/dist/mappers/coinflex.d.ts +1 -1
- package/dist/mappers/coinflex.d.ts.map +1 -1
- package/dist/mappers/coinflex.js +4 -0
- package/dist/mappers/coinflex.js.map +1 -1
- package/dist/mappers/cryptofacilities.d.ts +1 -1
- package/dist/mappers/cryptofacilities.d.ts.map +1 -1
- package/dist/mappers/cryptofacilities.js +6 -0
- package/dist/mappers/cryptofacilities.js.map +1 -1
- package/dist/mappers/delta.d.ts +1 -1
- package/dist/mappers/delta.d.ts.map +1 -1
- package/dist/mappers/delta.js +4 -0
- package/dist/mappers/delta.js.map +1 -1
- package/dist/mappers/deribit.d.ts +1 -1
- package/dist/mappers/deribit.d.ts.map +1 -1
- package/dist/mappers/deribit.js +6 -0
- package/dist/mappers/deribit.js.map +1 -1
- package/dist/mappers/dydx.d.ts +1 -1
- package/dist/mappers/dydx.d.ts.map +1 -1
- package/dist/mappers/dydx.js +4 -0
- package/dist/mappers/dydx.js.map +1 -1
- package/dist/mappers/ftx.d.ts +1 -1
- package/dist/mappers/ftx.d.ts.map +1 -1
- package/dist/mappers/ftx.js +5 -0
- package/dist/mappers/ftx.js.map +1 -1
- package/dist/mappers/gateio.d.ts.map +1 -1
- package/dist/mappers/gateio.js +3 -0
- package/dist/mappers/gateio.js.map +1 -1
- package/dist/mappers/gateiofutures.d.ts +1 -1
- package/dist/mappers/gateiofutures.d.ts.map +1 -1
- package/dist/mappers/gateiofutures.js +4 -0
- package/dist/mappers/gateiofutures.js.map +1 -1
- package/dist/mappers/gemini.d.ts.map +1 -1
- package/dist/mappers/gemini.js +3 -0
- package/dist/mappers/gemini.js.map +1 -1
- package/dist/mappers/hitbtc.d.ts.map +1 -1
- package/dist/mappers/hitbtc.js +3 -0
- package/dist/mappers/hitbtc.js.map +1 -1
- package/dist/mappers/huobi.d.ts +2 -2
- package/dist/mappers/huobi.d.ts.map +1 -1
- package/dist/mappers/huobi.js +3 -1
- package/dist/mappers/huobi.js.map +1 -1
- package/dist/mappers/index.d.ts +3 -3
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +43 -23
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/kraken.d.ts.map +1 -1
- package/dist/mappers/kraken.js +3 -0
- package/dist/mappers/kraken.js.map +1 -1
- package/dist/mappers/okex.d.ts +245 -1
- package/dist/mappers/okex.d.ts.map +1 -1
- package/dist/mappers/okex.js +396 -1
- package/dist/mappers/okex.js.map +1 -1
- package/dist/mappers/poloniex.d.ts.map +1 -1
- package/dist/mappers/poloniex.js +3 -0
- package/dist/mappers/poloniex.js.map +1 -1
- package/dist/mappers/serum.d.ts +1 -1
- package/dist/mappers/serum.d.ts.map +1 -1
- package/dist/mappers/serum.js +12 -3
- package/dist/mappers/serum.js.map +1 -1
- package/dist/mappers/upbit.d.ts +1 -1
- package/dist/mappers/upbit.d.ts.map +1 -1
- package/dist/mappers/upbit.js +3 -0
- package/dist/mappers/upbit.js.map +1 -1
- package/dist/realtimefeeds/okex.d.ts +4 -2
- package/dist/realtimefeeds/okex.d.ts.map +1 -1
- package/dist/realtimefeeds/okex.js +38 -10
- package/dist/realtimefeeds/okex.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +2 -6
- package/dist/replay.js.map +1 -1
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +2 -6
- package/dist/stream.js.map +1 -1
- package/package.json +13 -13
- package/src/consts.ts +62 -4
- package/src/handy.ts +14 -0
- package/src/mappers/ascendex.ts +6 -1
- package/src/mappers/binance.ts +2 -9
- package/src/mappers/binancedex.ts +6 -1
- package/src/mappers/binanceoptions.ts +7 -1
- package/src/mappers/bitfinex.ts +10 -1
- package/src/mappers/bitflyer.ts +8 -2
- package/src/mappers/bitmex.ts +12 -2
- package/src/mappers/bitstamp.ts +1 -7
- package/src/mappers/bybit.ts +9 -0
- package/src/mappers/coinbase.ts +7 -1
- package/src/mappers/coinflex.ts +8 -1
- package/src/mappers/cryptofacilities.ts +12 -1
- package/src/mappers/delta.ts +8 -1
- package/src/mappers/deribit.ts +14 -2
- package/src/mappers/dydx.ts +8 -1
- package/src/mappers/ftx.ts +12 -2
- package/src/mappers/gateio.ts +5 -0
- package/src/mappers/gateiofutures.ts +8 -1
- package/src/mappers/gemini.ts +5 -0
- package/src/mappers/hitbtc.ts +5 -0
- package/src/mappers/huobi.ts +6 -2
- package/src/mappers/index.ts +77 -24
- package/src/mappers/kraken.ts +7 -1
- package/src/mappers/okex.ts +591 -2
- package/src/mappers/poloniex.ts +5 -0
- package/src/mappers/serum.ts +17 -5
- package/src/mappers/upbit.ts +6 -1
- package/src/realtimefeeds/okex.ts +42 -10
- package/src/replay.ts +2 -7
- package/src/stream.ts +3 -7
package/src/mappers/okex.ts
CHANGED
|
@@ -1,7 +1,584 @@
|
|
|
1
|
-
import { asNumberIfValid } from '../handy'
|
|
2
|
-
import { BookChange, DerivativeTicker, Exchange,
|
|
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`,
|
package/src/mappers/poloniex.ts
CHANGED
|
@@ -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',
|