tradingview-strategy-pine-script-adding-inputs

Initial Optimisations For Your TradingView Strategy

If you followed our previous article you should now have a simple SMA CROSS strategy added to your chart. One thing you will notice though is that the strategy always plots an SMA with 100 periods, but ideally we will want to check different SMA values especially when trying the strategy in a different timeframe.

Thanks to TradingView’s input function it’s quite easy to add such a parameter to our strategy. We will create a variable called SMA_LENGTH and assign the result of the input function to it. We will then replace the number 100 with the SMA_LENGTH value.

Here is the updated strategy code:

//@version=4
strategy(title="SMA CROSS", initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=20, overlay=true)

SMA_LENGTH = input(title="SMA LENGTH", defval=100, minval=2)

sma_value = sma(close, SMA_LENGTH)

plot(sma_value, linewidth=4, color=color.green)

crossed_over  = close[0] > sma_value[0] and close[1] < sma_value[1]
crossed_under = close[0] < sma_value[0] and close[1] > sma_value[1]

if crossed_over
    strategy.close("short")
    strategy.entry("long", strategy.long)

if crossed_under
    strategy.close("long")
    strategy.entry("short", strategy.short)

After you have updated the code and clicked “Save”, you can move into the “Strategy Tester” tab and click the little “engine” icon next to your script name to edit your SMA length.

Strategy Tester – Settings

You should now see a little popup where you can change the length of the SMA.

Strategy Tester – Edit SMA Length

Naturally, changing the SMA length will change the amount of trades and the overall results of our strategy. By playing around with different SMAs, different timeframes and different markets, you will get very different results.

Testing a Specific Date Period

A very common question when backtesting TradingView strategies is “how do I test my strategy between specific start and end dates”.

For that we will create new inputs in our script to allow us to specify the dates we want to trade, which will update our strategy to only take trades during that period.

Here is the updated script:

//@version=4
strategy(title="SMA CROSS", initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=20, overlay=true)

// settings for date range
START_DAY = input(title="Start Day", type=input.integer, defval=1, minval=1, maxval=31)
START_MONTH = input(title="Start Month", type=input.integer, defval=1, minval=1, maxval=12)
START_YEAR = input(title="Start Year", type=input.integer,defval=2019, minval=1800, maxval=2100)

END_DAY = input(title="End Day", type=input.integer, defval=1, minval=1, maxval=31)
END_MONTH = input(title="End Month", type=input.integer, defval=1, minval=1, maxval=12)
END_YEAR = input(title="End Year", type=input.integer, defval=2021, minval=1800, maxval=2100)

after_start = time >= timestamp(syminfo.timezone, START_YEAR, START_MONTH, START_DAY, 0, 0)
before_end = time < timestamp(syminfo.timezone, END_YEAR, END_MONTH, END_DAY, 0, 0)
in_date_range = after_start and before_end

// our strategy
SMA_LENGTH = input(title="SMA LENGTH", defval=100, minval=2)

sma_value = sma(close, SMA_LENGTH)

plot(sma_value, linewidth=4, color=color.green)

crossed_over  = close[0] > sma_value[0] and close[1] < sma_value[1]
crossed_under = close[0] < sma_value[0] and close[1] > sma_value[1]

if not in_date_range
    strategy.close_all()

if in_date_range
    if crossed_over
        strategy.close("short")
        strategy.entry("long", strategy.long)

    if crossed_under
        strategy.close("long")
        strategy.entry("short", strategy.short)

By running this code we will backtest our strategy starting from 1st January 2019.

Strategy Tester – Edit Date Range

Analysing the Backtest Results

Now that we only have 12 trades on our backtest it’s much easier to go through the Overview, Performance Summary and List of Trades to gain a deeper understanding of our strategy.

Generally the first two values we note on our report are “Percent Profitable” and “Profit Factor”. The combination of both of these values gives you a quick idea of how your strategy performed.

Percent Profitable
The percentage of winning trades generated by a strategy. Calculated by dividing the number of winning trades by the total number of closed trades generated by a strategy. Percent profitable is not a very reliable measure by itself. A strategy could have many small winning trades, making the percent profitable high with a small average winning trade, or a few big winning trades accounting for a low percent profitable and a big average winning trade.

Profit Factor
The amount of money a trading strategy made for every unit of money it lost (in the selected currency). This value is calculated by dividing gross profits by gross losses.

You can also click the question mark on the right side of the “List of Trades” tab to display a complete list of definitions for each of the parameters in the backtester.

