tardis-dev Computing simple moving average of volume based trade bars
const { streamNormalized, normalizeTrades, compute, computeTradeBars } = require('tardis-dev')
class CircularBuffer {
constructor(_bufferSize) {
this._bufferSize = _bufferSize
this._buffer = []
this._index = 0
}
append(value) {
const isFull = this._buffer.length === this._bufferSize
let poppedValue
if (isFull) {
poppedValue = this._buffer[this._index]
}
this._buffer[this._index] = value
this._index = (this._index + 1) % this._bufferSize
return poppedValue
}
*items() {
for (let i = 0; i < this._buffer.length; i++) {
const index = (this._index + i) % this._buffer.length
yield this._buffer[index]
}
}
get count() {
return this._buffer.length
}
}
class SimpleMovingAverageComputable {
constructor({ periods }) {
this.sourceDataTypes = ['trade_bar']
this._average = 0
this._circularBuffer = new CircularBuffer(periods)
}
*compute(tradeBar) {
const result = this._circularBuffer.append(tradeBar.close)
const poppedVal = result !== undefined ? result : this._average
const increment = (tradeBar.close - poppedVal) / this._circularBuffer.count
this._average = this._average + increment
yield {
type: 'sma',
symbol: tradeBar.symbol,
exchange: tradeBar.exchange,
name: `sma_${tradeBar.name}`,
average: this._average,
interval: tradeBar.interval,
kind: tradeBar.kind,
timestamp: tradeBar.timestamp,
localTimestamp: tradeBar.localTimestamp
}
}
}
const computeSimpleMovingAverages = options => () => new SimpleMovingAverageComputable(options)
async function run() {
const messages = streamNormalized(
{
exchange: 'bitmex',
symbols: ['XBTUSD']
},
normalizeTrades
)
const withSimpleMovingAverage = compute(
messages,
computeTradeBars({
kind: 'volume',
interval: 10 * 1000
}),
computeSimpleMovingAverages({ period: 5 })
)
for await (message of withSimpleMovingAverage) {
if (message.type === 'sma') {
console.log(message)
}
}
}
run()
no comments