Стратегия представляет собой перенос советника MetaTrader Exp_SilverTrend_ColorJFatl_Digit_MMRec на инфраструктуру StockSharp. Сохраняется оригинальная архитектура из двух независимых логических блоков, каждый из которых ведёт собственную «виртуальную» позицию и в сумме формирует итоговый объём стратегии.
Блок SilverTrend — анализирует раскраску свечей индикатора SilverTrend и отслеживает выход цены за адаптивные границы канала.
Блок ColorJFatl — рассчитывает фильтрованную линию FATL с использованием опубликованной таблицы коэффициентов и сглаживания EMA, имитирующего Jurik MA из MetaTrader.
Оба блока могут по отдельности открывать длинные и короткие позиции, закрывать противоположные сделки при появлении нового сигнала и применять собственные стоп-лоссы и тейк-профиты. Итоговый нетто-объём стратегии равен сумме виртуальных позиций двух модулей.
Настройки по умолчанию
Таймфреймы: по умолчанию оба блока подписываются на 6-часовые свечи (можно изменить параметрами).
Объём сделок: у каждого блока свой параметр объёма (по умолчанию 1).
Инструмент: выбранная пользователем бумага, подключённая к стратегии.
Логика индикаторов и сигналов
SilverTrend
Формирует скользящий диапазон high/low за SSP последних свечей.
Сдвигает границы канала внутрь диапазона с коэффициентом (33 - Risk) / 100 — как в оригинальном коде.
Окрашивает каждую свечу в соответствии с трендом (0/1 — бычий цвет, 3/4 — медвежий, 2 — нейтральный).
Сигналы:
Лонг — когда свеча на смещении Signal Bar получает бычий цвет, а предыдущая не была бычьей.
Шорт — когда цвет становится медвежьим, а предыдущая свеча не была медвежьей.
Стоп-лосс и тейк-профит задаются в пунктах и пересчитываются через PriceStep инструмента.
ColorJFatl
Вычисляет значение FATL через таблицу коэффициентов и выбранный тип цены (Applied Price).
Сглаживает результат EMA длиной JMA Length; параметр JMA Phase оставлен для совместимости и описания.
Определяет цвет линии по наклону: 2 — рост, 0 — падение, 1 — боковик.
Сигналы:
Лонг — когда цвет становится 2, а предыдущий цвет был 0 или 1.
Шорт — когда цвет становится 0, а предыдущий цвет был 1 или 2.
Перед открытием можно отключить/включить закрытие противоположной позиции блока.
Управление рисками
Каждый блок хранит собственную цену входа и уровни SL/TP.
При срабатывании цели или стопа закрывается только позиция соответствующего блока.
Если блоки совпадают по направлению, их объёмы суммируются и увеличивают итоговую позицию.
Параметры
Группа
Параметр
Описание
SilverTrend
Silver Candle Type
Таймфрейм свечей для блока SilverTrend.
SilverTrend
SSP
Длина диапазона high/low.
SilverTrend
Risk
Коэффициент сжатия канала.
SilverTrend
Signal Bar
Смещение свечи, по которой анализируется сигнал.
SilverTrend
Allow Silver Long/Short
Разрешение на входы в каждом направлении.
SilverTrend
Close Silver Long/Short
Разрешение на принудительное закрытие противоположной позиции.
SilverTrend
Silver Volume
Объём заявок блока SilverTrend.
SilverTrend
Silver SL/TP
Стоп-лосс и тейк-профит в пунктах.
ColorJFatl
Color Candle Type
Таймфрейм свечей для блока ColorJFatl.
ColorJFatl
JMA Length
Длина сглаживания FATL.
ColorJFatl
JMA Phase
Параметр фазы (оставлен для совместимости).
ColorJFatl
Applied Price
Тип цены для расчёта FATL.
ColorJFatl
Digits
Точность округления значения FATL.
ColorJFatl
Color Signal Bar
Смещение свечи для сигналов ColorJFatl.
ColorJFatl
Allow/Close
Флаги включения входов и закрытия противоположных позиций.
ColorJFatl
Color Volume
Объём заявок блока ColorJFatl.
ColorJFatl
Color SL/TP
Стоп-лосс и тейк-профит в пунктах для блока.
Рекомендации по использованию
Перед запуском убедитесь, что у инструмента заполнены шаг цены и размер пункта — иначе стопы и цели не будут рассчитываться корректно.
Используйте флаги Allow/Close, чтобы отдельно протестировать каждый блок.
Блоки могут работать в разных направлениях: итоговая позиция равна сумме виртуальных объёмов, поэтому возможно одновременное наличие лонга и шорта.
Параметры SSP, Risk, JMA Length и тип цены целесообразно оптимизировать под конкретный рынок.
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>
/// SilverTrend ColorJFatl Digit MMRec strategy (simplified). Uses Highest/Lowest
/// channel breakout with EMA slope for trend confirmation and martingale recovery.
/// </summary>
public class SilverTrendColorJfatlDigitMmrecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _channelLength;
private readonly StrategyParam<int> _emaLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int ChannelLength
{
get => _channelLength.Value;
set => _channelLength.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public SilverTrendColorJfatlDigitMmrecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_channelLength = Param(nameof(ChannelLength), 21)
.SetGreaterThanZero()
.SetDisplay("Channel Length", "Highest/Lowest lookback", "Indicators");
_emaLength = Param(nameof(EmaLength), 14)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA period for confirmation", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = ChannelLength };
var lowest = new Lowest { Length = ChannelLength };
var lastTrend = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, (ICandleMessage candle, decimal highVal, decimal lowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var range = highVal - lowVal;
if (range <= 0)
return;
var close = candle.ClosePrice;
var mid = (highVal + lowVal) / 2m;
// Channel breakout detection
if (close > highVal - range * 0.1m)
lastTrend = 1;
else if (close < lowVal + range * 0.1m)
lastTrend = -1;
// Confirm with position relative to midpoint
if (lastTrend > 0 && close > mid && Position <= 0)
BuyMarket();
else if (lastTrend < 0 && close < mid && Position >= 0)
SellMarket();
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class silver_trend_color_jfatl_digit_mmrec_strategy(Strategy):
def __init__(self):
super(silver_trend_color_jfatl_digit_mmrec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._channel_length = self.Param("ChannelLength", 21) \
.SetDisplay("Channel Length", "Highest/Lowest lookback", "Indicators")
self._last_trend = 0
@property
def CandleType(self):
return self._candle_type.Value
@property
def ChannelLength(self):
return self._channel_length.Value
def OnReseted(self):
super(silver_trend_color_jfatl_digit_mmrec_strategy, self).OnReseted()
self._last_trend = 0
def OnStarted2(self, time):
super(silver_trend_color_jfatl_digit_mmrec_strategy, self).OnStarted2(time)
self._last_trend = 0
highest = Highest()
highest.Length = self.ChannelLength
lowest = Lowest()
lowest.Length = self.ChannelLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawIndicator(area, lowest)
self.DrawOwnTrades(area)
def _on_process(self, candle, high_value, low_value):
if candle.State != CandleStates.Finished:
return
hv = float(high_value)
lv = float(low_value)
rng = hv - lv
if rng <= 0:
return
close = float(candle.ClosePrice)
mid = (hv + lv) / 2.0
if close > hv - rng * 0.1:
self._last_trend = 1
elif close < lv + rng * 0.1:
self._last_trend = -1
if self._last_trend > 0 and close > mid and self.Position <= 0:
self.BuyMarket()
elif self._last_trend < 0 and close < mid and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return silver_trend_color_jfatl_digit_mmrec_strategy()