• Demo счет NinjaTrader, регистрируется в брокерской компании NinjaTrader Brokerage . NinjaTrader™, LLC
    Ссылка на демо счет NinjaTrader
    Фид на соединении Continuum/CQG.
    Для справки: Continuum - это брэнд CQG, и ни чем они не отличаются друг от друга.
  • Сколько я реально плачу комиссии?
    Подробнее по ссылке

Программирование Value && Values ?

hoz

Member
NinjaTrader
#1
Читаю справку:
Код:
Value references the first DataSeries object Values[0] in the indicator. This is the primary indicator value.
Сказано, что Value ссылается на первый объект датасерии в индикаторе. Имеется ввиду, что Value всегда является первым элементом таймсерии, т.е .самым последним начиная с самого первого истории, верно? Если так, огда зачем в кавычках указывать номер бара в квадратных скобках?
А касательно Values написано:
Код:
Values is a collection holding DataSeries objects that hold the indicator's underlying calculated values.

DataSeries objects held by this collection are added by calling the Add() method.
Выходит, что это, грубо говоря, коллекция элементов датасерии показаний индикатора, так?
 
#2
Value - это датасерия, первый элемент коллекции датасерий Values, т.е. Value[0]. Обратите внимание, что подобная семантика широко используется в NinjaScript.

Текущий (последний по факту, первый по индексации) элемент датасерии, т.е. числовое значение - это Value[0] или Values[0][0]
 

hoz

Member
NinjaTrader
#3
Value - это датасерия, первый элемент коллекции датасерий Values, т.е. Value[0]. Обратите внимание, что подобная семантика широко используется в NinjaScript.
Вижу. Но логически использовать отдельную переменную для того, чтоб получить доступ к первому элементу датасерии по-моему это расточительно... Смысл?

Текущий (последний по факту, первый по индексации) элемент датасерии, т.е. числовое значение - это Value[0] или Values[0][0]
Так Value[0] или Values[0][0] это ж ни одно и тоже...
 
#4
Вижу. Но логически использовать отдельную переменную для того, чтоб получить доступ к первому элементу датасерии по-моему это расточительно... Смысл?
Смысл в том, чтобы не загружать синтаксис дополнительной индексацией, т.к. большинство пользователей работает с одной серией. А с т.зр. производительности принципиальной разницы нет.

Так Value[0] или Values[0][0] это ж ни одно и тоже...
И все-таки, это одно и то же значение. Добавьте Plot и, например, такой код и убедитесь сами:

