SmartAssTrade V2 Strategy
SmartAssTrade V2 Strategy uses MACD histogram and 20-period moving averages across multiple timeframes (1m, 5m, 15m, 30m, 60m) combined with Williams %R and RSI filters to capture trend momentum. Optional trailing stop protects profits.
Details
- Entry Criteria: majority of timeframes show rising MACD histogram and MA with supporting WPR/RSI confirmation
- Long/Short: Both
- Exit Criteria: price reaches take profit or stop loss; optional trailing stop
- Stops: Absolute stop loss and take profit with optional trailing
- Default Values:
Volume= 1TakeProfit= 35StopLoss= 62UseTrailingStop= falseTrailingStop= 30TrailingStopStep= 1
- Filters:
- Category: Trend
- Direction: Both
- Indicators: MACD, SMA, Williams %R, RSI
- Stops: Optional
- Complexity: Intermediate
- Timeframe: Multi-timeframe (1m,5m,15m,30m,60m)
- Seasonality: No
- Neural networks: No
- Divergence: No
- Risk level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on MACD histogram direction, WilliamsR, RSI and MA trend.
/// Buys when MACD is rising, MA is trending up, WPR and RSI confirm momentum.
/// </summary>
public class SmartAssTradeV2Strategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfitPct;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<DataType> _candleType;
private MovingAverageConvergenceDivergence _macd;
private SimpleMovingAverage _ma;
private WilliamsR _wpr;
private RelativeStrengthIndex _rsi;
private decimal? _prevMacd;
private decimal? _prevMa;
private decimal? _prevWpr;
private decimal? _prevRsi;
public decimal TakeProfitPct { get => _takeProfitPct.Value; set => _takeProfitPct.Value = value; }
public decimal StopLossPct { get => _stopLossPct.Value; set => _stopLossPct.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public SmartAssTradeV2Strategy()
{
_takeProfitPct = Param(nameof(TakeProfitPct), 3m)
.SetDisplay("Take Profit %", "Take profit percentage", "Risk Management");
_stopLossPct = Param(nameof(StopLossPct), 2m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacd = null;
_prevMa = null;
_prevWpr = null;
_prevRsi = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_macd = new MovingAverageConvergenceDivergence();
_ma = new SimpleMovingAverage { Length = 20 };
_wpr = new WilliamsR { Length = 26 };
_rsi = new RelativeStrengthIndex { Length = 14 };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
StartProtection(
stopLoss: new Unit(StopLossPct, UnitTypes.Percent),
takeProfit: new Unit(TakeProfitPct, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var macdResult = _macd.Process(candle.ClosePrice, candle.OpenTime, true);
var maResult = _ma.Process(candle.ClosePrice, candle.OpenTime, true);
var wprResult = _wpr.Process(candle);
var rsiResult = _rsi.Process(candle.ClosePrice, candle.OpenTime, true);
if (!macdResult.IsFormed || !maResult.IsFormed || !wprResult.IsFormed || !rsiResult.IsFormed)
return;
var currMacd = macdResult.ToDecimal();
var currMa = maResult.ToDecimal();
var currWpr = wprResult.ToDecimal();
var currRsi = rsiResult.ToDecimal();
if (_prevMacd == null || _prevMa == null || _prevWpr == null || _prevRsi == null)
{
_prevMacd = currMacd;
_prevMa = currMa;
_prevWpr = currWpr;
_prevRsi = currRsi;
return;
}
var macdRising = currMacd > _prevMacd;
var macdFalling = currMacd < _prevMacd;
var maRising = currMa > _prevMa;
var maFalling = currMa < _prevMa;
// Buy signal: MACD rising, MA rising, WPR recovering, RSI rising below 70
var buySignal = macdRising && maRising
&& currWpr > _prevWpr && currRsi > _prevRsi
&& currRsi < 70m;
// Sell signal: MACD falling, MA falling, WPR declining, RSI falling above 30
var sellSignal = macdFalling && maFalling
&& currWpr < _prevWpr && currRsi < _prevRsi
&& currRsi > 30m;
if (Position <= 0 && buySignal)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (Position >= 0 && sellSignal)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevMacd = currMacd;
_prevMa = currMa;
_prevWpr = currWpr;
_prevRsi = currRsi;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergence, SimpleMovingAverage, WilliamsR, RelativeStrengthIndex, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class smart_ass_trade_v2_strategy(Strategy):
def __init__(self):
super(smart_ass_trade_v2_strategy, self).__init__()
self._take_profit_pct = self.Param("TakeProfitPct", 3.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk Management")
self._stop_loss_pct = self.Param("StopLossPct", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._macd = None
self._ma = None
self._wpr = None
self._rsi = None
self._prev_macd = None
self._prev_ma = None
self._prev_wpr = None
self._prev_rsi = None
@property
def take_profit_pct(self):
return self._take_profit_pct.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(smart_ass_trade_v2_strategy, self).OnReseted()
self._prev_macd = None
self._prev_ma = None
self._prev_wpr = None
self._prev_rsi = None
def OnStarted2(self, time):
super(smart_ass_trade_v2_strategy, self).OnStarted2(time)
self._macd = MovingAverageConvergenceDivergence()
self._ma = SimpleMovingAverage()
self._ma.Length = 20
self._wpr = WilliamsR()
self._wpr.Length = 26
self._rsi = RelativeStrengthIndex()
self._rsi.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
self.StartProtection(
Unit(float(self.take_profit_pct), UnitTypes.Percent),
Unit(float(self.stop_loss_pct), UnitTypes.Percent))
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
macd_result = process_float(self._macd, candle.ClosePrice, candle.OpenTime, True)
ma_result = process_float(self._ma, candle.ClosePrice, candle.OpenTime, True)
wpr_inp = CandleIndicatorValue(self._wpr, candle)
wpr_result = self._wpr.Process(wpr_inp)
rsi_result = process_float(self._rsi, candle.ClosePrice, candle.OpenTime, True)
if not macd_result.IsFormed or not ma_result.IsFormed or not wpr_result.IsFormed or not rsi_result.IsFormed:
return
curr_macd = float(macd_result)
curr_ma = float(ma_result)
curr_wpr = float(wpr_result)
curr_rsi = float(rsi_result)
if self._prev_macd is None or self._prev_ma is None or self._prev_wpr is None or self._prev_rsi is None:
self._prev_macd = curr_macd
self._prev_ma = curr_ma
self._prev_wpr = curr_wpr
self._prev_rsi = curr_rsi
return
macd_rising = curr_macd > self._prev_macd
macd_falling = curr_macd < self._prev_macd
ma_rising = curr_ma > self._prev_ma
ma_falling = curr_ma < self._prev_ma
buy_signal = (macd_rising and ma_rising and
curr_wpr > self._prev_wpr and curr_rsi > self._prev_rsi and
curr_rsi < 70.0)
sell_signal = (macd_falling and ma_falling and
curr_wpr < self._prev_wpr and curr_rsi < self._prev_rsi and
curr_rsi > 30.0)
if self.Position <= 0 and buy_signal:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self.Position >= 0 and sell_signal:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_macd = curr_macd
self._prev_ma = curr_ma
self._prev_wpr = curr_wpr
self._prev_rsi = curr_rsi
def CreateClone(self):
return smart_ass_trade_v2_strategy()