Forex / Форекс Инвестиции, доверительное управление, интернет трейдинг – NEUIMEX ::Обучение MQL : MQL Support
NEUIMEX TEAM
   
FOREX FUTURES CFD's АНАЛИТИКА

EN | DE
Компания
Главная страница
О компании
Международные офисы
Клиентам
Открыть счёт
Демо счёт
Конкурс Трейдеров
Пополнить счёт
Отзыв средств
купить путевку здесь
Платформы
NEXTT Trading Terminal
NEXTT Signal Base
NEXTT PDA Terminal
Как связаться
Обратная связь
Швейцария >>
Германия >>
Россия >>

MQL II Support
Советиники Форма Заказа

Содержание | назад | далее   
 

Написание пользовательских индикаторов и функций в торговой системе Neurex Direct также имеет ряд особенностей.

  • Параметры, которые принимают для расчета пользовательские индикаторы и функции должны быть описаны в секции Inputs и должны иметь числовой тип.
    Inputs: nPeriod(13),nDeviation(0.1),nAccountedBars(300);

  • Параметры передаются в функцию расчета пользовательского индикатора в том порядке, в котором они описаны. Например, вызов пользовательского индикатора с перечисленными выше параметрами будет выглядеть следующим образом:
    iCustom( "SomeIndicator", 13, 0.1, 300, MODE_FIRST, 0 );

  • Строго говоря, параметры можно не передавать в функцию. Если у функции нет секции Inputs, то параметры передавать бесполезно. Или можно воспользоваться начальными значениями, используемыми при описании параметров. Например, вызов того же пользовательского индикатора без параметров будет выглядеть следующим образом:
    iCustom( "SomeIndicator", MODE_FIRST, 0 );
    Это означает, что будут использованы, те значения, которые хранятся в переменных, описанных в секции Inputs, то есть 13, 0.1 и 300.

  • В чём заключаются основные отличия между функцией расчета пользовательского индикатора и простой пользовательской функции. Они определяются способами вызова. Функция пользовательского индикатора вызывается однократно при пересчёте всего массива ценовых данных. Простая же пользовательская функция вызывается в работе программы-эксперта, то есть с каждым тиком. У функции расчета пользовательского индикатора есть доступ к двум массивам, хранящим результаты расчета, при помощи функций SetIndexValue, SetIndexValue2, GetIndexValue, GetIndexValue2. А простая пользовательская функция имеет доступ к этим массивам при помощи функции iCustom. Функция расчета пользовательского индикатора не может вызывать торговые функции и функцию User Function. Пользовательская функция должна завершаться вызовом функции Return, для того чтобы передать рассчитанное значение вызывающей программе-эксперту.

  • Существует специальное значение индексного массива, которое означает отсутствие данных - 0. Если в каком-либо пользовательском индикаторе нулевое значение является значимым, то в этом случае необходимо использовать очень маленькое значение, например . Необходимо отметить, что при выводе значений пользовательских индикаторов во всплывающих подсказках используется точность 4 знака после десятичной точки. Индикатор, помещаемый на ценовой график не может иметь отрицательных данных, так как они все равно не могут быть отображены. Поэтому отрицательные значения индикатора, помещаемого на ценовой график, тоже воспринимаются в качестве специальных. (Особенности использования специальных значений пользовательских индикаторов, помещаемых на ценовой график, обсуждаются ниже.)

  • Значения переменных в функции расчета пользовательского индикатора, а также массивы данных с результатами расчета пользовательского индикатора инициализируются при первом запуске индикатора, а также при смене периода или инструмента на графике. То есть, между инициализациями все значения хранятся! При правильном и аккуратном программировании пользовательского индикатора можно предусмотреть возможность расчета только последних, еще не рассчитанных значений, массивов данных индикатора. Пример индикатора простой скользящей средней:
    /*[[
        Name := SimpleMA
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.neurex.ch/
        Separate Window := No
        First Color := Red
        First Draw Type := Line
        Use Second Data := No
    ]]*/
    Inputs : MAPeriod(13);
    Variables : shift(0), cnt(0), loopbegin(0), first(True), prevbars(0), sum(0);

    SetLoopCount(0);
    // initial checkings
    If MAPeriod < 1 Then Exit;
    // check for additional bars loading or total reloading
    If Bars < prevbars Or Bars-prevbars>1 Then first = True;
    prevbars = Bars;
    If first Then Begin
        // loopbegin prevent couning of counted bars exclude current
        loopbegin = Bars-MAPeriod-1;
        If loopbegin < 0 Then Exit; // not enough bars for counting
        first = False;
    End;

    // moving average
    loopbegin = loopbegin+1; // current bar is to be recounted too
    For shift = loopbegin Downto 0 Begin
        sum = 0;
        For cnt = 0 To MAPeriod-1 Begin
            sum = sum + Close[shift+cnt];
        End;
        SetIndexValue(shift,sum/MAPeriod);
        loopbegin = loopbegin-1; // prevent to previous bars recounting
    End;
    Некоторые пояснения к коду. В переменной first после инициализации хранится значение True. Как только индикатор запустится в первый раз, пройдёт проверка переменной first и будет установлено значение переменной loopbegin с таким расчетом, чтобы цикл запустился с начала данных. Во время цикла переменная loopbegin модифицируется и фактически содержит значение индекса последнего рассчитанного значения в индикаторном массиве. В случае ситуации "loop detected" индикаторный эксперт прервет свою работу. Но. Переменная first установлена в False, значит при следующем запуске переменная loopbegin уже не будет устанавливаться в начало индикаторного массива. То есть новый расчет продолжится с места остановки предыдущего расчета. В конце-концов все бары будут просчитаны. Но если нам нужно пересчитывать значение индикатора на текущем баре с приходом каждой новой котировки, то перед началом цикла мы модифицируем переменную loopbegin, увеличивая ее на 1, чтобы произошла как минимум 1 итерация цикла.
    Если произошла докачка исторических данных (Refresh Chart), либо была перезагрузка исторических данных (Erase and Refresh Chart), то условие сравнения текущего количества баров с предыдущим количеством позволит нам сделать пересчет индикатора на всех данных.

  • Функция пользовательского индикатора может быть вызвана не только из программы-эксперта, но и из окна Навигатора при выборе индикатора Custom Indicator. В связи с этим существуют некоторые особенности оформления такой программы. Приведем пример индикатора Envelopes:
    /*[[
        Name := Envelopes
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.metaquotes.net/
        Notes := Sample Custom Indicator program
        Separate Window := No
        First Color := Blue
        First Draw Type := Line
        Use Second Data := Yes
        Second Color := Red
        Second Draw Type := Line
    ]]*/
    Inputs : nPeriod(13),nDeviation(0.1),nAccountedBars(300);
    Vars : CurrentBar(0),shift(0),i(0),sum(0),UpperBand(0),LowerBand(0),BeginBar(0);
    Vars : prevBars(0);

    If prevBars = Bars Then Exit;
    prevBars = Bars;
    SetLoopCount(0);

    BeginBar = Bars - nAccountedBars;
    If BeginBar < 0 then BeginBar = 0;
    For CurrentBar = 0 To BeginBar-1 Begin
        shift = Bars-1-CurrentBar;
        SetIndexValue(shift, 0);
        SetIndexValue2(shift, 0);
    End;

    For CurrentBar = BeginBar To Bars-1 Begin
        shift = Bars - 1 - CurrentBar;
        If CurrentBar < nPeriod-1 Then Begin;
            SetIndexValue(shift, 0);
            SetIndexValue2(shift, 0);
            Continue;
        End;

        sum = 0;
        For i=0 To nPeriod-1 Begin
            sum = sum + Close[shift+i];
        End;
        sum = sum / nPeriod;
        UpperBand = sum * (1 + nDeviation/100);
        LowerBand = sum * (1 - nDeviation/100);
        SetIndexValue(shift, UpperBand);
        SetIndexValue2(shift, LowerBand);
    End;

    Как видно, мастер экспертов создает описание пользовательского индикатора, отличное от описания программы-эксперта.
    Separate Window := No - означает, что график индикатора будет нарисован в том же окне, что и график цен. Если же значения, рассчитанные пользовательским индикатором сильно отличаются от текущих цен, то график индикатора нужно выводить в отдельном окне.
    Draw Type := Line - означает, что график индикатора будет построен в виде линии. Возможно также построение гистограммы (Histogram) или вывод отдельного символа (Symbol; в этом случае символ задается в виде числа, которое определяет положение символа в таблице Wingdings. Например, First Symbol := 217).
    Use Second Data := Yes - означает, что результатом расчета индикатора будут 2 графика, а не один (другой пример: гистограмма MACD и сигнальная линия). First Color, First Draw Type и First Symbol относятся к первому графику индикатора, Second Color, Second Draw Type и Second Symbol - ко второму.
    Если индикатор выводится в отдельном окне и заранее известны предельные значения минимума и(или) максимума, то для убыстрения вывода на экран, а в некоторых случаях и для более красивого вывода (особенно это касается гистограмм) эти предельные значения можно задать. Мастер экспертов оформит это, например, следующим образом:
    Minimum Chart Limits := -1.000000
    Maximum Chart Limits := 1.000000
    Все перечисленные параметры, приготовленные мастером экспертов помогают быстро настроить Custom Indicator.

    Custom Indicator


  • Как уже было сказано выше, график пользовательского эксперта можно выводить в виде гистограммы. Есть особенность вывода гистограммы в окно графика цен. В процессе вывода гистограммы участвуют оба массива данных Custom индикатора. Линия рисуется на графике от первого значения до второго соответствующего значения. Если первое значение больше второго, то линия рисуется первым цветом. Иначе - вторым. Эту особенность можно применить при раскраске баров в разные цвета.
    /*[[
        Name := ColoredBars
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.metaquotes.net/
        Notes := Sample Custom Indicator program
        Separate Window := No
        First Color := Blue
        First Draw Type := Histogram
        Use Second Data := Yes
        Second Color := Pink
        Second Draw Type := Histogram
    ]]*/
    Variables : CurrentBar(0),shift(0),nBWMFI(0),prevBWMFI(0),value1(0),value2(0);

    SetLoopCount(0);
    For CurrentBar = 0 To Bars-1 Begin
        shift = Bars-1-CurrentBar;
        nBWMFI = (High[shift] - Low[shift]) / Volume[shift];
        If CurrentBar < 1 Then Begin
            SetIndexValue(shift, 0);
            SetIndexValue2(shift, 0);
            prevBWMFI = nBWMFI;
            Continue;
        End;

        value1 = 0;
        value2 = 0;
        If nBWMFI > prevBWMFI and Volume[shift] < Volume[shift+1] Then Begin
            value1 = High[shift];
            value2 = Low[shift];
        End;
        If nBWMFI < prevBWMFI and Volume[shift] > Volume[shift+1] Then Begin
            value1 = Low[shift];
            value2 = High[shift];
        End;
        SetIndexValue(shift, value1);
        SetIndexValue2(shift, value2);
        prevBWMFI = nBWMFI;
    End;

    Вышеприведенный пример иллюстрирует раскраску баров в стиле Билла Вильямса. При необходимости можно написать ещё одну программу пользовательского индикатора, чтобы раскрашивать бары в два других цвета в соответствии с другими условиями.

  • Выше было упомянуто об особенностях обработки специальных значений, меньших или равных 0, "линейных" пользовательских индикаторов, помещаемых на ценовой график. 0 означает отсутствие данных. Между точками, имеющими положительное значение, строится линия. Отрицательное значение означает окончание предыдущей линии. То есть линии могут прерываться. В качестве иллюстрации "отсутствия данных" ниже приводится пример индикатора ZigZag, который строит линии между локальными ценовыми экстремумами.
    /*[[
        Name := ZigZag
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.metaquotes.ru
        Separate Window := No
        First Color := Blue
        First Draw Type := Line
        Use Second Data := No
    ]]*/
    Inputs: depth(12),deviation(5),backstep(3);
    Variables : shift(0),lasthigh(-1),lastlow(-1),lasthighpos(0),lastlowpos(0);
    Variables : val(0),back(0),res(0);
    Variables : curlow(/spacer.gif),curhigh(/spacer.gif);

    SetLoopCount(0);
    lasthigh=-1;
    lastlow=-1;

    for shift = Bars-300 downto 0
    {
        //--- low
        val=Low[Lowest(MODE_LOW,shift+depth-1,depth)];
        if val==lastlow then val=0
        else
         {
            lastlow=val;
            if (Low[shift]-val)>(deviation*Point) then val=0
            else
             {
                for back=1 to backstep
                 {
                    res=GetIndexValue(shift+back);
                    if res!=0 and res>val then SetIndexValue(shift+back,0);
                 };
             };
         };
        SetIndexValue(shift,val);
        //--- high
        val=High[Highest(MODE_HIGH,shift+depth-1,depth)];
        if val==lasthigh then val=0
        else
         {
            lasthigh=val;
            if (val-High[shift])>(deviation*Point) then val=0
            else
             {
                for back=1 to backstep
                 {
                    res=GetIndexValue2(shift+back);
                    if res!=0 and res<val then SetIndexValue2(shift+back,0);
                 };
             };
         };
        SetIndexValue2(shift,val);
    };

    // final cutting
    lasthigh=-1; lasthighpos=-1;
    lastlow=-1; lastlowpos=-1;

    for shift = Bars-300 downto 0
    {
        curlow=GetIndexValue(/spacer.gif);
        curhigh=GetIndexValue2(shift);
        if curlow==0 & curhigh==0 then continue;
        //---
        if curhigh!=0 then
         {
            if lasthigh>0 then
             {
                if lasthigh<curhigh then SetIndexValue2(lasthighpos,0)
                else SetIndexValue2(shift,0);
             };
            //---
            if lasthigh<curhigh then
             {
                lasthigh=curhigh;
                lasthighpos=shift;
             };
            lastlow=-1;
         };
        if curlow!=0 then
         {
            if lastlow>0 then
             {
                if lastlow>curlow then SetIndexValue(/spacer.gif)
                else SetIndexValue(shift,0);
             };
            //---
            if curlow<lastlow | lastlow<0 then
             {
                lastlow=curlow;
                lastlowpos=shift;
             };
            lasthigh=-1;
         };
    };

    for shift = Bars-300 downto 0
    {
        res=GetIndexValue2(shift);
        if res!=0 then SetIndexValue(shift,res);
    };
    В итоге вышеприведенный индикатор заполняет экстремальными значениями первый массив данных индикатора. Значения между экстремумами - нулевые. Линии рисуются между экстремумами (то есть между положительными значениями).

  • В качестве иллюстрации вывода символов в определенные позиции графика цен приведем программу простейшего расчета фракталов Билла Вильямса:
    /*[[
        Name := Fractals
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.metaquotes.net/
        Notes := Sample Custom Indicator program
        Separate Window := No
        First Color := Blue
        First Draw Type := Symbol
        First Symbol := 217
        Use Second Data := Yes
        Second Color := Red
        Second Draw Type := Symbol
        Second Symbol := 218
    ]]*/
    Variable : value(0),CurrentBar(0), price(0);

    SetLoopCount(0);
    For CurrentBar = 0 To Bars-1 Begin
        If CurrentBar < 2 Or CurrentBar >= Bars-2 Then Begin
            SetIndexValue(CurrentBar, 0);
            SetIndexValue2(CurrentBar, 0);
            Continue;
        End;

        value = 0;
        price = High[CurrentBar];
        If price>High[CurrentBar+1] and price>High[CurrentBar+2] and price>High[CurrentBar-1] and price>High[CurrentBar-2] then
            value = price;
        SetIndexValue(CurrentBar, value);

        value = 0;
        price = Low[CurrentBar];
        If price<Low[CurrentBar+1] and price<Low[CurrentBar+2] and price<Low[CurrentBar-1] and price<Low[CurrentBar-2] then
            value = price;
        SetIndexValue2(CurrentBar, value);
    End;

  • Пример пользовательской функции. Перед использованием такой функции необходимо убедиться, что она успешно прошла трансляцию, и в каталоге экспертов присутствует соответствующий exp-файл.
    /*[[
        Name := UserFunc
        Author := Copyright © 2003-2004, Neurex Group
        Link := http://www.neurex.ch/
    ]]*/
    Input : parameter(0);

    print( "Input parameter is ", parameter );
    return( parameter );

    Пример вызова пользовательской функции:
    Variable: ReturnValue(0);

    ReturnValue = UserFunction( "UserFunc", Close );
    print( "Return value is ", ReturnValue );


  • Необходимо отметить, что излишнее количество пользовательских индикаторов, неправильно написанные пользовательские функции могут значительно замедлить работу клиентского терминала!



Содержание | назад | далее   
 














о компании | контакты © NEUIMEX TEAM ® Главная   о компании   Вверх
Forex / Форекс Инвестиции, доверительное управление, интернет трейдинг – NEUIMEX :: Articles catalogue

transmaster-omsk.ru v 4_2