Ejemplo n.º 1
0
        /// <summary>
        /// Основной метод бота
        /// </summary>
        /// <param name="ctx">Контекст TSLab</param>
        /// <param name="sec">Инструмент</param>
        public void Execute(IContext ctx, ISecurity sec)
        {
            // таймер для определения времени выполнения скрипта
            var sw = Stopwatch.StartNew();

            #region расчет индикаторов
            IList <double> upChannel = ctx.GetData("UpChannel",
                                                   new string[] { PeriodChannel.ToString() },
                                                   () => Series.Highest(sec.HighPrices, PeriodChannel));

            IList <double> downChannel = ctx.GetData("DownChannel",
                                                     new string[] { PeriodChannel.ToString() },
                                                     () => Series.Lowest(sec.LowPrices, PeriodChannel));
            #endregion

            #region первый и последний бар для расчетов
            // первый бар, используемый для расчетов
            int startBar = Math.Max(PeriodChannel + 1, ctx.TradeFromBar);

            // последний бар, используемый для расчетов
            var barsCount = sec.Bars.Count;
            if (!ctx.IsLastBarClosed)
            {
                barsCount--;
            }
            #endregion

            // цены закрытия инструмента
            var closePrices = sec.ClosePrices;

            #region Создание объекта для трейлинг стопа
            _trailStopHnd = new TrailStop()
            {
                StopLoss    = StopLossPct,
                TrailEnable = TrailLossEnablePct,
                TrailLoss   = TrailLossPct
            };
            #endregion


            #region Торговый цикл
            for (int i = startBar; i < barsCount; i++)
            {
                #region Формируем торговые сигналы
                // сигнал входа в лонг, сигнал активен в течение 2-х бар при выхода цены закрытия из канала
                bool signalLE = closePrices[i] > upChannel[i - 1] && closePrices[i - 2] <= upChannel[i - 3];

                // сигнал входа в шорт, сигнал активен в течение 2-х бар при выхода цены закрытия из канала
                bool signalSE = closePrices[i] < downChannel[i - 1] && closePrices[i - 2] >= downChannel[i - 3];

                // сигнал выхода из лонга
                bool signalLX = closePrices[i] < downChannel[i - 1];

                // сигнал выхода из шорта
                bool signalSX = closePrices[i] > upChannel[i - 1];
                #endregion

                #region Получаем активные позиции
                var lePosition    = sec.Positions.GetLastActiveForSignal("LE", i);
                var sePosition    = sec.Positions.GetLastActiveForSignal("SE", i);
                var openPositions = sec.Positions.GetActiveForBar(i).ToList();
                #endregion

                #region Выход из позиции, реверс позиции, установка стоп-лосса и тейк-профита
                if (openPositions.Count != 0)
                {
                    foreach (IPosition pos in openPositions)
                    {
                        switch (pos.EntrySignalName)
                        {
                            #region обработка позиции лонг LE
                        case "LE":
                            //условие выхода из лонга
                            if (signalLX)
                            {
                                //закрытие лонга по лимиту
                                pos.CloseAtPriceSlip(i + 1, closePrices[i], Slippage, "LX");

                                // условие реверса позиции
                                if (_regimeBot != RegimeBot.OnlyShort &&
                                    _regimeBot != RegimeBot.OnlyClosePosition)
                                {
                                    // открытие шорта по лимиту для реверса позиции
                                    sec.SellAtPriceSlip(i + 1, 1, closePrices[i], Slippage, "SE");
                                }
                            }
                            // если не было сигнала выхода, то выставляем стопы и профиты
                            else
                            {
                                // выставление стоп-лосса
                                if (OnStopLoss || OnBreakevenStop)
                                {
                                    SetStopLoss(pos, i);
                                }

                                // выставление тейк-профотита
                                if (OnTakeProfit)
                                {
                                    SetTakeProfit(pos, i);
                                }
                            }
                            break;
                            #endregion

                            #region обработка позиции шорт SE
                        case "SE":
                            // условие выхода из шорта
                            if (signalSX)
                            {
                                // закрытие шорта по лимиту
                                pos.CloseAtPriceSlip(i + 1, closePrices[i], Slippage, "SX");

                                // условие реверса позиции
                                if (_regimeBot != RegimeBot.OnlyShort &&
                                    _regimeBot != RegimeBot.OnlyClosePosition)
                                {
                                    // открытие лонга по лимиту для реверса позиции
                                    sec.BuyAtPriceSlip(i + 1, 1, closePrices[i], Slippage, "LE");
                                }
                            }
                            // если не было сигналов на выход, то выставляем стоп-лосс и тейк-профит
                            else
                            {
                                // выставление стопа-лосса
                                if (OnStopLoss || OnBreakevenStop)
                                {
                                    SetStopLoss(pos, i);
                                }

                                // выставление тейк-профита
                                if (OnTakeProfit)
                                {
                                    SetTakeProfit(pos, i);
                                }
                            }
                            break;
                            #endregion

                            #region обработка прочих позиций
                        default:
                            ctx.Log($"Обработка прочих позиций {pos.EntrySignalName}", MessageType.Warning);
                            break;
                            #endregion
                        }
                    }
                }
                #endregion

                if (_regimeBot == RegimeBot.OnlyClosePosition)
                {
                    continue;
                }

                #region Вход в первую позицию
                // если нет ни одной активной позиции, то проверяем условие входа в первую позицию
                if (openPositions.Count == 0)
                {
                    // лонг
                    if (signalLE && _regimeBot != RegimeBot.OnlyShort)
                    {
                        sec.BuyAtPriceSlip(i + 1, 1, closePrices[i], Slippage, "LE");
                    }
                    // шорт
                    else if (signalSE && _regimeBot != RegimeBot.OnlyLong)
                    {
                        sec.SellAtPriceSlip(i + 1, 1, closePrices[i], Slippage, "SE");
                    }
                }
                #endregion
            }
            #endregion

            #region Прорисовка графиков
            // Если идет процесс оптимизации, то графики рисовать не нужно, это замедляет работу
            if (ctx.IsOptimization)
            {
                return;
            }

            IGraphPane pane        = ctx.First ?? ctx.CreateGraphPane("First", "First");
            Color      colorCandle = ScriptColors.Black;
            pane.AddList(sec.Symbol, sec, CandleStyles.BAR_CANDLE, colorCandle, PaneSides.RIGHT);
            var lineUpChannel = pane.AddList(string.Format($"UpChannel ({PeriodChannel,0})"),
                                             upChannel,
                                             ListStyles.LINE,
                                             ScriptColors.Red,
                                             LineStyles.SOLID,
                                             PaneSides.RIGHT);

            //lineUpChannel.Thickness = 2;

            var lineDownChannel = pane.AddList(string.Format($"DwChannel ({PeriodChannel,0}"),
                                               downChannel,
                                               ListStyles.LINE,
                                               ScriptColors.Blue,
                                               LineStyles.SOLID,
                                               PaneSides.RIGHT);

            //lineDownChannel.Thickness = 2;

            #endregion

            #region Вывод в лог
            // Вывод в лог времени выполнения скрипта только в режиме Лаборатория
            if (!ctx.Runtime.IsAgentMode)
            {
                ctx.Log($"Скрипт выполнен за время: {sw.Elapsed}", MessageType.Info, true);
            }
            #endregion
        }