UNPKG

ta-lib

Version:

A technical analysis library written entirely in JavaScript/TypeScript

241 lines (240 loc) 7.92 kB
function arrayMax(array) { return Math.max.apply(Math, array.filter(function (n) { return !isNaN(n); })); } exports.arrayMax = arrayMax; function arrayMin(array) { return Math.min.apply(Math, array.filter(function (n) { return !isNaN(n); })); } exports.arrayMin = arrayMin; function upscale(number, places) { return Math.round(number * Math.pow(10, places)); } exports.upscale = upscale; function downscale(number, places) { return number / Math.pow(10, places); } exports.downscale = downscale; function diff(x, y) { return ((x - y) / ((x + y) / 2)) * 100; } exports.diff = diff; function average(a) { var r = { mean: 0, variance: 0, deviation: 0 }, t = a.length, m, l, s; for (m, s = 0, l = t; l--; s += a[l]) { } for (m = r.mean = s / t, l = t, s = 0; l--; s += Math.pow(a[l] - m, 2)) { } return r.deviation = Math.sqrt(r.variance = s / t), r; } exports.average = average; function BBANDS(array, period, deviation) { var bbands = { middleband: [], lowband: [], highband: [] }, sma = SMA(array, period), avg, i, arr; if (isNaN(deviation)) deviation = 2; for (i = period - 1; i >= 0; i--) { arr = array.slice(i, i + period); avg = average(arr); bbands.highband[i] = sma[i] + (deviation * avg.deviation); bbands.lowband[i] = sma[i] - (deviation * avg.deviation); bbands.middleband[i] = sma[i]; } return bbands; } exports.BBANDS = BBANDS; function AROON(higharray, lowarray, period) { var harr = higharray.slice(0, period), larr = lowarray.slice(0, period), hh = arrayMin(harr), hday = harr.indexOf(hh), ll = arrayMin(larr), lday = larr.indexOf(ll); return { up: ((period - hday) / period) * 100, down: ((period - lday) / period) * 100 }; } exports.AROON = AROON; function MFI(higharray, lowarray, closearray, volumearray, period) { var harr = higharray.slice(0, period).reverse(), larr = lowarray.slice(0, period).reverse(), clarr = closearray.slice(0, period).reverse(), vlarr = volumearray.slice(0, period).reverse(), lasttp = 0, first = true, posmf = 0, negmf = 0, i, tp; for (i = 0; i < closearray.length; i++) { if (first) { lasttp = (harr[i] + larr[i] + clarr[i]) / 3; first = false; } else { tp = (harr[i] + larr[i] + clarr[i]) / 3; if (tp > lasttp) { posmf += (tp * vlarr[0]); } else if (tp < lasttp) { negmf += (tp * vlarr[0]); } lasttp = tp; } } return (100 - (100 / (1 + (posmf / negmf)))); } exports.MFI = MFI; function RSI(array, rsiperiod) { var rsi = [], i, j, loss, gain, diff, avggain, avgloss, first = true; for (i = rsiperiod - 1; i >= 0; i--) { loss = gain = 0; if (first) { for (j = i + rsiperiod - 1; j >= i; j--) { diff = array[j + 1] - array[j]; if (diff > 0) { loss += Math.abs(diff); } else { gain += Math.abs(diff); } } first = false; avggain = gain / rsiperiod; avgloss = loss / rsiperiod; } else { diff = array[i + 1] - array[i]; if (diff > 0) { loss += Math.abs(diff); } else { gain += Math.abs(diff); } avggain = ((avggain * (rsiperiod - 1)) + gain) / rsiperiod; avgloss = ((avgloss * (rsiperiod - 1)) + loss) / rsiperiod; } //console.log("g", avggain, "l", avgloss); if (avgloss == 0) { rsi[i] = 100; } else { rsi[i] = 100 - (100 / (1 + (avggain / avgloss))); } } return rsi; } exports.RSI = RSI; function STOCHRSI(instruments, rsiperiod) { var stochrsi = [], rsiarray, rsimin, rsimax, i, arr; for (i = rsiperiod - 1; i >= 0; i--) { arr = instruments.slice(i); rsiarray = RSI(arr, rsiperiod); rsimin = arrayMin(rsiarray); rsimax = arrayMax(rsiarray); if (rsimax - rsimin == 0) { stochrsi[i] = 100; } else { stochrsi[i] = 100 * (rsiarray[0] - rsimin) / (rsimax - rsimin); } } return stochrsi; } exports.STOCHRSI = STOCHRSI; function SMA(originalArray, smaLength) { var array, sma = [], i; for (i = smaLength - 1; i >= 0; i--) { array = originalArray.slice(i, i + smaLength); sma[i] = array.reduce(function (a, b) { return a + b; }) / array.length; } return sma; } exports.SMA = SMA; function EMA(originalArray, emaLength) { var array = originalArray.slice().reverse(), iPos = 0, i, k, ema; // trim initial NaN values for (iPos = 0; iPos < array.length && isNaN(array[iPos]); iPos++) { } array = array.slice(iPos); // trim initial NaN values from array ema = []; k = 2 / (emaLength + 1); for (i = 0; i < emaLength - 1; i++) { ema[i] = NaN; } ema[emaLength - 1] = array.slice(0, emaLength).reduce(function (a, b) { return a + b; }) / emaLength; for (i = emaLength; i < array.length; i++) { ema[i] = array[i] * k + ema[i - 1] * (1 - k); } ema.reverse(); // reverse back for main consumption for (i = 0; i < iPos; i++) { ema.push(NaN); } return ema; } exports.EMA = EMA; function MACD(array, i12, i26, i9) { var ema12 = EMA(array, i12), ema26 = EMA(array, i26), macd = [], i, signal, histogram; for (i = 0; i < ema12.length; i++) { macd.push(ema12[i] - ema26[i]); } signal = EMA(macd, i9); histogram = []; for (i = 0; i < macd.length; i++) { histogram.push(macd[i] - signal[i]); } return { macd: macd, signal: signal, histogram: histogram }; } exports.MACD = MACD; function PERCPRICEOSC(array, i12, i26, i9) { var ema12 = EMA(array, 12), ema26 = EMA(array, 26), ppo = [], i, signal, histogram; for (i = 0; i < ema12.length; i++) { ppo.push((ema12[i] - ema26[i]) / ema26[i] * 100); } signal = EMA(ppo, 9); histogram = []; for (i = 0; i < ppo.length; i++) { histogram.push(ppo[i] - signal[i]); } return { ppo: ppo, signal: signal, histogram: histogram }; } exports.PERCPRICEOSC = PERCPRICEOSC; function WILLR(highs, lows, closes, lookback) { var willr = [], highest_high, lowest_low, curr_close, i; // computing only if highs and lows arrays are of equal length if (highs.length == lows.length && highs.length >= lookback) { /* * Willams %R exists only for the values which have atleast "lookback" values * so we iterate till ((length )-lookback)to calculate Willams %R */ var limit = highs.length - lookback; for (i = limit; i >= 0; i--) { highest_high = arrayMax(highs.slice(i, i + lookback)); lowest_low = arrayMin(lows.slice(i, i + lookback)); curr_close = closes[i]; willr[i] = (highest_high - curr_close) / (highest_high - lowest_low) * -100; } } return willr; } exports.WILLR = WILLR; function TRUERANGE(highs, lows, closes) { var tr = [], curr_diff, curr_high_diff, curr_low_diff, i; if (highs.length != lows.length || highs.length != closes.length) { //True ranges are found only when all arrays are of equal length return tr; } tr[0] = highs[0] - lows[0]; for (i = highs.length - 1; i > 0; i--) { var tmp = []; tmp.push(highs[i] - lows[i]); tmp.push(Math.abs(lows[i] - closes[i + 1])); tmp.push(Math.abs(highs[i] - closes[i + 1])); tr[i] = arrayMax(tmp); } return tr; } exports.TRUERANGE = TRUERANGE;