Изображение блога
OS_Engine_team
OS_Engine_team Блог компании OsEngine
14 апреля 2025, 18:32

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10

Сегодня будем смотреть пример, в котором трейлинг стоп по позиции подтягивается по ленте сделок, а сама позиция открывается из события завершения свечи.

На графике это выглядит так:

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10
 

1. Открываем робот-пример. StopByTradeFeedSample.

На гитХаб исходник примера находится здесь:

https://github.com/AlexWan/OsEngine/blob/master/project/OsEngine/Robots/TechSamples/StopByTradeFeedSample.cs

Внутри проекта:

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10


2. Конструктор и сервисный код.

КОД

private BotTabSimple _tab;

 // Basic settings
 private StrategyParameterString _regime;
 private StrategyParameterInt _<a class="dictionary_link" href="/finansoviy-slovar/slippage/">slippage</a>;

 // GetVolume settings
 private StrategyParameterString _volumeType;
 private StrategyParameterDecimal _volume;
 private StrategyParameterString _tradeAssetInPortfolio;

 // Indicator setting
 private StrategyParameterInt _indLength;
 
 // Indicator
 private Aindicator _pc;

 // Exit setting
 private StrategyParameterDecimal _trailStopPercent;

 public StopByTradeFeedSample(string name, StartProgram startProgram) : base(name, startProgram)
 {
     TabCreate(BotTabType.Simple);
     _tab = TabsSimple[0];

     // Basic settings
     _regime = CreateParameter("Regime", "Off", new[] { "Off", "On", "OnlyLong", "OnlyShort", "OnlyClosePosition" });
     _slippage = CreateParameter("Slippage in price step", 0, 0, 20, 1);
     _indLength = CreateParameter("<a class="dictionary_link" href="/finansoviy-slovar/price%20channel/">Price channel</a> length", 10, 10, 80, 3);

     // GetVolume settings
     _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");

     // Exit setting
     _trailStopPercent = CreateParameter("Trail stop percent", 0.2m, 0.5m, 5, 4);

     // Create indicator PriceChannel
     _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();

     // Subscribe to the candle finished event
     _tab.CandleFinishedEvent += _tab_CandleFinishedEvent;

     // Subscribe to the new tick event
     _tab.NewTickEvent += _tab_NewTickEvent;

     // Subscribe to the indicator update event
     ParametrsChangeByUser += Event_ParametrsChangeByUser;

     Description = OsLocalization.Description.DescriptionLabel108;
 }

КОНЕЦ КОДА

В картинке:

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10

  1. Поле для хранения источника BotTabSimple. В это поле потом мы положим объект источника и сможем обращаться к нему из любой части робота. Так удобнее.
  2. Поле для хранения индикатора.
  3. Параметры. Чуть позже поговорим про каждый.
  4. Создание источника BotTabSimple.
  5. Создание параметров.
  6. Создание индикатора PriceChannel. Установка его длины и отклонения из параметров.
  7. Подписка на событие CandleFinishedEvent (завершение свечи). В обработчике этого события логика открытия позиции.
  8. Подписка на событие NewTickEvent (новый трейд в ленте сделок). В обработчике этого события будет подтягивание стопа.
  9. Подписка на событие изменение параметров. В этом обработчике мы будем устанавливать индикатору новое значение длины.

 

3. Настройки и параметры.

Создание параметров происходит в конструкторе робота:

КОД

// Basic settings
_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);

// GetVolume settings
_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");

// Exit setting
_trailStopPercent = CreateParameter("Trail stop percent", 0.2m, 0.5m, 5, 4);

КОНЕЦ КОДА

В окне параметров это выглядит так:

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10

За что отвечают параметры:

  1. Regime – режим работы.
    1. Off – Выключен.
    2. On – включено без ограничений.
    3. OnlyLong – открытие только длинных позиций.
    4. OnlyShort – открытие только коротких позиций.
    5. OnlyClosePosition – доступно только закрытие позиций.
  2. Slippage in price step – проскальзывание для открытия и закрытия позиций в шагах цены.
  3. Price channel length – длина индикатора PriceChannel.
  4. Trail stop percent – величина трейлинг стопа для позиций в процентах.
  5. Volume type – режим выбора объёма.
    1. Contracts – кол-во контрактов инструмента.
    2. Contract currency – валюта контракта.
    3. Deposit percent – процент от депозита.
  6. Volume – значение объёма. Что именно, зависит от предыдущего пункта. В случае Contracts тут указывается объём инструмента. В случае Contract currency здесь указывается кол-во рублей или долларов, которыми нужно войти. В случае с Deposit percent здесь указывается % от общего депозита, которым нужно войти в контракт.
  7. Asset in portfolio – тут нужно указывать название валюты, которое будет использовано для расчёта объёма, если Вы выбрали тип объёма “Deposit percent”. В тестере оставляем «Prime». На крипте это обычно “USDT”.

 

4. Вход в логику в событии завершения свечи. Открытие позиции.

КОД

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);
                    }
                }
            }
        }

КОНЕЦ КОДА

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10 

  1. Если параметр Regime в положении Off, выходим из метода.
  2. Если данные по индикатору не начали формироваться, выходим из метода.
  3. Если кол-во данных в индикаторе меньше, чем длинна, указанная для его расчёта, выходим из метода.
  4. Если параметр Regime в положении OnlyClosePosition, выходим из метода.
  5. Запрашиваем текущие открытые позиции.
  6. Заходим в логику открытия позиции, только если позиций нет.
  7. Запрашиваем переменные, нужные для дальнейших расчётов.
  8. Входим в позицию лонг, если цена пробила ценовой канал вверх.
  9. Входим в позицию шорт, если цена пробила ценовой канал вниз.

 

5. Событие появления новой сделки в ленте сделок. Выставление стопа.

КОД

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#10 

  1. Если параметр Regime в положении Off, выходим из метода.
  2. Запрашиваем текущие открытые позиции.
  3. Если открытых позиций нет, выходим из метода.
  4. Берём открытую позицию из массива всех открытых позиций.
  5. Если статус позиции не равен Open, т.е. она ещё не до конца открыта или уже закрывается, ничего не делаем.
  6. Создаём переменные для стоп уровня и цены выставления ордера.
  7. Рассчитываем цену стопа и ордера для него для позиции типа BUY (лонг).
  8. Рассчитываем цену стопа и ордера для него для позиции типа SELL (шорт).
  9. Вызываем у источника метод для перевыставления трейлинг стопа.

Удачных алгоритмов!

Комментарии открыты для друзей!

Стандартный вход на свечках. Трейлинг стоп по ленте сделок. Микроменеджмент позиций в OsEngine#10

OsEnginehttps://github.com/AlexWan/OsEngine
Поддержка OsEngine: https://t.me/osengine_official_support

 

0 Комментариев

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн