all files / technicalindicators/lib/momentum/ Stochastic.js

98% Statements 49/50
94.44% Branches 17/18
100% Functions 5/5
98% Lines 49/50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95                                        60×   120× 120× 120×   52×     68× 68× 68× 68×               90×         90× 51×                   30× 30× 17×    
/**
 * Created by AAravindan on 5/10/16.
 */
"use strict"
 
const LinkedList = require('../Utils/FixedSizeLinkedList');
const SMA        = require('../moving_averages/SMA');
const nf         = require('../Utils/NumberFormatter');
 
let Stochastic;
 
module.exports = Stochastic = function(input) {
 
  let lows = input.low;
  let highs = input.high;
  let closes = input.close;
  let period = input.period;
  let signalPeriod = input.signalPeriod;
  let format = input.format || nf;
 
  if(I!((lows.length === highs.length) && (highs.length === closes.length) )){
    throw ('Inputs(low,high, close) not of equal size');
  }
 
  this.result = [];
  //%K = (Current Close - Lowest Low)/(Highest High - Lowest Low) * 100
  //%D = 3-day SMA of %K
  //
  //Lowest Low = lowest low for the look-back period
  //Highest High = highest high for the look-back period
  //%K is multiplied by 100 to move the decimal point two places
  this.generator = (function* (){
    let index = 1;
    let pastHighPeriods = new LinkedList(period, true, false);
    let pastLowPeriods = new LinkedList(period, false, true);
    let dSma           = new SMA({
      period : signalPeriod,
      values : [],
      format : (v) => {return v}
    });
    let k,d;
    var tick = yield;
    while (true) {
      pastHighPeriods.push(tick.high);
      pastLowPeriods.push(tick.low);
      if(index < period){
        index++;
        tick = yield;
        continue;
      }
      let periodLow = pastLowPeriods.periodLow;
      k = (tick.close - periodLow) / (pastHighPeriods.periodHigh - periodLow) * 100;
      d = dSma.nextValue(k);
      tick = yield {
        k : format(k),
        d : d ? format(d) : undefined
      }
    }
  })();
 
  this.generator.next();
 
  lows.forEach((tick, index) => {
    var result = this.generator.next({
      high : highs[index],
      low  : lows[index],
      close : closes[index]
    });
    if(result.value !== undefined){
      this.result.push(result.value);
    }
  });
};
 
Stochastic.calculate = function(input) {
  if(input.reversedInput) {
    input.high.reverse();
    input.low.reverse();
    input.close.reverse();
  }
  let result = (new Stochastic(input)).result;
  input.reversedInput ? result.reverse():undefined;
  return result;
};
 
Stochastic.prototype.getResult = function () {
  return this.result;
};
 
Stochastic.prototype.nextValue = function (input) {
  let nextResult = this.generator.next(input);
  if(nextResult.value !== undefined)
    return nextResult.value;
};