molestiasconsectetur
Version:
Multi Exchange Crypto Currency Trading bot, Data Analysis Library and Strategy Back testing Engine
135 lines (118 loc) • 4.58 kB
JavaScript
const {Strategy} = require("./Strategy")
/**
* Class RSITrend
*
* This class is a super simple RSI Strategy implementation
*
* It enters long trade positions when the trend is up and the RSI is below given threshold default is 30
* It enters short trade positions when the trend is down and the RSI above given threshold default is 80
*
* The trend direction is determined by checking 2 exponential moving average a fast and a slow moving.
*
*/
class RSITrend extends Strategy{
static RSI=Strategy.INDICATORS.RsiIndicator.className;
static MA= Strategy.INDICATORS.SmaIndicator.className;
/**
* @typedef {Object} rsiTrendExtras Engine configuration options
* @property {Number} fastPeriod Strategy property, the fast period to use for moving average
* @property {Number} slowPeriod Strategy property, the slow period to use for moving average
* @property {Number} rsiPeriod Strategy property, the rsi period
*
*/
/**
* @typedef {Object} rsiTrendConfig Strategy configuration options
* @property {number} sidePreference Strategy property, the trading preference long|short/biDirectional
* @property {rsiTrendExtras} strategyExtras Strategy property, strategy specific arguments for custom implementations
*/
/**
*
* @param args {rsiTrendConfig} - The Strategies Parameters
* @return {RSITrend}
*/
static init(args){
return new RSITrend( args);
}
/**
*
* @param args {rsiTrendConfig} - The Strategies Parameters
*/
constructor(args) {
super(args);
this.setContext("RSITrend")
this.RSI = null;
this.maFast = null;
this.maSlow = null;
this.sidePreference = args.sidePreference || 'biDirectional';
}
/**
*
* @param state {String} The Current State of the Strategy execution
*/
setState(state){ this.state = state; }
/**
*
* @return {String} The Current State of the Strategy execution
*/
getState(){ return this.state}
/**
*
* @param klineCandles {Array<Array<Number>>} Sets up the Strategy with Indicator Data and Historical Candle data
*/
async setup(klineCandles){
this.setIndicator(klineCandles,{period:this.custom.rsiPeriod || 14},RSITrend.RSI);
this.RSI = this.getIndicator()
this.setIndicator(klineCandles,{period:this.custom.fastPeriod || 20},RSITrend.MA);
this.maFast = this.getIndicator()
this.setIndicator(klineCandles,{period:this.custom.slowPeriod || 30},RSITrend.MA);
this.maSlow = this.getIndicator();
return this;
}
/**
*
* @return {Array<any>} returns an Indicator Data Array
*/
getIndicator(){return super.getIndicator()}
/**
*
* @param {number} _index
* @param {boolean} isBackTest
* @param {ticker} ticker
* @return {Promise<{custom: {}, context: null, state, timestamp: number}>}
*/
async run(_index=0, isBackTest=false, ticker=null){
var me = this;
let currPrice = this.kline.o[isBackTest ? _index : this.kline.o.length-1];
let currMa = this.maSlow[isBackTest ? _index : this.maSlow.length-1];
let currFastMa = this.maFast[isBackTest ? _index : this.maFast.length-1];
let currRsi = this.RSI[isBackTest ? _index : this.RSI.length - 1];
if(this.state === this.states.STATE_ENTER_LONG || this.state === this.states.STATE_ENTER_SHORT){
this.state = this.states.STATE_AWAIT_ORDER_FILLED;
return this.getStrategyResult(this.state, {});
}if(this.state === this.states.STATE_PENDING){
if(currRsi <=30 && currPrice>=currMa ){
this.state = (this.sidePreference === 'long' || this.sidePreference === 'biDirectional') ? this.states.STATE_ENTER_LONG : this.state;
}
if(currRsi >=70 && currPrice<=currMa ){
this.state = (this.sidePreference === 'short' || this.sidePreference === 'biDirectional') ? this.states.STATE_ENTER_SHORT : this.state;
}
return this.getStrategyResult(this.state,{
rsi:currRsi,
close:currPrice,
maSlow:currMa,
maFast:currFastMa
});
}
return this.getStrategyResult(this.state,{
rsi:currRsi,
close:currPrice,
maSlow:currMa,
maFast:currFastMa
});
}
}
/**
*
* @type {{RSITrend: RSITrend}}
*/
module.exports = {RSITrend:RSITrend}