This strategy is named “Dynamic Moving Average Strategy”. The main idea is to use the direction of the moving average and its relationship with price to determine the trend. Enter the market according to the trend direction and close positions when there is no trend.
The strategy uses source prices over a length period to calculate the moving average, where source prices can be OHLC4, HLC3, close price etc. The resulting moving average is defined as sma. Then the long line and short line are plotted based on percentage of the moving average value to determine if we are currently in an upward or downward trend.
Specifically, the short line is calculated as: shortline = sma * ((100 + shortlevel) / 100), where shortlevel is a positive number set by user, representing the percentage that the short line is above the moving average. The long line is similar, calculated as: longline = sma * ((100 + longlevel) / 100), where longlevel is a negative number set by user, representing the percentage that the long line is below the moving average.
Thus, short line value is always greater than moving average, and long line value is always less than moving average. When price crosses above short line, it represents that an upward trend begins. At this time if needlong allows long, it will place a long order at the long line price level. When price crosses below long line, it represents that a downward trend begins. At this time if needshort allows short, it will place a short order at the short line price level.
Regardless of long or short, when price moves back to the moving average, it means the trend ends. At this time it will close all previous positions.
So the trend direction and corresponding entries and exists are determined by the dynamic relationship between the long/short lines and the moving average line.
The biggest advantage of this strategy is that by dynamically setting the long and short lines, it can relatively flexibly capture the main trend direction. Compared to strategies that trigger entries and exits at fixed levels, this strategy is more advanced and intelligent.
Secondly, the moving average itself has a filtering effect to some extent, which avoids being trapped by high frequency fluctuations to some extent. Also, exiting in a timely manner when the trend is judged to be over based on the moving average level is very critical.
The biggest risk of this strategy is that the performance of moving averages differs in different periods. Normally the moving average is sufficient to represent trend direction, but in some extreme market conditions, the moving average could be penetrated in the short term, causing wrong entries, or top divergence etc. In this case longer period moving averages are needed to ensure accuracy of trend judgement.
Another aspect of the risk is that moving averages themselves have high inertia. For some short and intense price fluctuations, it is difficult for moving averages to respond in time, thus missing entry or exit points. The period needs to be reduced to accelerate reaction speed of the moving average.
The strategy can be further optimized in the following aspects:
Add stop loss logic. Since moving averages have lag in judging trends, being trapped cannot be completely avoided. So appropriate trailing stops can further reduce risks.
Optimize parameters of long/short lines. Currently the percentages long/short lines deviate from the moving average are fixed. These can be tested on different datasets to find optimal values.
Add trend strength judgement. Other than long/short line positions, algorithms can also judge the strength of the trend, to avoid errors from weak trend signals.
Try applying moving averages to other trading products to verify cross-product performance.
This strategy determines trend and places corresponding long/short trades by dynamically setting entry and exit points based on moving averages. This method of dynamically generating trading signals based on moving averages is more flexible and intelligent in capturing price trends compared to static trigger levels. It also solves the problem of lack of timeliness of moving averages themselves. With systematic backtesting and parameter optimization, this strategy can yield good profits.
/*backtest start: 2022-11-16 00:00:00 end: 2023-11-22 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //Noro //2018 //@version=3 strategy(title = "Noro's ShiftMA Strategy v1.1", shorttitle = "ShiftMA str 1.1", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, pyramiding = 100) //Settings needlong = input(true, defval = true, title = "Long") needshort = input(false, defval = false, title = "Short") capital = input(100, defval = 100, minval = 1, maxval = 10000, title = "Lot, %") per = input(3, title = "Length") src = input(ohlc4, title = "Source") shortlevel = input(10.0, title = "Short line (red)") longlevel = input(-5.0, title = "Long line (lime)") fromyear = input(1900, defval = 1900, minval = 1900, maxval = 2100, title = "From Year") toyear = input(2100, defval = 2100, minval = 1900, maxval = 2100, title = "To Year") frommonth = input(01, defval = 01, minval = 01, maxval = 12, title = "From Month") tomonth = input(12, defval = 12, minval = 01, maxval = 12, title = "To Month") fromday = input(01, defval = 01, minval = 01, maxval = 31, title = "From day") today = input(31, defval = 31, minval = 01, maxval = 31, title = "To day") //SMAs sma = sma(src, per) //sma = lowest(low, per) shortline = sma * ((100 + shortlevel) / 100) longline = sma * ((100 + longlevel) / 100) plot(shortline, linewidth = 2, color = red, title = "Short line") plot(sma, linewidth = 2, color = blue, title = "SMA line") plot(longline, linewidth = 2, color = lime, title = "Long line") //plot(round(buy * 100000000), linewidth = 2, color = lime) //plot(round(sell * 100000000), linewidth = 2, color = red) //Trading size = strategy.position_size lot = 0.0 lot := size == 0 ? strategy.equity / close * capital / 100 : lot[1] if (not na(close[per])) and size == 0 and needlong strategy.entry("L", strategy.long, lot, limit = longline, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59))) if (not na(close[per])) and size == 0 and needshort strategy.entry("S", strategy.short, lot, limit = shortline, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59))) if (not na(close[per])) and size > 0 strategy.entry("Close", strategy.short, 0, limit = sma, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59))) if (not na(close[per])) and size < 0 strategy.entry("Close", strategy.long, 0, limit = sma, when = (time > timestamp(fromyear, frommonth, fromday, 00, 00) and time < timestamp(toyear, tomonth, today, 23, 59))) if time > timestamp(toyear, tomonth, today, 23, 59) strategy.close_all()