Порт MetaTrader 4 советника «Bronzew_pan» на платформу StockSharp. Работает по одной бумаге, анализируя только завершённые свечи, и комбинирует осциллятор DayImpuls с индикаторами Williams %R и CCI для поиска импульсных разворотов.
Логика работы
Подписывается на выбранный таймфрейм и рассчитывает DayImpuls, Williams %R и CCI с одинаковым периодом.
Ведёт раздельный учёт длинных и коротких корзин, эмулируя хеджевый режим оригинального советника.
Закрывает все позиции, когда плавающая прибыль достигает ProfitTarget либо падает ниже LossTarget.
Открывает шорт, если DayImpuls выше DayImpulsShortLevel и снижается, Williams %R выше WilliamsLevelUp, а CCI превышает CciLevel.
Открывает лонг, если DayImpuls ниже DayImpulsLongLevel и растёт, Williams %R ниже WilliamsLevelDown, а CCI меньше -CciLevel.
При выходе плавающего PnL за пределы коридора PredBand отправляет крупный усредняющий ордер, умножая базовый объём на LotMultiplier, что повторяет аварийный разворот из MetaTrader.
Контролирует отдельные стоп-лоссы и тейк-профиты для лонгов и шортов, переводя указанные в пунктах расстояния в цену.
Новые сделки не открываются, если баланс ниже MinimumBalance или уже активны обе корзины одновременно.
Параметры
Название
Описание
Значение по умолчанию
TradeVolume
Базовый объём входа.
0.1
LongStopLossPips
Стоп-лосс для длинной корзины в пунктах.
0
ShortStopLossPips
Стоп-лосс для короткой корзины в пунктах.
0
LongTakeProfitPips
Тейк-профит для длинной корзины в пунктах.
0
ShortTakeProfitPips
Тейк-профит для короткой корзины в пунктах.
0
IndicatorPeriod
Период для DayImpuls, Williams %R и CCI.
14
CciLevel
Абсолютный порог CCI для подтверждения экстремума.
150
WilliamsLevelUp
Уровень Williams %R для входа в шорт.
-15
WilliamsLevelDown
Уровень Williams %R для входа в лонг.
-85
DayImpulsShortLevel
Порог DayImpuls для подтверждения шорта.
50
DayImpulsLongLevel
Порог DayImpuls для подтверждения лонга.
-50
ProfitTarget
Плавающая прибыль, при которой всё закрывается.
500
LossTarget
Плавающий убыток, при котором всё закрывается.
-2000
PredBand
Коридор прибыли для аварийного усреднения.
100
LotMultiplier
Множитель объёма при усреднении.
30
MinimumBalance
Минимальный баланс счёта для работы.
3000
CandleType
Таймфрейм свечей.
15m
Дополнительно
DayImpuls реализован как двойное EMA-сглаживание тела свечи, переведённого в пункты, полностью повторяя оригинал.
Нулевые значения стопов и тейков отключают соответствующую защиту.
Стратегия обрабатывает только свечи со статусом Finished.
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>
/// Bronze Pan strategy - CCI with momentum confirmation.
/// Buys when CCI crosses above positive level and momentum is positive.
/// Sells when CCI crosses below negative level and momentum is negative.
/// </summary>
public class BronzePanStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevCci;
private bool _hasPrev;
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BronzePanStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback", "Indicators");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold level", "Levels");
_momentumPeriod = Param(nameof(MomentumPeriod), 14)
.SetDisplay("Momentum Period", "Momentum lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevCci = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var mom = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, mom, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cci, decimal mom)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevCci = cci;
_hasPrev = true;
return;
}
if (_prevCci <= CciLevel && cci > CciLevel && mom > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (_prevCci >= -CciLevel && cci < -CciLevel && mom < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevCci = cci;
}
}