molestiasconsectetur
Version:
Multi Exchange Crypto Currency Trading bot, Data Analysis Library and Strategy Back testing Engine
211 lines (180 loc) • 6.93 kB
JavaScript
const {State} = require("../lib/states/States");
const utils = require("../lib/utility/util");
let Indicators = require("../lib/indicators/Indicators")
/**
* Class Strategy
*
* This class is the Base class for all current and future Strategies
*
*/
/**
* @typedef {Object} strategyConfiguration Strategy configuration options
* @property {String} sidePreference Strategy property, the trading preference lon|short/biDirectional
* @property {any} strategyExtras Strategy property, strategy specific arguments for custom implementations
*
*
*/
class Strategy {
static INDICATORS = Indicators;
/**
*
* @param args {strategyConfiguration} Strategy Specific arguments for set up
* @constructor
*/
constructor(args=null){
this.states=State;
this.state = this.states.STATE_PENDING;
this.indicators = Indicators;
this.indicator = null;
this.kline =null;
this.currentPrice =0;
this.args = args;
this.custom = args.RSITrend || {};
this.sidePreference = args.sidePreference || 'biDirectional';
this.allowLong = true;
this.allowShort = true;
this.context = null;
}
/**
*
* @param context {String} sets the current context of the Strategy
*/
setContext(context){
this.context = context;
}
/**
*
* @return {{context: any, params: *}} Returns the current context of this Strategy
*/
getContext(){
return {context:this.context,params:this.args};
}
/**
*
* @param state {String } allows setting the State for Strategy from an external context
*/
setState(state){ this.state = state; }
/**
*
* @param handler {any} an EventHandler instance capable of firing and listening to events
*/
setEventHandler(handler){
this.eventHandler = handler;
}
/**
*
* @param klineCandles {Array<Array<Number>>}
* @param args {strategyConfiguration} Indicator related custom parameters that you can supply
* @param target {String} the class name of the Indicator we want to use
*/
setIndicator(klineCandles, args=null, target){
let { o,h,l,c,v, buffer } = utils.createIndicatorData(klineCandles)
this.indicator = Indicators[target].getData(o,h,l,c,v, (args) ? args : this.custom,buffer);
this.kline = { o,h,l,c,v, buffer };
}
/**
*
* @return {any} returns an indicator instance with initialized data
*/
getIndicator(){
return this.indicator;
}
/**
*
* @param state {String} the current state of the Strategy
* @param custom {any} custom parameters that you can add
* @param context {String} the current context of this Strategy
* @return {{custom: {}, context: null, state, timestamp: number}}
*/
getStrategyResult(state, custom={}, context=null){
return { state:state, timestamp:new Date().getTime(), custom:custom, context:this.context}
}
/**
*
* @param sellPrice {Number} the price of the asset
* @param profitTarget {Number} the target percentage you want to hit to buy the asset back
* @return {number} the estimated buyback price
*/
calculateShortProfitTarget(sellPrice, profitTarget){ return sellPrice-(sellPrice*profitTarget);}
/**
*
* @param buyPrice e {Number} the price of the asset
* @param profitTarget {Number} the target percentage you want to hit to sell the asset back
* @return {number} the estimated sell back price
*/
calculateLongProfitTarget(buyPrice, profitTarget){return buyPrice+(buyPrice*profitTarget);}
/**
*
* @param sellPrice {Number} the price of the asset
* @param stopTarget {Number} the target percentage for the stop
* @return {number} the estimated stop loss price
*/
calculateShortStopTarget(sellPrice, stopTarget){ return sellPrice+(sellPrice*stopTarget);}
/**
*
* @param buyPrice {Number} the price of the asset
* @param stopTarget {Number} the target percentage for the stop
* @return {number} the estimated stop loss price
*/
calculateLongStopTarget(buyPrice, stopTarget){return buyPrice-(buyPrice*stopTarget);}
/**
*
* @param args {strategyConfiguration} an object with Strategy required arguments
* @param list {Array<String>} a list of keys to verify that the args instance has these keys
* @return {Boolean}
*/
hasValidArgs(args,list){
return utils.validateRequiredArgs(args,list);
}
/**
*
* @param isBackTest {Boolean} flag to indicate if the current STrategy is called from the BAck Testing Engine
* @param _index {number} the current index of the BackTest run!
* @return {number} the last price of the asset
*/
getApproximateCurrentPrice(isBackTest,_index){
return this.kline.o[isBackTest ? _index : this.kline.c.length-1];
}
/**
*
* @param tradeHistory {any} a trade history instance that holds an entry and an exit order
* @param currentCandle {Array<number>} The current Candle i.e. open, close,high, low data
* @param amount {number} The amount available in this Strategy context
* @return {{amount, funds: number}|{amount: number, funds: number}}
*/
determineUnrealizedBalance(tradeHistory = null, currentCandle, amount, ){
if(tradeHistory!== null && tradeHistory.entryOrder && tradeHistory.exitOrder){
if(tradeHistory.entryOrder.side === 'buy'){
let estimatedFunds = (tradeHistory.entryOrder.amount*tradeHistory.exitOrder.price);
let estimatedAmount = (estimatedFunds/currentCandle[3]);
return{funds:estimatedFunds, amount:estimatedAmount }
}
else{
let estimatedEntryFunds = (tradeHistory.entryOrder.amount*tradeHistory.entryOrder.price);
let estimatedAmount = (estimatedEntryFunds/currentCandle[2]);
let estimatedFunds = (estimatedAmount*currentCandle[2]);
return{funds:estimatedFunds, amount:estimatedAmount }
}
}
else{
return {amount:amount, funds:amount * currentCandle[4]};
}
}
/**
*
* @param currentCandle {Array<number>} The current Candle i.e. open, close,high, low data{Array<number>} The current Candle i.e. open, close,high, low data
* @param amount The amount available in this Strategy context
* @return {{amount, funds: number}}
*/
determineEntryBalance(currentCandle, amount ){
return {amount:amount, funds:amount * currentCandle[4]};
}
/**
*
* @param msg {String} a message for the user to print out the Strategy usage
*/
usage( msg){
console.log(msg);
}
}
module.exports = {Strategy:Strategy}