using System; using System.Collections.Generic; using System.ComponentModel; using GanovCubes; using TSLab.Script.Handlers; using static GanovCubes.FileLogger; namespace CubesLib { /// /// Тип сравнения показателей /// public enum RaiseFall { Растет, Падает, НеМеняется }; /// /// Делегат для сравнения двух чисел типа Double /// /// Число №1 /// Число №2 /// Результат сравнения public delegate bool CompareMethod(double val1, double val2); #region CubeDescription [Obsolete] [HandlerCategory("Ganov Cubes. Indicators")] [HandlerName("FallRaiseSomeBars", Language = "ru-ru")] [Description("Кубик выдает сигнал в случае если показатель растет/падает/равен эн-ное кол-во баров подряд. Обычно для выявления роста падения необходимо применять" + " формулу с указанием, что показатель на текущем баре больше покателя на предыдущем баре, показатель на предыдущем баре больше показетеля два бара назад" + " и так далее. Такие формулы усложняют скрипт и его восприятие, поэтому удобнее воспользоваться текущим кубиком. Кубик на вход может принимать как серию значений" + " так и рассчитываемые на каждом баре данные. На выходе кубик выдает булево")] [InputsCount(1)] [Input(0, TemplateTypes.DOUBLE, Name = "Значение")] [OutputsCount(1)] [OutputType(TemplateTypes.BOOL)] #endregion public class FallRaiseSomeBars : IValuesHandlerWithNumber, IStreamHandler, IDoubleInput0, IBooleanReturns, IContextUses { #region Fields private double[] _barsValues; private bool[] _boolValues; private CompareMethod _compare; #endregion #region Properties public IContext Context { get; set; } /// /// Баров для анализа /// [HandlerParameter(true, "1", NotOptimized = false, Name = "Баров для анализа", IsVisibleInBlock = false)] [Description("Данная настройка определяет количество баров от текущего назад, за которое будет анализироваться рост или падение (не включая текущий бар)" + " показателя. В случае если указано отрицательное или нелевое значение, то будет использовано значение по умолчанию \"один\", то есть будет показан" + " рост только с прошлого бара. В случае если указанное кол-во баров для анализа больше текущего кол-ва баров, то до момента достижения указанного " + " бара кубик будет выдавать \"false\". Например, если указано 5 баров, то первое значение появится только по закрытию пятого бара, то этого момента" + " кубик будет выдавать \"false\"")] public int BarsToAnalize { get; set; } /// /// Тип сравнения /// [HandlerParameter(true, "Растет", NotOptimized = true, Name = "Тип сравнения", IsVisibleInBlock = false)] [Description("Данная настройка задает тип справнения показателей: Растет, Падает, НеМеняется")] public RaiseFall СompareType { get; set; } #endregion public bool Execute(double value, int bar) { if (bar == 0) { if (BarsToAnalize <= 0) BarsToAnalize = 1; _barsValues = Context.GetArray(Context.BarsCount); _compare = СompareType switch { RaiseFall.Растет => CondRaise, RaiseFall.Падает => CondFall, _ => CondEquil }; } var retValue = false; _barsValues[bar] = value; if (bar >= BarsToAnalize) { for (int i = 0; i < BarsToAnalize; i++) { var barNum = i + (bar - BarsToAnalize); if (_compare(_barsValues[barNum], _barsValues[barNum + 1])) retValue = true; else { retValue = false; break; } } } return retValue; } public IList Execute(IList values) { _boolValues = Context.GetArray(Context.BarsCount); if (_boolValues.Length == values.Count) for (int i = 0; i < values.Count; i++) _boolValues[i] = Execute(values[i], i); return _boolValues; } /// /// Метод сравниваниет два входящих числа типа Double /// /// Число №1 /// Число №2 /// Первое больше второго - True, наоборот - False bool CondRaise(double val1, double val2) => val1 < val2; /// /// Метод сравниваниет два входящих числа типа Double /// /// Число №1 /// Число №2 /// Первое меньше второго - True, наоборот - False bool CondFall(double val1, double val2) => val1 > val2; /// /// Метод сравниваниет два входящих числа типа Double /// /// Число №1 /// Число №2 /// Первое равно второму - True, наоборот - False bool CondEquil(double val1, double val2) => val1.CompareDouble(val2); } }