using System.Collections.Generic; using TSLab.Script; using TSLab.Script.Handlers; using TSLab.DataSource; using TSLab.Script.Helpers; namespace test { public class ZigZag : IBar2DoubleHandler, IContextUses /// /// Индикатор ZigZag для TSLab /// /// /// { [HandlerParameter] public int Period { get; set; } public IList Execute(ISecurity source) { // Максимумы, минимумы, открытие, закрытие баров var highs = source.HighPrices; var lows = source.LowPrices; var opens = source.OpenPrices; var closes = source.ClosePrices; // Создаем возвращаемый массив в TSLab IList list = new List(highs.Count); // Создаем массивы для хранения Max и Min string[] maxArray = new string[closes.Count]; string[] minArray = new string[closes.Count]; // Устанавливаем первый бар для сравнения int NomerBar = 0; double High = highs[NomerBar]; double Low = lows[NomerBar]; // Основной цикл int i = 1; while (i <= (closes.Count - 1)) { bool VnutrBar = false; // Внутренний бар // Если бар внутренний if ((High >= highs[i]) && (Low <= lows[i])) { VnutrBar = true; // Запоминаем внутренний бар int NomerBarVn = i; double HighVn = highs[i]; double LowVn = lows[i]; // Ищем след. бар не внутри внутреннего if (i < (highs.Count - 1)) { int j = i + 1; while (j < (highs.Count - 1)) { // Если бар внутри внутреннего if ((HighVn >= highs[j]) && (LowVn <= lows[j])) j++; else break; } // Если бар внутри внутреннего и последний if ((HighVn >= highs[j]) && (LowVn <= lows[j]) && (j == (highs.Count - 1))) break; else i = j; // Если бар внешний if ((HighVn < highs[i]) && (LowVn > lows[i])) { // Если белый внешний бар if (opens[i] <= closes[i]) { // Если max меньше пред. max if ((highs[NomerBar] > highs[i]) && (maxArray[NomerBar] == "max")) { minArray[NomerBarVn] = "min"; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { // Если min меньше пред. min if ((lows[NomerBar] > lows[i]) && (minArray[NomerBar] == "min")) { minArray[NomerBar] = ""; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { maxArray[NomerBar] = ""; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } // Если черный внешний бар else { // Если min больше пред. min if ((lows[NomerBar] < lows[i]) && (minArray[NomerBar] == "min")) { maxArray[NomerBarVn] = "max"; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { // Если max больше пред. max if ((highs[NomerBar] < highs[i]) &&(maxArray[NomerBar] == "max")) { maxArray[NomerBar] = ""; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { minArray[NomerBar] = ""; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } } // Если обычный бар (не внутр. и не внеш.) else { // Если рост if (HighVn < highs[i]) { // Если до этого было падение if (minArray[NomerBar] == "min") { maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { // Если max больше предыдущего max if (highs[NomerBar] < highs[i]) { // Удаляем предыдущий max и ставим новый maxArray[NomerBar] = ""; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { minArray[NomerBarVn] = "min"; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } // Если падение else { // Если до этого был рост if (maxArray[NomerBar] == "max") { minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { // Если min меньше предыдущего min if (lows[NomerBar] > lows[i]) { // Удаляем предыдущий min и ставим новый minArray[NomerBar] = ""; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { maxArray[NomerBarVn] = "max"; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } } } } // Если бар не внутренний (основная обработка) if (!VnutrBar) { // Внешний бар if ((High < highs[i]) && (Low > lows[i])) { // Белый бар if (opens[i] <= closes[i]) { // Если был предыдущий min if (minArray[NomerBar] == "min") { minArray[NomerBar] = ""; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { maxArray[NomerBar] = ""; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } } // Черный бар else { // Если был предыдущий max if (maxArray[NomerBar] == "max") { maxArray[NomerBar] = ""; maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } else { minArray[NomerBar] = ""; minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } // Если обычный бар else { // Если рост if (High < highs[i]) { if (maxArray[i - 1] == "max") maxArray[i - 1] = ""; // Удаляем пред. max maxArray[i] = "max"; NomerBar = i; High = highs[i]; Low = lows[i]; } // Если падение else { if (minArray[i - 1] == "min") minArray[i - 1] = ""; // Удаляем пред. min minArray[i] = "min"; NomerBar = i; High = highs[i]; Low = lows[i]; } } } VnutrBar = false; i++; } // Заполняем возваращаемый массив ZigZag for (i = 0; i < closes.Count; i++) { if (maxArray[i] == "max") list.Add(highs[i]); else if (minArray[i] == "min") list.Add(lows[i]); else list.Add(0); } return list; } public IContext Context { get; set; } } }