Skip to content

Commit

Permalink
Bot comments added, packages updates
Browse files Browse the repository at this point in the history
  • Loading branch information
brianvilhelmsen committed Jul 20, 2023
1 parent 901576a commit a385051
Show file tree
Hide file tree
Showing 14 changed files with 4,924 additions and 88 deletions.
116 changes: 38 additions & 78 deletions strategies/deimos/Scanner.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const ta = require("./tools/ta.js");

// Create a new Scanner class
class Scanner {

// Create a constructor that accepts the config, database, utilities, taapiClient, order, and notifications objects
constructor(config, database, utilities, taapiClient, order, notifications) {
this.config = config;
this.database = database;
Expand All @@ -11,94 +11,54 @@ class Scanner {
this.notifications = notifications;
}

// Mandatory scan() function
async scan() {
console.log(`Scanning shortlist...`);

for(let symbol of this.config.bot.scanner.shortlist.assets) {

let allocationStats = await this.database.getAllocationStats();

if(!allocationStats.isMaxedOut) {

try {

this.taapiClient.resetBulkConstructs();

console.log("Scanning", symbol);

// Get latest 2 EMA 9 values
this.taapiClient.addCalculation("ema", symbol, this.config.bot.scanner.interval, "ema_9", { period: 9, backtracks: 2 });

// Get latest 2 EMA 20 values
this.taapiClient.addCalculation("ema", symbol, this.config.bot.scanner.interval, "ema_20", { period: 20, backtracks: 2 });

let ta = await this.taapiClient.executeBulk();

// Get EMA 9 values reversed
let ema9 = ta.ema_9.reverse(); // This makes the the latest value the first value in the array

// Get EMA 20 values reversed
let ema20 = ta.ema_20.reverse(); // This makes the the latest value the first value in the array

// Check for crossover
let isCrossover = ema9[0] > ema20[0] && ema9[1] < ema20[1];

// Check for crossunder
let isCrossunder = ema9[0] < ema20[0] && ema9[1] > ema20[1];

if(isCrossover) {

} else if(isCrossunder) {

}

let candles = scanTa.candles.reverse();

//let pricePrecision = this.utilities.countDecimals(candles[0].close);
let atrPercent = ta.getAtrPercent(candles[0].close, scanTa.atr.value);

let position = "cash";
//let targetPrice = null;

if(
atrPercent >= 1 &&
preScanTa.btcusdt_roc_1h.value > 0 &&
scanTa.roc.value > 0 &&
scanTa.macd[0].valueMACD > scanTa.macd[0].valueMACDSignal &&
scanTa.macd[1].valueMACD < scanTa.macd[1].valueMACDSignal) {
/**
* Fetch the shortlist using the configured shortlist ID and database name.
*
* The shortlist ID is used to identify the shortlist in the database. The next
* parameter is the query, which is used to filter the results. The third parameter
* is the sort, which is used to sort the results. The final parameter is the database
* name, which tells us that this shortlist is stored under a different bot.
*/
let shortlist = await this.database.getShortlist(this.config.bot.scanner.shortlist.id, {}, {}, this.config.bot.scanner.shortlist.dbName);

// Loop through each shortlist item
for(let s in shortlist) {

position = "long";
//targetPrice = this.utilities.roundDecimalValue(candles[0].close + scanTa.atr.value, pricePrecision);
// Get the symbol
let symbolInfo = shortlist[s];

} else if(
atrPercent >= 1 &&
preScanTa.btcusdt_roc_1h.value < 0 &&
scanTa.roc.value < 0 &&
scanTa.macd[0].valueMACD < scanTa.macd[0].valueMACDSignal &&
scanTa.macd[1].valueMACD > scanTa.macd[1].valueMACDSignal) {
// Reset bulk queires
this.taapiClient.resetBulkConstructs();

position = "short";
//targetPrice = this.utilities.roundDecimalValue(candles[0].close - scanTa.atr.value, pricePrecision);
}
// Add RSI calculation
this.taapiClient.addCalculation("rsi", symbolInfo.symbol, "1h", "rsi_1h");

if(position != "cash") {
// Add MACD calculation
this.taapiClient.addCalculation("macd", symbolInfo.symbol, "1h", "macd_1h");

try {
// Fetch all calculations
await this.taapiClient.executeBulk().then( async ta => {

await this.database.createTrade(this.config.exchange.id, symbol, this.config.bot.scanner.interval, `await_${position}`, position);
// If debug mode is enabled, log the scan item
if(this.config.server.debugMode) {
console.log(`Examining ${s}:${symbolInfo.symbol}...`);
}

this.notifications.postSlackMessage(`Creating trade for ${symbol} (${position})`);
// If the RSI is less than 30 and the MACD is greater than the MACD Signal
// then create the trade
if(ta.rsi_1h < 30 && ta.macd_1h.valueMACD > ta.macd_1h.valueMACDSignal) {
await this.database.createTrade(this.config.exchange.id, symbolInfo.symbol, "1h");

} catch( createTradeError ) {
console.log(createTradeError.message);
}
}
} catch( scannerEngineError ) {
console.log(scannerEngineError.message, `Scanning ${symbol} but threw an error (above)`);
// Post a message to Slack
this.notifications.postSlackMessage(`Found trade: ${symbolInfo.symbol} on ${this.config.exchange.id} on 1h.`);
}
});

await this.utilities.sleep(this.config.bot.scanner.assetDelay);
}
// Wait for the configured delay between each asset (rate-limits by TAAPI)
await this.utilities.sleep(this.config.bot.scanner.assetDelay);
}

this.notifications.postSlackMessage(`Scanning complete.`);
Expand Down
18 changes: 18 additions & 0 deletions strategies/deimos/strategy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
bot:
id: "deimos"
fsm:
isEnabled: true
tradeDelay: 500
tick:
schedule: "1 */15 * * * *"
scanner:
isEnabled: true
assetDelay: 500
shortlist:
id: "daily-ema30-cross"
dbName: "strategies_shortlist-daily-ema30-cross"
tick:
schedule: "1 5 * * * *"

trading:
liveEnabled: false
66 changes: 66 additions & 0 deletions strategies/phobos/Scanner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Create a new Scanner class
class Scanner {

// Create a constructor that accepts the config, database, utilities, taapiClient, order, and notifications objects
constructor(config, database, utilities, taapiClient, order, notifications) {
this.config = config;
this.database = database;
this.utilities = utilities;
this.taapiClient = taapiClient;
this.order = order;
this.notifications = notifications;
}

// Mandatory scan() function
async scan() {

// Post a message to Slack
this.notifications.postSlackMessage(`Scanning...`);

// Get all USDT pairs from the exchange through TAAPI
this.taapiClient.getNpmClient().getExchangeSymbols("crypto", this.config.exchange.id, "USDT").then( async symbols => {

// Loop through each symbol
for(let s in symbols) {

// Get the symbol
let symbol = symbols[s];

// Reset bulk queires
this.taapiClient.resetBulkConstructs();

// Add RSI calculation
this.taapiClient.addCalculation("rsi", symbol, "1h", "rsi_1h");

// Add MACD calculation
this.taapiClient.addCalculation("macd", symbol, "1h", "macd_1h");

// Fetch all calculations
await this.taapiClient.executeBulk().then( async ta => {

// If debug mode is enabled, log the scan item
if(this.config.server.debugMode) {
console.log(`Examining ${s}:${symbol}...`);
}

// If the RSI is less than 30 and the MACD is greater than the MACD Signal
// then create the trade
if(ta.rsi_1h.value < 30 && ta.macd_1h.valueMACD > ta.macd_1h.valueMACDSignal) {
await this.database.createTrade(this.config.exchange.id, symbol, "1h");

// Post a message to Slack
this.notifications.postSlackMessage(`Found trade: ${symbol} on ${this.config.exchange.id} on 1h.`);
}
});

// Wait for the configured delay between each asset (rate-limits by TAAPI)
await this.utilities.sleep(this.config.bot.scanner.assetDelay);
};

// Post a message to Slack
this.notifications.postSlackMessage(`Scanning complete.`);
});
}
}

module.exports = Scanner;
4 changes: 4 additions & 0 deletions strategies/phobos/State.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@

// Require the base framework state class
const BotState = require("taapi-strategies/dist/fsm/BotState.js").default;

// Create a new state class
class State extends BotState
{
// Constructor
constructor(trade, config, database, order) {

// Call parent constructor
super(trade, config, database, order);

// Get current price
Expand Down
13 changes: 13 additions & 0 deletions strategies/phobos/State_long.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
// Require your strategy's base state class
const State = require("./State.js");

// Create a new class that extends the base state class
class State_long extends State
{
// Create a constructor that accepts the trade, config, database, and order objects
constructor(trade, config, database, order) {

// Call the base state class constructor
super(trade, config, database, order);
}

/**
* Tick function is called every time the FSM Timer ticks. In our
* example every 1 second past every 5 minutes, plus the trade delay.
*/
async tick() {

// If debug mode is enabled, log the tick
if(this.config.server.debugMode) {
console.log(`Tick - ${this.trade.state}:${this.trade.symbol}:${this.trade.interval}`);
}

// Fetch all indicators added both in this class and in State.js
await this.executeBulk().then( ta => {

// If the 9 EMA is greater than the 20 EMA
if(ta.ema_9 < ta.ema_20) {

// Exit position
Expand All @@ -38,4 +50,5 @@ class State_long extends State
}
}

// Export the class
module.exports = State_long;
11 changes: 9 additions & 2 deletions strategies/phobos/State_short.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@

// Require your strategy's base state class
const State = require("./State.js");

// Create a new class that extends the base state class
class State_short extends State
{
// Create a constructor that accepts the trade, config, database, and order objects
constructor(trade, config, database, order) {

// Call the base state class constructor
super(trade, config, database, order);
}

async tick() {

// If debug mode is enabled, log the tick
if(this.config.server.debugMode) {
console.log(`Tick - ${this.trade.state}:${this.trade.symbol}:${this.trade.interval}`);
}

// Fetch all indicators added both in this class and in State.js
this.executeBulk().then( ta => {

// If the 9 EMA is greater than the 20 EMA
if(ta.ema_9 > ta.ema_20) {

// Exit position
Expand All @@ -35,8 +42,8 @@ class State_short extends State
});
}
});

}
}

// Export the class
module.exports = State_short;
17 changes: 16 additions & 1 deletion strategies/phobos/State_start.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
// Require your strategy's base state class
const State = require("./State.js");

// Create a new class that extends the base state class
class State_start extends State
{
// Create a constructor that accepts the trade, config, database, and order objects
constructor(trade, config, database, order) {

// Call the base state class constructor
super(trade, config, database, order);
}

/**
* Tick function is called every time the FSM Timer ticks. In our
* example every 1 second past every 5 minutes, plus the trade delay.
*/
async tick() {

// If debug mode is enabled, log the tick
if(this.config.server.debugMode) {
console.log(`Tick - ${this.trade.state}:${this.trade.symbol}:${this.trade.interval}`);
}

// Fetch all indicators added both in this class and in State.js
this.executeBulk().then( ta => {

// If the 9 EMA is greater than the 20 EMA
if(ta.ema_9 > ta.ema_20) {

// Enter long position
Expand All @@ -26,7 +37,10 @@ class State_start extends State
}
});

} else if(ta.ema_9 < ta.ema_20) {
}

// If the 9 EMA is less than the 20 EMA
else if(ta.ema_9 < ta.ema_20) {

// Enter short position
this.enterPosition("SHORT", ta.price).then( enterPositionResult => {
Expand All @@ -42,4 +56,5 @@ class State_start extends State
}
}

// Export the class
module.exports = State_start;
9 changes: 6 additions & 3 deletions strategies/phobos/strategy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ bot:
id: "phobos"
fsm:
isEnabled: true
tradeDelay: 1000
tradeDelay: 1000 # How big a delay between trades in milliseconds
tick:
schedule: "15 */5 * * * *"
schedule: "1 */5 * * * *"
scanner:
isEnabled: false
isEnabled: true
assetDelay: 500 # How big a delay between assets in milliseconds
tick:
schedule: "15 0 * * * *"

trading:
liveEnabled: false
Loading

0 comments on commit a385051

Please sign in to comment.