What's new

Level up your trading game with Naxbot

Naxbot R is the world's first fully programmable crypto trading bot with an integrated metaheuristic optimization engine. Join us today to automate the mundane aspects of trading, so you can spend more time crafting profitable strategies. Self-hosted with no DRM or licensing, buy once - own forever!

Create Your First Strategy

  • Views Views: 846
  • Last updated Last updated:
  • Introduction​

    Creating your first Strategy may seem like a daunting task, especially if you have little to no programming experience.

    It may seem overwhelming at first, but it is actually a lot easier than it seems. Be sure to check out the Script Engine Overview, as well as the API Reference before getting started, as it will make this guide a lot clearer.

    Where to begin​

    The first question you will need to ask yourself is what kind of Strategy you want to implement. Do you want to create a trend-following Strategy, or do you want to trade reversals? Do you want to make long-term trades, or focus on short-term scalping?

    A good starting point for finding some strategies is TradingView, which you can also search for popular indicators. If you want to learn how to transcribe indicators & strategies from TradingView to Naxbot R, have a look at Transcribing TradingView Strategies.

    For this tutorial however, we will be using a simple strategy based on the relative strength index (RSI).

    Defining the Strategy​

    As mentioned before, we will be using a simple RSI based strategy. Specifically, we will be calculating the difference between a faster moving RSI and a slower one, and using that difference to get our long & short signals.

    We will be trading on ftx-futures using the BTC-PERP market on the daily chart. We will use a single take profit target. These are the relevant settings:
    config.json:
    {
    "general": {
    "exchange_name": "ftx-futures",
    "timeframe": "OneDay",
    "quote_asset": "USD",
    "trading_pairs": [
    "BTC-PERP"
    ]
    },
    "crawler": {
    "tp_count": 1,
    "risk_percent": 2.0,
    "tp_weights": [
    100
    ]
    }
    }

    Next, we'll set up our strategy:
    strategy.lua:
    function process()
    return {
    long_entry_condition = constant(false),
    short_entry_condition = constant(false),
    stop_loss = constant(0),
    tp_1 = constant(0),
    }
    end

    So far so good, but our strategy doesn't do anything right now. Let's start by implementing the two RSI indicators we talked about earlier:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    return {
    long_entry_condition = constant(false),
    short_entry_condition = constant(false),
    stop_loss = constant(0),
    tp_1 = constant(0),
    }
    end

    Now we're getting somewhere. We can add the two indicators to our return table, so we can plot them into a spreadsheet, just to get an idea of what it looks like:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    return {
    long_entry_condition = constant(false),
    short_entry_condition = constant(false),
    stop_loss = constant(0),
    tp_1 = constant(0),
    fast_rsi = fast_rsi,
    slow_rsi = slow_rsi,
    }
    end

    Next, let's subtract the slow RSI from the fast RSI to get our divergence. We'll also add it to the return table, so we can plot it:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    local divergence = fast_rsi - slow_rsi;

    return {
    long_entry_condition = constant(false),
    short_entry_condition = constant(false),
    stop_loss = constant(0),
    tp_1 = constant(0),
    fast_rsi = fast_rsi,
    slow_rsi = slow_rsi,
    divergence = divergence,
    }
    end

    Now we need to define our long & short entry conditions. Since the RSI is an oscillating indicator (meaning it is moving around a fixed point, in this case the number 0), we can simply define our entry conditions as crossover / crossunder in relation to the fixed point it is oscillating around:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    local divergence = fast_rsi - slow_rsi;

    -- we declare the variable "zero", so we don't need
    -- to calculate the constant multiple times
    local zero = constant(0);

    local long_entry_condition = crossover(divergence, zero);
    local short_entry_condition = crossunder(divergence, zero);

    return {
    long_entry_condition = long_entry_condition,
    short_entry_condition = short_entry_condition,
    stop_loss = constant(0),
    tp_1 = constant(0),
    fast_rsi = fast_rsi,
    slow_rsi = slow_rsi,
    divergence = divergence,
    }
    end

    Things are finally starting to shape up! The only things we're missing now is a stop loss and a take profit target. For this example, we'll use multiples of the average true range to get our stop loss & take profit targets, but you can use any indicator you like:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    local divergence = fast_rsi - slow_rsi;

    -- we declare the variable "zero", so we don't need
    -- to calculate the constant multiple times
    local zero = constant(0);

    local long_entry_condition = crossover(divergence, zero);
    local short_entry_condition = crossunder(divergence, zero);

    -- again we declare a variable to avoid
    -- multiple future calculations
    local distance = atr(21);

    -- we set stop loss at 1.5x atr
    local stop_loss = close - distance * constant(1.5);

    -- while setting tp_1 at 3x atr
    local tp_1 = close + distance * constant(3);

    return {
    long_entry_condition = long_entry_condition,
    short_entry_condition = short_entry_condition,
    stop_loss = stop_loss,
    tp_1 = tp_1,
    fast_rsi = fast_rsi,
    slow_rsi = slow_rsi,
    divergence = divergence,
    }
    end

    Perfect! Except for one thing: These stop loss and take profit targets are only valid for long trades. For short trades, our stop loss needs to be above our entry price, not below. We can fix this however, by using the lif function. Refer to our API Reference for more info on how it works:
    Lua:
    function process()
    local fast_length = 5;
    local slow_length = 17;

    local fast_rsi = rsi(close, fast_length);
    local slow_rsi = rsi(close, slow_length);

    local divergence = fast_rsi - slow_rsi;

    -- we declare the variable "zero", so we don't need
    -- to calculate the constant multiple times
    local zero = constant(0);

    local long_entry_condition = crossover(divergence, zero);
    local short_entry_condition = crossunder(divergence, zero);

    -- again we declare a variable to avoid
    -- multiple future calculations
    local distance = atr(21);

    -- we now calculate both long & short stop loss,
    -- and then later decide which one to use based
    -- on whether the signal is long or not.
    local stop_loss_distance = distance * constant(1.5);
    local long_stop_loss = close - stop_loss_distance;
    local short_stop_loss = close + stop_loss_distance;
    local stop_loss = lif(long_entry_condition, long_stop_loss, short_stop_loss);

    -- we do the same for our take profit target
    local tp_1_distance = distance * constant(3);
    local long_tp_1 = close + tp_1_distance;
    local short_tp_1 = close - tp_1_distance;
    local tp_1 = lif(long_entry_condition, long_tp_1, short_tp_1);

    return {
    long_entry_condition = long_entry_condition,
    short_entry_condition = short_entry_condition,
    stop_loss = stop_loss,
    tp_1 = tp_1,
    fast_rsi = fast_rsi,
    slow_rsi = slow_rsi,
    divergence = divergence,
    }
    end

    Awesome! Now, let's backtest our new strategy:
    Code:
    [INFO] --- BACKTEST FINISHED ---
    [INFO] (this backtest is using your configured crawler settings to try to be as realistic as possible, unlike optimization mode)
    [INFO] Results are in:
    [INFO] Total Trades: 238
    [INFO] Successful Trades: 78
    [INFO] Longest Losing Streak: 12
    [INFO] Total Non-Compounded Profit: -8.00%
    [INFO] Total Compounded Profit: -15.90%
    [INFO] Hit Rate: 32.77%
    [INFO] Max Drawdown: 21.53% (theoretical, based on longest losing streak)
    [INFO] Total Klines in Test: 1088
    [INFO] Your observed R is: 2.00 (mean win / mean loss)
    [INFO] Based on the observed R, your strategy will break even at a 33.33% win rate.

    Well, now this isn't too encouraging... But regardless, you have successfully created your first strategy!

    And all hope is not yet lost, for Naxbot R has an integrated Optimizer that you can leverage in order to improve your strategy's performance. Continue this tutorial in: Optimizing Your First Strategy to see if we can make this strategy profitable!
Top