• Тинькофф Банк-лучшие банковские продукты еще выгоднее
    Выбирайте продукт от банка Тинькофф
  • Уважаемые форумчане, друзья и посетители!
    Поступило предложение ( ссылка на обсуждение ) на сбор средств поддержания форума в рабочем состоянии с 1 июня ( оплата хостинга, бэкап ежедневный на другой хостинг и тд), отчетность будет предоставляться ежемесячно. Пока на ЮMoney ( яндекс деньги), доступно картой перевод, далее добавлю другие способы. Сумму перевода указывайте на ваш выбор исходя из своих возможностей.
    Форум продолжает свою работу благодаря Вашим пожертвованиям.

С чего начать ?

zencoder

New Member
NinjaTrader
Всем дорого времени суток. Совсем недавно я начал изучать Ninja и ее язык программирования. Имею достаточно большой опыт программирования на C# и MQL4 (metatrader). Попытался написать простейший индикатор (с учебной целью) который просто рисует разницу между ценой закрытия текущего и предыдущего баров. не получилось :((

В МТ было все просто:
объявили обычный массив - double buf[]
связали его с "линией графика" - SetIndexBuffer(0,buf)
заполнили элементы массива значениями - for(i=0;i<Bars;i++) buf=Close[i+1]-Close
и платформа сама нарисовала линию графика.

Я рассчитывал что НТ тоже сделано както похоже. Но у меня ничего не получилось. Как то по своему сделано все НТ, но как именно - нигде толком не описано.

Уважаемые знатоки программирования НТ, потратьте пожалуйста немного своего времени - напишите этот простейший учебный индикатор и объясните где и как доступится к ценовым данным и как их отобразить на графике своего индикатора. Или дайте ссылку где это описано для начинающих (кроме хелпа и сайта производителя пожалуйста - эти я и так знаю).
 
zencoder сказал(а):
Всем дорого времени суток. Совсем недавно я начал изучать Ninja и ее язык программирования. Имею достаточно большой опыт программирования на C# и MQL4 (metatrader). Попытался написать простейший индикатор (с учебной целью) который просто рисует разницу между ценой закрытия текущего и предыдущего баров. не получилось :((

В МТ было все просто:
объявили обычный массив - double buf[]
связали его с "линией графика" - SetIndexBuffer(0,buf)
заполнили элементы массива значениями - for(i=0;i<Bars;i++) buf=Close[i+1]-Close
и платформа сама нарисовала линию графика.

Я рассчитывал что НТ тоже сделано както похоже. Но у меня ничего не получилось. Как то по своему сделано все НТ, но как именно - нигде толком не описано.

Уважаемые знатоки программирования НТ, потратьте пожалуйста немного своего времени - напишите этот простейший учебный индикатор и объясните где и как доступится к ценовым данным и как их отобразить на графике своего индикатора. Или дайте ссылку где это описано для начинающих (кроме хелпа и сайта производителя пожалуйста - эти я и так знаю).


Добрый день, а не пытались Вы открыть и посмотреть сами индикаторы в НТ? Они все открываются без проблем...и их несметное множество. Как вариант...
 
Еще как пытался. Добросовестно пересмотрел ВСЕ индикаторы из НТ. Но они все написаны для случая когда график строится по массиву который заполняется "массовой операцией" что то вроде Value.Set(Close[0]). А мне нужно пройтись по каждому бару, обсчитать его индивидуально (с учетом значений на соседних барах) и присвоить каждой точке графика свое значение.
Есть конструкция Value.Set(BarAgo, Close[0]) но что я не пытался с ней сделать и так писал и этак.... никак на графике ничего не рисуется.

поэтому и попросил для примера/обучения такой работающий код с поэлементным присваиванием получением и присваиванием значений.
 
zencoder сказал(а):
Еще как пытался. Добросовестно пересмотрел ВСЕ индикаторы из НТ. Но они все написаны для случая когда график строится по массиву который заполняется "массовой операцией" что то вроде Value.Set(Close[0]). А мне нужно пройтись по каждому бару, обсчитать его индивидуально (с учетом значений на соседних барах) и присвоить каждой точке графика свое значение.
Есть конструкция Value.Set(BarAgo, Close[0]) но что я не пытался с ней сделать и так писал и этак.... никак на графике ничего не рисуется.

