// From how many candles to calculate linear regression var BARS_COUNT_INTERVAL = 4 var MIN_SLOPE = 0.05 //console.log(chartData) //data for linear reggresion [[x,y], [x,y],....] var movingWindowPriceData = [] var movingWindowVolDeltaData = [] for(var i = 0; i < chartData.length;i++){ var candleData = chartData[i] // remove first data point from moving window data // so that contains only defined number of candles if(movingWindowPriceData.length >= BARS_COUNT_INTERVAL){ movingWindowPriceData .shift() movingWindowVolDeltaData.shift() } var x = candleData.dateInt // update moving window data var yPrice = candleData.vwap / candleData.volume movingWindowPriceData.push([x,yPrice]) // update moving window data var yVolDelta = Math.abs(candleData.sellVolume - candleData.buyVolume) movingWindowVolDeltaData.push([x,yVolDelta]) // go back and repeat if there's not enough data loaded if(movingWindowPriceData.length < BARS_COUNT_INTERVAL){ continue } // more about statistics library here: https://simplestatistics.org/docs/ // calculate linear regressions for price and volume delta var priceLinReg = statistics.linearRegression(movingWindowPriceData) if(Math.abs(priceLinReg.m) < MIN_SLOPE){ continue; } var volDeltaLinReg = statistics.linearRegression(movingWindowVolDeltaData) if(Math.abs(volDeltaLinReg.m) < MIN_SLOPE){ continue; } // linear regression function output object {m: slope, b: intersection} // compare linReg slopes and call it divergence if slopes' directions differ if((priceLinReg.m < 0 && volDeltaLinReg.m>0) || (priceLinReg.m > 0 && volDeltaLinReg.m<0)){ console.log("diveregence", x, priceLinReg, volDeltaLinReg) var isBuySignal = true if(priceLinReg.m > 0){ isBuySignal = false } //http://dnozay.github.io/cheatsheet/2014/09/23/glyphs.html showAnnotation({ x: x, price: isBuySignal ? candleData.low * 0.99 : candleData.high * 1.01, fontFamily: "Glyphicons Halflings", fontSize: 20, fill: isBuySignal ? "#00ff00" : "#ff0000", opacity: 0.8, text: isBuySignal ? "": "", }) }