/*================================================================================ * Стратегия: Envelope (конверт) * Платформа: TSLab версия 1.1.7.0 * Дата создания: 05.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.Envelope { //================================================================================ public class Envelope : IExternalScript { // используем переменные-флаги для сигналов public bool bBuy; // флаг сигнала открытия длинной позиции public bool bSell; // флаг сигнала закрытия длинной позиции public bool bShort; // флаг сигнала открытия короткой позиции public bool bCover; // флаг сигнала закрытия короткой позиции public IPosition LongPos, ShortPos; //================================================================================ // функция вычисления верхней границы конверта (последовательность значений) // nSMA - серия значений простой скользящей средней // Shift - смещение границы от скользящей средней public IList GenHighRange(ISecurity source, IList nSMA, double Shift) { double vHighRange = 0; // серия значений HighRange IList nHighRange = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vHighRange = nSMA[bar] * (1 + Shift); //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nHighRange.Add(vHighRange); } return nHighRange; } //================================================================================ // функция вычисления нижней границы конверта (последовательность значений) // nSMA - серия значений простой скользящей средней // Shift - смещение границы от скользящей средней public IList GenLowRange(ISecurity source, IList nSMA, double Shift) { double vLowRange = 0; // серия значений LowRange IList nLowRange = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vLowRange = nSMA[bar] * (1 - Shift); //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nLowRange.Add(vLowRange); } return nLowRange; } //================================================================================ // Параметры оптимизации // параметра для длинных позиций public OptimProperty LongPeriodParam = new OptimProperty(22, 2, 50, 2); public OptimProperty LongShiftParam = new OptimProperty(0.01, 0.01, 0.1, 0.005); // параметра для коротких позиций public OptimProperty ShortPeriodParam = new OptimProperty(24, 2, 50, 2); public OptimProperty ShortShiftParam = new OptimProperty(0.01, 0.01, 0.1, 0.005); //================================================================================ public virtual void Execute(IContext ctx, ISecurity source) { int StartBar = 0; #region Variables // для длинных позиций int LongPeriod; // период расчета простой скользящей средней SMA double LongShift; // смещение границ конверта от скользящей средней // для коротких длинных позиций int ShortPeriod; // период расчета простой скользящей средней SMA double ShortShift; // смещение границ конверта от скользящей средней #endregion //-------------------------------------------------------------------------------- #region Obtain parameters LongPeriod = LongPeriodParam; LongShift = LongShiftParam; ShortPeriod = ShortPeriodParam; ShortShift = ShortShiftParam; StartBar = LongPeriod + 1; if (ShortPeriod > LongPeriod) StartBar = ShortPeriod + 1; // Вычисляем верхнюю и нижнюю границы конверта. // Используем GetData для кеширования данных и ускорения оптимизации. // для длинных позиций // серия для простой скользящей средней SMA IList nLongSMA = ctx.GetData("LongSMA", new[] {LongPeriod.ToString()}, delegate { return Series.SMA(source.ClosePrices, LongPeriod); }); // серия значений верхней границы IList nLongHighRange = ctx.GetData("LongHighRange", new[] {LongPeriod.ToString()+LongShift.ToString()}, delegate { return GenHighRange(source, nLongSMA, LongShift); }); // серия значений нижней границы IList nLongLowRange = ctx.GetData("LongLowRange", new[] {LongPeriod.ToString()+LongShift.ToString()}, delegate { return GenLowRange(source, nLongSMA, LongShift); }); // для коротких позиций // серия для простой скользящей средней SMA IList nShortSMA = ctx.GetData("ShortSMA", new[] {ShortPeriod.ToString()}, delegate { return Series.SMA(source.ClosePrices, ShortPeriod); }); // серия значений верхней границы IList nShortHighRange = ctx.GetData("ShortHighRange", new[] {ShortPeriod.ToString()+ShortShift.ToString()}, delegate { return GenHighRange(source, nShortSMA, ShortShift); }); // серия значений нижней границы IList nShortLowRange = ctx.GetData("ShortLowRange", new[] {ShortPeriod.ToString()+ShortShift.ToString()}, delegate { return GenLowRange(source, nShortSMA, ShortShift); }); #endregion //================================================================================ #region основной цикл - проход по барам int barsCount = source.Bars.Count; for (int bar = StartBar; bar < barsCount-1; bar++) { //-------------------------------------------------------------------------------- #region generate signals // сброс значений сигналов bBuy = false; bSell = false; bShort = false; bCover = false; // установка сигналов по условиям // для длинных позиций if (source.ClosePrices[bar-1] > nLongHighRange[bar-1]) { if (source.ClosePrices[bar] > source.ClosePrices[bar-1]) bBuy = true; } if (source.ClosePrices[bar] < nLongLowRange[bar]) bSell = true; // для коротких позиций if (source.ClosePrices[bar-1] < nShortLowRange[bar-1]) { if (source.ClosePrices[bar] < source.ClosePrices[bar-1]) bShort = true; } if (source.ClosePrices[bar] > nShortHighRange[bar]) bCover = 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; // для длинных позиций // Отрисовка простой скользящей средней mainPane.AddList("LongSMA", nLongSMA, ListStyles.LINE, 0x00a0a0, LineStyles.DOT, PaneSides.RIGHT); // Отрисовка верхней и нижней границы конверта mainPane.AddList("LongHighRange", nLongHighRange, ListStyles.LINE, 0x0000a0, LineStyles.DOT, PaneSides.RIGHT); mainPane.AddList("LongLowRange", nLongLowRange, ListStyles.LINE, 0xf07070, LineStyles.DOT, PaneSides.RIGHT); // для коротких позиций // Отрисовка простой скользящей средней mainPane.AddList("ShortSMA", nShortSMA, ListStyles.LINE, 0xa000a0, LineStyles.DOT, PaneSides.RIGHT); // Отрисовка верхней и нижней границы конверта mainPane.AddList("ShortHighRange", nShortHighRange, ListStyles.LINE, 0x7070f0, LineStyles.DOT, PaneSides.RIGHT); mainPane.AddList("ShortLowRange", nShortLowRange, ListStyles.LINE, 0xa00000, LineStyles.DOT, PaneSides.RIGHT); #endregion //-------------------------------------------------------------------------------- } } }