Gonna Scalp — порт популярного MetaTrader-советника на платформу StockSharp с использованием высокоуровневого API. Стратегия работает на коротком таймфрейме, ищет быстрые возвраты к среднему и одновременно учитывает преобладающий тренд. Прежде чем открыть сделку, голосующий механизм анализирует сигналы от индикаторов Momentum, CCI, ATR, стохастика и MACD. В любой момент времени удерживается не более одной позиции; каждая сделка защищена фиксированными уровнями стоп-лосса и тейк-профита (в пунктах MetaTrader).
Логика торговли
Подготовка индикаторов
Быстрая и медленная WMA по типичной цене.
Индикатор Momentum (период 14), преобразованный в абсолютное отклонение от нейтрального уровня 100.
Индикаторы CCI (период 20) и ATR (период 12) выполняют роль фильтров направления.
Стохастик %K/%D (5/3/3) и MACD (12/26/9) рассчитываются по той же серии свечей.
Голосование сигналов
Каждый индикатор отдает голос в сторону покупки или продажи в зависимости от условий исходного эксперта.
Стратегия хранит три последних значения отклонения Momentum и требует, чтобы хотя бы одно превышало заданный порог.
Дополнительный фильтр по структуре требует: для покупок минимум свечи два бара назад должен быть ниже максимума предыдущей свечи (для продаж условие зеркальное).
Исполнение сделок
При превосходстве бычьих голосов и выполнении всех фильтров стратегия открывает длинную позицию базовым объемом.
При доминировании медвежьих голосов и подтверждении Momentum открывается короткая позиция.
Управление рисками
Для каждой позиции рассчитываются уровни стоп-лосса и тейк-профита в пунктах и конвертируются в реальные шаги цены.
При касании любого уровня на текущей свече позиция закрывается немедленно.
Основные параметры
Параметр
Описание
Значение по умолчанию
TradeVolume
Базовый торговый объем (в лотах) после выравнивания.
0.01
FastMaPeriod
Период быстрой WMA.
1
SlowMaPeriod
Период медленной WMA.
5
MomentumPeriod
Период индикатора Momentum.
14
MomentumBuyThreshold
Минимальное отклонение Momentum для покупок.
0.3
MomentumSellThreshold
Минимальное отклонение Momentum для продаж.
0.3
StopLossSteps
Дистанция стоп-лосса в пунктах MetaTrader.
200
TakeProfitSteps
Дистанция тейк-профита в пунктах MetaTrader.
200
CandleType
Таймфрейм свечей (по умолчанию 5 минут).
M5
Рекомендации по использованию
Подберите TradeVolume в соответствии с требованиями инструмента — стратегия автоматически приводит объем к биржевому шагу.
Параметры стоп-лосса и тейк-профита задаются в пунктах MetaTrader и далее переводятся в денежные шаги согласно точности инструмента.
Для формирования сигналов требуется как минимум три завершенные свечи, чтобы заполнить буфер истории Momentum.
Пирамидинг отсутствует: новая позиция не открывается, пока предыдущая полностью не закрыта.
Подключите стратегию к графикам StockSharp для визуализации WMA, стохастика и MACD при проверке сигналов.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Gonna Scalp strategy: WMA crossover with CCI momentum filter.
/// Buys when fast WMA above slow WMA and CCI above -100.
/// Sells when fast WMA below slow WMA and CCI below 100.
/// </summary>
public class GonnaScalpStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cciPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
public GonnaScalpStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new WeightedMovingAverage { Length = FastPeriod };
var slow = new WeightedMovingAverage { Length = SlowPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, cci, (candle, fastVal, slowVal, cciVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && cciVal > -100m && Position <= 0)
BuyMarket();
else if (crossDown && cciVal < 100m && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
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 WeightedMovingAverage, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class gonna_scalp_strategy(Strategy):
def __init__(self):
super(gonna_scalp_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetGreaterThanZero() \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._cci_period = self.Param("CciPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("CCI Period", "CCI period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(gonna_scalp_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(gonna_scalp_strategy, self).OnStarted2(time)
self._fast_ind = WeightedMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = WeightedMovingAverage()
self._slow_ind.Length = self._slow_period.Value
self._cci_ind = CommodityChannelIndex()
self._cci_ind.Length = self._cci_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._cci_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, cci_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
cci_val = float(cci_value)
if self._prev_fast is not None and self._prev_slow is not None:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and cci_val > -100.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and cci_val < 100.0 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return gonna_scalp_strategy()