Для начала скажу, что обнуления значений не происходит. Только перерасчёт. Почему же при перерасчёте получается другое значение?
Мы используем так называемый "экономный" метод расчёта скользящей средней. Приведу пример:
void sma() { double sum=0; int i,pos=Bars-ExtCountedBars-1; //---- initial accumulation if(pos<MA_Period) pos=MA_Period; for(i=1;i<MA_Period;i++,pos--) sum+=Close[pos]; //---- main calculation loop while(pos>=0) { sum+=Close[pos]; ExtMapBuffer[pos]=sum/MA_Period; sum-=Close[pos+MA_Period-1]; pos--; } //---- zero initial bars if(ExtCountedBars<1) for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0; }Сначала производится первоначальное накопление суммы, а потом только модификация - вычитание старого "левого" значения и прибавление очередного "правого" значения.
При экономном расчёте производится пересчёт только 2-х последних баров (высчитывается исходя из ExtCountedBars). При большом количестве итераций (я проводил тест на 15 тысячах барах) при первоначальном расчёте происходит накопление ошибки в 14-15 знаке после запятой. То есть, существует разница, которая зависит от того за сколько итераций мы подошли к нулевому бару, за 15 тысяч или за 2.
Спасибо, что подняли этот вопрос. Будем думать.
Вы подняли очень интересный вопрос.
Для начала скажу, что обнуления значений не происходит. Только перерасчёт. Почему же при перерасчёте получается другое значение?
Здесь, кстати, может быть зарыта и другая собака. Об этом в ветке 'Как замедлить работу советника в несколько раз?'.
_+_
/ @
Как зачем пересчитывать? Новое значение Close[0] меняет значение
индикатора на текущем баре. Поэтому текущий бар надо пересчитывать.
Вы спросите, а зачем пересчитывать 2 последних бара? Почитайте
замечание к функции IndicatorCounted.
Индикатор, вызываемый из эксперта и индикатор на графике - это
разные сущности. Один индикатор не имеет графического отображения
и выполняется в потоке эксперта. Другой индикатор рассчитывается
в интерфейсном потоке и отображается на графике и в окне данных.
И моменты пересчёта у этих индикаторов могут не совпадать. Индикатор
на графике пересчитывается всегда с приходом каждого нового
тика. "Экспертный" индикатор пересчитывается только тогда,
когда его вызвал эксперт. Даже если эксперт всегда вызывает
индикатор, то и тогда моменты расчёта двух индикаторов могут
не совпасть. Представьте, что какой-то тяжеловесный эксперт
работает долго и в процессе выполнения функции start придёт несколько
новых тиков. Индикатор на графике пересчитается, индикатор
в эксперте - нет.
Какие 5 значащих цифр? Выведите значения скользящего среднего
при помощи функции DoubleToStrMorePrecision и удивитесь результату. Индикаторные
массивы - это массивы вещественных чисел. И мы их в процессе
расчёта не нормализуем. Считаем как есть. Только вывод подсказок
(тултипы, окно данных) производится с определённой точностью,
как правило совпадающей с точностью инструмента, но бывают
и исключения.
Какие 5 значащих цифр? Выведите значения скользящего среднего
при помощи функции DoubleToStrMorePrecision и удивитесь результату. Индикаторные массивы - это массивы
вещественных чисел. И мы их в процессе расчёта не нормализуем.
Считаем как есть. Только вывод подсказок (тултипы, окно данных)
производится с определённой точностью, как правило совпадающей
с точностью инструмента, но бывают и исключения.
Я снес свое ложное утверждение за несколько секунд до Вашего ответа - mid-air collision. Мои извинения.
Как зачем пересчитывать? Новое значение Close[0] меняет значение
индикатора на текущем баре. Поэтому текущий бар надо пересчитывать.
Вы спросите, а зачем пересчитывать 2 последних бара? Почитайте
замечание к функции IndicatorCounted.
Вообще говоря, рассуждения по поводу последнего и предпоследнего тика в документации к IndicatorCounted достаточно умозрительны. Почему только предпоследний? MetaQuotes в описании кодов ошибок торговых операций предлагает использовать немалые таймауты для обработки определенных ситуаций. На форумах также обсуждалась проблема с подвисанием торговых функций в течение таймаута сервера (3 минуты?). Так что, предпоследний тик ничего гарантировать здесь не может. Честнее было бы использовать в потоке эксперта внутренний флажок в разделяемой памяти, вернее, счетчик, показывающий, сколько новых баров (или тиков) набежало с момента последнего вызова start().
Опять же, RefreshRates обещает, что все локальное окружение будет обновлено, включая таймсерии. Значит ли это, что и повторный вызов индикатора на первом баре может вернуть значение уже на следующем баре, если RefreshRates приведет к переходу на следующий бар? Документация этого, к сожалению, не специфицирует.
В любом случае, вся эта логика не имеет смысла в тестере, где новый тик никогда не появляется до завершения работы тик-хандлера. А значения индикатора на завершенных барах меняются.
Всё что Вы сказали, нам понятно. И мы будем думать, как ещё более экономно пересчитывать индикаторы, ничего не поломав при этом.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
выдает разные результаты в зависимости от того, вызывается индикатор в каждом тике или нет, то есть установлен или сброшен Kick:
2006.10.30 02:59:55 2005.10.26 19:20 test EURUSDm,M5: 0. 0000000000000000
2006.10.30 02:59:55 2005.10.26 19:15 test EURUSDm,M5: -0.0000000000510447
2006.10.30 02:59:55 test started for testing
2006.10.30 02:59:41 2005.10.26 19:25 test EURUSDm,M5: 0. 0000000000000000
2006.10.30 02:59:41 2005.10.26 19:20 test EURUSDm,M5: 0. 0000000000000000
2006.10.30 02:59:41 2005.10.26 19:15 test EURUSDm,M5: 0.0000000000510447
2006.10.30 02:59:41 test started for testing
Из-за этого глючит пользовательский индикатор, который сравнивает CCI с нулем.
Data Window показывает CCI(20) -0.0000 на баре 19:15.
Сборка 4.198.19.10.06