Стратегия повторяет советник MetaTrader 4 ArtificialIntelligence_Right.mq4. В её основе лежит однослойный перцептрон,
использующий значения индикатора Acceleration/Deceleration (AC) с четырьмя различными сдвигами. Знак выходного сигнала
определяет направление входа в рынок и выполняет роль фильтра при разворотах.
В версии StockSharp все действия выполняются на закрытии готовой свечи. Это делает поведение стратегии воспроизводимым при
историческом тестировании и оптимизации.
Индикаторы и расчёты
Acceleration/Deceleration строится через Awesome Oscillator: разница между SMA(5) и SMA(34) от средней HL2, затем из
полученного AO вычитается скользящая средняя AC (SMA(5)).
В кольцевом буфере хранятся 22 последних значения AC, что позволяет обращаться к индексам 0, 7, 14 и 21 так же, как в MQL-версии.
Перед вычислением скалярного произведения каждая входная величина перцептрона смещается на -100, полностью копируя
выражение w = x - 100 из исходника.
Правила торговли
Открытие позиций
Если выход перцептрона положителен и позиции нет, открывается покупка по рынку.
Если выход отрицателен и позиции нет, открывается продажа по рынку.
Стоп-лосс
После входа виртуальный стоп устанавливается на расстоянии StopLossPoints * PriceStep от цены входа. Тем самым
воспроизводится использование Point в MetaTrader.
Когда цена закрытия пересекает уровень стопа, позиция закрывается рыночной сделкой, имитируя срабатывание стоп-ордера.
Трейлинг и разворот
Когда плавающая прибыль превышает (2 * StopLossPoints + SpreadPoints) пунктов, оригинальный робот либо подтягивает стоп
на то же расстояние, либо разворачивается при смене знака перцептрона.
В адаптации для StockSharp используется тот же критерий: при достижении порога и смене знака выполняется сделка в объёме
2 * текущая позиция, что даёт разворот с прежним лотом; иначе стоп переносится на заданное расстояние от текущей цены.
Разворот через сделку двойного объёма полностью воспроизводит логику OrderCloseBy, оставляя открытую позицию в противоположную
сторону с тем же числом лотов.
Параметры
Имя
Описание
X1 … X4
Веса перцептрона. Значения по умолчанию (135, 127, 16, 93) совпадают с MQL-советником.
StopLoss
Расстояние стоп-лосса в пунктах MetaTrader. Умножается на PriceStep инструмента для получения абсолютной цены.
Spread
Дополнительный запас по спреду (по умолчанию 3 пункта), который участвует в условии активации трейлинга.
Candle Type
Тип свечей для расчётов. Значение по умолчанию — минутные свечи.
Свойство Volume заранее установлено в 1 лот, что соответствует параметру lots в исходном советнике.
Особенности реализации
При сбросе стратегии очищаются буферы индикатора и перцептрона, чтобы избежать ложных срабатываний из-за устаревших данных.
Если у инструмента отсутствует PriceStep, для расчётов используется значение 1, обеспечивая универсальность в тестах.
Реальные стоп-заявки не выставляются: логика стопов реализована через рыночные сделки внутри обработчика свечей, что
гарантирует одинаковое поведение на разных источниках данных и брокерах.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Artificial Intelligence Right strategy - perceptron-like logic.
/// Uses fast/slow SMA difference (Awesome Oscillator approximation).
/// Buys when AO crosses above 0, sells when below.
/// </summary>
public class ArtificialIntelligenceRightStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevDiff;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ArtificialIntelligenceRightStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 34)
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
_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();
_prevDiff = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
var diff = fast - slow;
if (!_hasPrev)
{
_prevDiff = diff;
_hasPrev = true;
return;
}
// AO crosses above 0
if (_prevDiff <= 0 && diff > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// AO crosses below 0
else if (_prevDiff >= 0 && diff < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevDiff = diff;
}
}