Форум » Статьи MQLabs » Что скрывают свечи? » Ответить

Что скрывают свечи?

Scriptong: Часть 1 Вычисление сил быков и медведей на основании тиковой истории, взятой в пределах одной свечи текущего таймфрейма - индикатор BearBullBalanceOnticks. Также на основании тиковой истории определяются уровни максимального объема, действующие в пределах одной свечи - индикатор AnyTFVerticalHistogramm. Часть 2. Модернизация сборщика тиков для обновленного MQL4. Изменение условий регистрации уровней максимальных объемов. Часть 3. Приближение вида графика к кластерному виду. Обновление от 17.09.14 для первых трех частей Улучшенная версия сборщика тиков. Новые версии подсчета сил быков и медведей. Важные уровни внутри свечи, они же приближение вида графика к кластерному виду - Вертикальное сечение рынка. Часть 4. 1. В сборщик тиков добавлен принудительный сброс накопленных данных с частотой, выраженной в тиках, что регулируется трейдером. 2. Разработана версия ClusterBox (ClusterBox_Histogramm), отображающая данные в виде гистограммы интерактивно настраиваемой продолжительности. 3. Индикатор ClusterBox_Histogramm может использоваться без параллельно работающего сборщика тиков, но это требует периодического удаления временных файлов в папке MQL4\Files. Часть 5. 1. Индикаторы ClusterBox и BearBulBalanceOnTick получили возможность сохранения накопленных данных во временный файл. 2. Изменен алгоритм перемещения прямоугольника, указывающего интервал отображения гистограммы, в индикаторе ClusterBox_Histogramm. 3. Индикатор ClusterBox_Histogramm теперь может отображать силы быков и медведей в разрезе уровней кластеров. 4. Мелкие фиксы в коде ClusterBox_Histogramm. Обновление от 17.09.14 для четвертой и пятой частей Улучшенная версия гистограммы и новый вид гистограммы для просмотра истории - Горизонтальное сечение рынка

Ответов - 147, стр: 1 2 3 4 5 6 7 8 9 10 All

Evgeny: Scriptong пишет: Оба индикатора (ClusterBox_NullDayHistogramm и ClusterBox_TicksDensity) работают на основе данных тиковой истории Игорь, я писал про индикатор который был разработан в теме "Охота на объемы" в части 4. Называется "гистограмма вертикальных объемов". Только не могу проверить сейчас этот или нет.

Scriptong: Evgeny пишет: Игорь, я писал про индикатор который был разработан в теме "Охота на объемы" в части 4. Называется "гистограмма вертикальных объемов". Вертикальные объемы - это немного другое: Это индикатор ClusterBox. А вот горизонтальные объемы - это то, что я привел.

Evgeny: Я вот про этот индикатор писал. Он выводит профиль рынка в режиме онлайн и на истории. Хотелось бы, чтобы в этом же индикаторе объемы делились на бары и выводились справа плотности. Тогда можно будет увидеть концентрацию объемов в местах, где цену разворачивают крупным точечным объемом на истории. Для этого я тогда предложил идею концентрации объемов. Жаль, что в тестере стратегий этот индикатор не показывает профиль рынка в динамике, а только по истечению суток.


