/*================================================================================ * Стратегия: KT trading system * Платформа: TSLab версия 1.1.8.0 * Дата создания: 16.09.2010 * Реализовано: Laber * модификация: Виктор Власенко (aka vito333) *================================================================================*/ using System; using System.Collections.Generic; using TSLab.Script; using TSLab.Script.Handlers; using TSLab.Script.Optimization; using TSLab.Script.Helpers; namespace TSLab.KT_trading { //================================================================================ public class KT_trading : IExternalScript { // используем переменные-флаги для сигналов public bool bBuy; // флаг сигнала открытия длинной позиции public bool bSell; // флаг сигнала закрытия длинной позиции public bool bShort; // флаг сигнала открытия короткой позиции public bool bCover; // флаг сигнала закрытия короткой позиции public IPosition LongPos, ShortPos; // функция вычисления StochK (последовательность значений) public IList GenStochK(ISecurity source, int Period) { var high = Series.Highest(source.HighPrices, Period); var low = Series.Lowest(source.LowPrices, Period); IList nValue = new List(source.Bars.Count); for (int i = 0; i < source.Bars.Count; i++) { var stochK = 100 * (source.ClosePrices[i] - low[i]) / (high[i] - low[i]); nValue.Add(stochK); } return nValue; } // функция вычисления (последовательность значений) public IList GenValue(ISecurity source, int Period) { double vValue = 0; // серия значений IList nValue = new List(source.Bars.Count); for (int bar = 0; bar < source.Bars.Count; bar++) { vValue = source.HighPrices[bar] - source.LowPrices[bar]; //-------------------------------------------------------------------------------- // добавление нового значения в последовательность nValue.Add(vValue); } return nValue; } //================================================================================ // Параметры оптимизации public OptimProperty optTradeSize = new OptimProperty(1, 1, 2, 1); // параметры для длинных позиций public OptimProperty optLongPeriod = new OptimProperty(30, 5, 50, 5); public OptimProperty optLongTrigger = new OptimProperty(5, 5, 20, 5); public OptimProperty optLongStart = new OptimProperty(5, 5, 20, 2); public OptimProperty optLongStep = new OptimProperty(6, 2, 10, 2); // параметры для коротких позиций public OptimProperty optShortPeriod = new OptimProperty(30, 5, 50, 5); public OptimProperty optShortTrigger = new OptimProperty(95, 80, 95, 5); // размер стопа public OptimProperty optStopSize = new OptimProperty(1000, 500, 1500, 25); public OptimProperty optLongTrailStopSize = new OptimProperty(1000, 500, 1500, 25); public OptimProperty optShortTrailStopSize = new OptimProperty(1000, 500, 1500, 25); //================================================================================ public virtual void Execute(IContext ctx, ISecurity source) { int StartBar = 0; #region Variables // для длинных позиций // период расчета bool bLT1, bLT2, bLT3, bLT4, bLT5; bool bST1, bST2, bST3, bST4, bST5; #endregion //-------------------------------------------------------------------------------- #region Obtain parameters int LongS1Period = optLongStart; int LongS2Period = LongS1Period + optLongStep; int LongS3Period = LongS2Period + optLongStep; int LongS4Period = LongS3Period + optLongStep; int LongS5Period = LongS4Period + optLongStep; StartBar = optLongPeriod; if (LongS5Period > StartBar) StartBar = LongS5Period; if (optShortPeriod > StartBar) StartBar = optShortPeriod; // Вычисляем верхнюю и нижнюю границы // Используем GetData для кеширования данных и ускорения оптимизации. // для коротких позиций // серия для простой скользящей средней SMA для открытия позиции IList nShortSMA = ctx.GetData("ShortSMA", new[] { optShortPeriod.ToString() }, delegate { return Series.SMA(source.ClosePrices, optShortPeriod); }); // для длинных позиций // серия для простой скользящей средней SMA для открытия позиции IList nLongSMA = ctx.GetData("LongSMA", new[] { optLongPeriod.ToString() }, delegate { return Series.SMA(source.ClosePrices, optLongPeriod); }); IList nLongS1 = ctx.GetData("LongStoch1", new[] { LongS1Period.ToString() }, delegate { return GenStochK(source, LongS1Period); }); IList nLongS2 = ctx.GetData("LongStoch2", new[] { LongS2Period.ToString() }, delegate { return GenStochK(source, LongS2Period); }); IList nLongS3 = ctx.GetData("LongStoch3", new[] { LongS3Period.ToString() }, delegate { return GenStochK(source, LongS3Period); }); IList nLongS4 = ctx.GetData("LongStoch4", new[] { LongS4Period.ToString() }, delegate { return GenStochK(source, LongS4Period); }); IList nLongS5 = ctx.GetData("LongStoch5", new[] { LongS5Period.ToString() }, delegate { return GenStochK(source, LongS5Period); }); #endregion //================================================================================ #region основной цикл - проход по барам int barsCount = source.Bars.Count; for (int bar = StartBar; bar < barsCount; bar++) { //-------------------------------------------------------------------------------- #region calculate values #endregion //-------------------------------------------------------------------------------- #region generate signals // сброс значений сигналов bBuy = false; bSell = false; bShort = false; bCover = false; // установка сигналов по условиям // для длинных позиций bLT1 = (nLongS1[bar] < optLongTrigger); bLT2 = (nLongS2[bar] < optLongTrigger); bLT3 = (nLongS3[bar] < optLongTrigger); bLT4 = (nLongS4[bar] < optLongTrigger); bLT5 = (nLongS5[bar] < optLongTrigger); if (bLT1 && bLT2 && bLT3 && bLT4 && bLT5) { bBuy = true; bCover = true; } LongPos = source.Positions.GetLastActiveForSignal("le"); if (LongPos != null) { // if ((bar - LongPos.EntryBarNum) > optLongPeriod) // bSell = true; } // установка сигналов по условиям // для коротких позиций bST1 = (nLongS1[bar] > optShortTrigger); bST2 = (nLongS2[bar] > optShortTrigger); bST3 = (nLongS3[bar] > optShortTrigger); bST4 = (nLongS4[bar] > optShortTrigger); bST5 = (nLongS5[bar] > optShortTrigger); if (bST1 && bST2 && bST3 && bST4 && bST5) { // bShort = true; // bSell = true; } ShortPos = source.Positions.GetLastActiveForSignal("se"); if (ShortPos != null) { // if ((bar - ShortPos.EntryBarNum) > optShortPeriod) // bCover = true; } #endregion #region execute signals -------------------------------------------------------------------- // выполнение сигналов для длинной позиции LongPos = source.Positions.GetLastActiveForSignal("le"); if (LongPos == null) { if (bBuy) { source.Positions.BuyAtMarket(bar + 1, optTradeSize, "le"); } } else { // Если есть активная длинная позиция if (bSell) { LongPos.CloseAtMarket(bar + 1, "lxm"); } else // переставляю стоп { if (bar == LongPos.EntryBarNum) // если смотрим бар входа { LongPos.CloseAtStop(bar + 1, (LongPos.EntryPrice - optStopSize), "lxe"); } else { //double highprice = source.Bars[bar].High; //for (int i = LongPos.EntryBarNum; i < bar; i++) //{ // if (source.Bars[i].High > highprice) // highprice = source.Bars[i].High; //} //LongPos.CloseAtStop(bar + 1, highprice - optLongTrailStopSize, "lxs"); double lowprice = LongPos.EntryPrice; for (int i = LongPos.EntryBarNum; i <= bar; i++) { if (source.Bars[i].Low > lowprice) lowprice = source.Bars[i].Low; } LongPos.CloseAtStop(bar + 1, lowprice - optLongTrailStopSize, "lxs"); } } } //-------------------------------------------------------------------------------- // выполнение сигналов для короткой позиции ShortPos = source.Positions.GetLastActiveForSignal("se"); if (ShortPos == null) { if (bShort) { source.Positions.SellAtMarket(bar + 1, optTradeSize, "se"); } } else { // Если есть активная короткая позиция, if (bCover) { // Если есть сигнал Cover // выдаем ордер на закрыте короткой позиции. ShortPos.CloseAtMarket(bar + 1, "sxm"); } else // переставляю стоп { if (bar == ShortPos.EntryBarNum) // если смотрим бар входа { ShortPos.CloseAtStop(bar + 1, (ShortPos.EntryPrice + optStopSize), "sxe"); } else { double lowprice = source.Bars[bar].Low; for (int i = ShortPos.EntryBarNum; i < bar; i++) { if (source.Bars[i].Low < lowprice) lowprice = source.Bars[i].Low; } ShortPos.CloseAtStop(bar + 1, lowprice + optShortTrailStopSize, "sxs"); } } } #endregion } #endregion //================================================================================ #region прорисовка графиков if (!ctx.IsOptimization) { // Берем основную панель (Pane) IPane mainPane = ctx.First; // для длинных позиций // Отрисовка скользящих средних mainPane.AddList("LongSMA", nLongSMA, ListStyles.LINE, 0x00a0a0, LineStyles.DOT, PaneSides.RIGHT); // для коротких позиций // Отрисовка скользящих средних mainPane.AddList("ShortSMA", nShortSMA, ListStyles.LINE, 0xa000a0, LineStyles.DOT, PaneSides.RIGHT); // Создаем дополнительную панель для индикатора. IPane LSPane = ctx.CreatePane("LongStochK", 10, false, false); // Отрисовка графика индикатора LSPane.AddList(string.Format("Stoch1"), nLongS1, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); LSPane.AddList(string.Format("Stoch2"), nLongS2, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); LSPane.AddList(string.Format("Stoch3"), nLongS3, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); LSPane.AddList(string.Format("Stoch4"), nLongS4, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); LSPane.AddList(string.Format("Stoch5"), nLongS5, ListStyles.LINE, 0x5050f0, LineStyles.SOLID, PaneSides.RIGHT); } #endregion //-------------------------------------------------------------------------------- } } }