Value.Set(CurrentBar / 3.0);
if (Values[0][0] != Value[0])
{
// не исполнится
 

hoz

Member
NinjaTrader
#5
А, в целом, Value это типа буфер что-ли? В мт4 я привык сам создавать буфера, и туда пихать расчёты индикатора, а значение его получать по вызову через ретурн. В нннзе пока что логику не совсем понимаю...
На данный момент смотрю индюк SMA:
Код:
protected override void OnBarUpdate()
        {
            if (CurrentBar == 0)
                Value.Set(Input[0]);
            else
            {
                double last = Value[1] * Math.Min(CurrentBar, Period);

                if (CurrentBar >= Period)
                    Value.Set((last + Input[0] - Input[Period]) / Math.Min(CurrentBar, Period));
                else
                    Value.Set((last + Input[0]) / (Math.Min(CurrentBar, Period) + 1));
            }
        }
Изначально в свойство Value, помещаем какое-то Input[0]. Я так понял, по ответам на оф. форуме нинзи, что через данный элемент датасерии передаётся некая датасерия. Типа как через параметр в функцию.. Тока тут через интерфейс. Я прав? На смысл в этом? Не проще ли сразу загнать для, например, цены закрытия... Close[0] ? Зачем этот Input[0] ?
Дальше ещё интереснее... Появился некий Value[1]. Что за он?
P.S. Хочу понять это строчки как базовые. Дальше всё въеду сам. Вот в этих моментах я как-то пригруз...
 
#6
Value - это серия, грубо говоря, массив с обратной индексацией, где каждый индекс - это бар. Это некие значения на барах.

Не проще ли сразу загнать для, например, цены закрытия... Close[0] ? Зачем этот Input[0] ?
Input[0] - это то, на чем ваш индикатор считается по умолчанию. Поьзователь может задавать свои серии (например посчитать SMA на High), а если вы жестко пропишете Close, то лишите его такой возможности. Input - это просто более общий подход.
 

hoz

Member
NinjaTrader
#7
Value - это серия, грубо говоря, массив с обратной индексацией, где каждый индекс - это бар. Это некие значения на барах.
Т.е. в Value хранится значение, рассчитываемое т.е. возвращаемое самим индикатором? На каждом баре своё есс-но. Так получается?
Но, опять же..
Код:
protected override void OnBarUpdate()
        {
            if (CurrentBar == 0)
                Value.Set(Input[0]);
            else
            {
                double last = Value[1] * Math.Min(CurrentBar, Period);

                if (CurrentBar >= Period)
                    Value.Set((last + Input[0] - Input[Period]) / Math.Min(CurrentBar, Period));
                else
                    Value.Set((last + Input[0]) / (Math.Min(CurrentBar, Period) + 1));
            }
        }
Тут сразу возникает какой-то головняк. Если расчёт на первом баре, то в первый элемент коллекции датасерии помещаем требуемую датасерию. А если нет... Расчитываем некое значение last. Что за оно, кстати?
При расчёте last используем Value[1]. Мы же его не расчитывали.. Откудого оно возьмётся тогда? Рассчитали только на первом баре.. А это уже на втором..
В МТ4 было иначе. Там задавался цикл от, например, нулевого бара и к последнему... и рассчитывался в диапазоне индюк. А тут я что-то не понимаю логику...
 
#8
Тут сразу возникает какой-то головняк. Если расчёт на первом баре, то в первый элемент коллекции датасерии помещаем требуемую датасерию.
В первый (и единственный пока) элемент датасерии (не коллекции датасерий, а одной датасерии) помещаем значение входной серии (обычно это Close, но может быть и другая - High, Low, Median, etc).

Далее идет оптимизированный расчет среднего. Это делается для того, чтобы избежать повторного вычисления "хвоста" выражаения (a + b + c + .....) / N, т.е. чтобы не было того самомого цикла.

Value[1] - это значение индикатора на предыдущем баре. Оно определено всегда, кроме частного случая CurrentBar == 0, который и обрабатывается отдельно.
 

hoz

Member
NinjaTrader
#9
В первый (и единственный пока) элемент датасерии (не коллекции датасерий, а одной датасерии) помещаем значение входной серии (обычно это Close, но может быть и другая - High, Low, Median, etc).
Это понятно и логично.

Далее идет оптимизированный расчет среднего. Это делается для того, чтобы избежать повторного вычисления "хвоста" выражаения (a + b + c + .....) / N, т.е. чтобы не было того самомого цикла.
Т.е.
Код:
double last = Value[1] * Math.Min(CurrentBar, Period);
это вычисление хвоста?
Странная логика... Умножаем значение из входной серии на количество баров либо периода. Но бары то не имеют одинаковое значение серии на всех заданных барах! Не логично же как-то.
А в данном коде:
Код:
if (CurrentBar >= Period)
                    Value.Set((last + Input[0] - Input[Period]) / Math.Min(CurrentBar, Period));
                else
                    Value.Set((last + Input[0]) / (Math.Min(CurrentBar, Period) + 1));
Значение вычисляется от нулевого бара и до .. крайнего или как-то иначе?
 
#10
Значения вычисляются последовательно на каждом новом баре. Если по коду сразу непонятно, то распишите результат функции ручкой на бумаге, для самого первого бара, для второго, и т.д. Потом сравните результат с прямым вычислением среднего (через цикл) - они совпадут. Выпишите код в алгебраической форме (как на уроках математики), это тоже поможет осмыслить формулу.