/*================================================================================ * Стратегия: TD Sequential * Платформа: TSLab версия 1.1.8.0 * Дата создания: 12.07.2010 * Реализовано: Laber *================================================================================*/ using System; using System.Collections.Generic; using TSLab.Script; using TSLab.Script.Handlers; using TSLab.Script.Optimization; using TSLab.Script.Helpers; namespace TSLab.Sequential { //================================================================================ public class Sequential : IExternalScript { // используем переменные-флаги для сигналов public bool bBuy; // флаг сигнала открытия длинной позиции public bool bSell; // флаг сигнала закрытия длинной позиции public bool bShort; // флаг сигнала открытия короткой позиции public bool bCover; // флаг сигнала закрытия короткой позиции public IPosition LongPos, ShortPos; //================================================================================ // функция вычисления CumUp (последовательность значений) // Period - период сравнения значений public IList GenCumUp(ISecurity source, int Period) { double Close, PClose; int UpCount = 0; // серия значений AVG IList nCumUp = new List(source.Bars.Count); PClose = source.ClosePrices[0]; for (int bar = 0; bar < source.Bars.Count; bar++) { UpCount = UpCount + 1; Close = source.ClosePrices[bar]; if (bar >= Period) { PClose = source.ClosePrices[bar-Period]; if (Close <= PClose) UpCount = 0; } //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nCumUp.Add(UpCount); } return nCumUp; } //================================================================================ // функция вычисления CumDown (последовательность значений) // Period - период сравнения значений public IList GenCumDown(ISecurity source, int Period) { double Close, PClose; int DownCount = 0; // серия значений AVG IList nCumDown = new List(source.Bars.Count); PClose = source.ClosePrices[0]; for (int bar = 0; bar < source.Bars.Count; bar++) { DownCount = DownCount + 1; Close = source.ClosePrices[bar]; if (bar >= Period) { PClose = source.ClosePrices[bar-Period]; if (Close >= PClose) DownCount = 0; } //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nCumDown.Add(DownCount); } return nCumDown; } //================================================================================ // Параметры оптимизации // период расчета CumUp и CumDown (4) public OptimProperty PeriodParam = new OptimProperty(6, 2, 10, 1); // период расчета максимумов и минимумов (9) public OptimProperty XPeriodParam = new OptimProperty(5, 5, 20, 1); //================================================================================ public virtual void Execute(IContext ctx, ISecurity source) { int StartBar = 0; #region Variables int Period; // период расчета CumUp и CumDown int XPeriod; // период расчета максимумов и минимумов bool bSetup; double MaxPrice, iPrice; int MaxBar, ibar; int Countdown; #endregion //-------------------------------------------------------------------------------- #region Obtain parameters Period = PeriodParam; XPeriod = XPeriodParam; StartBar = Period + 1; if (StartBar < XPeriod) StartBar = XPeriod; bSetup = false; // Вычисляем скользящие средние в качестве базовых рядов // Используем GetData для кеширования данных и ускорения оптимизации. IList nCumUp = ctx.GetData("CumUp", new[] {Period.ToString()}, delegate { return GenCumUp(source, Period); }); IList nCumDown = ctx.GetData("CumDown", new[] {Period.ToString()}, delegate { return GenCumDown(source, Period); }); #endregion //================================================================================ #region основной цикл - проход по барам int barsCount = source.Bars.Count; MaxPrice = source.HighPrices[0]; Countdown = 0; for (int bar = StartBar; bar < barsCount-1; bar++) { // сброс значений сигналов bBuy = false; bSell = false; //-------------------------------------------------------------------------------- #region calculate values if (bSetup) { if (nCumDown[bar] == 9) { bSetup = false; Countdown = 0; //-------------------------------------------------------------------------------- // определение бара и значений максимума цены MaxPrice = source.HighPrices[bar]; MaxBar = bar; for (int i=0; i MaxPrice) { MaxPrice = iPrice; MaxBar = ibar; } } } if (source.ClosePrices[bar-XPeriod-1] > MaxPrice) { MaxPrice = source.ClosePrices[bar-XPeriod-1]; MaxBar = bar-XPeriod-1; } //-------------------------------------------------------------------------------- } } if (!bSetup) { if (nCumDown[bar] == 9) { Countdown = 0; //-------------------------------------------------------------------------------- // определение бара и значений максимума цены MaxPrice = source.HighPrices[bar]; MaxBar = bar; for (int i=0; i MaxPrice) { MaxPrice = iPrice; MaxBar = ibar; } } } if (source.ClosePrices[bar-XPeriod-1] > MaxPrice) { MaxPrice = source.ClosePrices[bar-XPeriod-1]; MaxBar = bar-XPeriod-1; } //-------------------------------------------------------------------------------- } if (source.ClosePrices[bar] > MaxPrice) { bSetup = true; continue; } if (nCumUp[bar] == 9) { bSetup = true; continue; } if(source.ClosePrices[bar] <= source.LowPrices[bar-2] ) { if (Countdown == 12 && source.LowPrices[bar] > source.ClosePrices[bar-5]) { continue; } Countdown = Countdown + 1; if (Countdown == 13) { bSetup = true; // сигнал на открытие длинной позиции bBuy = true; } } } // сигнал на закрытие длдинной позиции if (nCumUp[bar] >= 9) bSell = true; #endregion //================================================================================ #region execute signals //-------------------------------------------------------------------------------- // выполнение сигналов для длинной позиции IPosition LongPos = source.Positions.GetLastActiveForSignal("LN"); if (LongPos == null) { // Если нет активной длинной позиции if (bBuy) { // Если есть сигнал Buy, // выдаем ордер на открыте новой длинной позиции. source.Positions.BuyAtMarket(bar+1, 1, "LN"); } } else { // Если есть активная длинная позиция if (bSell) { // Если есть сигнал Sell, // выдаем ордер на закрыте длинной позиции. LongPos.CloseAtMarket(bar+1, "LX"); } } //-------------------------------------------------------------------------------- // выполнение сигналов для короткой позиции IPosition ShortPos = source.Positions.GetLastActiveForSignal("SN"); if (ShortPos == null) { // Если нет активной короткой позиции if (bShort) { // Если есть сигнал Short // выдаем ордер на открыте новой короткой позиции. source.Positions.SellAtMarket(bar+1, 1, "SN"); } } else { // Если есть активная короткая позиция, if (bCover) { // Если есть сигнал Cover // выдаем ордер на закрыте короткой позиции. ShortPos.CloseAtMarket(bar+1, "SX"); } } #endregion } #endregion //================================================================================ #region прорисовка графиков // Берем основную панель (Pane) IPane mainPane = ctx.First; // Создаем дополнительную панель для индикатора CumUp IPane CumUpPane = ctx.CreatePane("CumUp", 10, false, false); // Отрисовка графика CumUp CumUpPane.AddList(string.Format("CumUp"), nCumUp, ListStyles.LINE, 0x000070, LineStyles.SOLID, PaneSides.RIGHT); // Создаем дополнительную панель для индикатора CumDown. IPane CumDownPane = ctx.CreatePane("CumDown", 10, false, false); // Отрисовка графика CumDown CumDownPane.AddList(string.Format("CumDown"), nCumDown, ListStyles.LINE, 0x700000, LineStyles.SOLID, PaneSides.RIGHT); #endregion //-------------------------------------------------------------------------------- } } }