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] = "";
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] = "";
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")
{
maxArray[i] = "max";
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; }
}
}