first commit
This commit is contained in:
commit
aa7869eb33
386 files changed
+69375
No files matched your search
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* CCI
|
||||
*/
|
||||
var log = require('../../core/log');
|
||||
|
||||
var Indicator = function(settings) {
|
||||
this.input = 'candle';
|
||||
this.tp = 0.0;
|
||||
this.result = false;
|
||||
this.hist = []; // needed for mean?
|
||||
this.mean = 0.0;
|
||||
this.size = 0;
|
||||
this.constant = settings.constant;
|
||||
this.maxSize = settings.history;
|
||||
for (var i = 0; i < this.maxSize; i++)
|
||||
this.hist.push(0.0);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(candle) {
|
||||
|
||||
// We need sufficient history to get the right result.
|
||||
|
||||
var tp = (candle.high + candle.close + candle.low) / 3;
|
||||
if (this.size < this.maxSize) {
|
||||
this.hist[this.size] = tp;
|
||||
this.size++;
|
||||
} else {
|
||||
for (var i = 0; i < this.maxSize-1; i++) {
|
||||
this.hist[i] = this.hist[i+1];
|
||||
}
|
||||
this.hist[this.maxSize-1] = tp;
|
||||
}
|
||||
|
||||
if (this.size < this.maxSize) {
|
||||
this.result = false;
|
||||
} else {
|
||||
this.calculate(tp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle calculations
|
||||
*/
|
||||
Indicator.prototype.calculate = function(tp) {
|
||||
|
||||
var sumtp = 0.0
|
||||
|
||||
for (var i = 0; i < this.size; i++) {
|
||||
sumtp = sumtp + this.hist[i];
|
||||
}
|
||||
|
||||
this.avgtp = sumtp / this.size;
|
||||
|
||||
this.tp = tp;
|
||||
|
||||
var sum = 0.0;
|
||||
// calculate tps
|
||||
for (var i = 0; i < this.size; i++) {
|
||||
|
||||
var z = (this.hist[i] - this.avgtp);
|
||||
if (z < 0) z = z * -1.0;
|
||||
sum = sum + z;
|
||||
|
||||
}
|
||||
|
||||
this.mean = (sum / this.size);
|
||||
|
||||
|
||||
|
||||
this.result = (this.tp - this.avgtp) / (this.constant * this.mean);
|
||||
|
||||
// log.debug("===\t", this.mean, "\t", this.tp, '\t', this.TP.result, "\t", sum, "\t", avgtp, '\t', this.result.toFixed(2));
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,19 @@
|
||||
// required indicators
|
||||
var EMA = require('./EMA.js');
|
||||
|
||||
var Indicator = function(config) {
|
||||
this.input = 'price';
|
||||
this.result = false;
|
||||
this.inner = new EMA(config.weight);
|
||||
this.outer = new EMA(config.weight);
|
||||
}
|
||||
|
||||
// add a price and calculate the EMAs and
|
||||
// the result
|
||||
Indicator.prototype.update = function(price) {
|
||||
this.inner.update(price);
|
||||
this.outer.update(this.inner.result);
|
||||
this.result = 2 * this.inner.result - this.outer.result;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,36 @@
|
||||
// @link http://en.wikipedia.org/wiki/Exponential_moving_average#Exponential_moving_average
|
||||
|
||||
var Indicator = function(weight) {
|
||||
this.input = 'price';
|
||||
this.weight = weight;
|
||||
this.result = false;
|
||||
this.age = 0;
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(price) {
|
||||
// The first time we can't calculate based on previous
|
||||
// ema, because we haven't calculated any yet.
|
||||
if(this.result === false)
|
||||
this.result = price;
|
||||
|
||||
this.age++;
|
||||
this.calculate(price);
|
||||
|
||||
return this.result;
|
||||
}
|
||||
|
||||
// calculation (based on tick/day):
|
||||
// EMA = Price(t) * k + EMA(y) * (1 – k)
|
||||
// t = today, y = yesterday, N = number of days in EMA, k = 2 / (N+1)
|
||||
Indicator.prototype.calculate = function(price) {
|
||||
// weight factor
|
||||
var k = 2 / (this.weight + 1);
|
||||
|
||||
// yesterday
|
||||
var y = this.result;
|
||||
|
||||
// calculation
|
||||
this.result = price * k + y * (1 - k);
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Linear regression curve
|
||||
*/
|
||||
var log = require('../../core/log');
|
||||
|
||||
var Indicator = function(settings) {
|
||||
this.input = 'price';
|
||||
this.depth = settings;
|
||||
this.result = false;
|
||||
this.age = 0;
|
||||
this.history = [];
|
||||
this.x = [];
|
||||
/*
|
||||
* Do not use array(depth) as it might not be implemented
|
||||
*/
|
||||
for (var i = 0; i < this.depth; i++) {
|
||||
this.history.push(0.0);
|
||||
this.x.push(i);
|
||||
}
|
||||
|
||||
// log.debug("Created LRC indicator with h: ", this.depth);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(price) {
|
||||
|
||||
// We need sufficient history to get the right result.
|
||||
if(this.result === false && this.age < this.depth) {
|
||||
|
||||
this.history[this.age] = price;
|
||||
this.age++;
|
||||
this.result = false;
|
||||
// log.debug("Waiting for sufficient age: ", this.age, " out of ", this.depth);
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
this.age++;
|
||||
// shift history
|
||||
for (var i = 0; i < (this.depth - 1); i++) {
|
||||
this.history[i] = this.history[i+1];
|
||||
}
|
||||
this.history[this.depth-1] = price;
|
||||
|
||||
this.calculate(price);
|
||||
|
||||
|
||||
// log.debug("Checking LRC: ", this.result.toFixed(8), "\tH: ", this.age);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Least squares linear regression fitting.
|
||||
*/
|
||||
function linreg(values_x, values_y) {
|
||||
var sum_x = 0;
|
||||
var sum_y = 0;
|
||||
var sum_xy = 0;
|
||||
var sum_xx = 0;
|
||||
var count = 0;
|
||||
|
||||
/*
|
||||
* We'll use those variables for faster read/write access.
|
||||
*/
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var values_length = values_x.length;
|
||||
|
||||
if (values_length != values_y.length) {
|
||||
throw new Error('The parameters values_x and values_y need to have same size!');
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to do.
|
||||
*/
|
||||
if (values_length === 0) {
|
||||
return [ [], [] ];
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the sum for each of the parts necessary.
|
||||
*/
|
||||
for (var v = 0; v < values_length; v++) {
|
||||
x = values_x[v];
|
||||
y = values_y[v];
|
||||
sum_x += x;
|
||||
sum_y += y;
|
||||
sum_xx += x*x;
|
||||
sum_xy += x*y;
|
||||
count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate m and b for the formular:
|
||||
* y = x * m + b
|
||||
*/
|
||||
var m = (count*sum_xy - sum_x*sum_y) / (count*sum_xx - sum_x*sum_x);
|
||||
var b = (sum_y/count) - (m*sum_x)/count;
|
||||
|
||||
return [m, b];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle calculations
|
||||
*/
|
||||
Indicator.prototype.calculate = function(price) {
|
||||
|
||||
// get the reg
|
||||
var reg = linreg(this.x, this.history);
|
||||
|
||||
// y = a * x + b
|
||||
this.result = ((this.depth-1) * reg[0]) + reg[1];
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,27 @@
|
||||
// required indicators
|
||||
var EMA = require('./EMA.js');
|
||||
|
||||
var Indicator = function(config) {
|
||||
this.input = 'price';
|
||||
this.diff = false;
|
||||
this.short = new EMA(config.short);
|
||||
this.long = new EMA(config.long);
|
||||
this.signal = new EMA(config.signal);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(price) {
|
||||
this.short.update(price);
|
||||
this.long.update(price);
|
||||
this.calculateEMAdiff();
|
||||
this.signal.update(this.diff);
|
||||
this.result = this.diff - this.signal.result;
|
||||
}
|
||||
|
||||
Indicator.prototype.calculateEMAdiff = function() {
|
||||
var shortEMA = this.short.result;
|
||||
var longEMA = this.long.result;
|
||||
|
||||
this.diff = shortEMA - longEMA;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,37 @@
|
||||
// required indicators
|
||||
var EMA = require('./EMA.js');
|
||||
|
||||
var Indicator = function(config) {
|
||||
this.result = {};
|
||||
this.input = 'price';
|
||||
this.macd = 0;
|
||||
this.ppo = 0;
|
||||
this.short = new EMA(config.short);
|
||||
this.long = new EMA(config.long);
|
||||
this.MACDsignal = new EMA(config.signal);
|
||||
this.PPOsignal = new EMA(config.signal);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(price) {
|
||||
this.short.update(price);
|
||||
this.long.update(price);
|
||||
this.calculatePPO();
|
||||
this.MACDsignal.update(this.result.macd);
|
||||
this.MACDhist = this.result.macd - this.MACDsignal.result;
|
||||
this.PPOsignal.update(this.result.ppo);
|
||||
this.PPOhist = this.result.ppo - this.PPOsignal.result;
|
||||
|
||||
this.result.MACDsignal = this.MACDsignal.result;
|
||||
this.result.MACDhist = this.MACDhist;
|
||||
this.result.PPOsignal = this.PPOsignal.result;
|
||||
this.result.PPOhist = this.PPOhist;
|
||||
}
|
||||
|
||||
Indicator.prototype.calculatePPO = function() {
|
||||
this.result.shortEMA = this.short.result;
|
||||
this.result.longEMA = this.long.result;
|
||||
this.result.macd = this.result.shortEMA - this.result.longEMA;
|
||||
this.result.ppo = 100 * (this.result.macd / this.result.longEMA);
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,53 @@
|
||||
// required indicators
|
||||
var SMMA = require('./SMMA.js');
|
||||
|
||||
var Indicator = function (settings) {
|
||||
this.input = 'candle';
|
||||
this.lastClose = null;
|
||||
this.weight = settings.interval;
|
||||
this.avgU = new SMMA(this.weight);
|
||||
this.avgD = new SMMA(this.weight);
|
||||
this.u = 0;
|
||||
this.d = 0;
|
||||
this.rs = 0;
|
||||
this.result = 0;
|
||||
this.age = 0;
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function (candle) {
|
||||
var currentClose = candle.close;
|
||||
|
||||
if (this.lastClose === null) {
|
||||
// Set initial price to prevent invalid change calculation
|
||||
this.lastClose = currentClose;
|
||||
|
||||
// Do not calculate RSI for this reason - there's no change!
|
||||
this.age++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentClose > this.lastClose) {
|
||||
this.u = currentClose - this.lastClose;
|
||||
this.d = 0;
|
||||
} else {
|
||||
this.u = 0;
|
||||
this.d = this.lastClose - currentClose;
|
||||
}
|
||||
|
||||
this.avgU.update(this.u);
|
||||
this.avgD.update(this.d);
|
||||
|
||||
this.rs = this.avgU.result / this.avgD.result;
|
||||
this.result = 100 - (100 / (1 + this.rs));
|
||||
|
||||
if (this.avgD.result === 0 && this.avgU.result !== 0) {
|
||||
this.result = 100;
|
||||
} else if (this.avgD.result === 0) {
|
||||
this.result = 0;
|
||||
}
|
||||
|
||||
this.lastClose = currentClose;
|
||||
this.age++;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,21 @@
|
||||
// required indicators
|
||||
// Simple Moving Average - O(1) implementation
|
||||
|
||||
var Indicator = function(windowLength) {
|
||||
this.input = 'price';
|
||||
this.windowLength = windowLength;
|
||||
this.prices = [];
|
||||
this.result = 0;
|
||||
this.age = 0;
|
||||
this.sum = 0;
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(price) {
|
||||
var tail = this.prices[this.age] || 0; // oldest price in window
|
||||
this.prices[this.age] = price;
|
||||
this.sum += price - tail;
|
||||
this.result = this.sum / this.prices.length;
|
||||
this.age = (this.age + 1) % this.windowLength
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,28 @@
|
||||
// required indicators
|
||||
var SMA = require('./SMA');
|
||||
|
||||
var Indicator = function (weight) {
|
||||
this.input = 'price';
|
||||
this.sma = new SMA(weight);
|
||||
this.weight = weight;
|
||||
this.prices = [];
|
||||
this.result = 0;
|
||||
this.age = 0;
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function (price) {
|
||||
this.prices[this.age] = price;
|
||||
|
||||
if(this.prices.length < this.weight) {
|
||||
this.sma.update(price);
|
||||
} else if(this.prices.length === this.weight) {
|
||||
this.sma.update(price);
|
||||
this.result = this.sma.result;
|
||||
} else {
|
||||
this.result = (this.result * (this.weight - 1) + price) / this.weight;
|
||||
}
|
||||
|
||||
this.age++;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,38 @@
|
||||
// required indicators
|
||||
var EMA = require('./EMA.js');
|
||||
|
||||
var Indicator = function(settings) {
|
||||
this.input = 'candle';
|
||||
this.lastClose = null;
|
||||
this.tsi = 0;
|
||||
this.inner = new EMA(settings.long);
|
||||
this.outer = new EMA(settings.short);
|
||||
this.absoluteInner = new EMA(settings.long);
|
||||
this.absoluteOuter = new EMA(settings.short);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(candle) {
|
||||
var close = candle.close;
|
||||
var prevClose = this.lastClose;
|
||||
|
||||
if (prevClose === null) {
|
||||
// Set initial price to prevent invalid change calculation
|
||||
this.lastClose = close;
|
||||
// Do not calculate TSI on first close
|
||||
return;
|
||||
}
|
||||
|
||||
var momentum = close - prevClose;
|
||||
|
||||
this.inner.update(momentum);
|
||||
this.outer.update(this.inner.result);
|
||||
|
||||
this.absoluteInner.update(Math.abs(momentum));
|
||||
this.absoluteOuter.update(this.absoluteInner.result);
|
||||
|
||||
this.tsi = 100 * this.outer.result / this.absoluteOuter.result;
|
||||
|
||||
this.lastClose = close;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
@@ -0,0 +1,45 @@
|
||||
// required indicators
|
||||
var SMA = require('./SMA.js');
|
||||
|
||||
var Indicator = function(settings) {
|
||||
this.input = 'candle';
|
||||
this.lastClose = 0;
|
||||
this.uo = 0;
|
||||
this.firstWeight = settings.first.weight;
|
||||
this.secondWeight = settings.second.weight;
|
||||
this.thirdWeight = settings.third.weight;
|
||||
this.firstLow = new SMA(settings.first.period);
|
||||
this.firstHigh = new SMA(settings.first.period);
|
||||
this.secondLow = new SMA(settings.second.period);
|
||||
this.secondHigh = new SMA(settings.second.period);
|
||||
this.thirdLow = new SMA(settings.third.period);
|
||||
this.thirdHigh = new SMA(settings.third.period);
|
||||
}
|
||||
|
||||
Indicator.prototype.update = function(candle) {
|
||||
var close = candle.close;
|
||||
var prevClose = this.lastClose;
|
||||
var low = candle.low;
|
||||
var high = candle.high;
|
||||
|
||||
var bp = close - Math.min(low, prevClose);
|
||||
var tr = Math.max(high, prevClose) - Math.min(low, prevClose);
|
||||
|
||||
this.firstLow.update(tr);
|
||||
this.secondLow.update(tr);
|
||||
this.thirdLow.update(tr);
|
||||
|
||||
this.firstHigh.update(bp);
|
||||
this.secondHigh.update(bp);
|
||||
this.thirdHigh.update(bp);
|
||||
|
||||
var first = this.firstHigh.result / this.firstLow.result;
|
||||
var second = this.secondHigh.result / this.secondLow.result;
|
||||
var third = this.thirdHigh.result / this.thirdLow.result;
|
||||
|
||||
this.uo = 100 * (this.firstWeight * first + this.secondWeight * second + this.thirdWeight * third) / (this.firstWeight + this.secondWeight + this.thirdWeight);
|
||||
|
||||
this.lastClose = close;
|
||||
}
|
||||
|
||||
module.exports = Indicator;
|
||||
Reference in new issue
Block a user