Добрый день, уважаемые разработчики.
Нашел признак некорректного расчета программой FT индикаторов в режиме ручного тестирования. Вот информация. Просьба исправить ошибку, поскольку оплаченную версию не могу использовать по назначению. Благодарю.
Вот картинка и код. На ней изображен один и тот же индикатор.
Причем:
1. Нижняя "версия" была нанесена перед прогоном цен в режиме "ручного тестирования", а затем режим ручного теста был запущен буквально на несколько свечей. Обратите внимание, что на ней есть места, где индикатор на соседних моментах времени имеет одинаковые значения +1,+1 или -1,-1.
2. Верхняя "версия" нанесена в режиме "пауза" до прогона графика. Аналогичная варианту 2 картинка будет, если построить индикатор в режиме редактирования, это тоже "статичный" режим.
Видно, что нижний индикатор показал не то, что верхний. И ошибка именно в нижнем, который "прогонялся" в режиме тестирования, потому что этот индикатор по своей формуле никогда не может иметь одинаковое значение на соседних свечках. Ошибка появляется на новых свечках, появившихся динамическим путем.
Сразу скажу, что у меня установлена единственная версия этого индикатора. Вариант, что я рисую разные, один из которых ошибочный, - невозможен.
Кроме того, сделав для вас эту первую картинку, я затем снова для эксперимента запустил правильный и неправильный вариант в режиме "ручного тестирования" - и теперь уже оба стали давать неверные значения. То есть режим ручного тестирования не позволяет индикатору рассчитываться верно по неизвестным мне причинам.
Когда я прогнал две уже построенные "версии" несколько свечек, а затем нанес в режиме паузы третий раз этот индикатор, история повторилась: "новая, статичная" версия показывает верно, а теперь уже две более ранних, подвергнутых прогону в режиме ручного теста, - ошибочные. А когда запустил все версии вместе в режиме ручного тестирования - снова все стали на новых свечках давать ошибки.
Уменьшение скорости движения цены вправо проблемы не искореняет. Я думал, что программе не хватает времени для расчета, уменьшал частоту появления новых свечей, но кажется, что дело совсем не в этом. Да и даже если в этом, то это неправильно, потому что фактически не позволяет использовать программу по назначению - в режиме тестирования.
Пока все.
Разный расчет индикатора в статичном режиме и в режиме теста
-
- Сообщения: 41
- Зарегистрирован: Чт окт 14, 2010 8:25 am
Разный расчет индикатора в статичном режиме и в режиме теста
- Вложения
-
- forextester error.jpg
- (48.79 КБ) 3177 скачиваний
-
- forextester error 2.jpg
- (52.56 КБ) 3177 скачиваний
-
- Raz_3.rar
- (2.03 МБ) 795 скачиваний
-
- Сообщения: 329
- Зарегистрирован: Сб июл 11, 2009 3:59 pm
Здравствуйте, Алексей,
Скорее всего ошибка в самом индикаторе.
Если бы в программе были такие ошибки, то наши стандартные индикаторы тоже отрисовывались бы по-разному в разных режимах, а этого не наблюдается.
Пожалуйста обратитесь к разработчику индикатора чтобы он исправил ошибку. Также пришлите нам код индикатора, может быть мы сможем найти в нём ошибку.
Скорее всего ошибка в самом индикаторе.
Если бы в программе были такие ошибки, то наши стандартные индикаторы тоже отрисовывались бы по-разному в разных режимах, а этого не наблюдается.
Пожалуйста обратитесь к разработчику индикатора чтобы он исправил ошибку. Также пришлите нам код индикатора, может быть мы сможем найти в нём ошибку.
-
- Сообщения: 41
- Зарегистрирован: Чт окт 14, 2010 8:25 am
Спасибо. Может быть, и я тоже думал об этом. Но странно, почему он в статичном варианте рисуется абсолютно корректно, а в динамике - нет. Язык-то один и тот же должен быть и история слева не изменилась с приходом бара в динамике.
Разработчик, точнее, "программист" - это я. Автор - Сафин В.И., система "Деньги в конвертах", 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.
Разработчик, точнее, "программист" - это я. Автор - Сафин В.И., система "Деньги в конвертах", 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
Основная ошибка при разработке таких индикаторов в том, что в статическом режиме индикатор рассчитывается 1 раз на каждый бар, а в динамическом он пересчитывается с каждым новым тиком (которых в одном баре много). Поэтому, если есть какие-то внутренние счетчики которые увеличиваются с каждым пересчетом индикатора, то и будет наблюдаться описанная ситуация.
Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
Asta la vista
Mike
Mike
-
- Сообщения: 36
- Зарегистрирован: Ср мар 18, 2009 9:03 am
-
- Сообщения: 41
- Зарегистрирован: Чт окт 14, 2010 8:25 am
Да, согласен: в динамическом варианте внутри бара есть тики. Но не понял пока идеи.. Последний тик очередной свечи точно отражает цену закрытия этой свечи. Поэтому, и конечный вид индикатора по логике должен точно соответствовать цене закрытия. Почему же расхождение есть?Terranin писал(а):Основная ошибка при разработке таких индикаторов в том, что в статическом режиме индикатор рассчитывается 1 раз на каждый бар, а в динамическом он пересчитывается с каждым новым тиком (которых в одном баре много). Поэтому, если есть какие-то внутренние счетчики которые увеличиваются с каждым пересчетом индикатора, то и будет наблюдаться описанная ситуация.
Может быть, Вы имеете ввиду, что каждый новый тик программой воспринимается как новая свеча и несколько внутренних тиков перед последним - как несколько предшествующих свечек?
А мой код чем-то отрицает это свойство индексации?Terranin писал(а):Также в статическом режиме 0й бар встречается только 1 раз. В динамическом - нулевым баром становится каждый новый бар последовательно.
Как сделано у меня:
- Бар появился - значит, номер правого бара = index = 0,
- Индикатор пересчитали по всем index и при index=0 - по всем i.
Таким образом, при появлении нового бара справа произведен перерасчет всего индикатора, и он должен иметь вид статичного.
Не могли бы Вы пояснить чуть более подробно, в чем цель проверки? Не понимаю, наверное, в силу плохого знания языка дэльфи, зачем это делать.Sharx писал(а):Рекомендую проверять время текущего бара с уже расщитанным баром в индекаторе перед новым расчетом индекатора
Спасибо.
- Terranin
- Site Admin
- Сообщения: 846
- Зарегистрирован: Вс июл 23, 2006 12:01 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
Mike
-
- Сообщения: 36
- Зарегистрирован: Ср мар 18, 2009 9:03 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;