This strategy uses two Arnaud Legoux Moving Averages (ALMA), one fast and one slow, to generate crossover signals. ALMA reduces lag and smooths the signal line compared to traditional MAs. Volume filter is added to improve signal accuracy. It is optimized for crypto but can be adjusted for other instruments. Alerts are included.
The core indicators and rules are:
Fast ALMA: Shorter period to catch breakouts.
Slow ALMA: Longer period to gauge the trend.
Volume filter: Valid when short EMA crosses above long EMA.
Buy signal: Fast ALMA crosses above slow ALMA and volume filter passes.
Sell signal: Fast ALMA crosses below slow ALMA.
Short signal: Fast ALMA crosses below slow ALMA and volume filter passes.
Cover signal: Fast ALMA crosses above slow ALMA.
The strategy combines trend, momentum and volume analysis for robust signals. ALMA reduces lagging while volume avoids false breakouts.
Compared to traditional moving average strategies, the main advantages are:
ALMA reduces lag and improves signal quality.
Volume filter avoids losses from false breakouts.
Fast/slow combo gauges the trend direction.
Simple and intuitive rules, easy to implement.
Flexible tuning of MA parameters for different markets.
Reasonable risk management.
Further optimization potential through parameter tuning.
Overall improved stability and quality over traditional crossover strategies.
Despite the merits, the following risks should be noted:
Crossover systems are intrinsically vulnerable to whipsaws.
ALMA performance depends on parameter tuning.
Volume spikes may mislead signal generation.
Some lag always exists, cannot avoid all losses.
Overfitting risk from excessive optimization.
Signals fail when volume is abnormal.
Machine learning techniques may generate better results.
Monitor reward/risk ratio to avoid excessive drawdowns.
To address the risks, enhancements can be made in the following areas:
Optimize ALMA parameters for better sensitivity.
Experiment with different volume metrics.
Introduce stop loss to control loss per trade.
Incorporate other indicators for robust signals.
Add machine learning module for smarter signal adjustment.
Deploy across multiple products for strategy diversification.
Optimize position sizing models for different markets.
Research robustness to prevent overfitting.
In conclusion, compared to traditional crossover strategies, this strategy improves signal quality and robustness through the ALMA algorithm and volume filter. But strategy optimization is an iterative process. It is important to keep improving the strategy from multiple dimensions to adapt to changing markets.
/*backtest start: 2022-09-16 00:00:00 end: 2023-09-22 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © Sarahann999 // Calculations for TP/SL based off: https://kodify.net/tradingview/orders/percentage-profit/ //@version=5 strategy("ALMA Cross", overlay=true) //User Inputs src= (close) long_entry = input(true, title='Long Entry') short_entry = input(true, title='Short Entry') //Fast Settings ALMA1 = input(100, "ALMA Lenghth 1", group= "ALMA Fast Length Settings") alma_offset = input.float(defval=0.85, title='Arnaud Legoux (ALMA) - Offset Value', minval=0, step=0.01) alma_sigma = input.int(defval=6, title='Arnaud Legoux (ALMA) - Sigma Value', minval=0) Alma1 = ta.alma(src, ALMA1, alma_offset, alma_sigma) //Slow Settings ALMA2 = input(120, "ALMA Length 2", group = "ALMA Slow Length Settings") alma_offset2 = input.float(defval=0.85, title='Arnaud Legoux (ALMA) - Offset Value', minval=0, step=0.01) alma_sigma2 = input.int(defval=6, title='Arnaud Legoux (ALMA) - Sigma Value', minval=0) Alma2 = ta.alma(src, ALMA2, alma_offset2, alma_sigma2) //Volume var cumVol = 0. cumVol += nz(volume) if barstate.islast and cumVol == 0 runtime.error("No volume is provided by the data vendor.") shortlen = input.int(5, minval=1, title = "Short Length", group= "Volume Settings") longlen = input.int(10, minval=1, title = "Long Length") short = ta.ema(volume, shortlen) long = ta.ema(volume, longlen) osc = 100 * (short - long) / long //Define Cross Conditions buy = ta.crossover(Alma1, Alma2) sell = ta.crossunder(Alma1, Alma2) //Calculate Take Profit Percentage longProfitPerc = input.float(title="Long Take Profit", group='Take Profit Percentage', minval=0.0, step=0.1, defval=2) / 100 shortProfitPerc = input.float(title="Short Take Profit", minval=0.0, step=0.1, defval=2) / 100 // Figure out take profit price 1 longExitPrice = strategy.position_avg_price * (1 + longProfitPerc) shortExitPrice = strategy.position_avg_price * (1 - shortProfitPerc) // Make inputs that set the stop % 1 longStopPerc = input.float(title="Long Stop Loss", group='Stop Percentage', minval=0.0, step=0.1, defval=2.5) / 100 shortStopPerc = input.float(title="Short Stop Loss", minval=0.0, step=0.1, defval=2.5) / 100 // Figure Out Stop Price longStopPrice = strategy.position_avg_price * (1 - longStopPerc) shortStopPrice = strategy.position_avg_price * (1 + shortStopPerc) //Define Conditions buySignal = buy and osc > 0 and strategy.position_size == 0 //sellSignal sellSignal = sell and osc > 0 and strategy.position_size == 0 // Submit entry orders if buySignal and long_entry strategy.entry(id="Long", direction=strategy.long, alert_message="Enter Long") alert(message="BUY Trade Entry Alert", freq=alert.freq_once_per_bar) if sellSignal and short_entry strategy.entry(id="Short", direction=strategy.short, alert_message="Enter Short") alert(message="SELL Trade Entry Alert", freq=alert.freq_once_per_bar) // Submit exit orders based on take profit price if (strategy.position_size > 0) strategy.exit(id="Long TP/SL", limit=longExitPrice, stop=longStopPrice, alert_message="Long Exit 1 at {{close}}") if (strategy.position_size < 0) strategy.exit(id="Short TP/SL", limit=shortExitPrice, stop=shortStopPrice, alert_message="Short Exit 1 at {{close}}") //Draw plot(Alma1,"Alma Fast", color=color.purple, style=plot.style_circles) plot(Alma2,"Alma Slow", color=#acb5c2, style=plot.style_circles)