hft-js
Version:
High-Frequency Trading in Node.js
150 lines • 5.51 kB
JavaScript
"use strict";
/*
* bar.ts
*
* Copyright (c) 2025 Xiongfei Shi
*
* Author: Xiongfei Shi <xiongfei.shi(a)icloud.com>
* License: Apache-2.0
*
* https://github.com/shixiongfei/hft.js
*/
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createBarGenerator = exports.BarGenerator = void 0;
var utils_js_1 = require("./utils.js");
var BarGenerator = /** @class */ (function () {
function BarGenerator(symbol, maxVolume) {
if (maxVolume === void 0) { maxVolume = 0; }
this.receivers = [];
this.symbol = symbol;
this.maxVolume = maxVolume;
this.shouldUpdate = 0;
}
Object.defineProperty(BarGenerator.prototype, "receiverCount", {
get: function () {
return this.receivers.length;
},
enumerable: false,
configurable: true
});
BarGenerator.prototype.addReceiver = function (receiver) {
if (!this.receivers.includes(receiver)) {
if (receiver.onUpdateBar) {
this.shouldUpdate += 1;
}
this.receivers.push(receiver);
}
};
BarGenerator.prototype.removeReceiver = function (receiver) {
var index = this.receivers.indexOf(receiver);
if (index >= 0) {
if (receiver.onUpdateBar) {
this.shouldUpdate -= 1;
}
this.receivers.splice(index, 1);
}
};
BarGenerator.prototype.onTick = function (tick, tape) {
if (tick.symbol !== this.symbol) {
return;
}
var date = tick.date;
var time = this.maxVolume > 0 ? tick.time : Math.floor(tick.time / 100) * 100;
if (this.bar) {
var isFinished = this.maxVolume > 0
? this.bar.volume >= this.maxVolume
: this.bar.date !== date || this.bar.time !== time;
if (isFinished) {
var bar_1 = Object.freeze(this.bar);
Object.freeze(bar_1.buyVolumes);
Object.freeze(bar_1.sellVolumes);
this.receivers.forEach(function (receiver) { return receiver.onBar(bar_1); });
this.bar = undefined;
}
}
if (tape.volumeDelta === 0) {
return;
}
if (!this.bar) {
this.bar = this._createBar(date, time, tick);
}
this.bar.openInterest = tick.openInterest;
this.bar.closePrice = tick.lastPrice;
this.bar.highPrice = Math.max(this.bar.highPrice, tick.lastPrice);
this.bar.lowPrice = Math.min(this.bar.lowPrice, tick.lastPrice);
this.bar.volume += tape.volumeDelta;
this.bar.amount += tape.amountDelta;
switch (tape.direction) {
case "up":
if (tick.lastPrice in this.bar.buyVolumes) {
this.bar.buyVolumes[tick.lastPrice] += tape.volumeDelta;
}
else {
this.bar.buyVolumes[tick.lastPrice] = tape.volumeDelta;
}
this.bar.delta += tape.volumeDelta;
break;
case "down":
if (tick.lastPrice in this.bar.sellVolumes) {
this.bar.sellVolumes[tick.lastPrice] += tape.volumeDelta;
}
else {
this.bar.sellVolumes[tick.lastPrice] = tape.volumeDelta;
}
this.bar.delta -= tape.volumeDelta;
break;
}
if (tick.lastPrice !== this.bar.poc && tape.direction !== "none") {
var tickVP = (0, utils_js_1.getBarVolume)(this.bar, tick.lastPrice);
var pocVP = (0, utils_js_1.getBarVolume)(this.bar, this.bar.poc);
if (tickVP > pocVP) {
this.bar.poc = tick.lastPrice;
}
}
if (this.shouldUpdate > 0) {
var bar_2 = Object.freeze(__assign(__assign({}, this.bar), { buyVolumes: Object.freeze(__assign({}, this.bar.buyVolumes)), sellVolumes: Object.freeze(__assign({}, this.bar.sellVolumes)) }));
this.receivers.forEach(function (receiver) {
if (receiver.onUpdateBar) {
receiver.onUpdateBar(bar_2, tick, tape);
}
});
}
};
BarGenerator.prototype._createBar = function (date, time, tick) {
return {
symbol: this.symbol,
date: date,
time: time,
openInterest: tick.openInterest,
openPrice: tick.lastPrice,
highPrice: tick.lastPrice,
lowPrice: tick.lastPrice,
closePrice: tick.lastPrice,
volume: 0,
amount: 0,
delta: 0,
poc: tick.lastPrice,
buyVolumes: {},
sellVolumes: {},
};
};
return BarGenerator;
}());
exports.BarGenerator = BarGenerator;
var createBarGenerator = function (symbol, maxVolume) {
if (maxVolume === void 0) { maxVolume = 0; }
return new BarGenerator(symbol, maxVolume);
};
exports.createBarGenerator = createBarGenerator;
//# sourceMappingURL=bar.js.map