поэтому и попросил для примера/обучения такой работающий код с поэлементным присваиванием получением и присваиванием значений.
с чего бы это "массовой операцией"?
есть метод OnBarUpdate, который дергается либо по закрытию бара, либо по каждому тику (если не на истории и выставлено CalculateOnBarClose = false), и из него можно обновлять все значения индюка, существующие на данный момент, Value[0] - текущий бар, Value[1] - предидущий и т.п. (т.е. в будущее штатными средствами залезть не выйдет). При этом при открытии чарта ниндзя честным образом рисует первый бар, дергает OnBarUpdate и считает значение индюка для него, потом рисует второй бар, и т.д. до текущего момента, таким образом обсчитывая все бары по очереди... И в принципе ничего не мешает из OnBarUpdate смотреть всю историю вглубь и пересчитывать значение индюка так как хочется.

как пример - @SMA.cs, @EMA.cs, @ParabolicSAR.cs, @SUM.cs
а для разницы цены между последим и предпоследним баром в OnBarUpdate достаточно прописать Value[0] = Close[0]-Close[1];
ну или Value[0] = Close[1]-Close[0];
:)

зы да, совсем забыл - чтобы обращаться к истории, нужно чтоб она была - т.е. если на первом баре попытаться смотреть Close[10], вылетишь по эксепшну
т.е. полный код OnBarUpdate для графика разницы текущего и прошлого бара будет
Код:
protected override void OnBarUpdate()
{
if (CurrentBar>0)
 {
 //считаем значения индюка со второго бара серии
 Value[0] = Close[1] - Close[0];
 }
}
 

Вложения

  • Diff01.tar.gz
    2 КБ · Просмотры: 118
K0T сказал(а):
zencoder сказал(а):
Еще как пытался. Добросовестно пересмотрел ВСЕ индикаторы из НТ. Но они все написаны для случая когда график строится по массиву который заполняется "массовой операцией" что то вроде Value.Set(Close[0]). А мне нужно пройтись по каждому бару, обсчитать его индивидуально (с учетом значений на соседних барах) и присвоить каждой точке графика свое значение.
Есть конструкция Value.Set(BarAgo, Close[0]) но что я не пытался с ней сделать и так писал и этак.... никак на графике ничего не рисуется.

поэтому и попросил для примера/обучения такой работающий код с поэлементным присваиванием получением и присваиванием значений.
с чего бы это "массовой операцией"?
есть метод OnBarUpdate, который дергается либо по закрытию бара, либо по каждому тику (если не на истории и выставлено CalculateOnBarClose = false), и из него можно обновлять все значения индюка, существующие на данный момент, Value[0] - текущий бар, Value[1] - предидущий и т.п. (т.е. в будущее штатными средствами залезть не выйдет). При этом при открытии чарта ниндзя честным образом рисует первый бар, дергает OnBarUpdate и считает значение индюка для него, потом рисует второй бар, и т.д. до текущего момента, таким образом обсчитывая все бары по очереди... И в принципе ничего не мешает из OnBarUpdate смотреть всю историю вглубь и пересчитывать значение индюка так как хочется.

как пример - @SMA.cs, @EMA.cs, @ParabolicSAR.cs, @SUM.cs
а для разницы цены между последим и предпоследним баром в OnBarUpdate достаточно прописать Value[0] = Close[0]-Close[1];
ну или Value[0] = Close[1]-Close[0];
:)

зы да, совсем забыл - чтобы обращаться к истории, нужно чтоб она была - т.е. если на первом баре попытаться смотреть Close[10], вылетишь по эксепшну
т.е. полный код OnBarUpdate для графика разницы текущего и прошлого бара будет
Код:
protected override void OnBarUpdate()
{
if (CurrentBar>0)
 {
 //считаем значения индюка со второго бара серии
 Value[0] = Close[1] - Close[0];
 }
}

В очередной раз спасибо :-)
 