Strategy Tester – Overview

Here are the results for our 100 periods SMA strategy running on the Daily chart for BTC/USD.

Strategy Tester – Performance Overview (1D Timeframe)

As you can see, even though our strategy only won 16.67% of the time, we still managed to have a 25% profit.

If you look at our Equity Curve you will notice that we lost a couple of trades at the beginning and then we made a significant profit on the 3rd trade. Having a closer look at the “List of Trades” will give us the exact numbers:

Strategy Tester – List of Trades

As you can see, our strategy relies heavily on those huge swings in price, but still doesn’t perform well when the market is sideways.

Checking the Strategy on the 4H Chart

To see the results in another timeframe, you can simply chose another timeframe on the chart and the backtest results will update accordingly.

Strategy Tester – Performance Overview (4H Timeframe)

As you can see on the 4H we had a higher percentage of profitable trades but a lower profit factor. You can also see that the strategy had a very profitable impulse right at the beginning during a nice bull run.

The Net Profit remained about the same at 27.99%.

What About the Exchange Fees?

So far when backtesting we are not taking in consideration the exchange fees, as you know every time an order gets filled the exchange will take a small fee, generally around 0.2%.

In order to backtest using such values we will be using the commission_type and commission_value parameters on the strategy function, updating the first line to:

strategy(title="SMA CROSS", initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=20, commission_type=strategy.commission.percent, commission_value=0.2, overlay=true)

Once you update the script, you should see a much different result:

Strategy Tester – Performance Overview with Fees (4H Timeframe)

Since we’re using 0.2% fee on our backtest, we now need our trades to make at least 0.4% in order to be profitable, which adds up quickly especially on shorter timeframes.

Quite often I see traders backtesting strategies with even higher fees to account for extra fees that might come from using Market Orders (as opposed to Limit Orders). That may not be a perfect way of simulating trading on a real account, but definitely helps having a more realistic result compared to using 0.2%.

For reference this is the latest version of our strategy:

//@version=4
strategy(title="SMA CROSS", initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=20, commission_type=strategy.commission.percent, commission_value=0.2, overlay=true)

// settings for date range
START_DAY = input(title="Start Day", type=input.integer, defval=1, minval=1, maxval=31)
START_MONTH = input(title="Start Month", type=input.integer, defval=1, minval=1, maxval=12)
START_YEAR = input(title="Start Year", type=input.integer,defval=2019, minval=1800, maxval=2100)

END_DAY = input(title="End Day", type=input.integer, defval=1, minval=1, maxval=31)
END_MONTH = input(title="End Month", type=input.integer, defval=1, minval=1, maxval=12)
END_YEAR = input(title="End Year", type=input.integer, defval=2021, minval=1800, maxval=2100)

after_start = time >= timestamp(syminfo.timezone, START_YEAR, START_MONTH, START_DAY, 0, 0)
before_end = time < timestamp(syminfo.timezone, END_YEAR, END_MONTH, END_DAY, 0, 0)
in_date_range = after_start and before_end

// our strategy
SMA_LENGTH = input(title="SMA LENGTH", defval=100, minval=2)

sma_value = sma(close, SMA_LENGTH)

plot(sma_value, linewidth=4, color=color.green)

crossed_over  = close[0] > sma_value[0] and close[1] < sma_value[1]
crossed_under = close[0] < sma_value[0] and close[1] > sma_value[1]

if not in_date_range
    strategy.close_all()

if in_date_range
    if crossed_over
        strategy.close("short")
        strategy.entry("long", strategy.long)

    if crossed_under
        strategy.close("long")
        strategy.entry("short", strategy.short)

Using a Different SMA Value

Now that we changed to a shorter timeframe, it would be interesting to see what happen if we change our SMA value to 150 periods.

Making our SMA slower decreases the amount of trades which means we will be paying less trading fees. Doing so also increased our Profit Factor which is a good improvement to our results, and the strategy now has about 28% profit after accounting for 0.2% trading fees.

Next Steps

Now that we know a little better about how to analyse our strategies and how the input function works, we’re ready to start playing around with more advanced strategies.

In the next article we will be updating our strategy to smooth the close price (as you guessed using another SMA!) to avoid some of those losing trades while the market goes sideways. We will also be looking at adding a STOP LOSS to our positions to have better risk management and also add TAKE PROFIT targets to maximise our gains.

If you have any questions or requests regarding our TradingView series, please get in touch with us at support@aluna.social or leave a comment below.

Leave a Reply