incumque
Version:
Multi Exchange Crypto Currency Trading bot, Data Analysis Library and Strategy Back testing Engine
1,554 lines (1,394 loc) • 72.6 kB
JavaScript
const technicalIndicators = require('technicalindicators');
technicalIndicators.setConfig('precision', 10);
let utils = require("../utility/util");
let MACD = technicalIndicators.MACD;
let RSI = technicalIndicators.RSI;
let ATR = technicalIndicators.ATR;
let BB = technicalIndicators.BollingerBands;
let EMA = technicalIndicators.EMA;
let SMA = technicalIndicators.SMA;
let OBV = technicalIndicators.OBV;
let MFI = technicalIndicators.MFI;
let KST = technicalIndicators.KST;
let Bullish = technicalIndicators.bullish;
let WilliamsR = technicalIndicators.WilliamsR;
let ADL = technicalIndicators.ADL;
let ADX = technicalIndicators.ADX;
let AwesomeOscillator = technicalIndicators.AwesomeOscillator;
let CCI = technicalIndicators.CCI;
let ForceIndex = technicalIndicators.ForceIndex;
let PSAR = technicalIndicators.PSAR;
let ROC = technicalIndicators.ROC;
let Stochastic = technicalIndicators.Stochastic;
let TRIX = technicalIndicators.TRIX;
let VWAP = technicalIndicators.VWAP;
let VP = technicalIndicators.VolumeProfile;
let WP = technicalIndicators.WMA;
let WEMA = technicalIndicators.WEMA;
let IchimokuCloud = technicalIndicators.IchimokuCloud;
const SuperTrend = require('node-super-trend');
class CustomIndicator {
constructor(o,h,l,c,v, args, candles){
this.o = o;
this.h = h;
this.l = l;
this.c = c,
this.v = v,
this.args = args,
this.candles= candles;
}
}
/**
* Class DynamicGridSignals
* @type Indicator
* */
class DynamicGridSignals extends CustomIndicator {
static className = 'DynamicGridSignals';
static getData(o,h,l,c,v, args, candles){
const st = new DynamicGridSignals(o,h,l,c,v, args, candles);
return st.calculate();
}
constructor(o,h,l,c,v, args, candles){
super(o,h,l,c,v, args, candles);
let cloneHigs = [...this.h];
let cloneLows = [...this.l];
this.upperBound = Math.max(...cloneHigs.reverse().slice(0, args.period || 200));
this.lowerBound = Math.min(...cloneLows.reverse().slice(0,args.period || 200));
this.grids = args.grids || 5;
}
calculateGridDistribution() {
const gridDistribution = [];
const range = this.upperBound - this.lowerBound;
const interval = range / this.grids;
for (let i = 0; i <= this.grids; i++) {
const gridValue = this.lowerBound + i * interval;
gridDistribution.push(gridValue);
}
return gridDistribution.sort((a, b) => a - b);
}
calculate(){
let grid = this.calculateGridDistribution();
let result = [];
this.o.forEach((element,index) => {
result.push({o:this.o[index], l:this.l[index], h:this.h[index], c:this.c[index],v:this.v[index], grid:grid});
});
return result;
}
}
/**
* Class MultiDivergenceDetector
* @type Indicator
* */
class MultiDivergenceDetector extends CustomIndicator {
static className = 'MultiDivergenceDetector';
static getData(o,h,l,c,v, args, candles){
const st = new MultiDivergenceDetector(o,h,l,c,v, args, candles);
return st.calculate();
}
calculateLengthDiff(){
//check which of the following arrays have the smallest length this.rsi, this.macd, this.obv, this.stoch and this.Williams
let minLength = Math.min(this.rsi.length, this.macd.length, this.stoch.length, this.williamsRIndicator.length);
return this.c.length - minLength;
}
constructor(o,h,l,c,v, args, candles){
super(o,h,l,c,v, args, candles);
this.lookback = args.lookback || 15;
this.rsi = RsiIndicator.getData(o,h,l,c,v, {}, candles);
this.macd = MacdIndicator.getData(o,h,l,c,v, {}, candles); // MACD+signal
this.stoch = StochasticIndicator.getData(o,h,l,c,v, {}, candles); //k+d
this.williamsRIndicator = WilliamsRIndicator.getData(o,h,l,c,v, {}, candles);
this.divergenceSignals =[];
let diff = this.calculateLengthDiff();
// when diff is greater than 0 we want to drop the first diff indexes of this.o
if( diff > 0 ){
this.o = this.o.slice(diff);
this.h = this.h.slice(diff);
this.l = this.l.slice(diff);
this.c = this.c.slice(diff);
this.v = this.v.slice(diff);
}
}
detectMacdDivergence(highBuffer, lowBuffer){
const length = this.c.length;
let highBufferStartIndex = 0;
let lowBufferStartIndex = 0;
for (let i = 0; i < length; i++) {
const currentOpen = this.o[i];
const currentClose = this.c[i];
const previousHigh = highBuffer[highBufferStartIndex].value;
const previousLow = lowBuffer[lowBufferStartIndex].value;
const currentMacdLine = this.macd[i].MACD + this.macd[i].signal;
const previousMacdOnHigh = this.macd[highBuffer[highBufferStartIndex].index].MACD + this.macd[highBuffer[highBufferStartIndex].index].signal;
const previousMacdOnLow = this.macd[lowBuffer[lowBufferStartIndex].index].MACD + this.macd[lowBuffer[lowBufferStartIndex].index].signal;
if (currentClose > previousHigh && currentMacdLine < previousMacdOnHigh) {
highBufferStartIndex++;
lowBufferStartIndex++
this.divergenceSignals.push({
type: 'MACD Bearish Divergence',
index: i,
open: currentOpen,
close: currentClose,
macd: this.macd[i].MACD,
signal: this.macd[i].signal,
});
}
// Bearish Divergence: Lower close, Higher RSI
else if (currentClose < previousLow && currentMacdLine > previousMacdOnLow) {
lowBufferStartIndex++;
highBufferStartIndex++;
this.divergenceSignals.push({
type: 'MACD Bullish Divergence',
index: i,
open: currentOpen,
close: currentClose,
macd: this.macd[i].MACD,
signal: this.macd[i].signal,
});
} else{
this.divergenceSignals.push({
type: 'Pending Divergence',
index: i,
open: currentOpen,
close: currentClose,
});
}
}
}
detectStochDivergence(highBuffer, lowBuffer){
const length = this.c.length;
let highBufferStartIndex = 0;
let lowBufferStartIndex = 0;
for (let i = 0; i < length; i++) {
const currentOpen = this.o[i];
const currentClose = this.c[i];
const previousHigh = highBuffer[highBufferStartIndex].value;
const previousLow = lowBuffer[lowBufferStartIndex].value;
const currentStochLine = this.stoch[i].k + this.stoch[i].d;
const previousStochOnHigh = this.stoch[highBuffer[highBufferStartIndex].index].k + this.stoch[highBuffer[highBufferStartIndex].index].d;
const previousStochOnLow = this.stoch[lowBuffer[lowBufferStartIndex].index].k + this.stoch[lowBuffer[lowBufferStartIndex].index].d;
if (currentClose > previousHigh && currentStochLine < previousStochOnHigh) {
highBufferStartIndex++;
lowBufferStartIndex++
this.divergenceSignals.push({
type: 'Stochastic Bearish Divergence',
index: i,
open: currentOpen,
close: currentClose,
k: this.stoch[i].k,
d: this.stoch[i].d,
});
}
// Bearish Divergence: Lower close, Higher RSI
else if (currentClose < previousLow && currentStochLine > previousStochOnLow) {
lowBufferStartIndex++;
highBufferStartIndex++;
this.divergenceSignals.push({
type: 'MACD Bullish Divergence',
index: i,
open: currentOpen,
close: currentClose,
k: this.stoch[i].k,
d: this.stoch[i].d,
});
} else {
this.divergenceSignals.push({
type: 'Pending Divergence',
index: i,
open: currentOpen,
close: currentClose,
});
}
}
}
detectWilliamsRDivergence(highBuffer, lowBuffer){
const length = this.c.length;
let highBufferStartIndex = 0;
let lowBufferStartIndex = 0;
for (let i = 0; i < length; i++) {
const currentOpen = this.o[i];
const currentClose = this.c[i];
const previousHigh = highBuffer[highBufferStartIndex].value;
const previousLow = lowBuffer[lowBufferStartIndex].value;
const currentWR = this.williamsRIndicator[i];
const previousWROnHigh = this.williamsRIndicator[highBuffer[highBufferStartIndex].index];
const previousWRIOnLow = this.williamsRIndicator[lowBuffer[lowBufferStartIndex].index];
// Bullish Divergence: Higher close, Lower RSI
if (currentClose > previousHigh && currentWR < previousWROnHigh) {
highBufferStartIndex++;
lowBufferStartIndex++
this.divergenceSignals.push({
type: 'Williams R Bearish Divergence',
index: i,
open: currentOpen,
close: currentClose,
wr: currentWR,
});
}
// Bearish Divergence: Lower close, Higher RSI
else if (currentClose < previousLow && currentWR > previousWRIOnLow) {
lowBufferStartIndex++;
highBufferStartIndex++;
this.divergenceSignals.push({
type: 'Williams R Bullish Divergence',
index: i,
open: currentOpen,
close: currentClose,
wr: currentWR,
});
} else{
this.divergenceSignals.push({
type: 'Pending Divergence',
index: i,
open: currentOpen,
close: currentClose,
});
}
}
}
detectRSIDivergence(highBuffer, lowBuffer) {
const length = this.c.length;
let highBufferStartIndex = 0;
let lowBufferStartIndex = 0;
for (let i = 0; i < length; i++) {
const currentOpen = this.o[i];
const currentClose = this.c[i];
const previousHigh = highBuffer[highBufferStartIndex].value;
const previousLow = lowBuffer[lowBufferStartIndex].value;
const currentRSI = this.rsi[i];
const previousRSIOnHigh = this.rsi[highBuffer[highBufferStartIndex].index];
const previousRSIOnLow = this.rsi[lowBuffer[lowBufferStartIndex].index];
// Bullish Divergence: Higher close, Lower RSI
if (currentClose > previousHigh && currentRSI < previousRSIOnHigh) {
highBufferStartIndex++;
lowBufferStartIndex++
this.divergenceSignals.push({
type: 'RSI Bearish Divergence',
index: i,
open: currentOpen,
close: currentClose,
rsi: currentRSI,
});
}
// Bearish Divergence: Lower close, Higher RSI
else if (currentClose < previousLow && currentRSI > previousRSIOnLow) {
lowBufferStartIndex++;
highBufferStartIndex++;
this.divergenceSignals.push({
type: 'RSI Bullish Divergence',
index: i,
open: currentOpen,
close: currentClose,
rsi: currentRSI,
});
} else {
this.divergenceSignals.push({
type: 'Pending Divergence',
index: i,
open: currentOpen,
close: currentClose,
});
}
}
}
calculate(){
// Example usage:
let highs = [...this.h]
let lows = [...this.l];
let highBuffer = []
let lowBuffer = []
let buffer = [];
highBuffer = utils.getLastLookbackHigh(highs,this.lookback) ;
lowBuffer =utils.getLastLookbackLow(lows,this.lookback);
this.detectRSIDivergence(highBuffer, lowBuffer)
this.detectMacdDivergence(highBuffer, lowBuffer)
this.detectStochDivergence(highBuffer, lowBuffer)
this.detectWilliamsRDivergence(highBuffer, lowBuffer)
this.c.forEach((close,index) =>{
let divergenceInst = this.divergenceSignals.filter((divergence)=>{ return divergence.index === index})
let hasDivergence = divergenceInst.filter((divergence)=>{ return divergence.type !== 'Pending Divergence' }).length > 0;
buffer.push({c:close, hasDivergence:hasDivergence, divergence:divergenceInst})
})
return buffer;
}
}
/**
* Class ZScore
* @type Indicator
* */
class ZScore extends CustomIndicator {
className = 'ZScore'
static getData(o,h,l,c,v, args, candles){
const st = new ZScore(o,h,l,c,v, args, candles);
return st.calculate();
}
constructor(o,h,l,c,v, args, candles){
super(o,h,l,c,v, args, candles);
this.period = args.period || 55;
}
calculateMovingAverage(values, period) {
const movingAverages = [];
for (let i = period - 1; i < values.length; i++) {
const sum = values.slice(i - period + 1, i + 1).reduce((acc, val) => acc + val, 0);
const average = sum / period;
movingAverages.push(average);
}
return movingAverages;
}
calculateStandardDeviation(values, period) {
const standardDeviations = [];
for (let i = period - 1; i < values.length; i++) {
const subset = values.slice(i - period + 1, i + 1);
const average = subset.reduce((acc, val) => acc + val, 0) / period;
const squaredDifferences = subset.map((val) => Math.pow(val - average, 2));
const variance = squaredDifferences.reduce((acc, val) => acc + val, 0) / period;
const standardDeviation = Math.sqrt(variance);
standardDeviations.push(standardDeviation);
}
return standardDeviations;
}
calculateZScore(values, period) {
const movingAverages = this.calculateMovingAverage(values, period);
const standardDeviations = this.calculateStandardDeviation(values, period);
const zScores = [];
for (let i = period - 1; i < values.length; i++) {
const zScore = (values[i] - movingAverages[i - period + 1]) / standardDeviations[i - period + 1];
zScores.push(zScore);
}
return zScores;
}
calculate(){
// Example usage:
const zScores = {
o:this.calculateZScore(this.o, this.period),
h:this.calculateZScore(this.h, this.period),
l:this.calculateZScore(this.l, this.period),
c:this.calculateZScore(this.c, this.period),
v:this.calculateZScore(this.v, this.period),
}
return zScores;
}
}
/**
* Class SupportAndResistance
* @type Indicator
* */
class SupportAndResistance extends CustomIndicator {
className = 'SupportAndResistance';
static getData(o,h,l,c,v, args, candles){
const st = new SupportAndResistance(o,h,l,c,v, args, candles);
return st.calculate();
}
constructor(o,h,l,c,v, args, candles){
super(o,h,l,c,v, args, candles);
this.period = args.period || 25;
}
calculateMovingAverage(data, period) {
const movingAverages = [];
for (let i = period - 1; i < data.length; i++) {
const sum = data.slice(i - period + 1, i + 1).reduce((acc, val) => acc + val, 0);
const average = sum / period;
movingAverages.push(average);
}
return movingAverages;
}
findSupportResistanceZones(closingPrices, threshold = 0.1, lookbackPeriod = 20, maPeriod = 50) {
const zones = [];
const movingAverages = this.calculateMovingAverage(closingPrices, maPeriod);
for (let i = lookbackPeriod; i < closingPrices.length; i++) {
const currentPrice = closingPrices[i];
const mean = movingAverages[i - lookbackPeriod];
const stdDev = Math.sqrt(closingPrices.slice(i - lookbackPeriod, i).reduce((sum, price) => sum + Math.pow(price - mean, 2), 0) / lookbackPeriod);
let zoneType = null;
// Check if the current price is close to the mean within the specified threshold
if (Math.abs(currentPrice - mean) < threshold * stdDev) {
// Determine if it's support or resistance based on the position relative to the mean
zoneType = currentPrice < mean ? 'Support' : 'Resistance';
zones.push({ level: currentPrice, type: zoneType });
}else{
zones.push({ level: currentPrice, type: "discovery" });
}
}
return zones;
}
// Example usage:
calculate(){
const supportResistanceZones = this.findSupportResistanceZones(this.c);
return supportResistanceZones;
}
}
/**
* Class SuperTrend
* @type Indicator
* */
class SuperTrendIndicator {
static className = 'SuperTrendIndicator';
/**
* @typedef {Object} superTrend
* @property {number} value - The Value of the current moving average
* @property {string} trend - The current Trend
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args.period {number} the moving average period (default 10)
* @param args.multiplier {number} the atr multiplier (default 3)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<superTrend>}
*/
static getData(o,h,l,c,v, args, candles){
const st = new SuperTrend(candles,args.period || 10,args.multiplier || 3);
return st.calculate();
}
}
/**
* Class Woodies
* @type Indicator
* */
class Woodies {
static className = "Woodies"
/**
* @typedef {Object} woodies
* @property {number} pivot - The Pivot Point
* @property {number} r1 - The first resistance
* @property {number} r2 - The second resistance
* @property {number} s1 - The first support
* @property {number} s2 - The second Support
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<woodies>}
*
*/
static getData(o,h,l,c,v, args, candles){
return utils.woodies(o,h,l,c,v, args, candles)
}
}
/**
* Class FloorPivots
* @type Indicator
* */
class FloorPivots {
static className = "FloorPivots"
/**
* @typedef {Object} floorPivot
* @property {number} pivot - The Pivot Point
* @property {number} r1 - The first resistance
* @property {number} r2 - The second resistance
* @property {number} r3 - The third resistance
* @property {number} s1 - The first support
* @property {number} s2 - The second Support
* @property {number} s2 - The third Support
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<floorPivot>}
*
*/
static getData(o,h,l,c,v, args, candles){
return utils.floorPivots(o,h,l,c,v, args, candles)
}
}
/**
* Class RsiIndicator
* @type Indicator
* */
class RsiIndicator {
static className = "RsiIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args.period {number}(the rsi period default 14)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let inputRSI = {
values: c,
period: args.period || 14
};
let rsi = new RSI(inputRSI);
return rsi.getResult();
}
}
/**
* Class RsiIndicator
* @type Indicator
* */
class AtrIndicator {
static className = "AtrIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args.period {number} (the atr period default 12)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let inputATR = {
high : h,
low : l,
close: c,
period : args.period || 21
};
let atr = new ATR(inputATR);
return atr.getResult();
}
}
/**
* Class BollingerIndicator
* @type Indicator
* */
class BollingerIndicator{
static className = "BollingerIndicator"
/**
* @typedef {Object} bollinger
* @property {number} middle - the center bands
* @property {string} upper - The upper bands
* @property {string} lower - The lower bands
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args.period {number} the moving average period
* @param args.stdDev {number} the standard deviation of bands
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<bollinger>}
*
*/
static getData(o,h,l,c,v, args, candles){
let input = {
period : args.period || 20,
values : c,
stdDev : args.stdDev || 2
};
let bb = new BB(input);
return bb.getResult();
}
}
/**
* Class MacdIndicator
* @type Indicator
* */
class MacdIndicator{
static className = "MacdIndicator"
/**
* @typedef {Object} macd
* @property {number} MACD - the macd
* @property {string} signal - The signal line
* @property {string} histogram - The histogram
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volume Data
* @param args.fastPeriod {number} the fast moving average period
* @param args.slowPeriod {number} the slow moving average period
* @param args.signalPeriod {number} the macd signal period
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<macd>}
*
*/
static getData(o,h,l,c,v, args, candles){
//fastPeriod=12,slowPeriod=26,signalPeriod=9
let macdInput = {
values : c,
fastPeriod : args.fastPeriod || 12,
slowPeriod : args.slowPeriod || 26,
signalPeriod : args.signalPeriod || 9,
SimpleMAOscillator: true,
SimpleMASignal : true
};
let macd= new MACD(macdInput);
return macd.getResult();
}
}
/**
* Class WilliamsRIndicator
* @type Indicator
* */
class WilliamsRIndicator{
static className = "WilliamsRIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 14)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high : h ,
low : l ,
period : args.period || 14,
close : c,
};
let WWR = new WilliamsR(input);
return WWR.getResult();
}
}
/**
* Class KsiIndicator
* @type Indicator
* */
class KsiIndicator{
static className = "KsiIndicator"
/**
* @typedef {Object} ksi
* @property {number} kst - The Kst Line
* @property {number} signal - The signal line
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<ksi>}
* */
static getData(o,h,l,c,v, args, candles){
let input = {
values : c,
ROCPer1 : 10,
ROCPer2 : 15,
ROCPer3 : 20,
ROCPer4 : 30,
SMAROCPer1 : 10,
SMAROCPer2 : 10,
SMAROCPer3 : 10,
SMAROCPer4 : 15,
signalPeriod: 9
};
KST = new KST(input);
return KST.getResult();
}
}
/**
* Class MfiIndicator
* @type Indicator
* */
class MfiIndicator{
static className = "MfiIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 14)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high : h ,
low : l ,
period : 14,
close : c,
volume : v
};
let mfi = new MFI(input);
return mfi.getResult();
}
}
/**
* Class ObvIndicator
* @type Indicator
* */
class ObvIndicator{
static className = "ObvIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 14)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high : h ,
low : l ,
period : args.period || 14,
close : c,
volume : v
};
let obv = new OBV(input);
return obv.getResult();
}
}
/**
* Class Ema4Indicator
* @type Indicator
* */
class Ema4Indicator{
static className ="Ema4Indicator";
/**
* @typedef {Object} ema4
* @property {Array<number>} ema8 - The ema8 values
* @property {Array<number>} ema13 - The ema13 values
* @property {Array<number>} ema21 - The ema21 values
* @property {Array<number>} ema55 - The ema55 values
* @property {Array<number>} ema100 - The ema100 values
* @property {Array<number>} ema200 - The ema200 values
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<ema4>}
* */
static getData(o,h,l,c,v, args, candles){
let EMA1 = new EMA({period : 8, values : c});
let EMA2 = new EMA({period : 13, values : c});
let EMA3 = new EMA({period : 21, values : c});
let EMA4 = new EMA({period : 55, values : c});
let EMA5 = new EMA({period : 100, values :c});
let EMA6 = new EMA({period : 200, values :c});
let object = {};
let tmpBuffer = EMA1.getResult();
object.ema8 = tmpBuffer;
tmpBuffer = EMA2.getResult();
object.ema13 = tmpBuffer;
tmpBuffer = EMA3.getResult();
object.ema21 = tmpBuffer;
tmpBuffer = EMA4.getResult();
object.ema55 = tmpBuffer;
tmpBuffer = EMA5.getResult();
object.ema100 = tmpBuffer;
tmpBuffer = EMA6.getResult();
object.ema200 = tmpBuffer;
return object
}
}
/**
* Class EMAIndicator
* @type Indicator
* */
class EMAIndicator{
static className = "EMAIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 9)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let ema = new EMA({period : args.period || 9, values : c});
return ema.getResult();
}
}
class ZEMAIndicator{
static className = "ZEMAIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 9)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let zema = [];
let ema = new EMA({period : args.period || 9, values : c});
let emaData = ema.getResult();
let zemaTmpInst = new EMA({period : args.period || 9, values : emaData});
let zemaTmp = zemaTmpInst.getResult();
let lengthDifference = (emaData.length - zemaTmp.length);
let length = emaData.length;
let j = 0;
for(let i = lengthDifference; i<length; i++ ){
let zmaDiff= emaData[i] - zemaTmp[j]
let zmaEntry= zemaTmp[j] + zmaDiff;
j++;
zema.push(zmaEntry);
}
return zema;
}
}
/**
* Class Ema10And20
* @type Indicator
* */
class Ema10And20{
static className ="Ema10And20";
/**
* @typedef {Object} ema1020
* @property {Array<number>} ema10 - The ema10 values
* @property {Array<number>} ema20 - The ema20 values
**/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<ema1020>}
* */
static getData(o,h,l,c,v, args, candles){
let EMA1 = new EMA({period : 10, values : c});
let EMA2 = new EMA({period : 20, values : c});
let object = {};
let tmpBuffer = EMA1.getResult();
object.ema10 = tmpBuffer;
tmpBuffer = EMA2.getResult();
object.ema20 = tmpBuffer;
return object;
}
}
/**
* Class Ema3Indicator
* @type Indicator
* */
class Ema3Indicator{
static className ="Ema3Indicator"
/**
* @typedef {Object} emas
* @property {Array<number>} ema1 - The ema1 values
* @property {Array<number>} ema2 - The ema2 values
* @property {Array<number>} ema3 - The ema3 values
**/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period1 {number} moving average period (default 9)
* @param args.period2 {number} moving average period (default 21)
* @param args.period3 {number} moving average period (default 55)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<emas>}
* */
static getData(o,h,l,c,v, args,candles ){
let EMA1 = new EMA({period : args.period1 || 9, values : c});
let EMA2 = new EMA({period : args.period2 || 21, values : c});
let EMA3 = new EMA({period : args.period3 || 55, values : c});
let object = {};
let tmpBuffer = EMA1.getResult();
object.ema1 = tmpBuffer;
tmpBuffer = EMA2.getResult();
object.ema2 = tmpBuffer;
tmpBuffer = EMA3.getResult();
object.ema3 = tmpBuffer;
return object;
}
}
/**
* Class Sma3Indicator
* @type Indicator
* */
class Sma3Indicator{
static className ="Sma3Indicator";
/**
* @typedef {Object} smas
* @property {Array<number>} sma1 - The sma1 values
* @property {Array<number>} sma2 - The sma2 values
* @property {Array<number>} sma3 - The sma3 values
**/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period1 {number} moving average period (default 50)
* @param args.period2 {number} moving average period (default 100)
* @param args.period3 {number} moving average period (default 200)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<smas>}
* */
static getData(o,h,l,c,v, args, candles){
let SMA1 = new SMA({period : args.period1 || 50, values : c});
let SMA2 = new SMA({period : args.period2 || 100, values : c});
let SMA3 = new SMA({period : args.period3 || 200, values : c});
let object = {};
let tmpBuffer = SMA1.getResult();
object.sma1 = tmpBuffer;
tmpBuffer = SMA2.getResult();
object.sma2 = tmpBuffer;
tmpBuffer = SMA3.getResult();
object.sma3 = tmpBuffer;
return object
}
}
/**
* Class SmaIndicator
* @type Indicator
* */
class SmaIndicator{
static className ="SmaIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 50)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let sma = new SMA({period : args.period || 50, values : c});
return sma.getResult();
}
}
/**
* Class AdlIndicator
* @type Indicator
* */
class AdlIndicator{
static className ="AdlIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args null
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input= {
high:h,
low:l,
close:c,
volume:v
}
return ADL.calculate(input);
}
}
/**
* Class AdxIndicator
* @type Indicator
* */
class AdxIndicator{
static className ="AdxIndicator"
/**
* @typedef {Object} adxIndicator
* @property {number} adx - The adx values
* @property {number} pdi - The pdi values
* @property {number} mdi - The mdi values
**/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} the moving average or atr period (default 14)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @return {Array<adxIndicator>}
* */
static getData(o,h,l,c,v, args, candles){
let input= {
high:h,
low:l,
close:c,
period:14
};
let adx = new ADX(input)
let data = adx.getResult();
return data;
}
}
/**
* Class AwesomeOscillatorIndicator
* @type Indicator
* */
class AwesomeOscillatorIndicator{
static className ="AwesomeOscillatorIndicator";
/**
*
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.fastPeriod {number} the moving average fast period (default 5)
* @param args.slowPeriod {number} the moving average slow period (default 34)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high : h,
low : l,
fastPeriod : args.fastPeriod || 5,
slowPeriod : args.slowPeriod || 34,
format : (a)=>parseFloat(a.toFixed(2))
}
return AwesomeOscillator.calculate(input)
}
}
/**
* Class CciIndicator
* @type Indicator
* */
class CciIndicator{
static className ="CciIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 20)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let inputCCI = {
open : o,
high : h,
low : l,
close : c,
period : args.period || 20
};
return CCI.calculate(inputCCI);
}
}
/**
* Class ForceIndexIndiactor
* @type Indicator
* */
class ForceIndexIndiactor{
static className ="ForceIndexIndiactor";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 1)
** @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input ={
close : c,
volume :v,
period : args.period || 1
};
return ForceIndex.calculate(input);
}
}
/**
* Class PsarIndicator
* @type Indicator
* */
class PsarIndicator{
static className = "PsarIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.step {number} (step float default 0.02 )
* @param args.max {number} ( max float default 0.02 )
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = { high:h, low:l, step:args.step || 0.02, max:args.max || 0.2};
return PSAR.calculate(input);
}
}
/**
* Class RocIndicator
* @type Indicator
* */
class RocIndicator{
static className = "RocIndicator";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (The moving average period default 12)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
return ROC.calculate({period:args.period || 12, values:c})
}
}
/**
* Class StochasticIndicator
* @type Indicator
* */
class StochasticIndicator{
static className = "StochasticIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 14)
* @param args.signalPeriod {number} (the signal period default 3)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [{k:Number}]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high: h,
low: l,
close: c,
period: args.period || 14,
signalPeriod: args.signalPeriod || 3
};
return Stochastic.calculate(input)
}
}
/**
* Class TrixIndicator
* @type Indicator
* */
class TrixIndicator{
static className = "TrixIndicator"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 18)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData( o,h,l,c,v,args, candles){
let input = {
values : c,
period : args.period || 18
};
return TRIX.calculate(input);
}
}
/**
* Class VolumeWeightedAvgPrice
* @type Indicator
* */
class VolumeWeightedAvgPrice{
static className = "VolumeWeightedAvgPrice"
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
let input = {
high :h,
low :l,
close : c,
volume :v,
};
return VWAP.calculate(input)
}
}
/**
* Class VolumeProfile
* @type Indicator
* */
class VolumeProfile{
static className = "VolumeProfile";
/**
* @typedef {Object} vp
* @property {number} rangeStart - The range start
* @property {number} rangeEnd - The range end
* @property {number} bullishVolume - The bullish volumes
* @property {number} bullishVolume - The bearish volumes
* @property {number} totalVolume - The total volume
** /
*
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number}(The Number of Bars to index)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns {Array<vp>}
* */
static getData(o,h,l,c,v, args, candles){
let input = {
open:o,
high :h,
low :l,
close : c,
volume :v,
noOfBars:args.period || 18
};
return VP.calculate(input)
}
}
/**
* Class WeighteMovingAvg
* @type Indicator
* */
class WeighteMovingAvg{
static className = "WeighteMovingAvg";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 12)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
return WP.calculate({period : args.period || 12, values : c})
}
}
/**
* Class WildersSmoothingWeighteMovingAvg
* @type Indicator
* */
class WildersSmoothingWeighteMovingAvg{
static className = "WildersSmoothingWeighteMovingAvg";
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.period {number} (the moving average period default 50)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @returns [Number]
* */
static getData(o,h,l,c,v, args, candles){
return WEMA.calculate({period : args.period || 50, values : c})
}
}
/**
* Class IchimokuCloudIndicator
* @type Indicator
* */
class IchimokuCloudIndicator{
static className = "IchimokuCloudIndicator";
/**
* @typedef {Object} itchyMicky
* @property {number} conversionPeriod - The conversionPeriod
* @property {number} base - The base-line
* @property {number} spanA - The span A Line
* @property {number} spanB - The span B Line
*/
/**
* @param o {Array<number>} The Opening Candles
* @param h {Array<number>} The Higher High Candles
* @param l {Array<number>} The Lower Low Candles
* @param c {Array<number>} The Closing Candles
* @param v {Array<number>} The Volumes
* @param args.conversionPeriod {number} (conversionPeriod default 9)
* @param args.basePeriod {number} (basePeriod default 26)
* @param args.spanPeriod {number} (spanPeriod default 52)
* @param args.displacement {number} (displacement default 26)
* @param candles {Array<Array<number>>} o,h,l,c,v array Buffer
* @return {Array<itchyMicky>}
* */
static getData(o,h,l,c,v, args, candles){
let input ={
high :h,
low : l,
conversionPeriod: args.conversionPeriod || 9,
basePeriod: args.basePeriod || 26,
spanPeriod: args.spanPeriod || 52,
displacement: args.displacement || 26
};
return IchimokuCloud.calculate(input)
}
}
/**
* Class IndicatorList
* @type Indicator
* */
class IndicatorList{
/**
*
* @return {string[]} List of Available Indicators
*/
static getData(){
return ["SuperTrendIndicator",
"RsiIndicator",
"AtrIndicator",
"BollingerIndicator",
"MacdIndicator",
"PatternRecognitionIndicator",
"WilliamsRIndicator",
"KsiIndicator",
"MfiIndicator",
"ObvIndicator",
"Ema4Indicator",
"Ema3Indicator",
"Ema10And20",
"Sma3Indicator",
"AdlIndicator",
"AdxIndicator",
"AwesomeOscillatorIndicator",
"CciIndicator",
"StochasticIndicator",
"IchimokuCloudIndicator",
"WildersSmoothingWeighteMovingAvg",
"WeighteMovingAvg",
"VolumeProfile",
"VolumeWeightedAvgPrice",
"TrixIndicator",
"ForceIndexIndiactor",
"RocIndicator",
"PsarIndicator",
"IndicatorUtils",