tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
191 lines (163 loc) • 4.83 kB
text/typescript
import { parseμs, upperCaseSymbols } from '../handy'
import { BookChange, BookTicker, Trade } from '../types'
import { Mapper } from './mapper'
export const bitflyerTradesMapper: Mapper<'bitflyer', Trade> = {
canHandle(message: BitflyerExecutions | BitflyerBoard) {
return message.params.channel.startsWith('lightning_executions')
},
getFilters(symbols?: string[]) {
symbols = upperCaseSymbols(symbols)
return [
{
channel: 'lightning_executions',
symbols
}
]
},
*map(bitflyerExecutions: BitflyerExecutions, localTimestamp: Date) {
const symbol = bitflyerExecutions.params.channel.replace('lightning_executions_', '')
for (const execution of bitflyerExecutions.params.message) {
const timestamp = new Date(execution.exec_date)
timestamp.μs = parseμs(execution.exec_date)
const trade: Trade = {
type: 'trade',
symbol,
exchange: 'bitflyer',
id: String(execution.id),
price: execution.price,
amount: execution.size,
side: execution.side === 'BUY' ? 'buy' : execution.side === 'SELL' ? 'sell' : 'unknown',
timestamp,
localTimestamp: localTimestamp
}
yield trade
}
}
}
const mapBookLevel = ({ price, size }: BitflyerBookLevel) => {
return { price, amount: size }
}
export class BitflyerBookChangeMapper implements Mapper<'bitflyer', BookChange> {
private readonly _snapshotsInfo: Map<string, boolean> = new Map()
canHandle(message: BitflyerExecutions | BitflyerBoard) {
return message.params.channel.startsWith('lightning_board')
}
getFilters(symbols?: string[]) {
symbols = upperCaseSymbols(symbols)
return [
{
channel: 'lightning_board_snapshot',
symbols
} as const,
{
channel: 'lightning_board',
symbols
} as const
]
}
*map(bitflyerBoard: BitflyerBoard, localTimestamp: Date): IterableIterator<BookChange> {
const channel = bitflyerBoard.params.channel
const isSnapshot = channel.startsWith('lightning_board_snapshot_')
const symbol = isSnapshot ? channel.replace('lightning_board_snapshot_', '') : channel.replace('lightning_board_', '')
if (this._snapshotsInfo.has(symbol) === false) {
if (isSnapshot) {
this._snapshotsInfo.set(symbol, true)
} else {
// skip change messages until we've received book snapshot
return
}
}
yield {
type: 'book_change',
symbol,
exchange: 'bitflyer',
isSnapshot,
bids: bitflyerBoard.params.message.bids.map(mapBookLevel),
asks: bitflyerBoard.params.message.asks.map(mapBookLevel),
timestamp: localTimestamp,
localTimestamp
}
}
}
export const bitflyerBookTickerMapper: Mapper<'bitflyer', BookTicker> = {
canHandle(message: BitflyerTicker) {
return message.params.channel.startsWith('lightning_ticker')
},
getFilters(symbols?: string[]) {
symbols = upperCaseSymbols(symbols)
return [
{
channel: 'lightning_ticker',
symbols
}
]
},
*map(bitflyerTickerMessage: BitflyerTicker, localTimestamp: Date) {
const symbol = bitflyerTickerMessage.params.channel.replace('lightning_ticker_', '')
const bitflyerTicker = bitflyerTickerMessage.params.message
const timestamp = new Date(bitflyerTicker.timestamp)
timestamp.μs = parseμs(bitflyerTicker.timestamp)
const ticker: BookTicker = {
type: 'book_ticker',
symbol,
exchange: 'bitflyer',
askAmount: bitflyerTicker.best_ask_size,
askPrice: bitflyerTicker.best_ask,
bidPrice: bitflyerTicker.best_bid,
bidAmount: bitflyerTicker.best_bid_size,
timestamp,
localTimestamp: localTimestamp
}
yield ticker
}
}
type BitflyerExecutions = {
method: 'channelMessage'
params: {
channel: string
message: {
id: number
side: 'SELL' | 'BUY'
price: number
size: number
exec_date: string
}[]
}
}
type BitflyerBookLevel = {
price: number
size: number
}
type BitflyerBoard = {
method: 'channelMessage'
params: {
channel: string
message: {
bids: BitflyerBookLevel[]
asks: BitflyerBookLevel[]
}
}
}
type BitflyerTicker = {
method: 'channelMessage'
params: {
channel: 'lightning_ticker_ETH_JPY'
message: {
product_code: 'ETH_JPY'
state: 'RUNNING'
timestamp: '2021-09-01T00:00:00.2115808Z'
tick_id: 2830807
best_bid: 376592.0
best_ask: 376676.0
best_bid_size: 0.01
best_ask_size: 0.4
total_bid_depth: 5234.4333389
total_ask_depth: 1511.52678
market_bid_size: 0.0
market_ask_size: 0.0
ltp: 376789.0
volume: 37853.5120461
volume_by_product: 37853.5120461
}
}
}