Разный расчет индикатора в статичном режиме и в режиме теста

Сообщайте о возможных ошибках в программе.
Ответить
Сообщение
Автор
Alexey
Сообщения: 41
Зарегистрирован: Чт окт 14, 2010 8:25 am

Разный расчет индикатора в статичном режиме и в режиме теста

#1 Сообщение Alexey » Ср янв 05, 2011 4:40 pm

Добрый день, уважаемые разработчики.

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


Вот картинка и код. На ней изображен один и тот же индикатор.

Причем:

1. Нижняя "версия" была нанесена перед прогоном цен в режиме "ручного тестирования", а затем режим ручного теста был запущен буквально на несколько свечей. Обратите внимание, что на ней есть места, где индикатор на соседних моментах времени имеет одинаковые значения +1,+1 или -1,-1.

2. Верхняя "версия" нанесена в режиме "пауза" до прогона графика. Аналогичная варианту 2 картинка будет, если построить индикатор в режиме редактирования, это тоже "статичный" режим.

Видно, что нижний индикатор показал не то, что верхний. И ошибка именно в нижнем, который "прогонялся" в режиме тестирования, потому что этот индикатор по своей формуле никогда не может иметь одинаковое значение на соседних свечках. Ошибка появляется на новых свечках, появившихся динамическим путем.

Сразу скажу, что у меня установлена единственная версия этого индикатора. Вариант, что я рисую разные, один из которых ошибочный, - невозможен.

Кроме того, сделав для вас эту первую картинку, я затем снова для эксперимента запустил правильный и неправильный вариант в режиме "ручного тестирования" - и теперь уже оба стали давать неверные значения. То есть режим ручного тестирования не позволяет индикатору рассчитываться верно по неизвестным мне причинам.

Когда я прогнал две уже построенные "версии" несколько свечек, а затем нанес в режиме паузы третий раз этот индикатор, история повторилась: "новая, статичная" версия показывает верно, а теперь уже две более ранних, подвергнутых прогону в режиме ручного теста, - ошибочные. А когда запустил все версии вместе в режиме ручного тестирования - снова все стали на новых свечках давать ошибки.

Уменьшение скорости движения цены вправо проблемы не искореняет. Я думал, что программе не хватает времени для расчета, уменьшал частоту появления новых свечей, но кажется, что дело совсем не в этом. Да и даже если в этом, то это неправильно, потому что фактически не позволяет использовать программу по назначению - в режиме тестирования.

Пока все.
Вложения
forextester error.jpg
(48.79 КБ) 3177 скачиваний
forextester error 2.jpg
(52.56 КБ) 3177 скачиваний
Raz_3.rar
(2.03 МБ) 652 скачивания

FT Support
Сообщения: 329
Зарегистрирован: Сб июл 11, 2009 3:59 pm

#2 Сообщение FT Support » Чт янв 06, 2011 12:07 pm

Здравствуйте, Алексей,

Скорее всего ошибка в самом индикаторе.

Если бы в программе были такие ошибки, то наши стандартные индикаторы тоже отрисовывались бы по-разному в разных режимах, а этого не наблюдается.

Пожалуйста обратитесь к разработчику индикатора чтобы он исправил ошибку. Также пришлите нам код индикатора, может быть мы сможем найти в нём ошибку.

Alexey
Сообщения: 41
Зарегистрирован: Чт окт 14, 2010 8:25 am

#3 Сообщение Alexey » Ср янв 12, 2011 2:16 pm

Спасибо. Может быть, и я тоже думал об этом. Но странно, почему он в статичном варианте рисуется абсолютно корректно, а в динамике - нет. Язык-то один и тот же должен быть и история слева не изменилась с приходом бара в динамике.

Разработчик, точнее, "программист" - это я. Автор - Сафин В.И., система "Деньги в конвертах", ForexClub, всем советую послушать умного человека.

Вот такой код:


// ----------------------------------------
// Raz 3 indicator
// ----------------------------------------
//
library Raz_3;

uses
SysUtils, Classes, Graphics, Interfaces, Windows, IndicatorInterfaceUnit,
TechnicalFunctions in 'TechnicalFunctions.pas';

var
// External variables
FastMAPeriod: integer;
SlowMAPeriod: integer;
MAtype: integer;
ApplyToPrice: integer;

// Buffers
FastMA, SlowMA, Z, Raz, Raz_2, Raz_3: TIndexBuffer;


