Настало время разобраться с новыми индикаторами, сегодня ими выступят RSI, STOCH, STOCHRSI, а так же мы немного модифицируем скользящие средние, что бы получать SMMA, MMA и RMA. Последние нам понадобятся для построения первых. С них и начнем.
Как мы уже знаем из первой части статьи, есть несколько видов скользящих – простая, где просто берется средняя за n периодов, и различного рода сглаживающие (у нас была экспоненциальная, EMA). Сглаживающие нужны для того, что убрать пики/провалы, шумы, усилить значения последних дней по сравнению с первыми и т.п.
Существует куча этих сглаживающих, но все они либо синонимы одной и той же, либо отличаются коэффициентом сглаживания. Например, EMA и EWMA – это одно и тоже, берется SMA и к ней применяется сглаживание по формуле 2/(period+1).
SMMA, MMA, RMA – три названия одной и той же сглаживающей, которая тоже самое, что EMA, но с коэффициентом сглаживания 1/period. Больше информации о скользящих можно получить тут.
Поэтому немного изменим наш код, создадим сущность generalEMA, которой на вход будем подавать параметры – массив цен, период и коэффициент, её будут вызывать «обычные» функции, такие как EMA и SMMA, что бы никто не путался.
Ссылку на код я дам ниже, пока несколько замечаний: как вы видите, мы только что добавили в библиотеку «несколько» новых индикаторов, каждый из которых вызывает EMA, под собственным именем, и коэффициенты зашиты внутри реализации, что бы не писать одно и тоже по 10 раз.
Если мне где-то, в какой то стратегии встретится, что нужно использовать MMA, то я не буду ничего изобретать, а просто использую MMA из свой библиотеки, и не буду помнить о том, что на самом деле MMA вызывает SMMA, а SMMA это в свою очередь обычная EMA, но с измененным коэффициентом сглаживания. Жаль, что не все, кто учит торговать по индикаторам, знают их особенности.
Еще замечание – функция generalEMA занимает 16 строк, не считая пробелов, функция SMA, которую она вызывает – 20 строк. В 36 строках кода – как минимум три уникальных скользящих. Я пишу это, не для того, чтобы подчеркнуть качество кода, а с целью указать на «интеллектуальность» этого класса индикаторов.
Вот результат вывода – вызвали каждую функцию, можно заметить, что у нужных функций одинаковые результаты:
Зачем мы всё это делаем? Нам нужна была функция RSI, а её создатель использовал SMMA. Давайте теперь сделаем RSI.
RSI позиционируется как индекс перекупленности/перепроданности. Он возвращает значения от 0 до 100, считается что значения ниже 30 говорят о недооценности рынка (пора покупать), а выше 70 – о перекупленности (не надо покупать, пора продавать).
Еще его используют для поиска дивергенций – простыми словами, если индикатор идет вверх, а общий график вниз, или наоборот, то, возможно, намечается разворот.
Для расчета RSI берутся все торговые дни (недели, часы – назовем периодами), и сравниваются цены их закрытия. Есть восходящие дни (где цена росла по отношению к предыдущему дню), нисходящие дни (где цена падала к предыдущему) и никчемные дни, когда цена оставалась такой же.
Если дать на вход RSI сто цен закрытия, то он
Проще посмотреть код, на мой взгляд. Вот он (не уверен даже, стоит ли его комментировать):
Реклама:
def RSI(data, period): u_days = [] d_days = [] for i, _ in enumerate(data): if i == 0: u_days.append(0) d_days.append(0) else: if data[i] > data[i-1] : u_days.append(data[i] - data[i-1]) d_days.append(0) elif data[i] < data[i-1]: d_days.append(data[i-1] - data[i]) u_days.append(0) else: u_days.append(0) d_days.append(0) smma_u = SMMA(u_days, period) smma_d = SMMA(d_days, period) result = [] for k, _ in enumerate(data): if smma_d[k] == 0: result.append(100) else: result.append(100 - (100 / (1 + smma_u[k]/smma_d[k]))) return result
Гуд! Пойдем к стохастикам
Задумка от автора такая – если цена растет, то она при закрытии следующего торгового периода цена будет недалеко от текущих максимумов. Если падает – то скорее всего будет при закрытии будет находиться около минимумов. Напоминанию, что это мнение автора.
Суть в том, что берутся минимумы, максимумы, текущие цены и сравниваются их отношения друг с другом. Это будет быстрой линией стохастика. Вторая линия – медленная, как вы может быть уже догадались, сглаженный вариант быстрой линии. Эти две линии сравниваются между собой, а дальше уже зависит от торговой стратегии. Простейший пример – если быстрая линия выше медленной, то нужно покупать, и наоборот.
Подробнее можете почитать в википедии, там маленькая статья и есть несколько примеров. Вот как реализуется индикатор:
def STOCH(high, low, closes, fastk_period, slowk_period, slowd_period): fastk = [] for i, _ in enumerate(closes): if (i + 1) < fastk_period: fastk.append(math.nan) else: lower_bound = i + 1 - fastk_period upper_bound = i + 1 curr_low = min(low[lower_bound:upper_bound]) curr_high = max(high[lower_bound:upper_bound]) fastk.append(((closes[i] - curr_low) / (curr_high - curr_low)) * 100) fastk = EMA(fastk, slowk_period) slowd = EMA(fastk, slowd_period) return fastk, slowd
Я взял EMA, хотя именно для этого индикатора каждый ставит сглаживающую на свой вкус. Так же я нашел несколько реализаций этой функции в разных источниках, если кто-то сможет указать на единственно верную реализацию, буду признателен.
Тут вообще всё просто. Взяли RSI и посчитали его значения с помощью стохастика. Вот так:
def STOCHRSI(data, period, fastk_period, fastd_period): rsi = RSI(data, period) return STOCH(rsi, rsi, rsi, period, fastk_period, fastd_period)
Вроде как он взял лучшее от двух индикаторов, и еще лучше всё считает. Им многие пользуются, но решать конечно вам.
В рамках одной статьи уже достаточно материала, в следующий раз рассмотрим D2 (DEMA), T3(TEMA) и линии Боллинджера.
Я надеюсь, что смог добавить крупицу знаний в вашу копилку, или дать повод для размышления.
Весь код, указанный в статье, вы можете найти тут и пользоваться, как вам угодно. Если что, там есть рядом такая же библиотека для голанга, там покрытие тестами и прочие радости. Велкам, если желаете поучаствовать.
Удачи!