Histo Scalper Strategy — перенос советника HistoScalperEA v1.0 на платформу StockSharp. Алгоритм объединяет восемь гистограммных индикаторов (ADX, ATR, полосы Боллинджера, Bulls/Bears Power, CCI, MACD, RSI и Stochastic). Сделка открывается только тогда, когда все включённые фильтры показывают одно направление, и хотя бы один из них демонстрировал противоположный сигнал на предыдущей свече. Тем самым сохраняется оригинальная двухсвечная логика подтверждения и снижается число входов в боковике.
Формирование сигналов
ADX — сравнение +DI и −DI, при необходимости направление можно инвертировать.
ATR — сравнение текущего ATR с SMA-базой; измеряется процентное отклонение. Для покупок требуется превышение AtrPositiveThreshold, для продаж — падение ниже AtrNegativeThreshold.
Полосы Боллинджера — требование пробоя верхней или нижней полосы закрытием свечи.
Bulls/Bears Power — Bulls Power используется для покупок, модуль Bears Power — для продаж.
CCI — реагирует на вход цены в зоны перепроданности/перекупленности.
MACD — анализирует гистограмму (расстояние между MACD и сигнальной линией).
RSI — классические уровни 30/70 (по умолчанию).
Stochastic — значения линии %K сравниваются с границами диапазона.
Если хотя бы один активный фильтр выдаёт нейтральное значение, обработка текущей свечи прекращается. Сигналы предыдущих свечей сохраняются для контроля условия «предыдущая свеча противоположна».
Управление рисками
Объём сделок задаётся параметром TradeVolume.
Параметр AllowPyramiding разрешает наращивать позицию при поступлении новых сигналов в том же направлении.
TakeProfitPoints и StopLossPoints (в шагах цены) сразу устанавливаются через методы SetTakeProfit и SetStopLoss.
Параметры UseTimeFilter, SessionStart, SessionEnd позволяют ограничить торговлю временным окном в течение суток.
Параметры
Параметр
Описание
TradeVolume
Базовый объём сделки.
AllowPyramiding
Разрешение на пирамидинг.
CloseOnOppositeSignal
Закрытие позиции при смене суммарного сигнала.
UseTimeFilter, SessionStart, SessionEnd
Торговый интервал по времени.
UseTakeProfit, TakeProfitPoints
Настройки тейк-профита в шагах цены.
UseStopLoss, StopLossPoints
Настройки стоп-лосса в шагах цены.
UseIndicator1 … UseIndicator8
Включение отдельных фильтров.
ModeIndicatorX
Прямой или инвертированный режим работы фильтра.
Остальные параметры
Периоды и пороги, повторяющие настройки исходного советника.
Отличия от версии MQL
Удалены управление «корзиной» ордеров, звуковые уведомления и сеточная логика.
Автоматический расчёт лота, безубыток и трейлинг-стоп не реализованы — вместо этого используйте стандартные стопы и тейк-профит.
Проверка спреда и обработка брокерских особенностей не перенесены.
Рекомендации по использованию
Перед запуском установите Security и Portfolio стратегии.
Настройте тип свечи (CandleType) под нужный таймфрейм.
Подберите пороги индикаторов под волатильность инструмента.
Во время оптимизации отключайте часть фильтров, чтобы сократить количество параметров.
Используйте AllowPyramiding и CloseOnOppositeSignal для контроля экспозиции на быстрых рынках.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Multi-indicator scalping strategy combining MACD, RSI, and CCI filters.
/// Buys when all indicators agree on bullish signal. Sells on bearish agreement.
/// </summary>
public class HistoScalperStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cciPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
public HistoScalperStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var macd = new MovingAverageConvergenceDivergence();
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
decimal? prevMacd = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(macd, rsi, cci, (candle, macdLine, rsiVal, cciVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevMacd.HasValue)
{
if (prevMacd.Value <= 0 && macdLine > 0 && rsiVal < 70m && cciVal > -100m && Position <= 0)
BuyMarket();
else if (prevMacd.Value >= 0 && macdLine < 0 && rsiVal > 30m && cciVal < 100m && Position >= 0)
SellMarket();
}
prevMacd = macdLine;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
}
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
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergence, RelativeStrengthIndex, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class histo_scalper_strategy(Strategy):
def __init__(self):
super(histo_scalper_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI period", "Indicators")
self._macd = None
self._rsi = None
self._cci = None
self._prev_macd = None
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def cci_period(self):
return self._cci_period.Value
def OnReseted(self):
super(histo_scalper_strategy, self).OnReseted()
self._macd = None
self._rsi = None
self._cci = None
self._prev_macd = None
def OnStarted2(self, time):
super(histo_scalper_strategy, self).OnStarted2(time)
self._macd = MovingAverageConvergenceDivergence()
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
self._cci = CommodityChannelIndex()
self._cci.Length = self.cci_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._macd, self._rsi, self._cci, self._process_candle)
subscription.Start()
def _process_candle(self, candle, macd_value, rsi_value, cci_value):
if candle.State != CandleStates.Finished:
return
if not self._macd.IsFormed or not self._rsi.IsFormed or not self._cci.IsFormed:
return
macd_line = float(macd_value)
rsi_val = float(rsi_value)
cci_val = float(cci_value)
if self._prev_macd is not None:
if self._prev_macd <= 0.0 and macd_line > 0.0 and rsi_val < 70.0 and cci_val > -100.0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_macd >= 0.0 and macd_line < 0.0 and rsi_val > 30.0 and cci_val < 100.0 and self.Position >= 0:
self.SellMarket()
self._prev_macd = macd_line
def CreateClone(self):
return histo_scalper_strategy()