Создание индикатора ATR Channel

export class Main extends Indicator {
 // создаём и экспортируем класс с именем Main - дочерний класс (наследующий свойства) предопределенного класса Indicator, который в свою очередь является дочерним для предопределенного класса mScript.
    
	// constructor создаёт и инициализирует объекты, необходимые для работы индикатора
    constructor() {
        // "В конструкторе ключевое слово super используется как функция, вызывающая родительский конструктор. Её необходимо вызвать до первого обращения к ключевому слову this в теле конструктора."
        super();
		
		// Данные индикатора отображаются в отдельном окне? нет, по умолчанию; здесь могла быть строка this.setProperty(Property.SeparateWindow, false);
		// здесь можно было задать отображаемое имя индикатора this.setProperty(Property.ShortName, "ATR_Channels"); или  this.setProperty(Property.ShortName, "Каналы ATR");
		// mtrader7.com/docs/Terminal/mScript/JavaScript/v1/mScript/setProperty

        //Добавим в диалоговое окно иницализации индикатора запросы о предпочтениях пользователя mtrader7.com/docs/Terminal/mScript/JavaScript/v1/mScript/addInput
		this.addInput("PeriodsATR", InputType.int, 18);                     // Период индикатора ATR (Average true Range, 

// mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/Indicators/ATR

this.addInput("MA_Periods", InputType.int, 49);                     // Период скользящей средней

        this.addInput("MA_type", InputType.int, Averaging.LinearWeighted);  // тип используемой скользящей средней 

//ширина каналов
		this.addInput("Mult_Factor1", InputType.float, 1.6);                // коэффициент умножения канала 1

        this.addInput("Mult_Factor2", InputType.float, 3.2);                // коэффициент умножения канала 2

        this.addInput("Mult_Factor3", InputType.float, 4.8);                // коэффициент умножения канала 3

        this.addInput("PriceType", InputType.PriceType, PriceType.Bid);     // тип используемой цены (PriceType) - Bid или Ask

this.buffers = { // создаём необходимые для работы буферы

// mtrader7.com/docs/Terminal/mScript/JavaScript/v1/mScript/addBuffer

// буфер линии скользящей средней 
            MA_Buffer0 : this.addBuffer(),     
            
			// буферы линий каналов 			
			Ch1up_Buffer1 : this.addBuffer(),  
            Ch1dn_Buffer2 : this.addBuffer(),
            Ch2up_Buffer3 : this.addBuffer(),
            Ch2dn_Buffer4 : this.addBuffer(),
            Ch3up_Buffer5 : this.addBuffer(),
            Ch3dn_Buffer6 : this.addBuffer(),
        };
    }  // конец метода constructor

    onInit() { // Процедура Инициализации индикатора, исполняется немедленно после загрузки клиентским терминалом	        		
        let {PeriodsATR, MA_Periods, Mult_Factor1, Mult_Factor2, Mult_Factor3} = this.getInputs(),  // получить заданные пользователем данные и занести их значения в соответствующие переменные,
																									// действительные только в пределах данного блока программы
            drawBegin = Math.max(PeriodsATR, MA_Periods); // вычислим номер бара, с которого начинается рисование линий индикатора: наибольшее значение из PeriodsATR, MA_Periods; 

// developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/max 

//инициализация буферов значений индикатора
this.buffers.MA_Buffer0
.setShape(Shape.Line) // задаём вид графика - линия
.setColor(Color.Green) // цвет линии по умолчанию; в диалоговом окне можно будет выбрать другой

.setDrawBegin(drawBegin) // установим номер бара (отсчитанный от начала данных), с которого начинается рисование данной линии индикатора // mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/Buffer/setDrawBegin
;

this.buffers.Ch1up_Buffer1
.setShape(Shape.Line)
.setColor(Color.DeepSkyBlue)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor1+")") // наименование пункта меню в окне диалога запуска индикатора - строка, составленная из значений по умолчанию переменных, заданных в constructor,
// обрамлённых соответствующим текстом
;

// аналогично - для остальных буферов
this.buffers.Ch1dn_Buffer2
.setShape(Shape.Line)
.setColor(Color.DeepSkyBlue)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor1+")")
;  // Настройки буферов 1-2 отвечают за две голубые паралельные линии индикатора

this.buffers.Ch2up_Buffer3
.setShape(Shape.Line)
.setColor(Color.Blue)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor2+")")
;

