Skip to content

Commit

Permalink
Fixed StochRSI calculations (DeviaVir#1196)
Browse files Browse the repository at this point in the history
* Fix SRSI calculation

* Added test case for SRSI. Switched RSI and SRSI output to float and adjusted display accordingly

* Oops, disabled all other tests by mistake

* Fix test assertion
  • Loading branch information
aquamanjl committed Jan 22, 2018
1 parent 55868ff commit d653c9f
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ temp.html
logs
.sync
dist/*
.idea
*.iml
3 changes: 2 additions & 1 deletion extensions/strategies/srsi_macd/strategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ module.exports = function container (get, set, clear) {
color = 'red'
}
cols.push(z(8, n(s.period.macd_histogram).format('+00.0000'), ' ')[color])
cols.push(z(8, n(s.period.srsi_K).format('000'), ' ').cyan)
cols.push(z(8, n(s.period.srsi_K).format('00.00'), ' ').cyan)
cols.push(z(8, n(s.period.srsi_D).format('00.00'), ' ').yellow)
}
else {
cols.push(' ')
Expand Down
4 changes: 3 additions & 1 deletion lib/rsi.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var mathjs = require('mathjs')

module.exports = function container (get, set, clear) {
return function rsi (s, key, length) {
if (s.lookback.length >= length) {
Expand Down Expand Up @@ -32,7 +34,7 @@ module.exports = function container (get, set, clear) {
s.period[key] = 100
} else {
var rs = s.period[key + '_avg_gain'] / s.period[key + '_avg_loss']
s.period[key] = Math.round(100 - (100 / (1 + rs)))
s.period[key] = mathjs.round(100 - (100 / (1 + rs)), 2)
}
}
}
Expand Down
85 changes: 62 additions & 23 deletions lib/srsi.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,64 @@
module.exports = function container (get, set, clear) {
return function srsi (s, key, rsi_length, k, d) {
get('lib.rsi')(s, 'rsi', rsi_length)
let RSI = []
let sum = 0
if (typeof s.period.rsi !== 'undefined')
s.lookback.slice(0, k).forEach(function (period) {
if (period.rsi)
RSI.push(period.rsi)
})

let highestRSI = Math.max(...RSI)
let lowestRSI = Math.min(...RSI)
let stochK = ((s.period.rsi - lowestRSI) / (highestRSI - lowestRSI)) * 100

s.lookback.slice(0, d).forEach(period => {
if (period.srsi_K)
sum += period.srsi_K
var mathjs = require('mathjs');

module.exports = function container(get, set, clear) {
return function srsi(s, key, rsi_periods, k_periods, d_periods) {
let samplesRequiredForStochRSI = rsi_periods + k_periods + 1;

if (s.lookback.length >= samplesRequiredForStochRSI - 1) {
let RSI = [];

if (typeof s.period.rsi !== 'undefined') {
RSI.push(s.period.rsi);
} else {
get('lib.rsi')(s, 'rsi', rsi_periods);
RSI.push(s.period.rsi);
}

s.lookback.slice(0, samplesRequiredForStochRSI - 1).forEach(function (period) {
if (period.rsi) {
RSI.push(period.rsi);
}
})
let stochD = sum / d
s.period[key + '_K'] = stochK
s.period[key + '_D'] = stochD
//console.log(s.lookback[0])

RSI.reverse();

if(RSI.length >= samplesRequiredForStochRSI) {
let stochRSI = [];
for(let i = 0; i < (k_periods + d_periods - 1); i++) {
let rsiForPeriod = RSI.slice(i, rsi_periods + i);
let highestRSI = Math.max(...rsiForPeriod);
let lowestRSI = Math.min(...rsiForPeriod);
if(highestRSI == lowestRSI) {
stochRSI.push(0);
} else {
stochRSI.push(((RSI[(rsi_periods - 1) + i] - lowestRSI) / (highestRSI - lowestRSI)) * 100);
}
}

stochRSI.reverse();

let percentK = [];
for(let i = 0; i < k_periods; i++) {
let kData = stochRSI.slice(i, k_periods + i);
if(kData.length == k_periods) {
percentK.push(mathjs.mean(kData));
}
}

let percentD = [];
for(let i = 0; i < d_periods; i++) {
let dData = percentK.slice(i, d_periods + i);
if(dData.length == d_periods) {
percentD.push(mathjs.mean(dData));
}
}

s.period[key + '_K'] = percentK[0] == 0 ? 0 : mathjs.round(percentK[0], 2);
s.period[key + '_D'] = percentD[0] == 0 ? 0 : mathjs.round(percentD[0], 2);

//console.log('lib.srsi: For RSI', RSI[RSI.length - 1], '-', '%K is', s.period[key + '_K'], ', %D is', s.period[key + '_D'], ', period info', s.period);
}
}
}
}
}

2 changes: 1 addition & 1 deletion test/lib/rsi.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('RSI (Relative Strength Index)', function () {
it('should calculate RSI with default period', function () {
(RSI())(normalData, 'rsi', 14)

expect(normalData.period.rsi).toEqual(32)
expect(normalData.period.rsi).toEqual(32.26)
})

it('should set RSI to 100 when there is no losses for the entire period', function() {
Expand Down
37 changes: 37 additions & 0 deletions test/lib/srsi.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
var RSI = require('../../lib/rsi');
var SRSI = require('../../lib/srsi')(RSI);

describe('SRSI (StochRSI Oscillator)', function () {

it('should calculate SRSI with default period', function () {
SRSI(data, 'srsi', 14, 3, 3);

expect(data.period.srsi_K).toEqual(19.38);
expect(data.period.srsi_D).toEqual(23.18);
})
});

var data = {
lookback: [
{rsi: 64.38},
{rsi: 66.71},
{rsi: 70.29},
{rsi: 66.49},
{rsi: 71.47},
{rsi: 76.17},
{rsi: 83.66},
{rsi: 81.85},
{rsi: 82.55},
{rsi: 82.89},
{rsi: 78.60},
{rsi: 64.78},
{rsi: 64.77},
{rsi: 70.05},
{rsi: 68.76},
{rsi: 69.53},
{rsi: 70.15}
].reverse(),
period: {
rsi: 65.61
}
};

0 comments on commit d653c9f

Please sign in to comment.