Tradingview: Reader Request – x% From Moving Average

Another week, another reader request. Well actually, that is not quite true… This particular request has been sitting in the comments section of the Tradingview: First Script post gathering cobwebs since December. As the saying goes better late than never!  So let’s take a look at Igor’s request and see what we can do:
I want to build up a strategy like “if the price stays 10% away from a moving average I’ll long, or I’ll short, and I’ll close the position when the price hits the moving average again or with a 10% stop loss. How would you do that? I’m trying to figure out, but I can’t do it. Thanks


So breaking down the request, the following requirements can be seen:
  • Long Criteria:
    • Close must be > x% away from a moving average
    • Closemust have have been > x% for x bars (stays 10% away)
  • Short Criteria:
    • As above be <x%
  • Exit Criteria
    • First Exit Strategy: When price touches the moving average
    • Second Exit Strategy: Fixed stop-loss at x% from entry
When translating the requirements some assumptions needed to be made about what “staying away” means. Also, it is assumed we will use stop losses to to take us out of a position so that we can exit as close to the SMA as possible. Finally, exit 2 might be a bit redundant on all but the longest of moving averages or volatile instruments. This is because the SMA will often be closer to price than 10% and as such will be triggered first. Having said that, some inputs will be provided so we can reign the 10% in a little.

Example Code

strategy("Reader Request: x% MA Strat", overlay=true)

lkb = input(200, minval=2, title='SMA Lookback Period')
delta = input(10, step=0.25, title='Entry Delta from MA')/100
bars = input(4, minval=0, title='Min Bars Above/Below Delta')
sl = input(10, step=0.25, title='Stop-Loss Percent')/100

// Create Moving Averages
ma = sma(close, lkb)
ma_upper = ma * (1 + delta)
ma_lower = ma * (1 - delta)

// -----------------
// -----------------
// Since break above
long_break = crossover(close, ma)
since_long_break = barssince(long_break)

short_break = crossunder(close, ma)
since_short_break = barssince(short_break)
long_entry = close >= ma_upper and since_long_break >= bars
short_entry = close <= ma_lower and since_long_break >= bars

strategy.entry("Long", strategy.long, when=long_entry)
strategy.entry("Short", strategy.short, when=short_entry)

// -----------------
// -----------------
// Create stop losses
long_stop = strategy.position_avg_price * (1 - sl)
short_stop = strategy.position_avg_price * (1 + sl)

// Detect whether the stop loss or MA is closer to price
long_exit = long_stop > ma ? long_stop : ma
short_exit = short_stop < ma ? short_stop : ma

strategy.exit("Long SL", "Long", stop=long_exit)
strategy.exit("Short SL", "Short", stop=short_exit)

ma_plot = plot(ma, color=maroon, linewidth=2, title='Moving Average')
ma_upper_plot = plot(ma_upper, color=red, linewidth=1, title='MA Upper Boundary')
ma_lower_plot = plot(ma_lower, color=red, linewidth=1, title='MA Lower Boundary')

fill(ma_lower_plot, ma_upper_plot, color=silver, transp=70)

Code Commentary

The first part to the challenge is to detect whether we are more than 10% above or below price. We can easily do this by working out 10% of the latest closeprice. Then we simply use that figure to add upper and lower bands to the SMA. These bands are not only handy for plotting, but they also make it easy to check if we are above the threshold at any given time. The second requirement was to ensure we stay above the band. This is achieved using barssince() and a simple crossover() and  crossover() checks. Once we crossover the upper band (for longs) or crossunder the lower band (for shorts), the we start counting the bars we stay above it. If we break back down in the opposite direction, there is no need to reset since_long_break and since_short_break because once that happens, we won’t be above/below 10% anymore and cannot enter a position. As such, it won’t interfere with the results. Moving onto the exits, we have two possible scenarios and they both use the same stop loss. As a recap, the first exit strategy is to exit when price hits the moving average. The second is to exit at fixed stop loss. Ideally, we do not want to have two separate stop loss orders in the market. This is because if we have a volatile move, both could get hit on the same bar and send us into an unintended position in the opposite direction. Therefore, in the code example above, we use a ternary conditional operator to work out which stop is closer to price and then we just send a single exit order at the closest level. That means if the fixed (10%) stop loss is closer, we use the fixed stop loss level. Conversely, if the moving average is closer, we set a stop at the current moving average level.

On The Charts

Running the strategy will result in a chart that looks like this: Moving Average Strategy on the charts Ignore the performance for now. It would be more helpful to focus on how these techniques can be adapted and used in your own strategies. I doubt this was the complete strategy Igor envisioned but rather a part of something he is working on.

Find This Post Useful?

If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.