Сегодня будем смотреть пример, в котором трейлинг стоп по позиции подтягивается по ленте сделок, а сама позиция открывается из события завершения свечи.
На графике это выглядит так:
На гитХаб исходник примера находится здесь:
Внутри проекта:
КОД
private BotTabSimple _tab; private Aindicator _pc; public StrategyParameterString Regime; public StrategyParameterInt IndLength; public StrategyParameterDecimal TrailStopPercent; public StrategyParameterInt Slippage; public StrategyParameterString VolumeType; public StrategyParameterDecimal Volume; public StrategyParameterString TradeAssetInPortfolio; public StopByTradeFeedSample(string name, StartProgram startProgram) : base(name, startProgram) { TabCreate(BotTabType.Simple); _tab = TabsSimple[0]; Regime = CreateParameter("Regime", "Off", new[] { "Off", "On", "OnlyLong", "OnlyShort", "OnlyClosePosition" }); Slippage = CreateParameter("Slippage in price step", 0, 0, 20, 1); IndLength = CreateParameter("Price channel length", 10, 10, 80, 3); TrailStopPercent = CreateParameter("Trail stop percent", 0.2m, 0.5m, 5, 4); VolumeType = CreateParameter("Volume type", "Deposit percent", new[] { "Contracts", "Contract currency", "Deposit percent" }); Volume = CreateParameter("Volume", 10, 1.0m, 50, 4); TradeAssetInPortfolio = CreateParameter("Asset in portfolio", "Prime"); _pc = IndicatorsFactory.CreateIndicatorByName("PriceChannel", name + "PriceChannel", false); _pc = (Aindicator)_tab.CreateCandleIndicator(_pc, "Prime"); _pc.ParametersDigit[0].Value = IndLength.ValueInt; _pc.ParametersDigit[1].Value = IndLength.ValueInt; _pc.Save(); _tab.CandleFinishedEvent += _tab_CandleFinishedEvent; _tab.NewTickEvent += _tab_NewTickEvent; ParametrsChangeByUser += Event_ParametrsChangeByUser; Description = "An example of a robot that pulls up the stop for a position based on changes in the deals feed. IMPORTANT! Tests of this robot should be conducted on the deals feed."; }
КОНЕЦ КОДА
В картинке:
Создание параметров происходит в конструкторе робота:
КОД
Regime = CreateParameter("Regime", "Off", new[] { "Off", "On", "OnlyLong", "OnlyShort", "OnlyClosePosition" }); Slippage = CreateParameter("Slippage in price step", 0, 0, 20, 1); IndLength = CreateParameter("Price channel length", 10, 10, 80, 3); TrailStopPercent = CreateParameter("Trail stop percent", 0.2m, 0.5m, 5, 4); VolumeType = CreateParameter("Volume type", "Deposit percent", new[] { "Contracts", "Contract currency", "Deposit percent" }); Volume = CreateParameter("Volume", 10, 1.0m, 50, 4); TradeAssetInPortfolio = CreateParameter("Asset in portfolio", "Prime");
КОНЕЦ КОДА
В окне параметров это выглядит так:
За что отвечают параметры:
КОД
private void _tab_CandleFinishedEvent(List<Candle> candles) { if (Regime.ValueString == "Off") { return; } if (_pc.DataSeries[0].Values == null || _pc.DataSeries[1].Values == null) { return; } if (_pc.DataSeries[0].Values.Count < _pc.ParametersDigit[0].Value + 2 || _pc.DataSeries[1].Values.Count < _pc.ParametersDigit[1].Value + 2) { return; } if (Regime.ValueString == "OnlyClosePosition") { return; } List<Position> openPositions = _tab.PositionsOpenAll; if (openPositions == null || openPositions.Count == 0) {// no positions decimal lastPrice = candles[candles.Count - 1].Close; decimal lastPcUp = _pc.DataSeries[0].Values[_pc.DataSeries[0].Values.Count - 2]; decimal lastPcDown = _pc.DataSeries[1].Values[_pc.DataSeries[1].Values.Count - 2]; // long if (Regime.ValueString != "OnlyShort") { if (lastPrice > lastPcUp) { _tab.BuyAtLimit(GetVolume(_tab), lastPrice + Slippage.ValueInt * _tab.Security.PriceStep); } } // Short if (Regime.ValueString != "OnlyLong") { if (lastPrice < lastPcDown) { _tab.SellAtLimit(GetVolume(_tab), lastPrice - Slippage.ValueInt * _tab.Security.PriceStep); } } } }
КОНЕЦ КОДА
КОД
private void _tab_NewTickEvent(Trade trade) { if (Regime.ValueString == "Off") { return; } List<Position> openPositions = _tab.PositionsOpenAll; if (openPositions == null || openPositions.Count == 0) { return; } Position myPos = openPositions[0]; if(myPos.State != PositionStateType.Open) { return; } decimal stopPrice = 0; decimal orderPrice = 0; if (myPos.Direction == Side.Buy) { stopPrice = trade.Price - (trade.Price * (TrailStopPercent.ValueDecimal/100)); orderPrice = stopPrice - Slippage.ValueInt * _tab.Security.PriceStep; } else if(myPos.Direction == Side.Sell) { stopPrice = trade.Price + (trade.Price * (TrailStopPercent.ValueDecimal / 100)); orderPrice = stopPrice + Slippage.ValueInt * _tab.Security.PriceStep; } _tab.CloseAtTrailingStop(myPos,stopPrice,orderPrice); }
КОНЕЦ КОДА
Удачных алгоритмов!
Комментарии открыты для друзей!
OsEngine: https://github.com/AlexWan/OsEngine
Поддержка OsEngine: https://t.me/osengine_official_support
Регистрируйся в АЛОР и получай бонусы: https://www.alorbroker.ru/open
Сайт АЛОР БРОКЕР: https://www.alorbroker.ru
Раздел «Для клиентов»: https://www.alorbroker.ru/openinfo/for-clients
Программа лояльности от АЛОР БРОКЕР и OsEngine: https://smart-lab.ru/company/os_engine/blog/972745.php