Evgeny: Evgeny пишет: Я вот про этот индикатор писал. Он выводит профиль рынка в режиме онлайн и на истории. Хотелось бы, чтобы в этом же индикаторе объемы делились на бары и выводились справа плотности. Тогда можно будет увидеть концентрацию объемов в местах, где цену разворачивают крупным точечным объемом на истории. Для этого я тогда предложил идею концентрации объемов. Жаль, что в тестере стратегий этот индикатор не показывает профиль рынка в динамике, а только по истечению суток. #property copyright "Scriptong" #property link "scriptong@mail.ru" #property indicator_chart_window #define MAX_DAY_VOLATILITY 2000 // Настроечные параметры индикатора extern color i_supportColor = DarkGray; extern color i_resistanceColor = DarkGray; extern color i_indefiniteColor = DarkGray; extern int i_indBarsCount = 5000; // Прочие глобальные переменные индикатора bool g_activate, // Признак успешной инициализации.. // ..индикатора g_init; // Переменная для инициализации.. // ..статических переменных внутри.. // ..функций в момент проведения.. // ..повторной инициализации int g_volumesArray[MAX_DAY_VOLATILITY]; // Массив для записи величин объемов datetime g_lastCheckedBar; // Время открытия последнего.. // ..проверенного бара ТФ М1 #define PREFIX "HVBVH2_" // Префикс графических объектов,.. // ..отображаемых индикатором #define SIGN_TREND_LINE "TR_LINE_" // Признак объекта "трендовая линия" #define SIGN_TEXT "TEXT_" // Признак объекта "Текст" #define TEXT_SIZE 10 // Размер шрифта текста #define TEXT_FONT "MS Sans Serif"// Имя шрифт для текста #include <stderror.mqh> //+-------------------------------------------------------------------------------------+ //| Custom indicator initialization function | //+-------------------------------------------------------------------------------------+ int init() { g_activate = false; // Индикатор не инициализирован g_init = true; g_lastCheckedBar = 0; if (!TuningParameters()) // Неверно указанные значения.. return (-1); // ..настроечных параметров - причина // ..неудачной инициализации IsAllBarsAvailable(PERIOD_M1); // Запуск подкачки данных по ТФ М1 g_activate = true; // Индикатор успешно инициализирован return(0); } //+-------------------------------------------------------------------------------------+ //| Проверка корректности настроечных параметров | //+-------------------------------------------------------------------------------------+ bool TuningParameters() { string name = WindowExpertName(); if (Period() > PERIOD_H4) { Print(name, ": Индикатор не работает на таймфреймах выше, чем H4."); return (false); } int period = Period(); if (period == 0) { Alert(name, ": фатальная ошибка терминала - период 0 минут. Индикатор отключен."); return (false); } if (Point == 0) { Alert(name, ": фатальная ошибка терминала - величина пункта равна нулю. ", "Индикатор отключен."); return (false); } return (true); } //+-------------------------------------------------------------------------------------+ //| Проверка доступности баров указанного таймфрейма | //+-------------------------------------------------------------------------------------+ bool IsAllBarsAvailable(int tf) { // Вычисление индекса бара, с которого необходимо начинать проверку if (g_lastCheckedBar == 0) int lastBar = iBars(NULL, tf) - 1; else lastBar = iBarShift(NULL, tf, g_lastCheckedBar); if (GetLastError() == ERR_HISTORY_WILL_UPDATED) return (false); // Проверка доступности баров for (int i = lastBar - 1; i > 0; i--) { iTime(NULL, tf, i); if (GetLastError() == ERR_HISTORY_WILL_UPDATED) return (false); } // Все бары доступны g_lastCheckedBar = iTime(NULL, tf, 1); return (true); } //+-------------------------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+-------------------------------------------------------------------------------------+ int deinit() { DeleteAllObjects(); return(0); } //+-------------------------------------------------------------------------------------+ //| Удаление всех объектов, созданных программой | //+-------------------------------------------------------------------------------------+ void DeleteAllObjects() { for (int i = ObjectsTotal() - 1; i >= 0; i--) if (StringSubstr(ObjectName(i), 0, StringLen(PREFIX)) == PREFIX) ObjectDelete(ObjectName(i)); } //+-------------------------------------------------------------------------------------+ //| Определение индекса бара, с которого необходимо производить перерасчет | //+-------------------------------------------------------------------------------------+ int GetRecalcIndex(int& total) { static int lastBarsCnt; // Определение первого бара истории,.. if (g_init) // ..на котором будут доступны.. { // ..адекватные значения lastBarsCnt = 0; g_init = false; } total = Bars - 2; if (i_indBarsCount > 0 && i_indBarsCount < total)// Если не нужно рассчитывать всю.. total = i_indBarsCount; // ..историю, то начнем с указанного.. // ..бара if (lastBarsCnt < Bars - 1) // Кол-во посчитанных баров - 0. Будут { // ..удалены все графические объекты lastBarsCnt = Bars; DeleteAllObjects(); return (total); // Если вся история - то total } int newBarsCnt = Bars - lastBarsCnt; lastBarsCnt = Bars; return (newBarsCnt); // Начинаем с нового бара } //+-------------------------------------------------------------------------------------+ //| Отображение трендовой линии | //+-------------------------------------------------------------------------------------+ void ShowTrendLine(int index, datetime leftTime, double leftPrice, datetime rightTime, color clr) { string name = PREFIX + SIGN_TREND_LINE + leftTime + index; if (ObjectFind(name) < 0) { ObjectCreate(name, OBJ_TREND, 0, leftTime, leftPrice, rightTime, leftPrice); ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID); ObjectSet(name, OBJPROP_COLOR, clr); ObjectSet(name, OBJPROP_BACK, true); ObjectSet(name, OBJPROP_RAY, false); return; } ObjectMove(name, 0, leftTime, leftPrice); ObjectMove(name, 1, rightTime, leftPrice); ObjectSet(name, OBJPROP_COLOR, clr); } //+-------------------------------------------------------------------------------------+ //| Отображение текста | //+-------------------------------------------------------------------------------------+ void ShowText(datetime time, double price, datetime id, string text, color clr) { string name = PREFIX + SIGN_TEXT + id; if (ObjectFind(name) < 0) { ObjectCreate(name, OBJ_TEXT, 0, time, price); ObjectSetText(name, text, TEXT_SIZE, TEXT_FONT, clr); return; } ObjectMove(name, 0, time, price); ObjectSetText(name, text, TEXT_SIZE, TEXT_FONT, clr); } //+-------------------------------------------------------------------------------------+ //| Определение экстремумов указанного дня и перераспределение массива объемов при.. | //| ..необходимости | //+-------------------------------------------------------------------------------------+ int GetDayVolatility(int leftIndex, int rightIndex, int& volumesArray[], double& minDayPrice) { int barsPerDay = leftIndex - rightIndex + 1; minDayPrice = iLow(NULL, PERIOD_M1, iLowest(NULL, PERIOD_M1, MODE_LOW, barsPerDay, rightIndex)); double maxDayPrice = iHigh(NULL, PERIOD_M1, iHighest(NULL, PERIOD_M1, MODE_HIGH, barsPerDay, rightIndex)); int dayVolatility = MathRound((maxDayPrice - minDayPrice + Point) / Point); if (dayVolatility > MAX_DAY_VOLATILITY) ArrayResize(volumesArray, dayVolatility); ArrayInitialize(volumesArray, 0); return (dayVolatility); } //+-------------------------------------------------------------------------------------+ //| Запись уровней одной свечи в массив объемов | //+-------------------------------------------------------------------------------------+ void SaveVolumes(double minBarPrice, double maxBarPrice, double minDayPrice, int volume, int& volumesArray[], int& maxVolume, double& maxVolumePrice) { for (double price = minBarPrice; IsFirstMoreOrEqualThanSecond(maxBarPrice, price); price += Point) { int indexOfArray = MathRound((price - minDayPrice) / Point); volumesArray[indexOfArray] += volume; if (maxVolume >= volumesArray[indexOfArray]) continue; maxVolume = volumesArray[indexOfArray]; maxVolumePrice = price; } } //+-------------------------------------------------------------------------------------+ //| Формирование массивов объемов и соответствующих им индексов баров | //+-------------------------------------------------------------------------------------+ void FormVolumesArray(int leftIndex, int rightIndex, int& volumesArray[], int& dayVolatility, double& minDayPrice, int& maxVolume, double& maxVolumePrice) { dayVolatility = GetDayVolatility(leftIndex, rightIndex, volumesArray, minDayPrice); maxVolume = 0; int volumeSumm = 0; for (int i = leftIndex; i >= rightIndex; i--) { double minBarPrice = iLow(NULL, PERIOD_M1, i); double maxBarPrice = iHigh(NULL, PERIOD_M1, i); if (IsValuesEquals(minBarPrice, maxBarPrice)) continue; int volume = iVolume(NULL, PERIOD_M1, i); SaveVolumes(minBarPrice, maxBarPrice, minDayPrice, volume, volumesArray, maxVolume, maxVolumePrice); } } //+-------------------------------------------------------------------------------------+ //| Вычисление индексов баров минутного ТФ, ограничивающих день перед указанным временем| //+-------------------------------------------------------------------------------------+ int GetIndexesOfDayRange(datetime timeOfNextDay, int& endDayBar, bool isNewDay) { endDayBar = 0; if (isNewDay) endDayBar = iBarShift(NULL, PERIOD_M1, timeOfNextDay) + 1; int beginDayBar = endDayBar; int total = iBars(NULL, PERIOD_M1); while (TimeDayOfYear(iTime(NULL, PERIOD_M1, beginDayBar)) == TimeDayOfYear(iTime(NULL, PERIOD_M1, endDayBar)) && beginDayBar < total) beginDayBar++; return (beginDayBar - 1); } //+-------------------------------------------------------------------------------------+ //| Больше или равно первое число, чем второе? | //+-------------------------------------------------------------------------------------+ bool IsFirstMoreOrEqualThanSecond(double first, double second) { return (first - second > - Point / 100); } //+-------------------------------------------------------------------------------------+ //| Определение равенства двух вещественных чисел | //+-------------------------------------------------------------------------------------+ bool IsValuesEquals(double first, double second) { return (MathAbs(first - second) < Point / 10); } //+-------------------------------------------------------------------------------------+ //| Определение цвета гистограммы | //+-------------------------------------------------------------------------------------+ color GetHistogrammColor(double maxVolumePrice, int beginDayBar, int endDayBar, double& probability) { int cntAbove = 0, cntBelow = 0; for (int i = beginDayBar; i >= endDayBar; i--) { double high = iHigh(NULL, PERIOD_M1, i); double low = iLow(NULL, PERIOD_M1, i); if (IsValuesEquals(high, low)) continue; if (IsFirstMoreOrEqualThanSecond(maxVolumePrice, high)) cntBelow++; if (IsFirstMoreOrEqualThanSecond(low, maxVolumePrice)) cntAbove++; } probability = 50; if (cntAbove == cntBelow) return (i_indefiniteColor); probability = 100 * MathMax(cntBelow, cntAbove) / 1.0 / (cntAbove + cntBelow); if (cntAbove > cntBelow) return (i_supportColor); return (i_resistanceColor); } //+-------------------------------------------------------------------------------------+ //| Отображение найденных уровней | //+-------------------------------------------------------------------------------------+ void ShowLevels(int dayVolatility, int& volumesArray[], double minDayPrice, datetime dayBeginTime, int beginDayBar, int endDayBar, int maxVolume, double maxVolumePrice) { // Определение количества секунд, приходящегося на единичный тиковый объем double secondsInDay = MathMax(1, iTime(NULL, PERIOD_M1, endDayBar) - dayBeginTime + 60); double secondsPerVolume = secondsInDay / maxVolume; // Определение цвета гистограммы и вероятности исхода double probability; color showColor = GetHistogrammColor(maxVolumePrice, beginDayBar, endDayBar, probability); // Отображение гистограммы for (int i = 0; i < dayVolatility; i++) { double price = minDayPrice + i * Point; datetime volume = dayBeginTime + MathRound(secondsPerVolume * volumesArray); ShowTrendLine(i, dayBeginTime, price, volume, showColor); } // Отображение вероятности int dayHalfIndex = (beginDayBar + endDayBar) / 2; ShowText(iTime(NULL, PERIOD_M1, dayHalfIndex), minDayPrice, dayBeginTime, DoubleToStr(probability, 2) + "%", showColor); } //+-------------------------------------------------------------------------------------+ //| Обработка одного заданного бара | //+-------------------------------------------------------------------------------------+ void ProcessOneCandle(int index) { // Если нет перехода через начало суток, то свеча не обрабатывается datetime timeOfBar = Time[index]; datetime prevBarTime = Time[index + 1]; if (TimeDayOfYear(timeOfBar) == TimeDayOfYear(prevBarTime) && index != 0) return; // Нахождение бара и времени начала дня int endDayBar; int beginDayBar = GetIndexesOfDayRange(timeOfBar, endDayBar, index != 0); datetime dayBeginTime = iTime(NULL, PERIOD_M1, beginDayBar); // Формирование массива данных для расчета статпараметров на их основе double minDayPrice, maxVolumePrice; int maxVolume, dayVolatility; FormVolumesArray(beginDayBar, endDayBar, g_volumesArray, dayVolatility, minDayPrice, maxVolume, maxVolumePrice); if (maxVolume == 0) return; // Отображение уровней ShowLevels(dayVolatility, g_volumesArray, minDayPrice, dayBeginTime, beginDayBar, endDayBar, maxVolume, maxVolumePrice); } //+-------------------------------------------------------------------------------------+ //| Отображение данных индикатора | //+-------------------------------------------------------------------------------------+ void ShowIndicatorData(int limit, int total) { for (int i = limit; i >= 0; i--) ProcessOneCandle(i); } //+-------------------------------------------------------------------------------------+ //| Custom indicator iteration function | //+-------------------------------------------------------------------------------------+ int start() { if (!g_activate) // Если индикатор не прошел.. return (0); // ..инициализацию, то работать он.. // ..не должен if (!IsAllBarsAvailable(PERIOD_M1)) // Проверка готовности данных на ТФ М1 return (0); int total; int limit = GetRecalcIndex(total); // С какого бара начинать обновление ShowIndicatorData(limit, total); // Отображение данных индикатора WindowRedraw(); return(0); }

