Как было отмечено в предыдущей части – вся суть технического анализа со всеми его индикаторами сводится к пересечению линий. Например, быстрая скользящая средняя пересекает медленную скользящую среднюю; цена пересекает уровень или любую линию какого-нибудь индикатора; RSI пересек уровень 70% и т.д. Ну пусть даже и есть исключения – напишем под них отдельные функции, главное, что наше обобщение будет охватывать 90% случаев ))).
Итак, из чего же состоят сигналы пересечения линий? А состоят они из событий и состояний. Событие – это факт пересечения, состояние – это фактическое расположение линий относительно друг друга.
На рисунке показано, как это выглядит геометрически на примере пересечения скользящих средних. А с точки зрения программирования эти события и состояния удобно представить в виде битовых флагов – сопоставить каждому из них определенный бит числа и если он установлен, то событие или состояние имеется и наоборот.Опишем биты для сигналов, в скобках указаны последовательно номер бита, соответствующее ему число в десятичной системе и в двоичной системе:
-- (8 - 128 - 1000 0000) = состояние расхождение вверх -- (7 - 64 - 0100 0000) - событие пересечение вверх -- (6 - 32 - 0010 0000) - событие пересечение обратное вниз -- (5 - 16 - 0001 0000) = состояние центральное -- (4 - 8 - 0000 1000) = состояние центральное -- (3 - 4 - 0000 0100) - событие пересечение обратное вверх -- (2 - 2 - 0000 0010) - событие пересечение вниз -- (1 - 1 - 0000 0001) = состояние расхождение вниз
Обычно одна из линий ведущая, поэтому расхождение или пересечение вверх подразумевает, что быстрая скользящая средняя находится выше медленной скользящей средней.
Каково преимущество битовых флагов? Оно заключается в том, что одним числом можно передавать несколько событий или состояний, меняя в нем битовые флаги. Исходя из представленного описания: 1100 0000 будет соответствовать «расхождению вверх» и «пересечению вверх».
Центральное состояние введено на случай равенства значений скользящих средних. Зачем два центральных состояния? На случай, если сигналы «вверх» и «вниз» независимы. В случае скользящих средних центральные состояния всегда одинаковы.
Может показаться, что биты 3 и 7, а также 6 и 2 дублируют друг друга, но на самом деле это не так, если значения скользящих средних совпадут, то пересечения еще нет, а обратное пересечение уже есть.
Все это муторно описывать словами, и кажется, что сложно вычислять, но если имеется уже готовая функция, делающая всю работу, то все становится просто.
-- Функция вычисляет битовый элементарный сигнал пересечения двух линий. -- Принимает: значения линий текущие (F1, S1) и предыдущие (F2, S2). -- Возвращает: сигнал. function FunctionBeepCross2Line (F1, F2, S1, S2) local beep = 0; if (F1 > S1) then beep = beep + 128; if (F2 <= S2) then beep = beep + 64; end else if (F2 > S2) then beep = beep + 32; end end if (F1 < S1) then beep = beep + 1; if (F2 >= S2) then beep = beep + 2; end else if (F2 < S2) then beep = beep + 4; end end if (F1 == S1) then beep = beep + 24; end return beep; end
С помощью этой функции на каждом баре можно вычислять первичный сигнал для пересекающихся линий (причем любых – не обязательно скользящих средних). Затем, с помощью другой функции можно узнать, чему равен интересующий бит и уже использовать эту информацию в дальнейшей работе.
В реальности часто используют пересечение линии и некоторого уровня, тогда в эту функцию можно передать значения исходя из того, что S1 = S2 (у уровня значения не меняются), либо переписать функцию под одно значение S.
Также могут быть и другие ситуации – например, пересечение линии и некоторого диапазона. Здесь уже придется написать еще одну функцию, принимающую границы диапазона, при этом битовые сигналы не меняются, и тут сразу приобретают особый смысл различие в битах 3 и 7, а также 6 и 2 – один из них теперь отвечает за пересечение одной границы диапазона, а другой за пересечение противоположной границы диапазона. Такая функция тоже уже написана, как-нибудь выложу её код, а пока на рисунке показаны значения битов для различных ситуаций пересечения линии и диапазона.
Вот таким нехитрым способом осуществляется приведение показаний различных индикаторов к однотипному представлению. Часто имеет смысл обработать не значение индикатора, а сразу тот показатель, который требуется в стратегии, либо из двух уже однотипных представлений всегда собрать нужный сигнал.
Ну например, допустим сигнал пересечения скользящих средних в соответствии со стратегией актуален только в течение трех баров, тогда имеет смысл объединить показания счетчика баров и пересечения скользящих средних в один первичный сигнал – суть не меняется, но уже абстрактное обратное пересечение всегда будет происходить через 3 бара после пересечения скользящих средних.
Здесь нужно уже переходить от рассмотренных ранее понятий «пересечений» (которые имеют смысл для линий) к более общим абстрактным понятиям событий «включения» и «отключения» сигнала, а также состоянию «включенного» сигнала. В этих терминах пересечение скользящих средних будет «включать» сигнал, а истечение трех баров будет «отключать» сигнал. И если подумать, то данный сигнал оказывается несимметричен, так как пока длится три бара, уже может осуществиться пересечение в обратную сторону, а значит, центральные состояния должны работать раздельно. Думаю понятно объяснил.
Ну и никаких догм тут нет – если кто-то предложит более универсальную абстракцию или дополнит существующую, то я выслушаю предложения. И не факт, что не появятся еще какие-то биты.
Может показаться, что этим сложно пользоваться, но на самом деле это не так, всю сложность на себя берут функции.
Продолжение следует!
По-моему, Вы перемудрили. Вводя это Ваше битовое представление, вы ограничиваете гибкость и усложняете без надобности. Все что вам надо, ловить события. вам нужен лишь ивентлуп, который запускает набор функций, где Вы описываете свободно любые расклады, отталкиваясь от координат. Например функция пересечения может выглядеть как то так:
crossLinesSygnal = function(){
getCoords(line1) equal (getCoords(line2)) && beep call
}
потом просто вешаете такие ф-ции на ивентлупы, и все. Вместо ивентлупа можно использовать кастомные события, по типу паттерна «Observer». Это проще, прозрачней и гибче, ящетаю. Таким образом Вы можете описывать любые расклады, а не только те что захардкорены в вашем битовом представлении.
и очень сомневаюсь, что это проще… но может когда-нибудь и до этого дойду, а пока так…
Несправедливо!
а теперь цель заключается в том, что надо перейти на нормальный язык программирования, так как это надежно и возможностей больше и гибкость просто несравнимая
А так тема хорошая.