Strategies – Framework [working with assets]

As we’ve now coded our first bot. It’s time to apply some actual assets, or coins to the bot.

A single strategy can handle multiple assets at the same time, but it’s up to your TAAPI.IO Rate Limits, how fast you can analyse coins. As an example, say that you’re on the pro plan. This gives you 30 api requests per 15 seconds, which equals 2 calls per second. But each request can handle 20 indicator calculations. This means that if you’re working with 20 assets, then you can analyse all these in 10 seconds, assuming you only need 20 indicators or less per coin.

Manual assets list

Lets assume that you have your favourite coins, and you only want to trade these. This can easily be accomplished by simply adding these to your bot. Take a look at the taapi-strategies/strategy/src/index.js file:

// Require taapi-strategies
const TaapiStrategies = require('taapi-strategies');

// Create a new instance of taapi-strategies
const app = new TaapiStrategies.default();

// Start the app
app.start({
    "start-bot": true, // Start the bot
    "start-api": true, // Start a REST API to interact with the bot
    "setup-webhook-endpoint": true, // Setup a webhook endpoint to receive signals
});

Notice the "start-api": true option, this boots up a REST API which allows you to interact with your bot, and one of the REST calls is to add assets to your bot. Simply make a POST request to your bot URL, which should be running on your localhost:3002 (unless you changed it).

[POST] http://localhost:3002/create-trade

Above we’re simply using one of the many popular REST Clients. This one is Insomnia.

As you can see, the trade has been added to the bot, and upon the next FSM tick, all trades added will be executed in the order they were added, separated by the configured FSM Trade Delay.

Scanning

The above manual list is fine, but if you’d like dive into a little deeper waters, then scanning the markets (or an exchange) is a powerful way of finding interesting assets to trade.

Making up fictive examples as we go, so, say that according to your strategy, we are looking to trade any coin where the RSI has fallen below the 30 line (oversold), and you’re waiting for a reversal signal. Let’s call this reversal signal the MACD Crossover to the upside, and let’s keep it to this for simplicity.

Now let’s say that you’re working with the hourly timeframe, and the Binance Futures USDT market, which at this writing contains roughly 200 symbols. And sticking to our pro plan, a total scan of this market will take: 200 assets on the hourly timeframe / 2 calls per second = 100 seconds which is 1 minute and 40 seconds. This is acceptable, so let’s go with this. Later we’ll get into longer asset lists, and discus our options.

Let’s take a look at our Phobos scanner:

// 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;

Finally, let’s enable the scanner in the configuration:

bot:
    id: "phobos"
    fsm:
        isEnabled: true
        tradeDelay: 1000 # How big a delay between trades in milliseconds
        tick:
            schedule: "1 */5 * * * *"
    scanner:
        isEnabled: true
        assetDelay: 500 # How big a delay between assets in milliseconds
        tick:
            schedule: "1 1 * * * *"

trading:
    liveEnabled: false

We’re now setting the isEnabled property to true and the assetDelay to 500ms (aka 2 calls per second), and last but not least a cron expression tick.schedule for when the scanner needs to kick in! In this case 1 second past the first minute of every hour. Why this complicated? Well, keep in mind that the FSM will also call TAAPI every 1 second past every 5 minutes, this essentially gives us 4 minutes to complete a scan that only takes 1 minute and 40 seconds, so we can stay within the pro plan, by compromising a one minute scan delay which really doesn’t matter much for this strategy on the hourly timeframe. Or maybe it does, but then please upgrade to a higher plan!

Conclusion

Wrapping up this chapter: In theory, this will set us up for assets that are ready to go long, and when adding them to the list of traded assets, the FSM will kick in and evaluate the states, starting from state start. Now the keen observer will notice that going short from the start state based on the scanner results, might be a bad idea, so this strategy might need some adjustments.