/// <summary> /// Calculate ATRM indicator for bars list /// </summary> public static IList <double> CalcATRM(IContext context, IReadOnlyList <IDataBar> bars, int period, Interval roundInterval, bool positive) { var count = bars.Count; var atrs = context.GetArray <double>(count) ?? new double[count]; if (count == 0) { return(atrs); } double high = 0, low = 0; double kr = 0, no = 0; var date = roundInterval.AlignDate(bars[0].Date); for (var i = 0; i < period; i++) { atrs[i] = 0; } double prevATR = 0; var first = true; for (var i = period; i < count; i++) { prevATR = Series.AverageTrueRange(bars, i, period, prevATR); var kirPer = prevATR; prevATR = kirPer; if (DoubleUtil.IsZero(kirPer)) { kirPer = 1e-10; } var date2 = roundInterval.AlignDate(bars[i].Date); var cur = bars[i].Close; if (first || date < date2) { first = false; date = date2; high = low = cur; kr = no = 0; } if (cur > high + kirPer) { var kk = Math.Floor((cur - (high + kirPer)) / kirPer) + 1; high = cur; low = cur - kirPer; kr = kr + kk; no = 0; } if (cur < low - kirPer) { var kn = Math.Floor((low - kirPer - cur) / kirPer) + 1; low = cur; high = cur + kirPer; no = no + kn; kr = 0; } var lowValue = -no; var highValue = kr; var value = highValue + lowValue; if (positive && value < 0) { value = 0; } if (!positive && value > 0) { value = 0; } atrs[i] = value; } return(atrs); }