Данная стратегия является C# конверсией MQL5 эксперта Exp_ColorSchaffJCCXTrendCycle.
Используется осциллятор Schaff Trend Cycle (STC) на основе алгоритма JCCX.
Логика торговли
На каждой завершённой свече рассчитывается значение Schaff Trend Cycle.
Когда осциллятор опускается ниже уровня High Level после его превышения, открывается длинная позиция и закрываются короткие.
Когда осциллятор поднимается выше уровня Low Level после его пробоя снизу, открывается короткая позиция и закрываются длинные.
Параметры
Название
Описание
Fast JCCX
Быстрый период JCCX индикатора.
Slow JCCX
Медленный период JCCX индикатора.
Smoothing
Коэффициент сглаживания JJMA.
Phase
Параметр фазы JJMA.
Cycle
Длина цикла для расчёта Schaff Trend.
High Level
Верхний триггерный уровень осциллятора.
Low Level
Нижний триггерный уровень осциллятора.
Open Long
Разрешить открытие длинных позиций.
Open Short
Разрешить открытие коротких позиций.
Close Long
Разрешить закрытие длинных позиций.
Close Short
Разрешить закрытие коротких позиций.
Примечания
Стратегия использует высокоуровневый API StockSharp и работает только с завершёнными свечами. Управление капиталом упрощено и предназначено для демонстрации возможностей.
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 the Schaff Trend Cycle indicator level crossovers.
/// </summary>
public class ColorSchaffJccxTrendCycleStrategy : Strategy
{
private readonly StrategyParam<decimal> _highLevel;
private readonly StrategyParam<decimal> _lowLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prev;
public decimal HighLevel { get => _highLevel.Value; set => _highLevel.Value = value; }
public decimal LowLevel { get => _lowLevel.Value; set => _lowLevel.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorSchaffJccxTrendCycleStrategy()
{
_highLevel = Param(nameof(HighLevel), 75m)
.SetDisplay("High Level", "Upper trigger level", "Signal");
_lowLevel = Param(nameof(LowLevel), 25m)
.SetDisplay("Low Level", "Lower trigger level", "Signal");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prev = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var stc = new SchaffTrendCycle();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(stc, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, stc);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal stc)
{
if (candle.State != CandleStates.Finished)
return;
if (_prev is null)
{
_prev = stc;
return;
}
if (_prev > HighLevel && stc <= HighLevel && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_prev < LowLevel && stc >= LowLevel && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prev = stc;
}
}
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 SchaffTrendCycle
from StockSharp.Algo.Strategies import Strategy
class color_schaff_jccx_trend_cycle_strategy(Strategy):
def __init__(self):
super(color_schaff_jccx_trend_cycle_strategy, self).__init__()
self._high_level = self.Param("HighLevel", 75.0) \
.SetDisplay("High Level", "Upper trigger level", "Signal")
self._low_level = self.Param("LowLevel", 25.0) \
.SetDisplay("Low Level", "Lower trigger level", "Signal")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev = None
@property
def high_level(self):
return self._high_level.Value
@property
def low_level(self):
return self._low_level.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_schaff_jccx_trend_cycle_strategy, self).OnReseted()
self._prev = None
def OnStarted2(self, time):
super(color_schaff_jccx_trend_cycle_strategy, self).OnStarted2(time)
stc = SchaffTrendCycle()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(stc, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, stc)
self.DrawOwnTrades(area)
def process_candle(self, candle, stc_val):
if candle.State != CandleStates.Finished:
return
stc_val = float(stc_val)
if self._prev is None:
self._prev = stc_val
return
if self._prev > float(self.high_level) and stc_val <= float(self.high_level) and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev < float(self.low_level) and stc_val >= float(self.low_level) and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev = stc_val
def CreateClone(self):
return color_schaff_jccx_trend_cycle_strategy()