UNPKG

hft-js

Version:

High-Frequency Trading in Node.js

120 lines 3.71 kB
/* * tape.ts * * Copyright (c) 2025 Xiongfei Shi * * Author: Xiongfei Shi <xiongfei.shi(a)icloud.com> * License: Apache-2.0 * * https://github.com/shixiongfei/hft.js */ const calcTapeType = (volumeDelta, interestDelta) => { if (interestDelta > 0) { return volumeDelta === interestDelta ? "dual-open" : "open"; } if (interestDelta < 0) { return volumeDelta + interestDelta === 0 ? "dual-close" : "close"; } if (volumeDelta > 0) { return "turnover"; } return "no-deal"; }; const calcTapeDirection = (tick, preTick) => { const lastPrice = tick.lastPrice; if (preTick) { const preAskPrice1 = preTick.orderBook.asks.price[0] ?? Number.MAX_VALUE; if (lastPrice >= preAskPrice1) { return "up"; } const preBidPrice1 = preTick.orderBook.bids.price[0] ?? Number.MIN_VALUE; if (lastPrice <= preBidPrice1) { return "down"; } const askPrice1 = tick.orderBook.asks.price[0] ?? Number.MAX_VALUE; if (lastPrice >= askPrice1) { return "up"; } const bidPrice1 = tick.orderBook.bids.price[0] ?? Number.MIN_VALUE; if (lastPrice <= bidPrice1) { return "down"; } const prePrice = preTick.lastPrice; if (lastPrice > prePrice) { return "up"; } if (lastPrice < prePrice) { return "down"; } if (bidPrice1 >= preAskPrice1) { return "up"; } if (askPrice1 <= preBidPrice1) { return "down"; } return "none"; } else { const askPrice1 = tick.orderBook.asks.price[0] ?? Number.MAX_VALUE; if (lastPrice >= askPrice1) { return "up"; } const bidPrice1 = tick.orderBook.bids.price[0] ?? Number.MIN_VALUE; if (lastPrice <= bidPrice1) { return "down"; } if (lastPrice > tick.preClose) { return "up"; } if (lastPrice < tick.preClose) { return "down"; } return "none"; } }; const calcTapeStatus = (tapeType, tapeDirection) => { if (tapeType === "open" && tapeDirection === "up") { return "open-long"; } if (tapeType === "open" && tapeDirection === "down") { return "open-short"; } if (tapeType === "close" && tapeDirection === "up") { return "close-short"; } if (tapeType === "close" && tapeDirection === "down") { return "close-long"; } if (tapeType === "turnover" && tapeDirection === "up") { return "turnover-long"; } if (tapeType === "turnover" && tapeDirection === "down") { return "turnover-short"; } if (tapeType === "dual-open") { return "dual-open"; } if (tapeType === "dual-close") { return "dual-close"; } return "invalid"; }; export const calcTapeData = (tick, preTick) => { const volumeDelta = preTick ? tick.volume - preTick.volume : tick.volume; const amountDelta = preTick ? tick.amount - preTick.amount : tick.amount; const interestDelta = preTick ? tick.openInterest - preTick.openInterest : tick.openInterest - tick.preOpenInterest; const tapeType = calcTapeType(volumeDelta, interestDelta); const tapeDirection = calcTapeDirection(tick, preTick); const tapeStatus = calcTapeStatus(tapeType, tapeDirection); return Object.freeze({ type: tapeType, direction: tapeDirection, status: tapeStatus, interestDelta: interestDelta, volumeDelta: volumeDelta, amountDelta: amountDelta, }); }; //# sourceMappingURL=tape.js.map