//---------------------------------------------------------------------------
// Initialize indicator
//---------------------------------------------------------------------------
procedure Init; stdcall;
begin
// define properties
IndicatorShortName('Raz_3');
SetOutputWindow(ow_SeparateWindow);
AddLevel(0, psDot, 1, clYellow); //GridColor

// register options
AddSeparator('Common');

RegOption('Fast MA period', ot_Integer, FastMAPeriod);
SetOptionRange('Fast MA period', 1, MaxInt);
FastMAPeriod := 1;

RegOption('Slow MA period', ot_Integer, SlowMAPeriod);
SetOptionRange('Slow MA period', 1, MaxInt);
SlowMAPeriod := 60;

RegMATypeOption(MAtype);
MAtype := 1;

RegApplyToPriceOption(ApplyToPrice);
ApplyToPrice := 0;

// create buffers
FastMA := CreateIndexBuffer;
SlowMA := CreateIndexBuffer;
Z := CreateIndexBuffer;
Raz := CreateIndexBuffer;
Raz_2 := CreateIndexBuffer;
Raz_3 := CreateIndexBuffer;

IndicatorBuffers(1);
// SetIndexBuffer(0, Raz);
// SetIndexBuffer(0, Raz_2);
SetIndexBuffer(0, Raz_3);
SetIndexStyle(0, ds_Histogram, psSolid, 1, clRed);
SetIndexLabel(0, 'Raz_3');

end;

//---------------------------------------------------------------------------
// Deinitialize indicator
//---------------------------------------------------------------------------
procedure Done; stdcall;
begin

end;

//---------------------------------------------------------------------------
// Calculate requested bar
//---------------------------------------------------------------------------
procedure Calculate(index: integer); stdcall;
var i: integer;

begin
if index + SlowMAPeriod >= Bars then exit;
FastMA[index] := GetMA(index, 0, FastMAPeriod, TMAType(MAtype), TPriceType(ApplyToPrice),
FastMA[index + 1]);
SlowMA[index] := GetMA(index, 0, SlowMAPeriod, TMAType(MAtype), TPriceType(ApplyToPrice),
SlowMA[index + 1]);
Z[index] := (FastMA[index] - SlowMA[index])/FastMA[index]*100;
Raz[index] := (Z[index]+Z[index + 1])/2;

if index = 0 then
begin
for i:= Raz.count downto 0 do
begin
Raz_2 := 0;
if Raz > Raz[i + 1] then Raz_2 := 1;
if Raz < Raz[i + 1] then Raz_2 := -1;
if (Raz_2 = 1) and (Raz_2[i + 1] = -1) then Raz_3 := 1;
if (Raz_2 = -1) and (Raz_2[i + 1] = 1) then Raz_3 := -1;
end;
end;

end;

exports

Init, Done, Calculate;

end.

Аватара пользователя
Terranin
Site Admin
Сообщения: 846
Зарегистрирован: Вс июл 23, 2006 12:01 pm

#4 Сообщение Terranin » Ср янв 12, 2011 6:19 pm

Основная ошибка при разработке таких индикаторов в том, что в статическом режиме индикатор рассчитывается 1 раз на каждый бар, а в динамическом он пересчитывается с каждым новым тиком (которых в одном баре много). Поэтому, если есть какие-то внутренние счетчики которые увеличиваются с каждым пересчетом индикатора, то и будет наблюдаться описанная ситуация.

Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
Asta la vista
Mike

Sharx
Сообщения: 36
Зарегистрирован: Ср мар 18, 2009 9:03 am

#5 Сообщение Sharx » Пт янв 14, 2011 8:53 am

Рекоммендую проверять время текущего бара с уже расщитанным баром в индекаторе перед новым расчетом индекатора

Alexey
Сообщения: 41
Зарегистрирован: Чт окт 14, 2010 8:25 am

#6 Сообщение Alexey » Пт янв 14, 2011 3:45 pm

Terranin писал(а):Основная ошибка при разработке таких индикаторов в том, что в статическом режиме индикатор рассчитывается 1 раз на каждый бар, а в динамическом он пересчитывается с каждым новым тиком (которых в одном баре много). Поэтому, если есть какие-то внутренние счетчики которые увеличиваются с каждым пересчетом индикатора, то и будет наблюдаться описанная ситуация.
Да, согласен: в динамическом варианте внутри бара есть тики. Но не понял пока идеи.. Последний тик очередной свечи точно отражает цену закрытия этой свечи. Поэтому, и конечный вид индикатора по логике должен точно соответствовать цене закрытия. Почему же расхождение есть?

