Это всё было довольно давно, а недавно я вспомнил про это и решил опять пустить изготовленный инструмент в дело.
Первая возникшая мысль была поискать в графике котировок периодичность. Может возникнуть вопрос зачем, ведь для поиска гармоник есть дискретное преобразование Фурье (ДПФ)? Но ДПФ даст только гармоники с периодом меньшим длины выборки. Мы же теперь можем попробовать примерить к графику цены гармоники с периодом большим длины выборки. Разумеется успешная примерка не будет "железным" доводом в пользу её реального существования, вопрос о степени доверия к конкретной аппроксимации нужно решать отдельно.
В прилагаемом индикаторе LSA_SinLRR.mq4 gрежде чем примерять гармонику вычитается линейный тренд. Рассчитывается он по старшему горизонту. Перебираются все возможные длины выборок в определённом диапазоне и выбирается та из них, для которой будет минимальна среднеквадратичная ошибка на out of Sample выборке (которая взята размером в 1/4 базовой выборки).
Период гармоники привязывается к длине выборки, посредством умножения её на заданный коэффициент. Если он будет равен, например, 2 - в выборке поместится полпериода гармоники, если же, например, 0.5 то два периода. Сама длина выборки определяется так же, как и для линейной регрессии, только перебор идёт внутри младшего горизонта.
Для сокращения объёма вычислений для каждого горизонта берётся свой шаг дискретизации.
Матрица векторов заполняется так
for(i = IntShift; i < Frame; i++) { pos = HShift+i*Step; VT[ind] = MathSin(AFreq*pos); ind ++; VT[ind] = MathCos(AFreq*pos); ind ++; VT[ind] = Resid[i]; ind ++; } // for(i = IntShift; i < Frame; i++)
Resid - это разница между ценой и старшим трендом.
Параметры индикатора:
extern double kPer = 4.0; // Коэффициент для определения периода
extern int LRRank = 1; // Номер старшего горизонта, больше 3-х не ставить
extern int FShift = 120; // Расстояние в барах, на которое производится экстраполяция в будущее
extern int HShift = 1; // Сдвиг текущего времени индикатора в прошлое в барах, бары правее него тоже будут проэктраполированы
extern double PointFactor = 0.1; // Масштабирование гистограммы ошибок аппроксимации, 0.1 подойдёт для минуток на пятизнаке
extern bool PriceClose = true; // Если false, то будет считаться по HL/2
Уф, как-то я устал писать :)
Кратко суть в следующем: Эта функция не претендует на оптимальность, она просто позволяет штамповать аппроксимации как блины и тут же пробовать, прямо со сковородки :) . Соответственно индикаторы именно так и слеплены, то есть ни на что не претендуют, в смысле стиля и эффективности.
Работает это дело не слишком быстро, поэтому история не рассчитывается. То есть изучать лучше в визуализаторе. Но это быстро надоедает :). Но нельзя исключить, что кто-нибудь терпеливый сможет найти способ извлечь из этого пользу :).
В общем я отдаю себе отчёт в том, что внятного описания мне сделать не удалось, если кого-то это заинтересует, скорее всего он сможет рассчитывать на пояснения.
В принципе, предполагается поговорить ещё об одном индикаторе, он аппроксимирует и экстраполирует покрасивее представленных. То есть меня это настолько впечатлило, что я видимо окончательно стал на позиции кусочной детерминированности цены. Что правда облегчения не приносит, поскольку длину этих кусков определить пока не удаётся :) .
Но сил писать больше нет, могу только пару картинок дать :)
Пример аппроксимации с удачной экстраполяцией
Пример аппроксимации с экстраполяцией, "сорванной" импульсом
а можете добавить кусочек кода чтобы HShift не задавался, а определялся по фактическому месту первой линии? точнее если он задан <0 - тогда будут работать оба механизма и можно будет тягать ее по графику вглубь истории и анализировать как прогноз в той точке совпал с тем что случилось после нее. интересно будет ;)
а можете добавить кусочек кода чтобы HShift не задавался, а определялся по фактическому месту первой линии? точнее если он задан <0 - тогда будут работать оба механизма и можно будет тягать ее по графику вглубь истории и анализировать как прогноз в той точке совпал с тем что случилось после нее. интересно будет ;)
Да, это довольно удобно, даю версию. Оговорюсь, что графическим управлением я особо не увлекался, гарантии что всё будет гладко не даю.
Кстати, вроде я нигде явно не сказал, что гистограммы в правом нижнем углу показывают ошибку аппроксимации на базовой выборке и ошибку экстраполяции на out of sample. Разумно предположить что эта информация имеет значение для оценки ситуации.
P.S. Ага, забыл одну строку добавить. Индикатор заменён в 11:50
Ещё пару слов. Почему старший тренд взят именно линейный? Так или иначе реальные тренды выглядят линейными. Предположение состоит в том, что такое детрендирование человек может производить бессознательно, тогда есть надежда что и за гармоникой может стоять реальность.
В принципе поднять степень полинома не проблема, на самом деле я начинал вариантом с параболой. Делается это элементарно, в несколько добавленных и исправленных строчек, любой может попробовать это сделать сам, в качестве упражнения.
Добрый день.
поясни пожалуйста рисунки. Интерисуют вертикальные линии. Правильно ли я понял, что именно в интервале между синими линиями данные для прогноза ? что означает красная ? - момент расхождения с прогнозом ? почему красные (синии) линии прогноза имеют разрывы ?
код не смотрел, т.к. твой уровень програмирования на MQL для меня не достижим, это как мечта хотя бы приблизиться к такому уровню
Prival:
поясни пожалуйста рисунки. Интерисуют вертикальные линии. Правильно ли я понял, что именно в интервале между синими линиями данные для прогноза ? что означает красная ? - момент расхождения с прогнозом ? почему красные (синии) линии прогноза имеют разрывы ?
Да, собственно аппроксимация ведётся между синими линиями. Между синей и красной рассчитывается СКО экстраполяции. правее красной - просто будущее, во всяком случае для индикатора. Просто в наших силах его сместить с помощью HShift (а теперь и просто таская линию по графику) и увидеть то, чего он не видит.
Разрывы - это "отходы", рабочее окно индикатора смещается со временем, сзади остаются хвосты. Это было бы легко исправить при постоянном окне, но поскольку оно адаптируется, дешёвый способ очистки мне пока в голову не пришёл.
Даю версию с перекрашенными линиями.
чтото ваш новый код не заработал как хотелось :(
вот я позволил себе снести свои правочки. замечательно работает особенно в паре с ft.AutoRefresh
ForexTools:
вот я позволил себе снести свои правочки. замечательно работает особенно в паре с ft.AutoRefresh
ну конечно! при анализе истории график никуда не должен ездить а "стоять" на том месте куда я линию поставил
Ну вот, а я сначала и сделал неподвижный вариант, а потом его заменил :). Меня-то в первую очередь интересовала как раз динамика перерисовки. Собственно легко добавить параметр типа
if (ModeMoving) HShift--;
Но слишком хорошо тоже нехорошо, пусть вылежится вариант.
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Однажды я вдруг осознал простую вещь: аппроксимация по методу наименьших квадратов по сути сводится к минимизации линейной комбинации векторов. То есть можно изготовить некую универсальную функцию-аппроксиматор. Сказано - сделано, вот заголовок функции:
Важная деталь, все массивы V и A реально одномерные, массив А впрочем чисто рабочий, а вот массив V должен быть правильно заполнен.
Для работы ей нужна также функция для решения системы линейных уравнений. Когда я это сочинял мне была известна только одна реализация на MQL, использованный ANG3110 для полиномиалной регрессии метод Гаусса. Естественно, я пошёл по пути наименьшего сопротивления и использовал для функции именно этот алгоритм. Другими словами существуют более эффективные алгоритмы, тем более что матрица получается симметричной, но я к ним не обращался.
Как ей пользоваться:
Сначала решим, какой функцией мы будем аппроксимировать. Пусть, для примера, это будет линейная регрессия. То есть у нас будет линейная комбинация A*1 + B*X, всего два вектора, единичный и собственно аргумент.
Заведём рабочие массивы и где-нибудь в init() отведём для них память
Осталось правильно заполнить массив V и рассчитать коэффициенты. Это можно сделать так:
Дело сделано, линейная регрессия C[0] + C[1]*pos готова.
Первым делом нам нужно проверить алгоритм. Для этого на базе индикатора ang_PR (Din)-v1.mq4 ( ANG3110 ) с использованием LSA был написан индикатор полиномиальной регрессии и произведено сравнение результатов. Результаты визуально совпали, на этом проверка была закончена :). Индикатор LSA_PR.mq4 прилагается.