Rampok Scalp Strategy
Scalping system that trades when price breaks moving average envelopes. The strategy enters long when price crosses above the lower band and short when price crosses below the upper band. Positions are protected by optional take-profit, stop-loss and trailing stop parameters.
Details
- Entry Criteria:
- Buy: previous close below lower band and current close above it.
- Sell: previous close above upper band and current close below it.
- Long/Short: Both.
- Exit Criteria:
- Take profit, stop loss or trailing stop.
- Stops: Configurable SL/TP and trailing.
- Filters: none.
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>
/// Envelope based scalping strategy.
/// Enters when price crosses moving average bands and exits with trailing stop.
/// </summary>
public class RampokScalpStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<decimal> _deviation;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevUpper;
private decimal _prevLower;
private decimal _prevClose;
private decimal _entryPrice;
private decimal _highestPrice;
private decimal _lowestPrice;
private bool _hasPrev;
public int Period { get => _period.Value; set => _period.Value = value; }
public decimal Deviation { get => _deviation.Value; set => _deviation.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RampokScalpStrategy()
{
_period = Param(nameof(Period), 15)
.SetGreaterThanZero()
.SetDisplay("Period", "Moving average period", "General");
_deviation = Param(nameof(Deviation), 0.07m)
.SetGreaterThanZero()
.SetDisplay("Deviation", "Envelope deviation percent", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevUpper = 0;
_prevLower = 0;
_prevClose = 0;
_entryPrice = 0;
_highestPrice = 0;
_lowestPrice = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = Period };
SubscribeCandles(CandleType).Bind(sma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished) return;
var upper = smaValue * (1 + Deviation);
var lower = smaValue * (1 - Deviation);
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevUpper = upper;
_prevLower = lower;
_prevClose = close;
_hasPrev = true;
return;
}
if (Position == 0)
{
if (_prevClose < _prevLower && close > lower)
{
BuyMarket();
_entryPrice = close;
_highestPrice = close;
}
else if (_prevClose > _prevUpper && close < upper)
{
SellMarket();
_entryPrice = close;
_lowestPrice = close;
}
}
else if (Position > 0)
{
_highestPrice = Math.Max(_highestPrice, candle.HighPrice);
// Exit at upper band or trailing
if (close >= upper)
SellMarket();
}
else if (Position < 0)
{
_lowestPrice = Math.Min(_lowestPrice, candle.LowPrice);
// Exit at lower band or trailing
if (close <= lower)
BuyMarket();
}
_prevUpper = upper;
_prevLower = lower;
_prevClose = close;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class rampok_scalp_strategy(Strategy):
def __init__(self):
super(rampok_scalp_strategy, self).__init__()
self._period = self.Param("Period", 15) \
.SetDisplay("Period", "Moving average period", "General")
self._deviation = self.Param("Deviation", 0.07) \
.SetDisplay("Deviation", "Envelope deviation percent", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle", "Candle type", "General")
self._prev_upper = 0.0
self._prev_lower = 0.0
self._prev_close = 0.0
self._entry_price = 0.0
self._highest_price = 0.0
self._lowest_price = 0.0
self._has_prev = False
@property
def period(self):
return self._period.Value
@property
def deviation(self):
return self._deviation.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rampok_scalp_strategy, self).OnReseted()
self._prev_upper = 0.0
self._prev_lower = 0.0
self._prev_close = 0.0
self._entry_price = 0.0
self._highest_price = 0.0
self._lowest_price = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(rampok_scalp_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
upper = sma_value * (1 + self.deviation)
lower = sma_value * (1 - self.deviation)
close = candle.ClosePrice
if not self._has_prev:
self._prev_upper = upper
self._prev_lower = lower
self._prev_close = close
self._has_prev = True
return
if self.Position == 0:
if self._prev_close < self._prev_lower and close > lower:
self.BuyMarket()
self._entry_price = close
self._highest_price = close
elif self._prev_close > self._prev_upper and close < upper:
self.SellMarket()
self._entry_price = close
self._lowest_price = close
elif self.Position > 0:
self._highest_price = max(self._highest_price, candle.HighPrice)
# Exit at upper band or trailing
if close >= upper:
self.SellMarket()
elif self.Position < 0:
self._lowest_price = min(self._lowest_price, candle.LowPrice)
# Exit at lower band or trailing
if close <= lower:
self.BuyMarket()
self._prev_upper = upper
self._prev_lower = lower
self._prev_close = close
def CreateClone(self):
return rampok_scalp_strategy()