this.buffers.Ch2dn_Buffer4
.setShape(Shape.Line)
.setColor(Color.Blue)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor2+")")
; // Настройки буферов 3-4 отвечают за две синие паралельные линии индикатора

this.buffers.Ch3up_Buffer5
.setShape(Shape.Line)
.setColor(Color.Red)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor3+")")
;

this.buffers.Ch3dn_Buffer6
.setShape(Shape.Line)
.setColor(Color.Red)
.setDrawBegin(drawBegin)
.setLabel("ATRd("+PeriodsATR+", "+Mult_Factor3+")")
;// Настройки буферов 5-6 отвечают за две красные паралельные линии индикатора
} // конец функции onInit

async onUpdate() {  // onUpdate - стандартная функция, исполняемая каждый раз при поступлении нового тика по символу, для которого рассчитывается индикатор
        const {PeriodsATR, MA_Periods, MA_type, Mult_Factor1, Mult_Factor2, Mult_Factor3, PriceType} = this.getInputs(),  // получить заданные пользователем данные и занести их значения в соответствующие константы,
              {MA_Buffer0, Ch1up_Buffer1, Ch1dn_Buffer2, Ch2up_Buffer3, Ch2dn_Buffer4, Ch3up_Buffer5, Ch3dn_Buffer6} = this.buffers,   // получить накопленные данные буфера
            { // запросить из терминала данные High, Low, Close для всех баров и дождаться заполнения соответствующих массивов 
// mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/Bar/load
                High,
                Low,
                Close,
            } = await Bar.load([ // await - исполнение программы приостанавливается до получения всех данных
                Bar.Mode.High,
                Bar.Mode.Low,
                Bar.Mode.Close,
            ], PriceType),
            barSize = Close.length; // barSize = количеству элементов массива Close

	    /*
		Здесь можно было добавить "защиту от дурака": MA_type - тип скользящей средней - должен быть 0, 1, 2 или 3, 
		а пользователю позволено ввести любое другое значение, в том числе и отрицательное
		*/
			
	let maList, atrList, atr, ma; // let - объявление переменных, действительных только в пределах данного блока программы

        if (barSize <= Math.max(PeriodsATR, MA_Periods)) { // если количества баров не достаточно для расчетов
            return; // прервать исполнение функции, вернуться к ожиданию нового тика
        } 

        // запросить (с соответствующими параметрами: символ, таймфрейм, период скользящей, смещение, тип скользящей, вид применяемой цены // mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/AppliedPrice, тип цены) 

		// массив значений скользящей средней 
	// mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/Indicators/MA
		maList = await Indicators.MA(Current.Symbol, Current.TimeFrame, MA_Periods, 0, MA_type, AppliedPrice.Typical, PriceType); // дождаться всех данных		
		
		// запросить (с соответствующими параметрами: символ, таймфрейм, период ATR, тип цены) массив значений индикатора ATR 
// mtrader7.com/ru/docs/Terminal/mScript/JavaScript/v1/Indicators/ATR
        atrList = await Indicators.ATR(Current.Symbol, Current.TimeFrame, PeriodsATR, PriceType);  // дождаться всех данных	

        for (let i = 0; i < barSize; i++) { // цикл по i с шагом 1 от последнего (текущего, нулевого) бара к началу данных
            // занести во временные переменные данные массивов для данного бара
			atr = atrList[i];
            ma = maList[i];
			
            // установить соответствующие значения буферов = отрисовать отрезок линии от предыдущего бара к данному; значение буфера - координаты Y соответствующей линии индикатора
			MA_Buffer0.set(i, ma); //  скользящая средняя
			
			// каналы = значение скользящей средней +/- значение индикатора ATR, умноженное на соответствующий коэффициент
            Ch1up_Buffer1.set(i, (ma + atr * Mult_Factor1)); 
            Ch1dn_Buffer2.set(i, (ma - atr * Mult_Factor1));
            Ch2up_Buffer3.set(i, (ma + atr * Mult_Factor2));
            Ch2dn_Buffer4.set(i, (ma - atr * Mult_Factor2));
            Ch3up_Buffer5.set(i, (ma + atr * Mult_Factor3));
            Ch3dn_Buffer6.set(i, (ma - atr * Mult_Factor3));
        } // конец цикла
    } // конец функции onUpdate
} // конец кода индикатора