/*================================================================================ * Стратегия: Two-Bar Reversal Pattern * Платформа: TSLab версия 1.1.8.0 * Дата создания: 00.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.ReversalPattern { //================================================================================ public class ReversalPattern : IExternalScript { // используем переменные-флаги для сигналов public bool bBuy; // флаг сигнала открытия длинной позиции public bool bSell; // флаг сигнала закрытия длинной позиции public bool bShort; // флаг сигнала открытия короткой позиции public bool bCover; // флаг сигнала закрытия короткой позиции public IPosition LongPos, ShortPos; //================================================================================ // функция вычисления значений для CloseNearHigh (последовательность значений) public IList Gen_CloseNearHigh(ISecurity source) { double vValue, Size, SizeClose; // серия значений IList nValue = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vValue = 100; Size = source.HighPrices[bar] - source.LowPrices[bar]; if (Size > 0) { SizeClose = source.HighPrices[bar] - source.ClosePrices[bar]; vValue = SizeClose / Size; } //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // функция вычисления значений для CloseNearLow (последовательность значений) public IList Gen_CloseNearLow(ISecurity source) { double vValue, Size, SizeClose; // серия значений IList nValue = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vValue = 100; Size = source.HighPrices[bar] - source.LowPrices[bar]; if (Size > 0) { SizeClose = source.ClosePrices[bar] - source.LowPrices[bar]; vValue = SizeClose / Size; } //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // функция вычисления значений для BarsSameSize (последовательность значений) public IList Gen_BarsSameSize(ISecurity source) { double vValue, Size1, Size2; double Diff, Avg; // серия значений IList nValue = new List(source.Bars.Count); nValue.Add(1); for (int bar = 1; bar < source.Bars.Count; bar++) { Size1 = source.HighPrices[bar] - source.LowPrices[bar]; Size2 = source.HighPrices[bar-1] - source.LowPrices[bar-1]; Diff = Math.Abs(Size1 - Size2); Avg = (Size1 + Size2) / 2; vValue = Diff / Avg; //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // функция вычисления значений для BarsSameHigh (последовательность значений) public IList Gen_BarsSameHigh(ISecurity source) { double vValue; double Diff, Avg; // серия значений IList nValue = new List(source.Bars.Count); nValue.Add(1); for (int bar = 1; bar < source.Bars.Count; bar++) { Diff = Math.Abs(source.HighPrices[bar] - source.HighPrices[bar-1]); Avg = (source.HighPrices[bar] + source.HighPrices[bar-1]) / 2; vValue = Diff / Avg * 100; //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // функция вычисления значений для Momentum (последовательность значений) public IList Gen_Momentum(ISecurity source, int Period) { double vValue; // серия значений IList nValue = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vValue = 0; if (bar >= Period) { vValue = source.ClosePrices[bar] - source.ClosePrices[bar-Period]; vValue = vValue / source.ClosePrices[bar] * 100; } //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // Параметры оптимизации // параметра для длинных позиций public OptimProperty LongATRPeriodParam = new OptimProperty(14, 5, 30, 1); public OptimProperty LongMomPeriodParam = new OptimProperty(5, 3, 10, 1); public OptimProperty LongNearLimitParam = new OptimProperty(1, 0.1, 1.0, 0.05); public OptimProperty LongStopKoefParam = new OptimProperty(10, 1, 20, 0.5); public OptimProperty LongTargetKoefParam = new OptimProperty(15, 1, 20, 0.5); public OptimProperty LongBarSizeLimitParam = new OptimProperty(0.2, 0.1, 1, 0.1); public OptimProperty LongBarHighLimitParam = new OptimProperty(0.023, 0.001, 0.1, 0.001); public OptimProperty LongMomLimitParam = new OptimProperty(0.8, 0.1, 1, 0.1); // параметра для коротких позиций public OptimProperty ShortATRPeriodParam = new OptimProperty(14, 5, 30, 1); public OptimProperty ShortMomPeriodParam = new OptimProperty(5, 3, 10, 1); public OptimProperty ShortNearLimitParam = new OptimProperty(1, 0.1, 1.0, 0.05); public OptimProperty ShortStopKoefParam = new OptimProperty(6, 1, 20, 0.5); public OptimProperty ShortTargetKoefParam = new OptimProperty(20, 1, 20, 0.5); public OptimProperty ShortBarSizeLimitParam = new OptimProperty(0.2, 0.1, 1, 0.1); public OptimProperty ShortBarHighLimitParam = new OptimProperty(0.071, 0.001, 0.1, 0.001); public OptimProperty ShortMomLimitParam = new OptimProperty(0.1, 0.1, 1, 0.1); //================================================================================ public virtual void Execute(IContext ctx, ISecurity source) { int StartBar = 0; #region Variables // для длинных позиций // период расчета int LongATRPeriod; // период расчета ATR int LongMomPeriod; // период расчета Momentum int LongNearLimit; // пороговое значение для функции CloseNearHigh, CloseNearLow int LongStopKoef; // размер стоп-лосс в процентах int LongTargetKoef; // размер тэйк-профит в процентах double LongBarSizeLimit; // пороговое значение для сравнения размера баров double LongBarHighLimit; // пороговое значение для сравнения High баров double LongMomLimit; // пороговое значение для Momentum // для коротких позиций // период расчета int ShortATRPeriod; // период расчета ATR int ShortMomPeriod; // период расчета Momentum int ShortNearLimit; // пороговое значение для функции CloseNearHigh, CloseNearLow int ShortStopKoef; // размер стоп-лосс в процентах int ShortTargetKoef; // размер тэйк-профит в процентах double ShortBarSizeLimit; // пороговое значение для сравнения размера баров double ShortBarHighLimit; // пороговое значение для сравнения High баров double ShortMomLimit; // пороговое значение для Momentum bool bLongWideRange, bLongMomUp, bLongMomDown, bLongBarSame; bool bLongCNH, bLongPrevCNH, bLongCNL, bLongPrevCNL; bool bShortWideRange, bShortMomUp, bShortMomDown, bShortBarSame; bool bShortCNH, bShortPrevCNH, bShortCNL, bShortPrevCNL; double LongStopPrice, LongTargetPrice; double ShortStopPrice, ShortTargetPrice; #endregion //-------------------------------------------------------------------------------- #region Obtain parameters LongATRPeriod = LongATRPeriodParam; LongMomPeriod = LongMomPeriodParam; LongNearLimit = LongNearLimitParam; LongStopKoef = LongStopKoefParam; LongTargetKoef = LongTargetKoefParam; LongBarSizeLimit = LongBarSizeLimitParam; LongBarHighLimit = LongBarHighLimitParam; LongMomLimit = LongMomLimitParam; ShortATRPeriod = ShortATRPeriodParam; ShortMomPeriod = ShortMomPeriodParam; ShortNearLimit = ShortNearLimitParam; ShortStopKoef = ShortStopKoefParam; ShortTargetKoef = ShortTargetKoefParam; ShortBarSizeLimit = ShortBarSizeLimitParam; ShortBarHighLimit = ShortBarHighLimitParam; ShortMomLimit = ShortMomLimitParam; StartBar = LongATRPeriod; if (LongMomPeriod > StartBar) StartBar = LongMomPeriod; if (ShortATRPeriod > StartBar) StartBar = ShortATRPeriod; if (ShortMomPeriod > StartBar) StartBar = ShortMomPeriod; // Вычисляем последовательности значений // Используем GetData для кеширования данных и ускорения оптимизации. // для длинных позиций // серия для функции CloseNearHigh IList nLongCNH = ctx.GetData("LongCNH", new[] {"1"}, delegate { return Gen_CloseNearHigh(source); }); // серия для функции CloseNearLow IList nLongCNL = ctx.GetData("LongCNL", new[] {"1"}, delegate { return Gen_CloseNearLow(source); }); // серия для функции BarsSameSize IList nLongBSS = ctx.GetData("LongBSS", new[] {"1"}, delegate { return Gen_BarsSameSize(source); }); // серия для функции BarsSameHigh IList nLongBSH = ctx.GetData("LongBSH", new[] {"1"}, delegate { return Gen_BarsSameHigh(source); }); // серия для TrueRange IList nLongTR = ctx.GetData("LongTrueRange", new[] {"1"}, delegate { return Series.TrueRange(source.Bars); }); // серия для ATR IList nLongATR = ctx.GetData("LongATR", new[] {LongATRPeriod.ToString()}, delegate { return Series.AverageTrueRange(source.Bars, LongATRPeriod); }); // серия для Momentum IList nLongMom = ctx.GetData("LongMom", new[] {LongMomPeriod.ToString()}, delegate { return Gen_Momentum(source, LongMomPeriod); }); // для коротких позиций // серия для функции CloseNearHigh IList nShortCNH = ctx.GetData("ShortCNH", new[] {"1"}, delegate { return Gen_CloseNearHigh(source); }); // серия для функции CloseNearLow IList nShortCNL = ctx.GetData("ShortCNL", new[] {"1"}, delegate { return Gen_CloseNearLow(source); }); // серия для функции BarsSameSize IList nShortBSS = ctx.GetData("ShortBSS", new[] {"1"}, delegate { return Gen_BarsSameSize(source); }); // серия для функции BarsSameHigh IList nShortBSH = ctx.GetData("ShortBSH", new[] {"1"}, delegate { return Gen_BarsSameHigh(source); }); // серия для TrueRange IList nShortTR = ctx.GetData("ShortTrueRange", new[] {"1"}, delegate { return Series.TrueRange(source.Bars); }); // серия для ATR IList nShortATR = ctx.GetData("ShortATR", new[] {ShortATRPeriod.ToString()}, delegate { return Series.AverageTrueRange(source.Bars, ShortATRPeriod); }); // серия для Momentum IList nShortMom = ctx.GetData("ShortMom", new[] {ShortMomPeriod.ToString()}, delegate { return Gen_Momentum(source, ShortMomPeriod); }); #endregion //================================================================================ #region основной цикл - проход по барам int barsCount = source.Bars.Count; for (int bar = StartBar; bar < barsCount-1; bar++) { //-------------------------------------------------------------------------------- #region calculate values bLongWideRange = (nLongTR[bar] > nLongATR[bar]) || (nLongTR[bar-1] > nLongATR[bar-1]); bLongMomUp = (nLongMom[bar] > LongMomLimit); bLongMomDown = (nLongMom[bar] < -LongMomLimit); bLongBarSame = (nLongBSS[bar] < LongBarSizeLimit) && (nLongBSH[bar] < LongBarHighLimit); bLongCNH = (nLongCNH[bar] < LongNearLimit); bLongPrevCNH = (nLongCNH[bar-1] < LongNearLimit); bLongCNL = (nLongCNL[bar] < LongNearLimit); bLongPrevCNL = (nLongCNL[bar-1] < LongNearLimit); bShortWideRange = (nShortTR[bar] > nShortATR[bar]) || (nShortTR[bar-1] > nShortATR[bar-1]); bShortMomUp = (nShortMom[bar] > ShortMomLimit); bShortMomDown = (nShortMom[bar] < -ShortMomLimit); bShortBarSame = (nShortBSS[bar] < ShortBarSizeLimit) && (nShortBSH[bar] < ShortBarHighLimit); bShortCNH = (nShortCNH[bar] < ShortNearLimit); bShortPrevCNH = (nShortCNH[bar-1] < ShortNearLimit); bShortCNL = (nShortCNL[bar] < ShortNearLimit); bShortPrevCNL = (nShortCNL[bar-1] < ShortNearLimit); #endregion //-------------------------------------------------------------------------------- #region generate signals // сброс значений сигналов bBuy = false; bSell = false; bShort = false; bCover = false; LongStopPrice = 0; LongTargetPrice = 0; ShortStopPrice = 0; ShortTargetPrice = 0; // установка сигналов по условиям if (bLongWideRange && bLongBarSame && bLongPrevCNL && bLongCNH && bLongMomDown) bBuy = true; if (bLongWideRange && bShortBarSame && bShortPrevCNH && bShortCNL && bShortMomUp) bShort = true; // для длинных позиций LongPos = source.Positions.GetLastActiveForSignal("LN"); if (LongPos != null) { LongStopPrice = LongPos.EntryPrice - LongStopKoef; LongTargetPrice = LongPos.EntryPrice + LongTargetKoef; } // для коротких позиций ShortPos = source.Positions.GetLastActiveForSignal("SN"); if (ShortPos != null) { ShortStopPrice = ShortPos.EntryPrice + ShortStopKoef; ShortTargetPrice = ShortPos.EntryPrice - ShortTargetKoef; } #endregion //================================================================================ #region execute signals //-------------------------------------------------------------------------------- // выполнение сигналов для длинной позиции LongPos = source.Positions.GetLastActiveForSignal("LN"); if (LongPos == null) { // Если нет активной длинной позиции if (bBuy) { // Если есть сигнал Buy, // выдаем ордер на открыте новой длинной позиции. source.Positions.BuyAtMarket(bar+1, 1, "LN"); } } else { // Если есть активная длинная позиция LongPos.CloseAtStop(bar+1, LongStopPrice, "LX"); if (LongPos.IsActive) { LongPos.CloseAtProfit(bar+1, LongTargetPrice, "LX"); } } //-------------------------------------------------------------------------------- // выполнение сигналов для короткой позиции ShortPos = source.Positions.GetLastActiveForSignal("SN"); if (ShortPos == null) { // Если нет активной короткой позиции if (bShort) { // Если есть сигнал Short // выдаем ордер на открыте новой короткой позиции. source.Positions.SellAtMarket(bar+1, 1, "SN"); } } else { // Если есть активная короткая позиция, ShortPos.CloseAtStop(bar+1, ShortStopPrice, "SX"); if (ShortPos.IsActive) { ShortPos.CloseAtProfit(bar+1, ShortTargetPrice, "SX"); } } #endregion } #endregion //================================================================================ #region прорисовка графиков // Берем основную панель (Pane) IPane mainPane = ctx.First; // Создаем дополнительную панель для функций CLoseNearHigh и CLoseNearLow. IPane CNPane = ctx.CreatePane("CloseNear", 10, false, false); // Отрисовка графика CloseNearHigh CNPane.AddList(string.Format("CloseNearHigh"), nLongCNH, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); // Отрисовка графика CloseNearLow CNPane.AddList(string.Format("CloseNearLow"), nLongCNL, ListStyles.LINE, 0xf05050, LineStyles.SOLID, PaneSides.RIGHT); // Создаем дополнительную панель для функций BarsSameSize и BarsSameHigh. IPane BarsPane = ctx.CreatePane("BarsSame", 10, false, false); // Отрисовка графика BarsSameSize BarsPane.AddList(string.Format("SameSize"), nLongBSS, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); // Отрисовка графика BarsSameHigh BarsPane.AddList(string.Format("SameHigh"), nLongBSH, ListStyles.LINE, 0xf05050, LineStyles.SOLID, PaneSides.RIGHT); // Создаем дополнительную панель для TrueRange и ATR IPane ATRPane = ctx.CreatePane("ATR", 10, false, false); // Отрисовка графика TrueRange ATRPane.AddList(string.Format("TrueRange"), nLongTR, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); // Отрисовка графика ATR ATRPane.AddList(string.Format("AverageTrueRange"), nLongATR, ListStyles.LINE, 0x000070, LineStyles.SOLID, PaneSides.RIGHT); // Создаем дополнительную панель для Momentum IPane MomPane = ctx.CreatePane("Momentum", 10, false, false); // Отрисовка графика Momentum MomPane.AddList(string.Format("Momentum"), nLongMom, ListStyles.LINE, 0x007070, LineStyles.SOLID, PaneSides.RIGHT); #endregion //-------------------------------------------------------------------------------- } } }