Сегодня будем смотреть пример, в котором трейлинг стоп по позиции подтягивается по ленте сделок, а сама позиция открывается из события завершения свечи.
На графике это выглядит так:
На гитХаб исходник примера находится здесь:
Внутри проекта:
КОД
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