Может быть, Вы имеете ввиду, что каждый новый тик программой воспринимается как новая свеча и несколько внутренних тиков перед последним - как несколько предшествующих свечек?
Terranin писал(а):Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
А мой код чем-то отрицает это свойство индексации?

Как сделано у меня:
- Бар появился - значит, номер правого бара = index = 0,
- Индикатор пересчитали по всем index и при index=0 - по всем i.

Таким образом, при появлении нового бара справа произведен перерасчет всего индикатора, и он должен иметь вид статичного.
Sharx писал(а):Рекомендую проверять время текущего бара с уже расщитанным баром в индекаторе перед новым расчетом индекатора
Не могли бы Вы пояснить чуть более подробно, в чем цель проверки? Не понимаю, наверное, в силу плохого знания языка дэльфи, зачем это делать.


Спасибо.

Аватара пользователя
Terranin
Site Admin
Сообщения: 846
Зарегистрирован: Вс июл 23, 2006 12:01 pm

#7 Сообщение Terranin » Пт янв 14, 2011 4:10 pm

Alexey писал(а):
Terranin писал(а):Основная ошибка при разработке таких индикаторов в том, что в статическом режиме индикатор рассчитывается 1 раз на каждый бар, а в динамическом он пересчитывается с каждым новым тиком (которых в одном баре много). Поэтому, если есть какие-то внутренние счетчики которые увеличиваются с каждым пересчетом индикатора, то и будет наблюдаться описанная ситуация.
Да, согласен: в динамическом варианте внутри бара есть тики. Но не понял пока идеи.. Последний тик очередной свечи точно отражает цену закрытия этой свечи. Поэтому, и конечный вид индикатора по логике должен точно соответствовать цене закрытия. Почему же расхождение есть?

Может быть, Вы имеете ввиду, что каждый новый тик программой воспринимается как новая свеча и несколько внутренних тиков перед последним - как несколько предшествующих свечек?
Terranin писал(а):Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
А мой код чем-то отрицает это свойство индексации?

Как сделано у меня:
- Бар появился - значит, номер правого бара = index = 0,
- Индикатор пересчитали по всем index и при index=0 - по всем i.

Таким образом, при появлении нового бара справа произведен перерасчет всего индикатора, и он должен иметь вид статичного.
Sharx писал(а):Рекомендую проверять время текущего бара с уже расщитанным баром в индекаторе перед новым расчетом индекатора
Не могли бы Вы пояснить чуть более подробно, в чем цель проверки? Не понимаю, наверное, в силу плохого знания языка дэльфи, зачем это делать.


Спасибо.
Я просто перечислил основные ошибки которые делают программисты. Глядя на конкретно Ваш индикатор я затрудняюсь даже сказать в чем проблема. Единственное что я вижу это в цикле не совсем верно указано вместо:

for i:= Raz.count downto 0 do

Надо использовать

for i:=Bars - 2 downto 0 do

потому что максимальный индекс Bars - 1 и используется index + 1

а также надо установить первый элемент, например Raz[Bars - 1] := 0; Raz_2[Bars - 1] := 0; до начала рассчета
Asta la vista
Mike

Sharx
Сообщения: 36
Зарегистрирован: Ср мар 18, 2009 9:03 am

#8 Сообщение Sharx » Пн янв 17, 2011 7:16 am

Sharx писал(а):Рекомендую проверять время текущего бара с уже расщитанным баром в индекаторе перед новым расчетом индекатора
Не могли бы Вы пояснить чуть более подробно, в чем цель проверки? Не понимаю, наверное, в силу плохого знания языка дэльфи, зачем это делать.


Спасибо.[/quote]

Это делается для того чтобы, в расчет индикатора не брался один итотже бар с разными значениями. Насколько я понял от Поддержки программы: тики, которые поступают со смещением Shift=0 не дают все цены 0-го бара на первом тике расчета, поnому надо отсчитывать каждый 4-й если котировки генерировались по методу OHCL, в этом случае лучше смотреть на один бар назад, т.е. Shift=1. А для того чтобы те же тики не расчитавались как 4 разных бара в индекаторе использойте стек магазинного типа. Я использую такую проверку в GetSingleTick() для смещения больше 0.

if not( (StekTime[0] = iTime(Symbol, TimeFrame, Shift)) or (StekTime[1]= iTime(Symbol, TimeFrame, Shift)) ) then
begin
StekTime[1] := StekTime[0];
StekTime[0] = iTime(Symbol, TimeFrame, Shift);
//Здесь Расчет индикатора ...
end;

Ответить