Scriptong: Evgeny пишет: Evgeny пишет: Это индикатор HighVolumeBar_VerticalHistogram_v2 из статьи "Охота на объемы. Часть 4" от 22.11.2013. Да, он оперирует тиковыми объемами, взятыми с минутного графика. Реальный тиковый поток не используется. При подсчете плотности тиков такой способ тоже можно использовать, но он даст некоторое увеличение погрешности расчетов. Погрешность будет тем больше, чем длиннее окажутся минутные свечи. То есть ночью точность увеличится, а днем (или же в период высокой волатильности) - уменьшится.

Evgeny: Игорь, добрый день. Я вчера показал код вашего индикатора горизонтальных обьемов, про который говорил. Он ещё показывает ежедневно процент нахождения цены над и под максимальным дневным профилем рынка. Вы его успели посмотреть? Я удалил сегодня. Вот про него и писал

Scriptong: Evgeny пишет: Вы его успели посмотреть? Нет, не успел. Зачем удалили то? Если что-то секретное, то можно было в личку скинуть.

Evgeny: Игорь, добрый день. Просто большой пост получился, вот и удалил. Выложу вечером ещё раз код Вашего индикатора и ещё раз попробую написать, что хотелось бы...

Evgeny: Scriptong пишет: Да, он оперирует тиковыми объемами, взятыми с минутного графика Я сравнивал профили HighVolumeBar_VerticalHistogram_v2 с профилями, которые формируются на реальных объемах по фьючерсам. Профили совпадают по общему виду, показывают в одних и тех же местах относительно свечного графика зоны накопления объемов, картина "пиков и впадин" та же. Отличия только в "длине" пиков, что для интерпретации не критично. Причина отличий понятна: на фьючерсах абсолютные объемы, в нашем случае тики. Как уже обсуждалось ранее, оперировать абсолютными величинами в интерпретации рынка и принятия решений в целом даже менее эффективно, чем относительными величинами. С другой стороны, в индикаторе HighVolumeBar_VerticalHistogram_v2 есть преимущество. Можно в любое время открыть терминал и сразу увидеть текущий профиль рынка. Не нужно постоянно держать включенным компьютер, чтобы накопить в коллекторе исходные данные для кластерного анализа. В этой ситуации все становится гораздо интереснее в плане оперативности получения данных для реальной внутридневной торговли. Также это будет необходимо для материала, который я готовлю сейчас. Хочу показать, как использовать в торговле инструменты кластерного анализа в комплексе. На данный момент нет логически завершенной аналитической платформы, которая была бы достаточно проста, понятна и использовалась бы в торговле ежедневно. Единственное "замечание" к индикатору HighVolumeBar_VerticalHistogram_v2 заключается в высоте кластера. Нет никакой необходимости делать высоту равной 1 тику. В анализе реальных объемов не используется пятый знак. Профиль рынка отражается до четвертого знака, т.е. высоту кластера нужно сделать 10 на пятизнаке.

