tardis-dev
Advanced tools
Comparing version 8.0.5 to 9.0.0
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const handy_1 = require("./handy"); | ||
const NODE_MAJOR_VERSION = Number(process.versions.node.split('.')[0]); | ||
const DATE_MAX = new Date(8640000000000000); | ||
@@ -6,0 +5,0 @@ async function nextWithIndex(iterator, index) { |
@@ -23,2 +23,3 @@ import { Mapper } from './mappers'; | ||
export declare function batch(symbols: string[], batchSize: number): Generator<string[], void, unknown>; | ||
export declare function parseμs(dateString: string): number; | ||
//# sourceMappingURL=handy.d.ts.map |
@@ -148,2 +148,11 @@ "use strict"; | ||
exports.batch = batch; | ||
function parseμs(dateString) { | ||
// check if we have ISO 8601 format date string, e.g: 2019-06-01T00:03:03.1238784Z | ||
// or 2020-03-01T00:00:24.893456+00:00 | ||
if (dateString.length === 28 || dateString.length === 32) { | ||
return Number(dateString.slice(23, 26)); | ||
} | ||
return 0; | ||
} | ||
exports.parseμs = parseμs; | ||
//# sourceMappingURL=handy.js.map |
@@ -97,2 +97,3 @@ import { BookChange, DerivativeTicker, Exchange, FilterForExchange, Trade } from '../types'; | ||
r: string; | ||
T: number; | ||
}; | ||
@@ -99,0 +100,0 @@ declare type BinanceFuturesTickerData = { |
@@ -266,2 +266,3 @@ "use strict"; | ||
pendingTickerInfo.updateFundingRate(Number(message.data.r)); | ||
pendingTickerInfo.updateFundingTimestamp(new Date(message.data.T)); | ||
pendingTickerInfo.updateMarkPrice(Number(message.data.p)); | ||
@@ -268,0 +269,0 @@ pendingTickerInfo.updateTimestamp(new Date(message.data.E)); |
@@ -169,4 +169,8 @@ "use strict"; | ||
const openInterest = statusInfo[17]; | ||
const nextFundingTimestamp = statusInfo[7]; | ||
const predictedFundingRate = statusInfo[8]; | ||
const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(symbol, 'bitfinex-derivatives'); | ||
pendingTickerInfo.updateFundingRate(fundingRate); | ||
pendingTickerInfo.updateFundingTimestamp(nextFundingTimestamp !== undefined ? new Date(nextFundingTimestamp) : undefined); | ||
pendingTickerInfo.updatePredictedFundingRate(predictedFundingRate); | ||
pendingTickerInfo.updateIndexPrice(indexPrice); | ||
@@ -173,0 +177,0 @@ pendingTickerInfo.updateLastPrice(lastPrice); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const handy_1 = require("../handy"); | ||
exports.bitflyerTradesMapper = { | ||
@@ -18,2 +19,4 @@ canHandle(message) { | ||
for (const execution of bitflyerExecutions.params.message) { | ||
const timestamp = new Date(execution.exec_date); | ||
timestamp.μs = handy_1.parseμs(execution.exec_date); | ||
yield { | ||
@@ -27,3 +30,3 @@ type: 'trade', | ||
side: execution.side === 'BUY' ? 'buy' : execution.side === 'SELL' ? 'sell' : 'unknown', | ||
timestamp: new Date(execution.exec_date), | ||
timestamp, | ||
localTimestamp: localTimestamp | ||
@@ -30,0 +33,0 @@ }; |
@@ -33,2 +33,4 @@ import { BookChange, DerivativeTicker, FilterForExchange, Trade } from '../types'; | ||
indicativeSettlePrice?: number | null; | ||
indicativeFundingRate?: number | null; | ||
fundingTimestamp?: string | null; | ||
timestamp?: string; | ||
@@ -35,0 +37,0 @@ }; |
@@ -126,2 +126,4 @@ "use strict"; | ||
pendingTickerInfo.updateFundingRate(bitmexInstrument.fundingRate); | ||
pendingTickerInfo.updatePredictedFundingRate(bitmexInstrument.indicativeFundingRate); | ||
pendingTickerInfo.updateFundingTimestamp(bitmexInstrument.fundingTimestamp ? new Date(bitmexInstrument.fundingTimestamp) : undefined); | ||
pendingTickerInfo.updateIndexPrice(bitmexInstrument.indicativeSettlePrice); | ||
@@ -128,0 +130,0 @@ pendingTickerInfo.updateMarkPrice(bitmexInstrument.markPrice); |
@@ -42,2 +42,3 @@ import { BookChange, Trade } from '../types'; | ||
timestamp: string; | ||
microtimestamp?: string; | ||
bids: BitstampBookLevel[]; | ||
@@ -44,0 +45,0 @@ asks: BitstampBookLevel[]; |
@@ -23,2 +23,5 @@ "use strict"; | ||
const symbol = bitstampTradeResponse.channel.slice(bitstampTradeResponse.channel.lastIndexOf('_') + 1); | ||
const microtimestamp = Number(bitstampTrade.microtimestamp); | ||
const timestamp = new Date(microtimestamp / 1000); | ||
timestamp.μs = microtimestamp % 1000; | ||
yield { | ||
@@ -32,4 +35,4 @@ type: 'trade', | ||
side: bitstampTrade.type === 0 ? 'buy' : 'sell', | ||
timestamp: new Date(Number(bitstampTrade.microtimestamp) / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
}; | ||
@@ -69,2 +72,11 @@ } | ||
// produce snapshot book_change | ||
let timestamp; | ||
if (message.data.microtimestamp !== undefined) { | ||
const microtimestamp = Number(message.data.microtimestamp); | ||
timestamp = new Date(microtimestamp / 1000); | ||
timestamp.μs = microtimestamp % 1000; | ||
} | ||
else { | ||
timestamp = new Date(Number(message.data.timestamp) * 1000); | ||
} | ||
yield { | ||
@@ -77,3 +89,3 @@ type: 'book_change', | ||
asks: message.data.asks.map(this._mapBookLevel), | ||
timestamp: localTimestamp, | ||
timestamp, | ||
localTimestamp | ||
@@ -83,2 +95,5 @@ }; | ||
symbolDepthInfo.lastUpdateTimestamp = Number(message.data.timestamp); | ||
if (message.data.microtimestamp !== undefined) { | ||
symbolDepthInfo.lastUpdateMicroTimestamp = Number(message.data.microtimestamp); | ||
} | ||
symbolDepthInfo.snapshotProcessed = true; | ||
@@ -108,6 +123,14 @@ // if there were any depth updates buffered, let's proccess those | ||
_mapBookDepthUpdate(bitstampBookUpdate, localTimestamp, depthInfo, symbol) { | ||
const microtimestamp = Number(bitstampBookUpdate.data.microtimestamp); | ||
// skip all book updates that preceed book snapshot | ||
if (Number(bitstampBookUpdate.data.timestamp) < depthInfo.lastUpdateTimestamp) { | ||
// REST API not always returned microtimestamps for initial order book snapshots | ||
// fallback to timestamp | ||
if (depthInfo.lastUpdateMicroTimestamp !== undefined && microtimestamp < depthInfo.lastUpdateMicroTimestamp) { | ||
return; | ||
} | ||
else if (Number(bitstampBookUpdate.data.timestamp) < depthInfo.lastUpdateTimestamp) { | ||
return; | ||
} | ||
const timestamp = new Date(microtimestamp / 1000); | ||
timestamp.μs = microtimestamp % 1000; | ||
return { | ||
@@ -120,4 +143,4 @@ type: 'book_change', | ||
asks: bitstampBookUpdate.data.asks.map(this._mapBookLevel), | ||
timestamp: new Date(Number(bitstampBookUpdate.data.microtimestamp) / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp: timestamp, | ||
localTimestamp | ||
}; | ||
@@ -124,0 +147,0 @@ } |
@@ -58,2 +58,3 @@ import { BookChange, DerivativeTicker, Exchange, Trade } from '../types'; | ||
timestamp: string; | ||
trade_time_ms?: number; | ||
symbol: string; | ||
@@ -91,2 +92,4 @@ side: 'Buy' | 'Sell'; | ||
funding_rate_e6?: number; | ||
predicted_funding_rate_e6?: number; | ||
next_funding_time?: string; | ||
last_price_e4?: number; | ||
@@ -93,0 +96,0 @@ updated_at: string; |
@@ -25,2 +25,3 @@ "use strict"; | ||
for (const trade of message.data) { | ||
const timestamp = trade.trade_time_ms !== undefined ? new Date(trade.trade_time_ms) : new Date(trade.timestamp); | ||
yield { | ||
@@ -34,4 +35,4 @@ type: 'trade', | ||
side: trade.side == 'Buy' ? 'buy' : trade.side === 'Sell' ? 'sell' : 'unknown', | ||
timestamp: new Date(trade.timestamp), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
}; | ||
@@ -85,2 +86,4 @@ } | ||
const data = message.type === 'snapshot' ? message.data : [...message.data.delete, ...message.data.update, ...message.data.insert]; | ||
const timestamp = new Date(message.timestamp_e6 / 1000); | ||
timestamp.μs = message.timestamp_e6 % 1000; | ||
yield { | ||
@@ -93,4 +96,4 @@ type: 'book_change', | ||
asks: data.filter(d => d.side === 'Sell').map(this._mapBookLevel), | ||
timestamp: new Date(message.timestamp_e6 / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
}; | ||
@@ -125,2 +128,4 @@ } | ||
pendingTickerInfo.updateFundingRate(instrumentInfo.funding_rate_e6 !== undefined ? instrumentInfo.funding_rate_e6 / 1000000 : undefined); | ||
pendingTickerInfo.updatePredictedFundingRate(instrumentInfo.predicted_funding_rate_e6 !== undefined ? instrumentInfo.predicted_funding_rate_e6 / 1000000 : undefined); | ||
pendingTickerInfo.updateFundingTimestamp(instrumentInfo.next_funding_time !== undefined ? new Date(instrumentInfo.next_funding_time) : undefined); | ||
pendingTickerInfo.updateIndexPrice(instrumentInfo.index_price_e4 !== undefined ? instrumentInfo.index_price_e4 / 10000 : undefined); | ||
@@ -127,0 +132,0 @@ pendingTickerInfo.updateMarkPrice(instrumentInfo.mark_price_e4 !== undefined ? instrumentInfo.mark_price_e4 / 10000 : undefined); |
@@ -33,2 +33,4 @@ import { BookChange, DerivativeTicker, Trade } from '../types'; | ||
funding_rate: number | undefined; | ||
funding_rate_prediction: number | undefined; | ||
next_funding_rate_time: number | undefined; | ||
time: number; | ||
@@ -35,0 +37,0 @@ }; |
@@ -102,2 +102,4 @@ "use strict"; | ||
pendingTickerInfo.updateFundingRate(ticker.funding_rate); | ||
pendingTickerInfo.updatePredictedFundingRate(ticker.funding_rate_prediction); | ||
pendingTickerInfo.updateFundingTimestamp(ticker.next_funding_rate_time !== undefined ? new Date(ticker.next_funding_rate_time) : undefined); | ||
pendingTickerInfo.updateIndexPrice(ticker.index); | ||
@@ -104,0 +106,0 @@ pendingTickerInfo.updateMarkPrice(ticker.markPrice); |
@@ -96,3 +96,4 @@ "use strict"; | ||
const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(deribitTicker.instrument_name, 'deribit'); | ||
pendingTickerInfo.updateFundingRate(deribitTicker.funding_8h); | ||
pendingTickerInfo.updateFundingRate(deribitTicker.current_funding); | ||
pendingTickerInfo.updatePredictedFundingRate(deribitTicker.funding_8h); | ||
pendingTickerInfo.updateIndexPrice(deribitTicker.index_price); | ||
@@ -99,0 +100,0 @@ pendingTickerInfo.updateMarkPrice(deribitTicker.mark_price); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const handy_1 = require("../handy"); | ||
// https://docs.ftx.com/#websocket-api | ||
@@ -21,2 +22,4 @@ exports.ftxTradesMapper = { | ||
for (const ftxTrade of ftxTrades.data) { | ||
const timestamp = new Date(ftxTrade.time); | ||
timestamp.μs = handy_1.parseμs(ftxTrade.time); | ||
yield { | ||
@@ -30,4 +33,4 @@ type: 'trade', | ||
side: ftxTrade.side, | ||
timestamp: new Date(ftxTrade.time), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
}; | ||
@@ -58,2 +61,4 @@ } | ||
*map(ftxOrderBook, localTimestamp) { | ||
const timestamp = new Date(ftxOrderBook.data.time * 1000); | ||
timestamp.μs = Math.floor(ftxOrderBook.data.time * 1000000) % 1000; | ||
yield { | ||
@@ -66,3 +71,3 @@ type: 'book_change', | ||
asks: ftxOrderBook.data.asks.map(exports.mapBookLevel), | ||
timestamp: new Date(Math.floor(ftxOrderBook.data.time * 1000)), | ||
timestamp, | ||
localTimestamp | ||
@@ -69,0 +74,0 @@ }; |
@@ -23,2 +23,5 @@ "use strict"; | ||
for (const [price, amount, time, side] of trades) { | ||
const timeExchange = Number(time); | ||
const timestamp = new Date(timeExchange * 1000); | ||
timestamp.μs = Math.floor(timeExchange * 1000000) % 1000; | ||
yield { | ||
@@ -32,4 +35,4 @@ type: 'trade', | ||
side: side === 'b' ? 'buy' : 'sell', | ||
timestamp: new Date(Number(time) * 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
}; | ||
@@ -36,0 +39,0 @@ } |
@@ -19,2 +19,4 @@ import { DerivativeTicker, Exchange, FilterForExchange, NormalizedData } from '../types'; | ||
updateFundingRate(fundingRate: number | undefined | null): void; | ||
updatePredictedFundingRate(predictedFundingRate: number | undefined | null): void; | ||
updateFundingTimestamp(fundingTimestamp: Date | undefined | null): void; | ||
updateIndexPrice(indexPrice: number | undefined | null): void; | ||
@@ -21,0 +23,0 @@ updateLastPrice(lastPrice: number | undefined | null): void; |
@@ -27,2 +27,4 @@ "use strict"; | ||
fundingRate: undefined, | ||
fundingTimestamp: undefined, | ||
predictedFundingRate: undefined, | ||
indexPrice: undefined, | ||
@@ -62,2 +64,20 @@ markPrice: undefined, | ||
} | ||
updatePredictedFundingRate(predictedFundingRate) { | ||
if (isNullOrUndefined(predictedFundingRate)) { | ||
return; | ||
} | ||
if (this._pendingTicker.predictedFundingRate !== predictedFundingRate) { | ||
this._pendingTicker.predictedFundingRate = predictedFundingRate; | ||
this._hasChanged = true; | ||
} | ||
} | ||
updateFundingTimestamp(fundingTimestamp) { | ||
if (isNullOrUndefined(fundingTimestamp)) { | ||
return; | ||
} | ||
if (this._pendingTicker.fundingTimestamp !== fundingTimestamp) { | ||
this._pendingTicker.fundingTimestamp = fundingTimestamp; | ||
this._hasChanged = true; | ||
} | ||
} | ||
updateIndexPrice(indexPrice) { | ||
@@ -64,0 +84,0 @@ if (isNullOrUndefined(indexPrice)) { |
@@ -66,2 +66,4 @@ import { BookChange, DerivativeTicker, Exchange, FilterForExchange, Trade } from '../types'; | ||
funding_rate: string; | ||
funding_time: string; | ||
estimated_rate: string; | ||
instrument_id: string; | ||
@@ -68,0 +70,0 @@ timestamp: undefined; |
@@ -126,2 +126,4 @@ "use strict"; | ||
pendingTickerInfo.updateFundingRate(Number(okexMessage.funding_rate)); | ||
pendingTickerInfo.updatePredictedFundingRate(Number(okexMessage.estimated_rate)); | ||
pendingTickerInfo.updateFundingTimestamp(new Date(okexMessage.funding_time)); | ||
} | ||
@@ -128,0 +130,0 @@ if ('mark_price' in okexMessage) { |
/// <reference types="node" /> | ||
import { MapperFactory } from './mappers'; | ||
import { Disconnect, Exchange, FilterForExchange } from './types'; | ||
export declare function replay<T extends Exchange, U extends boolean = false, Z extends boolean = false>({ exchange, from, to, filters, skipDecoding, withDisconnects, apiKey }: ReplayOptions<T, U, Z>): AsyncIterableIterator<Z extends true ? U extends true ? { | ||
export declare function replay<T extends Exchange, U extends boolean = false, Z extends boolean = false>({ exchange, from, to, filters, skipDecoding, withDisconnects, apiKey, withMicroseconds }: ReplayOptions<T, U, Z>): AsyncIterableIterator<Z extends true ? U extends true ? { | ||
localTimestamp: Buffer; | ||
@@ -26,2 +26,3 @@ message: Buffer; | ||
readonly apiKey?: string; | ||
readonly withMicroseconds?: boolean; | ||
}; | ||
@@ -28,0 +29,0 @@ export declare type ReplayNormalizedOptions<T extends Exchange, U extends boolean = false> = { |
@@ -16,3 +16,3 @@ "use strict"; | ||
const options_1 = require("./options"); | ||
async function* replay({ exchange, from, to, filters, skipDecoding = undefined, withDisconnects = undefined, apiKey = undefined }) { | ||
async function* replay({ exchange, from, to, filters, skipDecoding = undefined, withDisconnects = undefined, apiKey = undefined, withMicroseconds = undefined }) { | ||
validateReplayOptions(exchange, from, to, filters); | ||
@@ -96,6 +96,14 @@ const fromDate = handy_1.parseAsUTCDate(from); | ||
else { | ||
const message = JSON.parse(messageBuffer); | ||
const localTimestampString = localTimestampBuffer.toString(); | ||
const localTimestamp = new Date(localTimestampString); | ||
if (withMicroseconds) { | ||
// provide additionally fractions of millisecond at microsecond resolution | ||
// local timestamp always has format like this 2019-06-01T00:03:03.1238784Z | ||
localTimestamp.μs = handy_1.parseμs(localTimestampString); | ||
} | ||
yield { | ||
// when skipDecoding is not set, decode timestamp to Date and message to object | ||
localTimestamp: new Date(localTimestampBuffer.toString()), | ||
message: JSON.parse(messageBuffer) | ||
localTimestamp, | ||
message | ||
}; | ||
@@ -142,3 +150,4 @@ } | ||
filters, | ||
apiKey | ||
apiKey, | ||
withMicroseconds: true | ||
}); | ||
@@ -145,0 +154,0 @@ // filter normalized messages by symbol as some exchanges do not provide server side filtering so we could end up with messages |
@@ -53,2 +53,4 @@ import { EXCHANGES, EXCHANGE_CHANNELS_INFO } from './consts'; | ||
readonly fundingRate: number | undefined; | ||
readonly fundingTimestamp: Date | undefined; | ||
readonly predictedFundingRate: number | undefined; | ||
readonly indexPrice: number | undefined; | ||
@@ -97,2 +99,7 @@ readonly markPrice: number | undefined; | ||
}; | ||
declare global { | ||
interface Date { | ||
μs?: number; | ||
} | ||
} | ||
//# sourceMappingURL=types.d.ts.map |
{ | ||
"name": "tardis-dev", | ||
"version": "8.0.5", | ||
"version": "9.0.0", | ||
"engines": { | ||
@@ -54,12 +54,12 @@ "node": ">=12" | ||
"debug": "^4.1.1", | ||
"fs-extra": "^8.1.0", | ||
"got": "^10.6.0", | ||
"p-map": "^3.0.0", | ||
"ws": "^7.2.1" | ||
"fs-extra": "^9.0.0", | ||
"got": "^10.7.0", | ||
"p-map": "^4.0.0", | ||
"ws": "^7.2.3" | ||
}, | ||
"devDependencies": { | ||
"@types/ws": "^7.2.2", | ||
"@types/ws": "^7.2.3", | ||
"@types/debug": "^4.1.5", | ||
"@types/fs-extra": "^8.1.0", | ||
"@types/jest": "^25.1.3", | ||
"@types/jest": "^25.1.4", | ||
"@types/node": "^13.7.7", | ||
@@ -69,4 +69,4 @@ "cross-var": "^1.1.0", | ||
"jest": "^25.1.0", | ||
"lint-staged": "^10.0.8", | ||
"prettier": "^1.19.1", | ||
"lint-staged": "^10.0.9", | ||
"prettier": "^2.0.2", | ||
"source-map-support": "^0.5.16", | ||
@@ -73,0 +73,0 @@ "ts-jest": "^25.2.1", |
@@ -10,4 +10,2 @@ import { ONE_SEC_IN_MS } from './handy' | ||
const NODE_MAJOR_VERSION = Number(process.versions.node.split('.')[0]) | ||
const DATE_MAX = new Date(8640000000000000) | ||
@@ -14,0 +12,0 @@ |
@@ -164,1 +164,11 @@ import { createHash } from 'crypto' | ||
} | ||
export function parseμs(dateString: string): number { | ||
// check if we have ISO 8601 format date string, e.g: 2019-06-01T00:03:03.1238784Z | ||
// or 2020-03-01T00:00:24.893456+00:00 | ||
if (dateString.length === 28 || dateString.length === 32) { | ||
return Number(dateString.slice(23, 26)) | ||
} | ||
return 0 | ||
} |
@@ -305,5 +305,7 @@ import { BookChange, DerivativeTicker, Exchange, FilterForExchange, Trade } from '../types' | ||
pendingTickerInfo.updateFundingRate(Number(message.data.r)) | ||
pendingTickerInfo.updateFundingTimestamp(new Date(message.data.T)) | ||
pendingTickerInfo.updateMarkPrice(Number(message.data.p)) | ||
pendingTickerInfo.updateTimestamp(new Date(message.data.E)) | ||
} | ||
if ('c' in message.data) { | ||
@@ -375,2 +377,3 @@ pendingTickerInfo.updateLastPrice(Number(message.data.c)) | ||
r: string // Funding rate | ||
T: number // Next funding time | ||
} | ||
@@ -377,0 +380,0 @@ |
@@ -199,2 +199,4 @@ import { BookChange, DerivativeTicker, Exchange, FilterForExchange, Trade } from '../types' | ||
const openInterest = statusInfo[17] | ||
const nextFundingTimestamp = statusInfo[7] | ||
const predictedFundingRate = statusInfo[8] | ||
@@ -204,2 +206,5 @@ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(symbol, 'bitfinex-derivatives') | ||
pendingTickerInfo.updateFundingRate(fundingRate) | ||
pendingTickerInfo.updateFundingTimestamp(nextFundingTimestamp !== undefined ? new Date(nextFundingTimestamp) : undefined) | ||
pendingTickerInfo.updatePredictedFundingRate(predictedFundingRate) | ||
pendingTickerInfo.updateIndexPrice(indexPrice) | ||
@@ -209,2 +214,3 @@ pendingTickerInfo.updateLastPrice(lastPrice) | ||
pendingTickerInfo.updateOpenInterest(openInterest) | ||
pendingTickerInfo.updateTimestamp(new Date(message[3])) | ||
@@ -211,0 +217,0 @@ |
import { BookChange, Trade } from '../types' | ||
import { Mapper } from './mapper' | ||
import { parseμs } from '../handy' | ||
@@ -22,2 +23,5 @@ export const bitflyerTradesMapper: Mapper<'bitflyer', Trade> = { | ||
for (const execution of bitflyerExecutions.params.message) { | ||
const timestamp = new Date(execution.exec_date) | ||
timestamp.μs = parseμs(execution.exec_date) | ||
yield { | ||
@@ -31,3 +35,3 @@ type: 'trade', | ||
side: execution.side === 'BUY' ? 'buy' : execution.side === 'SELL' ? 'sell' : 'unknown', | ||
timestamp: new Date(execution.exec_date), | ||
timestamp, | ||
localTimestamp: localTimestamp | ||
@@ -34,0 +38,0 @@ } |
@@ -141,2 +141,4 @@ import { BookChange, BookPriceLevel, DerivativeTicker, FilterForExchange, Trade } from '../types' | ||
pendingTickerInfo.updateFundingRate(bitmexInstrument.fundingRate) | ||
pendingTickerInfo.updatePredictedFundingRate(bitmexInstrument.indicativeFundingRate) | ||
pendingTickerInfo.updateFundingTimestamp(bitmexInstrument.fundingTimestamp ? new Date(bitmexInstrument.fundingTimestamp) : undefined) | ||
pendingTickerInfo.updateIndexPrice(bitmexInstrument.indicativeSettlePrice) | ||
@@ -176,2 +178,4 @@ pendingTickerInfo.updateMarkPrice(bitmexInstrument.markPrice) | ||
indicativeSettlePrice?: number | null | ||
indicativeFundingRate?: number | null | ||
fundingTimestamp?: string | null | ||
timestamp?: string | ||
@@ -178,0 +182,0 @@ } |
@@ -29,2 +29,6 @@ import { BookChange, Trade } from '../types' | ||
const symbol = bitstampTradeResponse.channel.slice(bitstampTradeResponse.channel.lastIndexOf('_') + 1) | ||
const microtimestamp = Number(bitstampTrade.microtimestamp) | ||
const timestamp = new Date(microtimestamp / 1000) | ||
timestamp.μs = microtimestamp % 1000 | ||
yield { | ||
@@ -38,4 +42,4 @@ type: 'trade', | ||
side: bitstampTrade.type === 0 ? 'buy' : 'sell', | ||
timestamp: new Date(Number(bitstampTrade.microtimestamp) / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
} | ||
@@ -82,2 +86,12 @@ } | ||
// produce snapshot book_change | ||
let timestamp | ||
if (message.data.microtimestamp !== undefined) { | ||
const microtimestamp = Number(message.data.microtimestamp) | ||
timestamp = new Date(microtimestamp / 1000) | ||
timestamp.μs = microtimestamp % 1000 | ||
} else { | ||
timestamp = new Date(Number(message.data.timestamp) * 1000) | ||
} | ||
yield { | ||
@@ -90,3 +104,3 @@ type: 'book_change', | ||
asks: message.data.asks.map(this._mapBookLevel), | ||
timestamp: localTimestamp, | ||
timestamp, | ||
localTimestamp | ||
@@ -97,2 +111,5 @@ } | ||
symbolDepthInfo.lastUpdateTimestamp = Number(message.data.timestamp) | ||
if (message.data.microtimestamp !== undefined) { | ||
symbolDepthInfo.lastUpdateMicroTimestamp = Number(message.data.microtimestamp) | ||
} | ||
symbolDepthInfo.snapshotProcessed = true | ||
@@ -127,7 +144,15 @@ | ||
): BookChange | undefined { | ||
const microtimestamp = Number(bitstampBookUpdate.data.microtimestamp) | ||
// skip all book updates that preceed book snapshot | ||
if (Number(bitstampBookUpdate.data.timestamp) < depthInfo.lastUpdateTimestamp!) { | ||
// REST API not always returned microtimestamps for initial order book snapshots | ||
// fallback to timestamp | ||
if (depthInfo.lastUpdateMicroTimestamp !== undefined && microtimestamp < depthInfo.lastUpdateMicroTimestamp) { | ||
return | ||
} else if (Number(bitstampBookUpdate.data.timestamp) < depthInfo.lastUpdateTimestamp!) { | ||
return | ||
} | ||
const timestamp = new Date(microtimestamp / 1000) | ||
timestamp.μs = microtimestamp % 1000 | ||
return { | ||
@@ -138,7 +163,6 @@ type: 'book_change', | ||
isSnapshot: false, | ||
bids: bitstampBookUpdate.data.bids.map(this._mapBookLevel), | ||
asks: bitstampBookUpdate.data.asks.map(this._mapBookLevel), | ||
timestamp: new Date(Number(bitstampBookUpdate.data.microtimestamp) / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp: timestamp, | ||
localTimestamp | ||
} | ||
@@ -190,2 +214,3 @@ } | ||
timestamp: string | ||
microtimestamp?: string | ||
bids: BitstampBookLevel[] | ||
@@ -200,2 +225,3 @@ asks: BitstampBookLevel[] | ||
lastUpdateTimestamp?: number | ||
lastUpdateMicroTimestamp?: number | ||
} |
@@ -27,2 +27,4 @@ import { BookChange, DerivativeTicker, Exchange, Trade } from '../types' | ||
for (const trade of message.data) { | ||
const timestamp = trade.trade_time_ms !== undefined ? new Date(trade.trade_time_ms) : new Date(trade.timestamp) | ||
yield { | ||
@@ -36,4 +38,4 @@ type: 'trade', | ||
side: trade.side == 'Buy' ? 'buy' : trade.side === 'Sell' ? 'sell' : 'unknown', | ||
timestamp: new Date(trade.timestamp), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
} | ||
@@ -89,2 +91,4 @@ } | ||
const data = message.type === 'snapshot' ? message.data : [...message.data.delete, ...message.data.update, ...message.data.insert] | ||
const timestamp = new Date(message.timestamp_e6 / 1000) | ||
timestamp.μs = message.timestamp_e6 % 1000 | ||
@@ -98,4 +102,4 @@ yield { | ||
asks: data.filter(d => d.side === 'Sell').map(this._mapBookLevel), | ||
timestamp: new Date(message.timestamp_e6 / 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
} as const | ||
@@ -135,2 +139,8 @@ } | ||
pendingTickerInfo.updateFundingRate(instrumentInfo.funding_rate_e6 !== undefined ? instrumentInfo.funding_rate_e6 / 1000000 : undefined) | ||
pendingTickerInfo.updatePredictedFundingRate( | ||
instrumentInfo.predicted_funding_rate_e6 !== undefined ? instrumentInfo.predicted_funding_rate_e6 / 1000000 : undefined | ||
) | ||
pendingTickerInfo.updateFundingTimestamp( | ||
instrumentInfo.next_funding_time !== undefined ? new Date(instrumentInfo.next_funding_time) : undefined | ||
) | ||
pendingTickerInfo.updateIndexPrice(instrumentInfo.index_price_e4 !== undefined ? instrumentInfo.index_price_e4 / 10000 : undefined) | ||
@@ -155,2 +165,3 @@ pendingTickerInfo.updateMarkPrice(instrumentInfo.mark_price_e4 !== undefined ? instrumentInfo.mark_price_e4 / 10000 : undefined) | ||
timestamp: string | ||
trade_time_ms?: number | ||
symbol: string | ||
@@ -192,2 +203,4 @@ side: 'Buy' | 'Sell' | ||
funding_rate_e6?: number | ||
predicted_funding_rate_e6?: number | ||
next_funding_time?: string | ||
last_price_e4?: number | ||
@@ -194,0 +207,0 @@ updated_at: string |
@@ -111,2 +111,6 @@ import { BookChange, DerivativeTicker, Trade } from '../types' | ||
pendingTickerInfo.updateFundingRate(ticker.funding_rate) | ||
pendingTickerInfo.updatePredictedFundingRate(ticker.funding_rate_prediction) | ||
pendingTickerInfo.updateFundingTimestamp( | ||
ticker.next_funding_rate_time !== undefined ? new Date(ticker.next_funding_rate_time) : undefined | ||
) | ||
pendingTickerInfo.updateIndexPrice(ticker.index) | ||
@@ -144,2 +148,4 @@ pendingTickerInfo.updateMarkPrice(ticker.markPrice) | ||
funding_rate: number | undefined | ||
funding_rate_prediction: number | undefined | ||
next_funding_rate_time: number | undefined | ||
time: number | ||
@@ -146,0 +152,0 @@ } |
@@ -111,3 +111,4 @@ import { BookChange, DerivativeTicker, Trade } from '../types' | ||
pendingTickerInfo.updateFundingRate(deribitTicker.funding_8h) | ||
pendingTickerInfo.updateFundingRate(deribitTicker.current_funding) | ||
pendingTickerInfo.updatePredictedFundingRate(deribitTicker.funding_8h) | ||
pendingTickerInfo.updateIndexPrice(deribitTicker.index_price) | ||
@@ -114,0 +115,0 @@ pendingTickerInfo.updateMarkPrice(deribitTicker.mark_price) |
import { BookChange, Trade } from '../types' | ||
import { Mapper } from './mapper' | ||
import { parseμs } from '../handy' | ||
@@ -26,2 +27,5 @@ // https://docs.ftx.com/#websocket-api | ||
for (const ftxTrade of ftxTrades.data) { | ||
const timestamp = new Date(ftxTrade.time) | ||
timestamp.μs = parseμs(ftxTrade.time) | ||
yield { | ||
@@ -35,4 +39,4 @@ type: 'trade', | ||
side: ftxTrade.side, | ||
timestamp: new Date(ftxTrade.time), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
} | ||
@@ -69,2 +73,5 @@ } | ||
*map(ftxOrderBook: FtxOrderBook, localTimestamp: Date): IterableIterator<BookChange> { | ||
const timestamp = new Date(ftxOrderBook.data.time * 1000) | ||
timestamp.μs = Math.floor(ftxOrderBook.data.time * 1000000) % 1000 | ||
yield { | ||
@@ -77,3 +84,3 @@ type: 'book_change', | ||
asks: ftxOrderBook.data.asks.map(mapBookLevel), | ||
timestamp: new Date(Math.floor(ftxOrderBook.data.time * 1000)), | ||
timestamp, | ||
localTimestamp | ||
@@ -80,0 +87,0 @@ } |
@@ -29,2 +29,6 @@ import { BookChange, Trade } from '../types' | ||
for (const [price, amount, time, side] of trades) { | ||
const timeExchange = Number(time) | ||
const timestamp = new Date(timeExchange * 1000) | ||
timestamp.μs = Math.floor(timeExchange * 1000000) % 1000 | ||
yield { | ||
@@ -38,4 +42,4 @@ type: 'trade', | ||
side: side === 'b' ? 'buy' : 'sell', | ||
timestamp: new Date(Number(time) * 1000), | ||
localTimestamp: localTimestamp | ||
timestamp, | ||
localTimestamp | ||
} | ||
@@ -42,0 +46,0 @@ } |
@@ -15,3 +15,3 @@ import { DerivativeTicker, Exchange, FilterForExchange, NormalizedData } from '../types' | ||
const isNullOrUndefined = (input: number | undefined | null): input is null | undefined => input === undefined || input === null | ||
const isNullOrUndefined = (input: number | Date | undefined | null): input is null | undefined => input === undefined || input === null | ||
@@ -44,2 +44,4 @@ export class PendingTickerInfoHelper { | ||
fundingRate: undefined, | ||
fundingTimestamp: undefined, | ||
predictedFundingRate: undefined, | ||
indexPrice: undefined, | ||
@@ -87,2 +89,24 @@ markPrice: undefined, | ||
public updatePredictedFundingRate(predictedFundingRate: number | undefined | null) { | ||
if (isNullOrUndefined(predictedFundingRate)) { | ||
return | ||
} | ||
if (this._pendingTicker.predictedFundingRate !== predictedFundingRate) { | ||
this._pendingTicker.predictedFundingRate = predictedFundingRate | ||
this._hasChanged = true | ||
} | ||
} | ||
public updateFundingTimestamp(fundingTimestamp: Date | undefined | null) { | ||
if (isNullOrUndefined(fundingTimestamp)) { | ||
return | ||
} | ||
if (this._pendingTicker.fundingTimestamp !== fundingTimestamp) { | ||
this._pendingTicker.fundingTimestamp = fundingTimestamp | ||
this._hasChanged = true | ||
} | ||
} | ||
public updateIndexPrice(indexPrice: number | undefined | null) { | ||
@@ -89,0 +113,0 @@ if (isNullOrUndefined(indexPrice)) { |
@@ -141,2 +141,4 @@ import { BookChange, DerivativeTicker, Exchange, FilterForExchange, Trade } from '../types' | ||
pendingTickerInfo.updateFundingRate(Number(okexMessage.funding_rate)) | ||
pendingTickerInfo.updatePredictedFundingRate(Number(okexMessage.estimated_rate)) | ||
pendingTickerInfo.updateFundingTimestamp(new Date(okexMessage.funding_time)) | ||
} | ||
@@ -195,2 +197,4 @@ | ||
funding_rate: string | ||
funding_time: string | ||
estimated_rate: string | ||
instrument_id: string | ||
@@ -197,0 +201,0 @@ timestamp: undefined |
@@ -8,3 +8,3 @@ import { createReadStream } from 'fs-extra' | ||
import { debug } from './debug' | ||
import { getFilters, normalizeMessages, parseAsUTCDate, wait } from './handy' | ||
import { getFilters, normalizeMessages, parseAsUTCDate, wait, parseμs } from './handy' | ||
import { MapperFactory, normalizeBookChanges } from './mappers' | ||
@@ -22,3 +22,4 @@ import { getOptions } from './options' | ||
withDisconnects = undefined, | ||
apiKey = undefined | ||
apiKey = undefined, | ||
withMicroseconds = undefined | ||
}: ReplayOptions<T, U, Z>): AsyncIterableIterator< | ||
@@ -127,6 +128,15 @@ Z extends true | ||
} else { | ||
const message = JSON.parse(messageBuffer as any) | ||
const localTimestampString = localTimestampBuffer.toString() | ||
const localTimestamp = new Date(localTimestampString) | ||
if (withMicroseconds) { | ||
// provide additionally fractions of millisecond at microsecond resolution | ||
// local timestamp always has format like this 2019-06-01T00:03:03.1238784Z | ||
localTimestamp.μs = parseμs(localTimestampString) | ||
} | ||
yield { | ||
// when skipDecoding is not set, decode timestamp to Date and message to object | ||
localTimestamp: new Date(localTimestampBuffer.toString()), | ||
message: JSON.parse(messageBuffer as any) | ||
localTimestamp, | ||
message | ||
} as any | ||
@@ -195,3 +205,4 @@ } | ||
filters, | ||
apiKey | ||
apiKey, | ||
withMicroseconds: true | ||
}) | ||
@@ -263,2 +274,3 @@ | ||
readonly apiKey?: string | ||
readonly withMicroseconds?: boolean | ||
} | ||
@@ -265,0 +277,0 @@ |
@@ -59,2 +59,4 @@ import { EXCHANGES, EXCHANGE_CHANNELS_INFO } from './consts' | ||
readonly fundingRate: number | undefined | ||
readonly fundingTimestamp: Date | undefined | ||
readonly predictedFundingRate: number | undefined | ||
readonly indexPrice: number | undefined | ||
@@ -110,1 +112,7 @@ readonly markPrice: number | undefined | ||
} | ||
declare global { | ||
interface Date { | ||
μs?: number | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
620020
10871
291
+ Addedat-least-node@1.0.0(transitive)
+ Addedfs-extra@9.1.0(transitive)
+ Addedjsonfile@6.1.0(transitive)
+ Addedp-map@4.0.0(transitive)
+ Addeduniversalify@2.0.1(transitive)
- Removedfs-extra@8.1.0(transitive)
- Removedjsonfile@4.0.0(transitive)
- Removedp-map@3.0.0(transitive)
- Removeduniversalify@0.1.2(transitive)
Updatedfs-extra@^9.0.0
Updatedgot@^10.7.0
Updatedp-map@^4.0.0
Updatedws@^7.2.3