По просьбе одного из участников форума была реализована стратегия Супертренд (в том незамысловатом варианте, как можно было понять из скрипта на MQL). Суть ее проста как три копейки. Граница канала подтягивается за ценой (по аналлогии со скользящим стопом) на расстоянии, вычисляемом через ATR. При движении цены в обратную сторону граница остается на месте, и при ее пересечении происходит переворот позиции (типа Stop And Reverse).



Вот так эта система выглядит в коде:

Ссылка на файл: http://www.tslab.ru/ubb/ubbthreads.php?u...trend_script.cs

Code:
/*================================================================================
 * Стратегия: Supertrend
 * Платформа: TSLab версия 1.1.7.0
 * Дата создания: 02.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.Supertrend
{

	//================================================================================
	public class Supertrend : IExternalScript
	{
		// используем переменные-флаги для сигналов
		public bool bBuy; // флаг сигнала открытия длинной позиции
		public bool bSell;
		public bool bShort;
		public bool bCover;
		public IPosition LongPos, ShortPos;
		 
		//================================================================================
		// функция вычисления ATR (последовательность значений)
		// Period -  период скользящей средней для расчета ATR
		public IList<double> GenATR(ISecurity source, int Period)
		{
			double TrueRange; // значение "истинного диапазона"
			double vATR; // значение ATR для текущего бара

			// серия значений ATR
			IList<double> nATR = new List<double>(source.Bars.Count);

			TrueRange = source.HighPrices[0] - source.LowPrices[0];
			vATR = TrueRange;

			for (int bar = 0; bar < source.Bars.Count; bar++)
			{

				TrueRange = source.HighPrices[bar] - source.LowPrices[bar];
				if (bar > 0) 
				{
					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) / Period;
				//--------------------------------------------------------------------------------
				// добавление нового значения в последовательность
				nATR.Add(vATR);
			}
			return nATR;
		}
		
		//================================================================================
		// Параметры оптимизации
		public OptimProperty PeriodParam = new OptimProperty(20, 2, 20, 2);
		public OptimProperty MultiplierParam = new OptimProperty(9, 1, 10, 0.5);

		//================================================================================
		public virtual void Execute(IContext ctx, ISecurity source)
		{
			#region Variables
			int Period; // период расчета ATR
			double vATR; // значение ATR для текущего бара
			int Dir; // направление тренда (+1 вверх, -1 вниз)
			int PrevDir; // предыдущее направление тренда
			double Up; // значение верхней границы для текущего бара
			double Down; // значение нижней границы для текущего бара
			double Multiplier; // множитель
			
			double vTrend;
			double PrevUp, PrevDown;
			double Price; // цена закрытия текущего бара
			double AvgPrice; // средняя цена дл ятекущего бара
			
			// серия значений верхней границы
			IList<double> nHighRange = new List<double>(source.Bars.Count);
			// серия значений нижней границы
			IList<double> nLowRange = new List<double>(source.Bars.Count);
			// серия значений для фильтра тренда
			IList<double> nDir = new List<double>(source.Bars.Count);
			// серия значений индикатора тренда
			IList<double> nTrend = new List<double>(source.Bars.Count);
			#endregion
			//--------------------------------------------------------------------------------
			#region Init vars
			Dir = 0;
			Up = 0;
			Down = 0;
			 
			#endregion
			//--------------------------------------------------------------------------------
			#region Obtain parameters
			Period = PeriodParam;
			Multiplier = MultiplierParam;

			// серия значений ATR
			// кэширование с учетом параметра Period
			IList<double> nATR = ctx.GetData("ATR", new[] {Period.ToString()},
			delegate { return GenATR(source, Period); });

			#endregion
			//================================================================================
			#region основной цикл - проход по барам
			int barsCount = source.Bars.Count;
			vATR = source.ClosePrices[0];
			for (int bar = 0; bar < barsCount-1; bar++)
			{
				//--------------------------------------------------------------------------------
				#region calculate values
				Price = source.ClosePrices[bar];
				vATR = nATR[bar];
				vTrend = 0;

				PrevUp = Up;
				PrevDown = Down;
				PrevDir = Dir;

				AvgPrice = (source.HighPrices[bar] + source.LowPrices[bar]) / 2;
				Up = AvgPrice + Multiplier * vATR;
				Down = AvgPrice - Multiplier * vATR;
				
				if (Price > PrevUp) Dir = 1;
				if (Price < PrevDown) Dir = -1;
				
				if (Dir > 0 && Down < PrevDown) Down = PrevDown;
				if (Dir < 0 && Up > PrevUp) Up = PrevUp;

				if (Dir > 0 && PrevDir < 0) Down = AvgPrice - Multiplier * vATR;
				if (Dir < 0 && PrevDir > 0) Up = AvgPrice + Multiplier * vATR;
					
				if (Dir == 1) vTrend = Down;
				if (Dir == -1) vTrend = Up;
				

				#endregion
				//--------------------------------------------------------------------------------
				#region data series
				nHighRange.Add(Up);
				nLowRange.Add(Down);
				nATR.Add(vATR);
				nDir.Add(Dir);
				nTrend.Add(vTrend);
				
				#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);

			mainPane.AddList("Trend Indicator", nTrend, ListStyles.LINE, 0xa000a0, LineStyles.DOT, PaneSides.RIGHT);
			
			// Создаем дополнительную панель для ATR.
			IPane ATRPane = ctx.CreatePane("ATR", 10, false, false);

			// Отрисовка графика ATR
			ATRPane.AddList(string.Format("ATR"), nATR, ListStyles.LINE,
			0x5050a0, LineStyles.SOLID, PaneSides.RIGHT);
			
			// Создаем дополнительную панель для филтра тренда.
			IPane FilterPane = ctx.CreatePane("Filtr", 10, false, false);

			// Отрисовка графика фильтра тренда
			FilterPane.AddList(string.Format("TREND"), nDir, ListStyles.HISTOHRAM_FILL,
			0x00ff00, LineStyles.SOLID, PaneSides.RIGHT);

			#endregion
			//--------------------------------------------------------------------------------
		}
	}
}




На графике отображены границы ценовых каналов:





Результаты тестирования стратегии.


Кривая капитала:




Отчет с результатами тестирования:





В прикрепленных файлах можно найти всю необходимую информацию по этой стратегии.


Attachments
chart.png (6319 downloads)
Description: сриншот графика с границами ценовых каналов

equity.png (5870 downloads)
Description: скриншот кривой капитала (доходности стратегии)

report.png (5788 downloads)
Description: скриншот отчета по результатам тестирования

supertrend_scheme.xml (737 downloads)
Description: блок-схема в xml-формате

supertrend_script.cs (1506 downloads)
Description: скрипт на C#




Отредактировано Laber (Fri Jul 02 2010 05:45 PM)