molestiasconsectetur
Version:
Multi Exchange Crypto Currency Trading bot, Data Analysis Library and Strategy Back testing Engine
505 lines (468 loc) • 19.4 kB
JavaScript
let {DataLoaderBuilder,Strategy,utils,getModels} = require("../engine/BitFox");
let{ Point, Edge, IndicatorConvergence} = getModels;
const profitTargetPct = 0.003
const stopLossPct = 0.002
const longExitCallback = (entryPrice, currentPrice, profitTargetPct, stopLossPct=null) =>{
let data = {};
data.side = 'long'
data.isInProfit = currentPrice > utils.calculateLongProfitTarget(entryPrice,profitTargetPct);
data.isStopped = (stopLossPct=== null) ? false : currentPrice < utils.calculateLongStopTarget(entryPrice,stopLossPct);
return data;
}
const shortExitCallback = (entryPrice, currentPrice, profitTargetPct, stopLossPct=null) =>{
let data = {};
data.side = 'short'
data.isInProfit = currentPrice < utils.calculateShortProfitTarget(entryPrice,profitTargetPct);
data.isStopped = (stopLossPct=== null) ? false : currentPrice > utils.calculateShortStopTarget(entryPrice,stopLossPct);
return data;
}
function checkProfitStatus(waitFor, pointA, buffer, i) {
return waitFor(pointA.getX(), buffer[i][2], profitTargetPct, stopLossPct).isInProfit ||
waitFor(pointA.getX(), buffer[i][3], profitTargetPct, stopLossPct).isStopped;
}
function getExitPoint(pointB, buffer, i) {
pointB = Point.getInstance();
pointB.setX(buffer[i][4]);
pointB.setY(new Date(buffer[i][0]));
pointB.setIndex(i);
return pointB;
}
function getEntryPoint(pointA, buffer, i) {
pointA = Point.getInstance();
pointA.setX(buffer[i][4]);
pointA.setY(new Date(buffer[i][0]));
pointA.setIndex(i);
return pointA;
}
let dataLoader = DataLoaderBuilder()
.setExchangeName("bybit")
.setPollRate(10)
.setRequiredCandles(200)
.setStorage()
.setSymbol("BTCUSDT")
.setTimeFrame("5m")
.setVerbose(false)
.build();
let kline = null;
const createSuperTrendConvergence = (data, buffer, diff) =>{
let trendSet = null;
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
for( let i =diff; i < data.length; i++){
if(i === diff && isRefresh){
trendSet = data[i].trend;
pointA = getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(data[i].trend !== trendSet){
pointB = getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(`SuperTrend::${data[i].trend}`);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
trendSet = data[i].trend;
convBuffer.push(convergence);
isRefresh = true;
}
}
return convBuffer;
}
function isExit(isRefresh, waitFor, pointA, buffer, i) {
return !isRefresh && checkProfitStatus(waitFor, pointA, buffer, i);
}
const createRsiConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastRSI =50;
let waitFor=null;
let context = "";
for( let i =diff; i < data.length; i++){
lastRSI = data[i]
if((lastRSI < 30 || lastRSI > 70) && isRefresh){
context = "RSI"+(lastRSI < 30 ?"::Long" : "::Short")
waitFor = (lastRSI < 30) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB = getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
isRefresh = true;
}
}
return convBuffer;
}
const createAtrConvergence = (data, buffer, diff) =>{
}
const createBollingerConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastBoll =null;
let waitFor=null;
let context = "";
const isBullish =(lastBoll, currentPrice)=>{
let {lower} = lastBoll
return currentPrice <= lower;
}
const isBearish =(lastBoll,currentPrice)=>{
let {upper} = lastBoll
return currentPrice >= upper;
}
for( let i =diff; i < data.length; i++){
lastBoll = data[i]
if((isBearish(lastBoll,buffer[i][2]) || isBullish(lastBoll,buffer[i][2])) && isRefresh){
context = "Bollinger"+( isBullish(lastBoll,buffer[i][2]) ? "::Long" : "::Short")
waitFor = isBullish(lastBoll,buffer[i][2]) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
isRefresh = true;
}
}
return convBuffer;
}
const createMfiConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastMFI =50;
let waitFor=null;
let context = "";
for( let i =diff; i < data.length; i++){
lastMFI = data[i]
if((lastMFI < 20 || lastMFI > 80) && isRefresh){
context = "MFI"+(lastMFI < 20 ?"::Long" : "::Short")
waitFor = (lastMFI < 30) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index) ;
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
isRefresh = true;
}
}
return convBuffer;
}
const createStochConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastStock ={k:50,d:50};
let waitFor=null;
let context = "";
const isBullish =(lastStoch)=>{
let {k,d} = lastStoch
return k < 2 && d < 2 && ( k>d)
}
const isBearish =(lastStoch)=>{
let {k,d} = lastStoch
return k >70 && d > 70 && (k < d)
}
for( let i =diff; i < data.length; i++){
lastStock = data[i]
if((isBearish(lastStock) || isBullish(lastStock)) && isRefresh){
context = "Stoch"+( isBullish(lastStock) ? "::Long" : "::Short")
waitFor = isBullish(lastStock) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
isRefresh = true;
}
}
return convBuffer;
}
const createEmaTrendConvergence = (fast, slow, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastFast = fast;
let lastSlow = slow;
let waitFor=null;
let context = "";
let AWAIT_CROSS_UP = false;
let AWAIT_CROSS_DOWN = false;
let lastEntry = "";
const isCrossUp =(fast,slow)=>{
return fast > slow;
}
const isCrossDown =(fast,slow)=>{
return fast < slow;
}
for( let i =diff; i < slow.length; i++){
lastFast = fast[i]
lastSlow = slow[i]
if(!AWAIT_CROSS_UP && !AWAIT_CROSS_DOWN){
AWAIT_CROSS_UP = lastFast < lastSlow;
AWAIT_CROSS_DOWN = lastFast > lastSlow;
continue;
}
if((isCrossUp(lastFast, lastSlow) || isCrossDown(lastFast, lastSlow)) && isRefresh){
context = "Stoch"+( isCrossUp(lastFast, lastSlow) ? "::Long" : "::Short")
waitFor =isCrossUp(lastFast, lastSlow) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
lastEntry = isCrossUp(lastFast,lastFast) ? "long" : 'short'
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
AWAIT_CROSS_DOWN = false;
AWAIT_CROSS_UP = false;
isRefresh = true;
}
}
return convBuffer;
}
const createZemaCrossConvergence = (fast, slow, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastFast = fast;
let lastSlow = slow;
let waitFor=null;
let context = "";
let AWAIT_CROSS_UP = false;
let AWAIT_CROSS_DOWN = false;
let lastEntry = "";
const isCrossUp =(fast,slow)=>{
return fast > slow;
}
const isCrossDown =(fast,slow)=>{
return fast < slow;
}
for( let i =diff; i < slow.length; i++){
lastFast = fast[i]
lastSlow = slow[i]
if(!AWAIT_CROSS_UP && !AWAIT_CROSS_DOWN){
AWAIT_CROSS_UP = lastFast < lastSlow;
AWAIT_CROSS_DOWN = lastFast > lastSlow;
continue;
}
if((isCrossUp(lastFast, lastSlow) || isCrossDown(lastFast, lastSlow)) && isRefresh){
context = "ZEMA"+( isCrossUp(lastFast, lastSlow) ? "::Long" : "::Short")
waitFor =isCrossUp(lastFast, lastSlow) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
lastEntry = isCrossUp(lastFast,lastFast) ? "long" : 'short'
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
AWAIT_CROSS_DOWN = false;
AWAIT_CROSS_UP = false;
isRefresh = true;
}
}
return convBuffer;
}
const createSmaTrendConvergence = (fast, slow, buffer, diff) =>{
return createEmaTrendConvergence(fast, slow, buffer, diff)
}
const createFloorConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let reloadPivots = true;
let lastFloor =null;
let waitFor=null;
let context = "";
const isBullish =(lastFloor, currentPrice)=>{
let {s3} = lastFloor.floor
return currentPrice <= s3;
}
const isBearish =(lastFloor,currentPrice)=>{
let {r3} = lastFloor.floor
return currentPrice >= r3;
}
for( let i =diff; i < data.length; i++){
lastFloor = lastFloor = reloadPivots ? data[i] : lastFloor;
reloadPivots = false
if((isBearish(lastFloor,buffer[i][2]) || isBullish(lastFloor,buffer[i][2])) && isRefresh){
context = "FloorPivots"+( isBullish(lastFloor,buffer[i][2]) ? "::Long" : "::Short")
waitFor = isBullish(lastFloor,buffer[i][2]) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
reloadPivots = true;
isRefresh = true;
}
}
return convBuffer;
}
const createWoodiesConvergence = (data, buffer, diff) =>{
let convBuffer = [];
let pointA = null;
let pointB = null;
let edge = null;
let isRefresh = true;
let lastFloor =null;
let waitFor=null;
let reloadPivots = true;
let context = "";
const isBullish =(lastFloor, currentPrice)=>{
let {s2} = lastFloor.woodies
return currentPrice <= s2;
}
const isBearish =(lastFloor,currentPrice)=>{
let {r2} = lastFloor.woodies
return currentPrice >= r2;
}
for( let i =diff; i < data.length; i++){
lastFloor = reloadPivots ? data[i] : lastFloor;
reloadPivots = false;
if((isBearish(lastFloor,buffer[i][2]) || isBullish(lastFloor,buffer[i][2])) && isRefresh){
context = "Woodies"+( isBullish(lastFloor,buffer[i][2]) ? "::Long" : "::Short")
waitFor = isBullish(lastFloor,buffer[i][2]) ? longExitCallback : shortExitCallback
pointA= getEntryPoint(pointA, buffer, i);
isRefresh = false;
}
if(isExit(isRefresh, waitFor, pointA, buffer, i)){
pointB= getExitPoint(pointB, buffer, i);
edge = Edge.getInstance(pointA, pointB)
let convergence = IndicatorConvergence.getInstance(context);
convergence.setEdge(edge)
convergence.setEdgeIndexes(pointA.getPoint().index, pointB.getPoint().index)
convergence.setStopped(waitFor(pointA.getX(), buffer[i][4], profitTargetPct, stopLossPct).isStopped);
convBuffer.push(convergence);
reloadPivots = true;
isRefresh = true;
}
}
return convBuffer;
}
const test = async () =>{
let indicators = ["SuperTrendIndicator",
"RsiIndicator",
"AtrIndicator",
"BollingerIndicator",
"MfiIndicator",
"StochasticIndicator",
"EMAIndicator",
"SmaIndicator",
"FloorPivots",
"Woodies"];
await dataLoader.setUpClient()
let IndicatorConvergenceList = [];
let indicatorData = {}
let data = await dataLoader.load();
let { o,h,l,c,v, buffer } = utils.createIndicatorData(data)
// Strategy.INDICATORS.PatternRecognitionIndicator.getPatterns().forEach( key =>{
// if(key !== "getPatterns"){
// console.log(`Pattern ${key} `,indicatorData[key] = Strategy.INDICATORS.PatternRecognitionIndicator[key](o,h,l,c,v));
// }
// });
// indicatorData["emaSlow"] = Strategy.INDICATORS["EMAIndicator"].getData(o,h,l,c,v,{period:200},buffer);
// indicatorData["emaFast"] = Strategy.INDICATORS["EMAIndicator"].getData(o,h,l,c,v,{period:55},buffer);
// indicatorData["smaSlow"] = Strategy.INDICATORS["SmaIndicator"].getData(o,h,l,c,v,{period:200},buffer);
// indicatorData["smaFast"] = Strategy.INDICATORS["SmaIndicator"].getData(o,h,l,c,v,{period:55},buffer);
indicatorData["zmaSlow"] = Strategy.INDICATORS["ZEMAIndicator"].getData(o,h,l,c,v,{period:200},buffer);
indicatorData["zmaFast"] = Strategy.INDICATORS["ZEMAIndicator"].getData(o,h,l,c,v,{period:55},buffer);
//
let min = 100000;
Object.keys(indicatorData).forEach( key =>{
if(indicatorData[key].length < min){ min = indicatorData[key].length}
})
//
let diff = (buffer.length - min);
let length = buffer.length;
//
// IndicatorConvergenceList.push(createSuperTrendConvergence(indicatorData["SuperTrendIndicator"],buffer,diff));
// IndicatorConvergenceList.push(createRsiConvergence(indicatorData["RsiIndicator"],buffer,diff));
// IndicatorConvergenceList.push(createBollingerConvergence(indicatorData["BollingerIndicator"],buffer,diff));
// IndicatorConvergenceList.push(createMfiConvergence(indicatorData["MfiIndicator"],buffer,diff));
// IndicatorConvergenceList.push(createStochConvergence(indicatorData["StochasticIndicator"],buffer,diff));
// IndicatorConvergenceList.push(createEmaTrendConvergence(indicatorData["emaFast"],indicatorData["emaSlow"],buffer,diff));
// IndicatorConvergenceList.push(createSmaTrendConvergence(indicatorData["smaFast"],indicatorData["smaSlow"],buffer,diff));
// IndicatorConvergenceList.push(createFloorConvergence(indicatorData["FloorPivots"],buffer,diff));
// IndicatorConvergenceList.push(createWoodiesConvergence(indicatorData["Woodies"],buffer,diff));
IndicatorConvergenceList.push(createZemaCrossConvergence(indicatorData["zmaFast"],indicatorData["zmaSlow"],buffer,diff));
//
let obj = {};
let barCount=[];
IndicatorConvergenceList.forEach(convergence =>{
let targetKey = convergence[0].getContext()
obj[targetKey] = {
stopped:0,
wins:0,
overall: convergence.length,
winPct:0,
avgBarCount:0,
};
convergence.forEach( entry =>{
let inst = entry.toInstance();
if(inst.isStopped){ obj[targetKey].stopped = obj[targetKey].stopped+1 }
else{
obj[targetKey].wins = obj[targetKey].wins + 1;
}
barCount.push((inst.index[1]-inst.index[0]))
})
obj[targetKey].winPct = (obj[targetKey].wins / obj[targetKey].overall) * 100;
obj[targetKey].avgBarCount = utils.average(barCount);
});
console.log(JSON.stringify(obj,null,2));
}
test();