Спасибо! МТшная "идеология" попутала :(
Я думал что Close[0] это массив цен закрытия (всех баров) с индексом ноль, а Close[1] это как бы второй буфер содержащий копию опять таки массив всех цен закрытия.
Соотвественно я думал, что если я хотел нарисовать две линии то Value[0] - это массив всех значений первой линии, а вторая линия содержит свои данные в Value[1]. И чтобы получить предыдущий элемент первого графика мне надо написать Value[0][1].
Теперь все стало на свои места.

Получается что если на графике нажимаю кнопочку F5 или первый раз присоединяю индикатор, то он для всех имеющихся баров истории поочереди дергает событие OnBarUpdate? и Close[ Bars.Count-1 ] при переходе к следующему бару станет на место Bars.Count-2 а на его месте (Bars.Count-1) будет цена открытия только что появившегося бара?
 
zencoder сказал(а):
Спасибо! МТшная "идеология" попутала :(
Я думал что Close[0] это массив цен закрытия (всех баров) с индексом ноль, а Close[1] это как бы второй буфер содержащий копию опять таки массив всех цен закрытия.
Соотвественно если я хотел нарисовать две линии то Value[0] - это массив всех значений первой линии, а вторая линия содержит свои данные в Value[1]. И чтобы получить предыдущий элемент первого графика мне надо написать Value[0][1].
Теперь все стало на свои места.

Получается что если на графике нажимаю кнопочку F5 или первый раз присоединяю индикатор, то он для всех имеющихся баров истории поочереди дергает событие OnBarUpdate? и Close[ Bars.Count-1 ] при переходе к следующему бару станет на место Bars.Count-2 а на его месте (Bars.Count-1) будет цена открытия только что появившегося бара?
Почти так. Только нумерация серии идет от текущего момента назад в историю. В [0] всегда текущее значение (самый свежий по времени бар), и как только появляется новый бар, [0] становится [1], [1] - [2] и т.п. Соответственно Close[Bars.Count], он же, если я правильно помню, Close[CurrentBar]- это закрытие самого первого бара на чарте.
Да, а если нужно несколько датасерий, то первая серия это Values[0], вторая Values[1] и далее, а их элементы - Values[0][0] , Values[0][1]
 
Спасибо. все потихоньку становится на свои места.
Проясните пожалуйста еще одни вопрос.
В МТ есть такое понятие как скрипты - это своего рода однократно выполняющиеся эксперты. Я с их помощью делаю две вещи: собственно торгую (открываю/закрываю ордера) и управляю работой обычного эксперта (сброс скрипта устанавливает значение глобальной переменной которое я могу получить и обработать в непрерывно работающем эксперте, например, изментиь параметры настройки, ММ, тот же размер торгуемого лота).

Можно ли в нинзе реализовать такое же?
Как можно в произвольное время, вручную, передать какойто "параметр" внутрь эксперта или индикатора? Как (кроме параметров эксперта) можно управлять его работой?
 
zencoder сказал(а):
Спасибо. все потихоньку становится на свои места.
Проясните пожалуйста еще одни вопрос.
В МТ есть такое понятие как скрипты - это своего рода однократно выполняющиеся эксперты. Я с их помощью делаю две вещи: собственно торгую (открываю/закрываю ордера) и управляю работой обычного эксперта (сброс скрипта устанавливает значение глобальной переменной которое я могу получить и обработать в непрерывно работающем эксперте, например, изментиь параметры настройки, ММ, тот же размер торгуемого лота).

Можно ли в нинзе реализовать такое же?
Как можно в произвольное время, вручную, передать какойто "параметр" внутрь эксперта или индикатора? Как (кроме параметров эксперта) можно управлять его работой?
подергать один индюк из другого в пределах одного чарта возможно, но не тривиально.
для NT6.5 вот например так:
Код:
for (int di=0;di<ChartControl.Indicators.Length;di++){
   if (ChartControl.Indicators[di].Name=="SMA"){
    smaIndNum=di;
    Print("SMA indicator found, name="+ChartControl.Indicators[di].Name+",number="+di);
   }
}

ChartControl.Indicators[smaIndNum].ПодергатьКакойНибудьМетод();
так же можно подергать индюки в пределах одной стратегии, а вот чтобы достучаться из одного чарта в другой наверное нужно лезть в дебри C#, пайпы и т.п ...
 
K0T сказал(а):
В [0] всегда текущее значение (самый свежий по времени бар), и как только появляется новый бар, [0] становится [1], [1] - [2] и т.п.

а в хелпе написано вот такое
CurrentBar
A number representing the current bar in a Bars object that the OnBarUpdate() method in an indicator or strategy is currently processing. For example, if a chart has 100 bars of data, the very first bar of the chart (left most bar) will be number 0 (zero) and each subsequent bar from left to right is incremented by 1.

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

Еще если можно еще пару слов: можно писать коды индикаторов и экспертов не во встроенном редакторе а в MS VS 2010 C# Express? Ну хотябы сначала сгенерить пустышку-заготовку индикатора мастером нинзи, но потом работать с ней уже в VS2010? Если да - то как их "состыковать"?
 
zencoder сказал(а):
аха. вот теперь понятен смысл бывшей ранее загадки: зачем проверять CurrentBar на равенство нулю.

Еще если можно еще пару слов: можно писать коды индикаторов и экспертов не во встроенном редакторе а в MS VS 2010 C# Express? Ну хотябы сначала сгенерить пустышку-заготовку индикатора мастером нинзи, но потом работать с ней уже в VS2010? Если да - то как их "состыковать"?
смысл встроенного редактора в том, что он по ф5 индюк компилит, и результат вставляет в dll существующих индюков, ну и по ниндзевским методам предоставляет хелп. как это из другой проги сделать - хз, а редактировать - это в чем угодно, хоть в VS, хоть в фаре :) исходники живут в <мои документы>\NinjaTrader [6.5|7]\bin\Custom\Indicator
 
чтобы индюк или стратегия могла подергать информацию из индюка или стратегии в соседнем чарте, есть путь через запись в файл: в скрипте в соседнем окне должна быть конструкция записи в файл типа:
в
#region Variables
// Wizard generated variables
private string pathEntrySignals = @"C:\_(файл формата блокнот )______
а в
protected override void OnBarUpdate()
{
StreamWriter SW = new StreamWriter(pathEntrySignals,false);
string rrec="";
и например
if (UP) rrec = "1"; if (DN) rrec = "2"; if (!UP && !DN) rrec = "0";
SW.WriteLine(rrec); SW.Close();

Результатом будет 1 или 2 или 0 в блокноте (старые данные заменяются новыми)

а вот дальше ------ вопрос, кто знает - как считать содержимое блокнота стратегией?
или есть путь попроще?
 
как поймать момент смены бара? или момент первого тика нового бара...
чтобы в стратегии написать что-то вроде
if (first tick) n = n+1; // n - количество баров с момента запуска стратегии
if (n>m) //(сделать что-то); // когда накопится m баров с момента запуска, сделать что-то
 
если мне нужно поработать на информации 2009 года. она загружена в датасерию. построен минутный график. как соответствуют бары графика данным таймсерии? почему в начале графика CurrentBar равен нулю и номера баров полученные через Bars.GetBar(time) возрастаю слева направо? получается что это не номера баров в таймсерии а просто номера баров на графике? а нахрен они вообще нужны? почему на 12-м баре я уже получаю ошибку out of range? хотя баров загружена огромная куча.
 
Vitar007 сказал(а):
как поймать момент смены бара? или момент первого тика нового бара...
чтобы в стратегии написать что-то вроде
if (first tick) n = n+1; // n - количество баров с момента запуска стратегии
if (n>m) //(сделать что-то); // когда накопится m баров с момента запуска, сделать что-то

Код:
			if (FirstTickOfBar)
    		{
				Print("Первый тик бара " + Bars.TickCount.ToString());
		}
 
K0T сказал(а):
Еще если можно еще пару слов: можно писать коды индикаторов и экспертов не во встроенном редакторе а в MS VS 2010 C# Express? Ну хотябы сначала сгенерить пустышку-заготовку индикатора мастером нинзи, но потом работать с ней уже в VS2010? Если да - то как их "состыковать"?
Здравствуйте, присоединяюсь к теме. Озадачен проблемой дружбы внешней программы (торговый робот) и NT. Если есть у кого-нибудь примеры простенькие, которые подключают внешнюю программу, написанную на C# к NT, поделитесь пожалуйста.

Нашел документацию, но без примеров сложно переварить информацию.
 
Назад
Верх Низ