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");
// mtrader6.com/docs/Terminal/mScript/JavaScript/v1/mScript/setProperty
//Добавим в диалоговое окно иницализации индикатора запросы о предпочтениях пользователя https://mtrader6.com/docs/Terminal/mScript/JavaScript/v1/mScript/addInput
this.addInput("PeriodsATR", InputType.int, 18); // Период индикатора ATR (Average true Range,
// mtrader6.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 = { // создаём необходимые для работы буферы
// mtrader6.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) // установим номер бара (отсчитанный от начала данных), с которого начинается рисование данной линии индикатора // mtrader6.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 для всех баров и дождаться заполнения соответствующих массивов
// mtrader6.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; // прервать исполнение функции, вернуться к ожиданию нового тика
}
// запросить (с соответствующими параметрами: символ, таймфрейм, период скользящей, смещение, тип скользящей, вид применяемой цены // mtrader6.com/ru/docs/Terminal/mScript/JavaScript/v1/AppliedPrice, тип цены)
// массив значений скользящей средней
// mtrader6.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
// mtrader6.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
} // конец кода индикатора