Scriptong: Evgeny пишет: Можно в любое время открыть терминал и сразу увидеть текущий профиль рынка. Не нужно постоянно держать включенным компьютер, чтобы накопить в коллекторе исходные данные для кластерного анализа. В этой ситуации все становится гораздо интереснее в плане оперативности получения данных для реальной внутридневной торговли. Тиковые данные можно подставить. У меня на сайте есть данные за каждую прошедшую неделю. Evgeny пишет: Нет никакой необходимости делать высоту равной 1 тику. Этот индикатор разрабатывался еще во времена Admiral Markets. Тогда у них еще было много 4-хзначных счетов. Ими я и пользовался.

Evgeny: Scriptong пишет: Тиковые данные можно подставить. У меня на сайте есть данные за каждую прошедшую неделю. Так в том и проблема - за прошедший период. А чтобы торговать, нужно здесь и сейчас. Что толку от прошлого. Объёмы наторговываются "сегодня" и цена двигается от объемов сегодня. Это же классика жанра. Весь этот бизнес строится на отьеме денег у того большинства, кто каждый день наступает на заботливо подложенные грабли. Что делает большинство? То чему его "научили": ломает голову куда пойдёт рынок на основе данных "вчера", заходит на пробой "чего то там" фантазируя о крупном "наваре" и ловит развороты, когда цена летит в фазе распрелеления. Это же идеальный отьем денег. Вот смотрите вчера и позавчера был восходящий тренд...я сам отслеживал психологию торговли людей: часть их клепает сделки на пробой флета, на пробой "канала" или уровня либо "по тренду", другая находит кучу аргументов на разворот "против тренда". И всех их опрокидывают с утречка часов так в 9-11 и потом ещё в течение дня для особо упёртых. Меняя картинку как выгодно. Это манипуляция ценой, которая раскрывается при анализе объемов "здесь и сейчас". Я сам это вижу, когда торгую. Примеров на каждый день в изобилии.

Scriptong: Evgeny пишет: А чтобы торговать, нужно здесь и сейчас. Тогда да - требуется запуск сборщика тиков. Он немного ресурсов занимает. Не вижу проблемы.



полная версия страницы