04-13-2018, 11:10 AM
Hi all, I would like to thank Mike and the community for all the wonderful work on Gekko!
Even if I'm not a javascript expert I tried to give my small contribution writing the code as a native indicator (STC.js):
this is a test strategy which buys and sells at oversold/overbought crossing (testSTC.js):
and finally this is the code for testSTC.toml:
I couldn't make any serious test, just briefly compared with plotted indicator values, however I compared my result with Zschoro's implementation and found some different values.
Maybe somebody can have a look at the code or has some thoughts about how to test it against known correct results.
Even if I'm not a javascript expert I tried to give my small contribution writing the code as a native indicator (STC.js):
Code:
// SCHAFF TREND CYCLE INDICATOR
// ported to Gekko from ProRealCode.com Indicator: https://www.prorealcode.com/prorealtime-indicators/schaff-trend-cycle2/
// 2018 rob2112
var _ = require('lodash');
// required indicators
var EMA = require('./EMA.js');
var Indicator = function(config) {
this.input = 'price'
this.result = false;
this.TCLen = config.TCLen;
this.Factor = config.Factor;
this.MA1Len = config.MA1Len;
this.MA2Len = config.MA2Len;
this.MA1 = new EMA(this.MA1Len);
this.MA2 = new EMA(this.MA2Len);
this.XMAChistory = [];
this.PFhistory = [];
this.PF = 0;
this.PFF = 0;
this.prevPF = 0;
this.prevPFF = 0;
}
Indicator.prototype.update = function (candle)
{
// macd
this.MA1.update(candle);
this.MA2.update(candle);
this.XMAC = this.MA1.result-this.MA2.result;
// macd stochastic
this.XMAChistory.push(this.XMAC);
if(_.size(this.XMAChistory) > this.TCLen)
// remove oldest XMAC value
this.XMAChistory.shift();
this.Value1 = _.min(this.XMAChistory);
this.Value2 = _.max(this.XMAChistory) - this.Value1;
// %Fast K of macd
if (this.Value2 > 0) this.Frac1 = ((this.XMAC -this.Value1)/this.Value2) * 100;
else this.Value2 = this. prevValue2;
// smoothed %Fast D of macd
this.PF = this.prevPF + this.Factor*(this.Frac1-this.prevPF);
// %Fast D stochastic
this.PFhistory.push(this.PF);
if(_.size(this.PFhistory) > this.TCLen)
// remove oldest PF value
this.PFhistory.shift();
this.Value3 = _.min(this.PFhistory);
this.Value4 = _.max(this.PFhistory) - this.Value3;
// %Fast K of PF
if (this.Value4 > 0) this.Frac2 = ((this.PF -this.Value3)/this.Value4)* 100;
else this.Value4 = this. prevValue4;
// smoothed %Fast D of PF
this.PFF = this.prevPFF + this.Factor*(this.Frac2-this.prevPFF);
this.result = this.PFF;
if (this.Value2) this.prevValue2 = this.Value2;
if (this.Value4) this.prevValue4 = this.Value4;
if (this.PF) this.prevPF = this.PF;
if (this.PFF) this.prevPFF = this.PFF;
}
module.exports = Indicator;
this is a test strategy which buys and sells at oversold/overbought crossing (testSTC.js):
Code:
// This is a basic example strategy for Gekko.
// For more information on everything please refer
// to this document:
//
// https://gekko.wizb.it/docs/strategies/creating_a_strategy.html
//
var log = require('../core/log');
// Let's create our own strat
var strat = {};
// Prepare everything our method needs
strat.init = function() {
this.input = 'candle';
this.currentTrend = 'long';
this.requiredHistory = 0;
this.STC = this.addIndicator('stc', 'STC', this.settings);
}
// What happens on every new candle?
strat.update = function(candle) {
this.stc = this.indicators.stc.result;
}
// For debugging purposes.
strat.log = function() {
console.log('STC:'+this.stc.toFixed(3));
//log.debug('\t', this.stc.toFixed(3));
}
// Based on the newly calculated
// information, check if we should
// update or not.
strat.check = function() {
// Test advice buying when exiting oversold condition and selling when exiting overbought condition
if(this.stc > 20 && this.prevstc < 20) this.advice('long');
if(this.stc < 80 && this.prevstc > 80) this.advice('short');
this.prevstc = this.stc;
}
module.exports = strat;
and finally this is the code for testSTC.toml:
Code:
TCLen = 10
Factor = 0.5
MA1Len = 23
MA2Len = 50
I couldn't make any serious test, just briefly compared with plotted indicator values, however I compared my result with Zschoro's implementation and found some different values.
Maybe somebody can have a look at the code or has some thoughts about how to test it against known correct results.