/*================================================================================ * Стратегия: Графический метод Ренко * Платформа: TSLab версия 1.1.7.0 * Дата создания: 03.06.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.Renko { //================================================================================ public class Renko : IExternalScript { // используем переменные-флаги для сигналов public bool bBuy; // флаг сигнала открытия длинной позиции public bool bSell; public bool bShort; public bool bCover; public IPosition LongPos, ShortPos; //================================================================================ // Параметры оптимизации public OptimProperty Param_Period = new OptimProperty(10, 2, 20, 2); public OptimProperty Param_Koef = new OptimProperty(10, 2, 20, 2); //================================================================================ public virtual void Execute(IContext ctx, ISecurity source) { int StartBar = 1; #region Variables int ATR_period; // период расчета ATR double vATR; // значение ATR для текущего бара double CurATR; // текущее примененное значение ATR double kATR; // коэффициент для расчета CurATR int Dir; // направление последовательности Ренко (+1 вверх, -1 вниз) int PrevDir; // предыдущее направление последовательности double HighRange; // значение верхней границы для текущего бара double LowRange; // значение нижней границы для текущего бара double TrueRange; // значение "истинного диапазона" // независимых данных нет - кэширование не применяется // серия значений верхней границы IList nHighRange = new List(source.Bars.Count); // серия значений нижней границы IList nLowRange = new List(source.Bars.Count); #endregion //-------------------------------------------------------------------------------- #region Init vars Dir = 0; #endregion //-------------------------------------------------------------------------------- // Obtain parameters ATR_period = Param_Period; kATR = Param_Koef * 1.0 / 10; #region значения для первой свечи TrueRange = source.HighPrices[StartBar] - source.LowPrices[StartBar]; vATR = TrueRange; CurATR = vATR * kATR; HighRange = source.HighPrices[StartBar]; LowRange = source.LowPrices[StartBar]; #endregion //================================================================================ #region основной цикл - проход по барам int barsCount = source.Bars.Count; for (int bar = 0; bar < barsCount-1; bar++) { //-------------------------------------------------------------------------------- #region calculate values TrueRange = source.HighPrices[bar] - source.LowPrices[bar]; if (bar > StartBar) { if (source.LowPrices[bar] > source.ClosePrices[bar-1]) TrueRange = TrueRange + (source.LowPrices[bar] - source.ClosePrices[bar-1]); if (source.HighPrices[bar] < source.ClosePrices[bar-1]) TrueRange = TrueRange + (source.ClosePrices[bar-1] - source.HighPrices[bar]); } vATR = vATR + (TrueRange - vATR) / ATR_period; int CDir = 0; if ((source.ClosePrices[bar] - HighRange) > CurATR) { HighRange = HighRange + Math.Floor((source.ClosePrices[bar] - HighRange) / CurATR) * CurATR; CurATR = vATR * kATR; LowRange = HighRange - CurATR; CDir = 1; } if ((LowRange - source.ClosePrices[bar]) > CurATR) { LowRange = LowRange - Math.Floor((LowRange - source.ClosePrices[bar]) / CurATR) * CurATR; CurATR = vATR * kATR; HighRange = LowRange + CurATR; CDir = -1; } PrevDir = Dir; int NewDir = Dir; if ((Dir > -1) && (CDir < 0)) NewDir = -1; if ((Dir < 1) && (CDir > 0)) NewDir = 1; Dir = NewDir; #endregion //-------------------------------------------------------------------------------- #region data series nHighRange.Add(HighRange); nLowRange.Add(LowRange); #endregion //-------------------------------------------------------------------------------- #region generate signals // сброс значений сигналов bBuy = false; bSell = false; bShort = false; bCover = false; // установка сигналов по условиям if (Dir > 0 && PrevDir <= 0) { bBuy = true; bCover = true; } if (Dir < 0 && PrevDir >= 0) { bShort = true; 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; // Отрисовка верхней и нижней границы условных прямоугольников mainPane.AddList("HighRange", nHighRange, ListStyles.LINE, 0x0000a0, LineStyles.DOT, PaneSides.RIGHT); mainPane.AddList("LowRange", nLowRange, ListStyles.LINE, 0xa00000, LineStyles.DOT, PaneSides.RIGHT); #endregion //-------------------------------------------------------------------------------- } } }