MarketProfile
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «market profile 1.19 (1).mq4» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
MarketProfile — пользовательский индикатор для MetaTrader 4, отображающий рыночный профиль за внутридневные, дневные, недельные или месячные торговые сессии. Индикатор строит гистограмму распределения цены по уровням, отмечает зону стоимости (VAH/VAL), медиану (POC) и уровни одиночных тиков (Single Print). Поддерживает режим Rectangle, при котором сессии задаются нарисованными на графике прямоугольниками. Доступны настройки цветовых схем, стилей и толщины линий, а также режим Developing POC для отображения развивающегося POC в реальном времени. Индикатор может выдавать оповещения при пересечении ценой уровней медианы, зоны стоимости и Single Print, а также при разрывах. Для оповещений доступны всплывающие уведомления, электронная почта и push-уведомления, а также отрисовка стрелок на графике. Настройки производительности позволяют управлять частотой перерисовки и количеством объектов. Индикатор работает в окне графика, использует 5 буферов для отображения Developing POC и стрелок оповещений. Поддерживаются внутридневные сессии с настраиваемыми временными интервалами и цветовыми схемами. Предусмотрены настройки для учета выходных дней и отключения оповещений на неподходящих таймфреймах.
Настройки программы
| Настройка | Описание |
|---|---|
| Session | Сессия — Выбор периода сессии: дневная, недельная, месячная, внутридневная или прямоугольник. |
| StartFromDate: lower priority. (StartFromDate) | Начинать с даты — Дата начала отображения (имеет более низкий приоритет). |
| StartFromCurrentSession: higher priority. (StartFromCurrentSession) | Начинать с текущей сессии — Начинать с текущей сессии (имеет более высокий приоритет). |
| SessionsToCount: Number of sessions to count Market Profile. (SessionsToCount) | Количество сессий — Количество сессий для расчета рыночного профиля. |
| SeamlessScrollingMode: show sessions on current screen. (SeamlessScrollingMode) | Режим бесшовной прокрутки — Показывать сессии на текущем экране. |
| Enable Developing POC. (EnableDevelopingPOC) | Включить Developing POC — Включить отображение развивающегося POC. |
| ValueAreaPercentage: Percentage of TPO's inside Value Area. (ValueAreaPercentage) | Процент зоны стоимости — Процент TPO внутри зоны стоимости. |
| ColorScheme | Цветовая схема — Выбор цветовой схемы для отображения профиля. |
| SingleColor: if ColorScheme is set to Single_Color. (SingleColor) | Одиночный цвет — Цвет, используемый, если выбрана одноцветная схема. |
| ColorBullBear: If true, colors are from bars' direction. (ColorBullBear) | Цвет по быкам/медведям — Если включено, цвета берутся из направления баров. |
| MedianColor | Цвет медианы — Цвет линии медианы. |
| ValueAreaSidesColor | Цвет боковых линий зоны стоимости — Цвет боковых линий зоны стоимости. |
| ValueAreaHighLowColor | Цвет максимума/минимума зоны стоимости — Цвет линий максимума и минимума зоны стоимости. |
| MedianStyle | Стиль медианы — Стиль линии медианы. |
| MedianRayStyle | Стиль луча медианы — Стиль линии луча медианы. |
| ValueAreaSidesStyle | Стиль боковых линий зоны стоимости — Стиль боковых линий зоны стоимости. |
| ValueAreaHighLowStyle | Стиль максимума/минимума зоны стоимости — Стиль линий максимума и минимума зоны стоимости. |
| ValueAreaRayHighLowStyle | Стиль лучей максимума/минимума зоны стоимости — Стиль лучей максимума и минимума зоны стоимости. |
| MedianWidth | Толщина медианы — Толщина линии медианы. |
| MedianRayWidth | Толщина луча медианы — Толщина линии луча медианы. |
| ValueAreaSidesWidth | Толщина боковых линий зоны стоимости — Толщина боковых линий зоны стоимости. |
| ValueAreaHighLowWidth | Толщина максимума/минимума зоны стоимости — Толщина линий максимума и минимума зоны стоимости. |
| ValueAreaRayHighLowWidth | Толщина лучей максимума/минимума зоны стоимости — Толщина лучей максимума и минимума зоны стоимости. |
| ShowValueAreaRays: draw previous value area high/low rays. (ShowValueAreaRays) | Показывать лучи зоны стоимости — Рисовать лучи максимума/минимума зоны стоимости предыдущих сессий. |
| ShowMedianRays: draw previous median rays. (ShowMedianRays) | Показывать лучи медианы — Рисовать лучи медианы предыдущих сессий. |
| RaysUntilIntersection: which rays stop when hit another MP. (RaysUntilIntersection) | Лучи до пересечения — Выбор лучей, которые останавливаются при пересечении с другим профилем. |
| HideRaysFromInvisibleSessions: hide rays from behind the screen. (HideRaysFromInvisibleSessions) | Скрывать лучи невидимых сессий — Скрывать лучи от сессий, находящихся за пределами экрана. |
| TimeShiftMinutes: shift session + to the left, - to the right. (TimeShiftMinutes) | Сдвиг времени в минутах — Сдвиг сессии в минутах: положительное значение — влево, отрицательное — вправо. |
| ShowSinglePrint: mark Single Print profile levels. (ShowSinglePrint) | Показывать Single Print — Отмечать уровни Single Print в профиле. |
| SinglePrintColor | Цвет Single Print — Цвет отметок Single Print. |
| SinglePrintRays: mark Single Print edges with rays. (SinglePrintRays) | Лучи Single Print — Отмечать границы Single Print лучами. |
| SinglePrintRayStyle | Стиль лучей Single Print — Стиль линии лучей Single Print. |
| SinglePrintRayWidth | Толщина лучей Single Print — Толщина линии лучей Single Print. |
| ProminentMedianColor | Цвет выделенной медианы — Цвет выделенной медианы. |
| ProminentMedianStyle | Стиль выделенной медианы — Стиль линии выделенной медианы. |
| ProminentMedianWidth | Толщина выделенной медианы — Толщина линии выделенной медианы. |
| RightToLeft: Draw histogram from right to left. (RightToLeft) | Справа налево — Рисовать гистограмму справа налево. |
| PointMultiplier: higher value = fewer objects. 0 - adaptive. (PointMultiplier) | Множитель пунктов — Множитель пунктов: большее значение — меньше объектов. 0 — адаптивный режим. |
| ThrottleRedraw: delay (in seconds) for updating Market Profile. (ThrottleRedraw) | Задержка перерисовки — Задержка в секундах для обновления рыночного профиля. |
| DisableHistogram: do not draw profile, VAH, VAL, and POC still visible. (DisableHistogram) | Отключить гистограмму — Не рисовать гистограмму профиля, при этом VAH, VAL и POC остаются видимыми. |
| AlertNative: issue native pop-up alerts. (AlertNative) | Всплывающие оповещения — Выдавать всплывающие оповещения в терминале. |
| AlertEmail: issue email alerts. (AlertEmail) | Оповещения по email — Отправлять оповещения по электронной почте. |
| AlertPush: issue push-notification alerts. (AlertPush) | Push-уведомления — Отправлять push-уведомления. |
| AlertArrows: draw chart arrows on alerts. (AlertArrows) | Стрелки оповещений — Отрисовывать стрелки на графике при оповещениях. |
| AlertCheckBar: which bar to check for alerts? (AlertCheckBar) | Проверяемый бар — Выбор бара для проверки оповещений: текущий или предыдущий. |
| AlertForValueArea: alerts for Value Area (VAH, VAL) rays. (AlertForValueArea) | Оповещения для зоны стоимости — Оповещения при пересечении лучей зоны стоимости (VAH, VAL). |
| AlertForMedian: alerts for POC (Median) rays' crossing. (AlertForMedian) | Оповещения для медианы — Оповещения при пересечении лучей медианы (POC). |
| AlertForSinglePrint: alerts for single print rays' crossing. (AlertForSinglePrint) | Оповещения для Single Print — Оповещения при пересечении лучей Single Print. |
| AlertOnPriceBreak: price breaking above/below the ray. (AlertOnPriceBreak) | Оповещение при пробое цены — Оповещать, когда цена пробивает уровень выше/ниже луча. |
| AlertOnCandleClose: candle closing above/below the ray. (AlertOnCandleClose) | Оповещение при закрытии свечи — Оповещать, когда свеча закрывается выше/ниже луча. |
| AlertOnGapCross: bar gap above/below the ray. (AlertOnGapCross) | Оповещение при разрыве — Оповещать, когда бар образует разрыв выше/ниже луча. |
| AlertArrowCodePB: arrow code for price break alerts. (AlertArrowCodePB) | Код стрелки для пробоя цены — Код стрелки для оповещений о пробое ценой уровня. |
| AlertArrowCodeCC: arrow code for candle close alerts. (AlertArrowCodeCC) | Код стрелки для закрытия свечи — Код стрелки для оповещений о закрытии свечи выше/ниже луча. |
| AlertArrowCodeGC: arrow code for gap crossover alerts. (AlertArrowCodeGC) | Код стрелки для разрыва — Код стрелки для оповещений о разрыве выше/ниже луча. |
| EnableIntradaySession1 | Включить внутридневную сессию 1 — Включить первую внутридневную сессию. |
| IntradaySession1StartTime | Время начала сессии 1 — Время начала первой внутридневной сессии. |
| IntradaySession1EndTime | Время окончания сессии 1 — Время окончания первой внутридневной сессии. |
| IntradaySession1ColorScheme | Цветовая схема сессии 1 — Цветовая схема для первой внутридневной сессии. |
| EnableIntradaySession2 | Включить внутридневную сессию 2 — Включить вторую внутридневную сессию. |
| IntradaySession2StartTime | Время начала сессии 2 — Время начала второй внутридневной сессии. |
| IntradaySession2EndTime | Время окончания сессии 2 — Время окончания второй внутридневной сессии. |
| IntradaySession2ColorScheme | Цветовая схема сессии 2 — Цветовая схема для второй внутридневной сессии. |
| EnableIntradaySession3 | Включить внутридневную сессию 3 — Включить третью внутридневную сессию. |
| IntradaySession3StartTime | Время начала сессии 3 — Время начала третьей внутридневной сессии. |
| IntradaySession3EndTime | Время окончания сессии 3 — Время окончания третьей внутридневной сессии. |
| IntradaySession3ColorScheme | Цветовая схема сессии 3 — Цветовая схема для третьей внутридневной сессии. |
| EnableIntradaySession4 | Включить внутридневную сессию 4 — Включить четвертую внутридневную сессию. |
| IntradaySession4StartTime | Время начала сессии 4 — Время начала четвертой внутридневной сессии. |
| IntradaySession4EndTime | Время окончания сессии 4 — Время окончания четвертой внутридневной сессии. |
| IntradaySession4ColorScheme | Цветовая схема сессии 4 — Цветовая схема для четвертой внутридневной сессии. |
| SaturdaySunday | Суббота и воскресенье — Обработка субботы и воскресенья: нормальные сессии, игнорировать или добавлять. |
| Disable alerts on wrong timeframes. (DisableAlertsOnWrongTimeframes) | Отключить оповещения на неправильных таймфреймах — Отключать оповещения на неподходящих таймфреймах. |
| Percentage of Median TPOs out of total for a Prominent one. (ProminentMedianPercentage) | Процент выделенной медианы — Процент TPO медианы от общего числа для выделения. |
Поиск по коду файла
???//+------------------------------------------------------------------+
#property version "1.19"
#property strict
#property description "Displays the Market Profile indicator for intraday, daily, weekly, or monthly trading sessions."
#property description "Daily - should be attached to M5-M30 timeframes. M30 is recommended."
#property description "Weekly - should be attached to M30-H4 timeframes. H1 is recommended."
#property description "Weeks start on Sunday."
#property description "Monthly - should be attached to H1-D1 timeframes. H4 is recommended."
#property description "Intraday - should be attached to M1-M15 timeframes. M5 is recommended.\r\n"
#property description "Designed for major currency pairs, but should work also with exotic pairs, CFDs, or commodities."
#property indicator_chart_window
#property indicator_plots 5
#property indicator_buffers 5
#property indicator_color1 clrGreen
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
#property indicator_color4 clrBlue
#property indicator_color5 clrYellow
#property indicator_width1 5
#property indicator_width2 5
#property indicator_width3 5
#property indicator_width4 5
#property indicator_width5 5
#property indicator_type1 DRAW_LINE
#property indicator_type2 DRAW_LINE
#property indicator_type3 DRAW_ARROW
#property indicator_type4 DRAW_ARROW
#property indicator_type5 DRAW_ARROW
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_label1 "Developing POC"
#property indicator_label2 "Developing POC"
#property indicator_label3 "Price break"
#property indicator_label4 "Candle close crossover"
#property indicator_label5 "Gap crossover"
enum color_scheme
{
Blue_to_Red, // Blue to Red
Red_to_Green, // Red to Green
Green_to_Blue, // Green to Blue
Yellow_to_Cyan, // Yellow to Cyan
Magenta_to_Yellow, // Magenta to Yellow
Cyan_to_Magenta, // Cyan to Magenta
Single_Color // Single Color
};
enum session_period
{
Daily,
Weekly,
Monthly,
Intraday,
Rectangle
};
enum sat_sun_solution
{
Saturday_Sunday_Normal_Days, // Normal sessions
Ignore_Saturday_Sunday, // Ignore Saturday and Sunday
Append_Saturday_Sunday // Append Saturday and Sunday
};
enum sessions_to_draw_rays
{
None,
Previous,
Current,
PreviousCurrent, // Previous & Current
AllPrevious, // All Previous
All
};
enum ways_to_stop_rays
{
Stop_No_Rays, // Stop no rays
Stop_All_Rays, // Stop all rays
Stop_All_Rays_Except_Prev_Session, // Stop all rays except previous session
Stop_Only_Previous_Session, // Stop only previous session's rays
};
enum bar_direction
{
Bullish,
Bearish,
Neutral
};
enum single_print_type
{
No,
Leftside,
Rightside
};
enum alert_check_bar
{
CheckCurrentBar, // Current
CheckPreviousBar // Previous
};
enum alert_types // Required to type a parameter of DoAlerts().
{
PriceBreak, // Price Break
CandleCloseCrossover, // Candle Close Crossover
GapCrossover // Gap Crossover
};
input group "Main"
input session_period Session = Daily;
input datetime StartFromDate = __DATE__; // StartFromDate: lower priority.
input bool StartFromCurrentSession = true; // StartFromCurrentSession: higher priority.
input int SessionsToCount = 5; // SessionsToCount: Number of sessions to count Market Profile.
input bool SeamlessScrollingMode = true; // SeamlessScrollingMode: show sessions on current screen.
input bool EnableDevelopingPOC = true; // Enable Developing POC.
input int ValueAreaPercentage = 70; // ValueAreaPercentage: Percentage of TPO's inside Value Area.
input group "Colors and looks"
input color_scheme ColorScheme = Blue_to_Red;
input color SingleColor = clrBlue; // SingleColor: if ColorScheme is set to Single_Color.
input bool ColorBullBear = false; // ColorBullBear: If true, colors are from bars' direction.
input color MedianColor = clrDarkGoldenrod;
input color ValueAreaSidesColor = clrDarkGreen;
input color ValueAreaHighLowColor = clrCrimson;
input ENUM_LINE_STYLE MedianStyle = STYLE_SOLID;
input ENUM_LINE_STYLE MedianRayStyle = STYLE_DASH;
input ENUM_LINE_STYLE ValueAreaSidesStyle = STYLE_SOLID;
input ENUM_LINE_STYLE ValueAreaHighLowStyle = STYLE_SOLID;
input ENUM_LINE_STYLE ValueAreaRayHighLowStyle= STYLE_DOT;
input int MedianWidth = 1;
input int MedianRayWidth = 1;
input int ValueAreaSidesWidth = 1;
input int ValueAreaHighLowWidth = 1;
input int ValueAreaRayHighLowWidth = 1;
input sessions_to_draw_rays ShowValueAreaRays = None; // ShowValueAreaRays: draw previous value area high/low rays.
input sessions_to_draw_rays ShowMedianRays = None; // ShowMedianRays: draw previous median rays.
input ways_to_stop_rays RaysUntilIntersection = Stop_No_Rays; // RaysUntilIntersection: which rays stop when hit another MP.
input bool HideRaysFromInvisibleSessions = false; // HideRaysFromInvisibleSessions: hide rays from behind the screen.
input int TimeShiftMinutes = 0; // TimeShiftMinutes: shift session + to the left, - to the right.
input bool ShowKeyValues = true; // ShowKeyValues: print out VAH, VAL, POC on chart.
input color KeyValuesColor = clrDarkGreen; // KeyValuesColor: color for VAH, VAL, POC printout.
input int KeyValuesSize = 8; // KeyValuesSize: font size for VAH, VAL, POC printout.
input single_print_type ShowSinglePrint = No; // ShowSinglePrint: mark Single Print profile levels.
input color SinglePrintColor = clrGold;
input bool SinglePrintRays = false; // SinglePrintRays: mark Single Print edges with rays.
input ENUM_LINE_STYLE SinglePrintRayStyle = STYLE_SOLID;
input int SinglePrintRayWidth = 1;
input color ProminentMedianColor = clrYellow;
input ENUM_LINE_STYLE ProminentMedianStyle = STYLE_SOLID;
input int ProminentMedianWidth = 4;
input bool RightToLeft = false; // RightToLeft: Draw histogram from right to left.
input group "Performance"
input int PointMultiplier = 0; // PointMultiplier: higher value = fewer objects. 0 - adaptive.
input int ThrottleRedraw = 0; // ThrottleRedraw: delay (in seconds) for updating Market Profile.
input bool DisableHistogram = false; // DisableHistogram: do not draw profile, VAH, VAL, and POC still visible.
input group "Alerts"
input bool AlertNative = false; // AlertNative: issue native pop-up alerts.
input bool AlertEmail = false; // AlertEmail: issue email alerts.
input bool AlertPush = false; // AlertPush: issue push-notification alerts.
input bool AlertArrows = false; // AlertArrows: draw chart arrows on alerts.
input alert_check_bar AlertCheckBar = CheckCurrentBar; // AlertCheckBar: which bar to check for alerts?
input bool AlertForValueArea = false; // AlertForValueArea: alerts for Value Area (VAH, VAL) rays.
input bool AlertForMedian = false; // AlertForMedian: alerts for POC (Median) rays' crossing.
input bool AlertForSinglePrint = false; // AlertForSinglePrint: alerts for single print rays' crossing.
input bool AlertOnPriceBreak = false; // AlertOnPriceBreak: price breaking above/below the ray.
input bool AlertOnCandleClose = false; // AlertOnCandleClose: candle closing above/below the ray.
input bool AlertOnGapCross = false; // AlertOnGapCross: bar gap above/below the ray.
input int AlertArrowCodePB = 108; // AlertArrowCodePB: arrow code for price break alerts.
input int AlertArrowCodeCC = 110; // AlertArrowCodeCC: arrow code for candle close alerts.
input int AlertArrowCodeGC = 117; // AlertArrowCodeGC: arrow code for gap crossover alerts.
input group "Intraday settings"
input bool EnableIntradaySession1 = true;
input string IntradaySession1StartTime = "00:00";
input string IntradaySession1EndTime = "06:00";
input color_scheme IntradaySession1ColorScheme = Blue_to_Red;
input bool EnableIntradaySession2 = true;
input string IntradaySession2StartTime = "06:00";
input string IntradaySession2EndTime = "12:00";
input color_scheme IntradaySession2ColorScheme = Red_to_Green;
input bool EnableIntradaySession3 = true;
input string IntradaySession3StartTime = "12:00";
input string IntradaySession3EndTime = "18:00";
input color_scheme IntradaySession3ColorScheme = Green_to_Blue;
input bool EnableIntradaySession4 = true;
input string IntradaySession4StartTime = "18:00";
input string IntradaySession4EndTime = "00:00";
input color_scheme IntradaySession4ColorScheme = Yellow_to_Cyan;
input group "Miscellaneous"
input sat_sun_solution SaturdaySunday = Saturday_Sunday_Normal_Days;
input bool DisableAlertsOnWrongTimeframes = false; // Disable alerts on wrong timeframes.
input int ProminentMedianPercentage = 101; // Percentage of Median TPOs out of total for a Prominent one.
int PointMultiplier_calculated; // Will have to be calculated based number digits in a quote if PointMultiplier input is 0.
int DigitsM; // Number of digits normalized based on PointMultiplier_calculated.
bool InitFailed; // Used for soft INIT_FAILED. Hard INIT_FAILED resets input parameters.
datetime StartDate; // Will hold either StartFromDate or Time[0].
double onetick; // One normalized pip.
bool FirstRunDone = false; // If true - OnCalculate() was already executed once.
string Suffix = "_"; // Will store object name suffix depending on timeframe.
color_scheme CurrentColorScheme; // Required due to intraday sessions.
int Max_number_of_bars_in_a_session = 1;
int Timer = 0; // For throttling updates of market profiles in slow systems.
bool NeedToRestartDrawing = false; // Global flag for RightToLeft redrawing;
int CleanedUpOn = 0; // To prevent cleaning up the buffers again and again when the platform just starts.
double ValueAreaPercentage_double = 0.7; // Will be calculated based on the input parameter in OnInit().
datetime LastAlertTime_CandleCross = 0, LastAlertTime_GapCross = 0; // For CheckCurrentBar alerts.
datetime LastAlertTime = 0; // For CheckPreviousBar alerts;
double Close_prev = EMPTY_VALUE; // Previous price value for Price Break alerts.
bar_direction CurrentBarDirection = Neutral;
bar_direction PreviousBarDirection = Neutral;
bool NeedToReviewColors = false;
int IDStartHours[4];
int IDStartMinutes[4];
int IDStartTime[4]; // Stores IDStartHours x 60 + IDStartMinutes for comparison purposes.
int IDEndHours[4];
int IDEndMinutes[4];
int IDEndTime[4]; // Stores IDEndHours x 60 + IDEndMinutes for comparison purposes.
color_scheme IDColorScheme[4];
bool IntradayCheckPassed = false;
int IntradaySessionCount = 0;
int _SessionsToCount;
int IntradayCrossSessionDefined = -1; // For special case used only with Ignore_Saturday_Sunday on Monday.
double RememberSessionMax[], RememberSessionMin[];
datetime RememberSessionStart[];
string RememberSessionSuffix[];
int SessionsNumber = 0; // Different from _SessionsToCount when working with Intraday sessions and for RaysUntilIntersection != Stop_No_Rays.
class CRectangleMP
{
private:
datetime prev_Time0;
double prev_High, prev_Low;
double prev_RectanglePriceMax, prev_RectanglePriceMin;
int Number; // Order number of the rectangle;
public:
double RectanglePriceMax, RectanglePriceMin;
datetime RectangleTimeMax, RectangleTimeMin;
datetime t1, t2; // To avoid reading object properties in Process() after sorting was done.
string name;
CRectangleMP(string);
~CRectangleMP(void) {};
void Process(int);
};
CRectangleMP* MPR_Array[];
int mpr_total = 0;
uint LastRecalculationTime = 0;
double DevelopingPOC_1[], DevelopingPOC_2[]; // Indicator buffers for Developing POC.
double ArrowsPB[], ArrowsCC[], ArrowsGC[]; // Indicator buffers for alert arrows.
int OnInit()
{
// код доступен только после оплаты
}
void OnDeinit(const int reason)
{
if (Session == Rectangle)
{
for (int i = 0; i < mpr_total; i++)
{
ObjectCleanup(MPR_Array[i].name + "_");
delete MPR_Array[i];
}
}
else ObjectCleanup();
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time_timeseries[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[]
)
{
// код доступен только после оплаты
}
int FindSessionStart(const int n)
{
if (Session == Daily) return FindDayStart(n);
else if (Session == Weekly) return FindWeekStart(n);
else if (Session == Monthly) return FindMonthStart(n);
else if (Session == Intraday)
{
if ((SaturdaySunday == Append_Saturday_Sunday) && (TimeDayOfWeek(Time[n] + TimeShiftMinutes * 60) == 1))
{
for (int intraday_i = 0; intraday_i < IntradaySessionCount; intraday_i++)
{
if ((IDStartTime[intraday_i] == 0) || (IDStartTime[intraday_i] > IDEndTime[intraday_i]))
{
if ((TimeHour(Time[n]) * 60 + TimeMinute(Time[n]) >= IDEndTime[intraday_i]) && (IDStartTime[intraday_i] > IDEndTime[intraday_i]))
{
int x = n;
while ((x < Bars) && (TimeHour(Time[x]) * 60 + TimeMinute(Time[x]) >= IDEndTime[intraday_i]))
{
x++;
if (TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60) > 1) return FindDayStart(n);
}
return (x - 1);
}
else
{
int x = n;
while ((x < Bars) && ((TimeDayOfYear(Time[n] + TimeShiftMinutes * 60) == TimeDayOfYear(Time[x] + TimeShiftMinutes * 60)) || (TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60) == 0))) x++;
_SessionsToCount++;
return (x - 1);
}
}
}
}
return FindDayStart(n);
}
return -1;
}
int FindDayStart(const int n)
{
if (n >= Bars) return -1;
int x = n;
int time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
int time_n_day_of_week = time_x_day_of_week;
while ((TimeDayOfYear(Time[n] + TimeShiftMinutes * 60) == TimeDayOfYear(Time[x] + TimeShiftMinutes * 60)) || ((SaturdaySunday == Append_Saturday_Sunday) && ((time_x_day_of_week == 0) || ((time_x_day_of_week == 5) && (time_n_day_of_week == 6)))))
{
x++;
if (x >= Bars) break;
time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
}
return (x - 1);
}
int FindWeekStart(const int n)
{
if (n >= Bars) return -1;
int x = n;
int time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
while ((SameWeek(Time[n] + TimeShiftMinutes * 60, Time[x] + TimeShiftMinutes * 60)) || ((SaturdaySunday == Append_Saturday_Sunday) && (time_x_day_of_week == 0)))
{
if ((SaturdaySunday == Ignore_Saturday_Sunday) && (time_x_day_of_week == 0)) break;
x++;
if (x >= Bars) break;
time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
}
return (x - 1);
}
int FindMonthStart(const int n)
{
if (n >= Bars) return -1;
int x = n;
int time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
int time_n_day_of_week = TimeDayOfWeek(Time[n] + TimeShiftMinutes * 60);
int time_n_day = TimeDay(Time[n] + TimeShiftMinutes * 60);
int time_n_month = TimeMonth(Time[n] + TimeShiftMinutes * 60);
while ((time_n_month == TimeMonth(Time[x] + TimeShiftMinutes * 60)) || ((SaturdaySunday == Append_Saturday_Sunday) && ((time_x_day_of_week == 0) || ((time_n_day_of_week == 6) && (time_n_day == 1)))))
{
int month_distance = time_n_month - TimeMonth(Time[x] + TimeShiftMinutes * 60);
if (month_distance < 0) month_distance = 12 - month_distance;
if (month_distance > 1) break;
if (SaturdaySunday == Append_Saturday_Sunday)
{
if ((time_x_day_of_week == 6) && (TimeDay(Time[x] + TimeShiftMinutes * 60) == 1) && (time_n_day != TimeDay(Time[x] + TimeShiftMinutes * 60))) break;
}
if (SaturdaySunday == Ignore_Saturday_Sunday)
{
if (((time_x_day_of_week == 0) || (time_x_day_of_week == 6)) && ((TimeDay(Time[x] + TimeShiftMinutes * 60) == 1) || (TimeDay(Time[x] + TimeShiftMinutes * 60) == 2))) break;
}
x++;
if (x >= Bars) break;
time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
}
return (x - 1);
}
int FindSessionEndByDate(const datetime date)
{
if (Session == Daily) return FindDayEndByDate(date);
else if (Session == Weekly) return FindWeekEndByDate(date);
else if (Session == Monthly) return FindMonthEndByDate(date);
else if (Session == Intraday)
{
if ((SaturdaySunday == Append_Saturday_Sunday) && (TimeDayOfWeek(date + TimeShiftMinutes * 60) == 0))
{
for (int intraday_i = 0; intraday_i < IntradaySessionCount; intraday_i++)
{
if ((IDStartTime[intraday_i] == 0) || (IDStartTime[intraday_i] > IDEndTime[intraday_i]))
{
int x = 0;
int abs_day = TimeAbsoluteDay(date + TimeShiftMinutes * 60);
while ((x < Bars) && (abs_day < TimeAbsoluteDay(Time[x] + TimeShiftMinutes * 60))) // It's Sunday.
{
if (TimeAbsoluteDay(Time[x] + TimeShiftMinutes * 60) == abs_day + 1)
{
if (TimeHour(Time[x]) * 60 + TimeMinute(Time[x]) < IDEndTime[intraday_i]) break;
if (IDStartTime[intraday_i] == 0) break;
}
x++;
}
return x;
}
}
}
return FindDayEndByDate(date);
}
return -1;
}
int FindDayEndByDate(const datetime date)
{
int x = 0;
while ((x < Bars) && (TimeAbsoluteDay(date + TimeShiftMinutes * 60) < TimeAbsoluteDay(Time[x] + TimeShiftMinutes * 60)))
{
if (SaturdaySunday == Append_Saturday_Sunday)
{
if (((TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60) == 6) || (TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60) == 1)) && (TimeAbsoluteDay(Time[x] + TimeShiftMinutes * 60) - TimeAbsoluteDay(date + TimeShiftMinutes * 60) == 1)) break;
}
x++;
}
return x;
}
int FindWeekEndByDate(const datetime date)
{
int x = 0;
int time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
while ((SameWeek(date + TimeShiftMinutes * 60, Time[x] + TimeShiftMinutes * 60) != true) || ((SaturdaySunday == Append_Saturday_Sunday) && (time_x_day_of_week == 0)) || ((SaturdaySunday == Ignore_Saturday_Sunday) && ((time_x_day_of_week == 0) || (time_x_day_of_week == 6))))
{
x++;
if (x >= Bars) break;
time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
}
return x;
}
int FindMonthEndByDate(const datetime date)
{
int x = 0;
int time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
while ((SameMonth(date + TimeShiftMinutes * 60, Time[x] + TimeShiftMinutes * 60) != true) || ((SaturdaySunday == Append_Saturday_Sunday) && (time_x_day_of_week == 0)) || ((SaturdaySunday == Ignore_Saturday_Sunday) && ((time_x_day_of_week == 0) || (time_x_day_of_week == 6))))
{
if (SaturdaySunday == Append_Saturday_Sunday)
{
if ((time_x_day_of_week == 6) && (TimeDay(Time[x] + TimeShiftMinutes * 60) == 1) && (TimeYear(Time[x] + TimeShiftMinutes * 60) * 12 + TimeMonth(Time[x] + TimeShiftMinutes * 60) - TimeYear(date + TimeShiftMinutes * 60) * 12 - TimeMonth(date + TimeShiftMinutes * 60) == 1)) break;
if ((TimeDayOfWeek(date + TimeShiftMinutes * 60) == 0) && (TimeYear(Time[x] + TimeShiftMinutes * 60) * 12 + TimeMonth(Time[x] + TimeShiftMinutes * 60) - TimeYear(date + TimeShiftMinutes * 60) * 12 - TimeMonth(date + TimeShiftMinutes * 60) == 1)) break;
}
x++;
if (x >= Bars) break;
time_x_day_of_week = TimeDayOfWeek(Time[x] + TimeShiftMinutes * 60);
}
return x;
}
int SameWeek(const datetime date1, const datetime date2)
{
int seconds_from_start = TimeDayOfWeek(date1) * 24 * 3600 + TimeHour(date1) * 3600 + TimeMinute(date1) * 60 + TimeSeconds(date1);
if (date1 == date2) return true;
else if (date2 < date1)
{
if (date1 - date2 <= seconds_from_start) return true;
}
else if (date2 - date1 < 604800 - seconds_from_start) return true;
return false;
}
int SameMonth(const datetime date1, const datetime date2)
{
if ((TimeMonth(date1) == TimeMonth(date2)) && (TimeYear(date1) == TimeYear(date2))) return true;
return false;
}
datetime PutDot(const double price, const int start_bar, const int range, const int bar, string rectangle_prefix = "", datetime converted_time = 0)
{
double divisor, color_shift;
int colour = -1;
string LastNameStart = " " + TimeToString(Time[bar + start_bar]) + " ";
string LastName = LastNameStart + DoubleToString(price, _Digits);
if (ColorBullBear) colour = CalculateProperColor();
if (NeedToReviewColors)
{
int obj_total = ObjectsTotal(ChartID(), -1, OBJ_RECTANGLE);
for (int i = obj_total - 1; i >= 0; i--)
{
string obj = ObjectName(ChartID(), i, -1, OBJ_RECTANGLE);
if (StringSubstr(obj, 0, StringLen(rectangle_prefix + "MP" + Suffix)) != rectangle_prefix + "MP" + Suffix) continue;
if (StringSubstr(obj, 0, StringLen(rectangle_prefix + "MP" + Suffix + LastNameStart)) != rectangle_prefix + "MP" + Suffix + LastNameStart) break;
ObjectSetInteger(0, obj, OBJPROP_COLOR, colour);
}
}
if (ObjectFind(0, rectangle_prefix + "MP" + Suffix + LastName) >= 0)
{
if ((!RightToLeft) || (converted_time == 0)) return 0; // Normal case;
}
datetime time_end, time_start;
datetime prev_time = converted_time; // For drawing, we need two times.
if (converted_time != 0) // This is the right-to-left mode and the right-most session.
{
static datetime prev_time_start_bar = 0;
if ((Time[start_bar] != prev_time_start_bar) && (prev_time_start_bar != 0)) // New right-most session arrived - recalculate everything.
{
NeedToRestartDrawing = true;
}
prev_time_start_bar = Time[start_bar];
int x = -1;
for (int i = range + 1; i > 0; i--) // + 1 to get a bit "lefter" time in converted_time, and actual dot's time into prev_time.
{
prev_time = converted_time;
if (converted_time == Time[0]) // First time stepped into existing candles.
{
x = i + 1; // Remember the position.
converted_time = Time[1]; // Move further.
}
else if (converted_time < Time[0])
{
if (x == -1) x = iBarShift(Symbol(), Period(), converted_time) + i + 1;
converted_time = Time[x - i]; // While inside the existing candles, use existing Time for candles.
}
else converted_time -= PeriodSeconds(); // While beyond the current candle, subtract fixed time periods to move left on the time scale.
}
time_end = converted_time;
time_start = prev_time;
}
else
{
if (start_bar - (range + 1) < 0) time_end = Time[0] + PeriodSeconds(); // Protection from 'Array out of range' error.
else time_end = Time[start_bar - (range + 1)];
time_start = Time[start_bar - range];
}
if (ObjectFind(0, rectangle_prefix + "MP" + Suffix + LastName) >= 0) // Need to move the rectangle.
{
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_TIME, 0, time_start);
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_TIME, 1, time_end);
}
else ObjectCreate(0, rectangle_prefix + "MP" + Suffix + LastName, OBJ_RECTANGLE, 0, time_start, price, time_end, price - onetick);
if (!ColorBullBear) // Otherwise, colour is already calculated.
{
int offset1, offset2;
switch (CurrentColorScheme)
{
case Blue_to_Red:
colour = 0xFF0000; // clrBlue;
offset1 = 0x030000;
offset2 = 0x000003;
break;
case Red_to_Green:
colour = 0x0000FF; // clrDarkRed;
offset1 = 0x000003;
offset2 = 0x000300;
break;
case Green_to_Blue:
colour = 0x00FF00; // clrDarkGreen;
offset1 = 0x000300;
offset2 = 0x030000;
break;
case Yellow_to_Cyan:
colour = 0x00FFFF; // clrYellow;
offset1 = 0x000003;
offset2 = 0x030000;
break;
case Magenta_to_Yellow:
colour = 0xFF00FF; // clrMagenta;
offset1 = 0x030000;
offset2 = 0x000300;
break;
case Cyan_to_Magenta:
colour = 0xFFFF00; // clrCyan;
offset1 = 0x000300;
offset2 = 0x000003;
break;
case Single_Color:
colour = SingleColor;
offset1 = 0;
offset2 = 0;
break;
default:
colour = SingleColor;
offset1 = 0;
offset2 = 0;
break;
}
if (CurrentColorScheme != Single_Color)
{
divisor = 3.0 / 0xFF * (double)Max_number_of_bars_in_a_session;
color_shift = MathFloor((double)bar / divisor);
if ((int)color_shift < -85) color_shift = -85;
colour += (int)color_shift * offset1;
colour -= (int)color_shift * offset2;
}
}
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_COLOR, colour);
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_BACK, true);
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "MP" + Suffix + LastName, OBJPROP_HIDDEN, true);
return time_end;
}
void ObjectCleanup(string rectangle_prefix = "")
{
ObjectsDeleteAll(0, rectangle_prefix + "MP" + Suffix, EMPTY, OBJ_RECTANGLE);
ObjectsDeleteAll(0, rectangle_prefix + "Median" + Suffix, EMPTY, OBJ_TREND);
ObjectsDeleteAll(0, rectangle_prefix + "VA_LeftSide" + Suffix, EMPTY, OBJ_TREND);
ObjectsDeleteAll(0, rectangle_prefix + "VA_RightSide" + Suffix, EMPTY, OBJ_TREND);
ObjectsDeleteAll(0, rectangle_prefix + "VA_Top" + Suffix, EMPTY, OBJ_TREND);
ObjectsDeleteAll(0, rectangle_prefix + "VA_Bottom" + Suffix, EMPTY, OBJ_TREND);
if (ShowValueAreaRays != None)
{
ObjectsDeleteAll(0, rectangle_prefix + "Value Area HighRay" + Suffix, EMPTY, OBJ_TREND);
ObjectsDeleteAll(0, rectangle_prefix + "Value Area LowRay" + Suffix, EMPTY, OBJ_TREND);
}
if (ShowMedianRays != None)
{
ObjectsDeleteAll(0, rectangle_prefix + "Median Ray" + Suffix, EMPTY, OBJ_TREND);
}
if (ShowKeyValues)
{
ObjectsDeleteAll(0, rectangle_prefix + "VAH" + Suffix, EMPTY, OBJ_TEXT);
ObjectsDeleteAll(0, rectangle_prefix + "VAL" + Suffix, EMPTY, OBJ_TEXT);
ObjectsDeleteAll(0, rectangle_prefix + "POC" + Suffix, EMPTY, OBJ_TEXT);
}
if (ShowSinglePrint)
{
ObjectsDeleteAll(0, rectangle_prefix + "MPSP" + Suffix, EMPTY, OBJ_RECTANGLE);
}
if (SinglePrintRays)
{
ObjectsDeleteAll(0, rectangle_prefix + "MPSPR" + Suffix, EMPTY, OBJ_TREND);
}
}
bool GetHoursAndMinutes(string time_string, int& hours, int& minutes, int& time)
{
if (StringLen(time_string) == 4) time_string = "0" + time_string;
if (
(StringLen(time_string) != 5) ||
(time_string[2] != ':') ||
((time_string[0] < '0') || (time_string[0] > '2')) ||
(((time_string[0] == '0') || (time_string[0] == '1')) && ((time_string[1] < '0') || (time_string[1] > '9'))) ||
((time_string[0] == '2') && ((time_string[1] < '0') || (time_string[1] > '3'))) ||
((time_string[3] < '0') || (time_string[3] > '5')) ||
((time_string[4] < '0') || (time_string[4] > '9'))
)
{
Print("Wrong time string: ", time_string, ". Please use HH:MM format.");
return false;
}
string result[];
int number_of_substrings = StringSplit(time_string, ':', result);
hours = (int)StringToInteger(result[0]);
minutes = (int)StringToInteger(result[1]);
time = hours * 60 + minutes;
return true;
}
bool CheckIntradaySession(const bool enable, const string start_time, const string end_time, const color_scheme cs)
{
if (enable)
{
if (!GetHoursAndMinutes(start_time, IDStartHours[IntradaySessionCount], IDStartMinutes[IntradaySessionCount], IDStartTime[IntradaySessionCount]))
{
Alert("Wrong time string format: ", start_time, ".");
return false;
}
if (!GetHoursAndMinutes(end_time, IDEndHours[IntradaySessionCount], IDEndMinutes[IntradaySessionCount], IDEndTime[IntradaySessionCount]))
{
Alert("Wrong time string format: ", end_time, ".");
return false;
}
if (IDEndTime[IntradaySessionCount] == 0)
{
IDEndHours[IntradaySessionCount] = 24;
IDEndMinutes[IntradaySessionCount] = 0;
IDEndTime[IntradaySessionCount] = 24 * 60;
}
IDColorScheme[IntradaySessionCount] = cs;
if (IDEndTime[IntradaySessionCount] < IDStartTime[IntradaySessionCount]) IntradayCrossSessionDefined = IntradaySessionCount;
IntradaySessionCount++;
}
return true;
}
bool ProcessSession(const int sessionstart, const int sessionend, const int i, CRectangleMP* rectangle = NULL)
{
string rectangle_prefix = ""; // Only for rectangle sessions.
if (sessionstart >= Bars) return false; // Data not yet ready.
double SessionMax = DBL_MIN, SessionMin = DBL_MAX;
for (int bar = sessionstart; bar >= sessionend; bar--)
{
if (High[bar] > SessionMax) SessionMax = High[bar];
if (Low[bar] < SessionMin) SessionMin = Low[bar];
}
SessionMax = NormalizeDouble(SessionMax, DigitsM);
SessionMin = NormalizeDouble(SessionMin, DigitsM);
int session_counter = i;
if (Session == Rectangle)
{
rectangle_prefix = rectangle.name + "_";
if (SessionMax > rectangle.RectanglePriceMax) SessionMax = NormalizeDouble(rectangle.RectanglePriceMax, DigitsM);
if (SessionMin < rectangle.RectanglePriceMin) SessionMin = NormalizeDouble(rectangle.RectanglePriceMin, DigitsM);
}
else
{
bool need_to_increment = true;
for (int j = 0; j < SessionsNumber; j++)
{
if (RememberSessionStart[j] == Time[sessionstart])
{
need_to_increment = false;
session_counter = j; // Real number of the session.
break;
}
}
if (need_to_increment)
{
SessionsNumber++;
session_counter = SessionsNumber - 1; // Newest session.
ArrayResize(RememberSessionMax, SessionsNumber);
ArrayResize(RememberSessionMin, SessionsNumber);
ArrayResize(RememberSessionStart, SessionsNumber);
ArrayResize(RememberSessionSuffix, SessionsNumber);
}
}
SessionMax = NormalizeDouble(MathRound(SessionMax / onetick) * onetick, DigitsM);
SessionMin = NormalizeDouble(MathRound(SessionMin / onetick) * onetick, DigitsM);
RememberSessionMax[session_counter] = SessionMax;
RememberSessionMin[session_counter] = SessionMin;
RememberSessionStart[session_counter] = Time[sessionstart];
RememberSessionSuffix[session_counter] = Suffix;
static double PreviousSessionMax = DBL_MIN;
static datetime PreviousSessionStartTime = 0;
if (Time[sessionstart] > PreviousSessionStartTime)
{
PreviousSessionMax = DBL_MIN;
PreviousSessionStartTime = Time[sessionstart];
}
if ((FirstRunDone) && (i == _SessionsToCount - 1) && (PointMultiplier_calculated > 1)) // Updating the latest trading session.
{
if (SessionMax - PreviousSessionMax < onetick) // SessionMax increased only slightly - too small to use the new value with the current onetick.
{
SessionMax = PreviousSessionMax; // Do not update session max.
}
else
{
if (PreviousSessionMax != DBL_MIN)
{
double nc = (SessionMax - PreviousSessionMax) / onetick;
SessionMax = NormalizeDouble(PreviousSessionMax + MathRound(nc) * onetick, DigitsM);
}
PreviousSessionMax = SessionMax;
}
}
int TPOperPrice[];
int max = (int)MathRound((SessionMax - SessionMin) / onetick + 2); // + 2 because further we will be possibly checking array at SessionMax + 1.
ArrayResize(TPOperPrice, max);
ArrayInitialize(TPOperPrice, 0);
bool SinglePrintTracking_array[]; // For SinglePrint rays.
if (SinglePrintRays)
{
ArrayResize(SinglePrintTracking_array, max);
ArrayInitialize(SinglePrintTracking_array, false);
}
int MaxRange = 0; // Maximum distance from session start to the drawn dot.
double PriceOfMaxRange = 0; // Level of the maximum range, required to draw Median.
double DistanceToCenter = DBL_MAX; // Closest distance to center for the Median.
datetime converted_time = 0;
datetime converted_end_time = 0;
datetime min_converted_end_time = UINT_MAX;
if ((RightToLeft) && ((sessionend == 0) || (Session == Rectangle)))
{
int dummy_subwindow;
double dummy_price;
if (Session == Rectangle) converted_time = rectangle.RectangleTimeMax;
else ChartXYToTimePrice(0, (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS), 0, dummy_subwindow, converted_time, dummy_price);
}
int TotalTPO = 0; // Total amount of dots (TPO's).
for (double price = SessionMax; price >= SessionMin; price -= onetick)
{
price = NormalizeDouble(price, DigitsM);
int range = 0; // Distance from first bar to the current bar.
for (int bar = sessionstart; bar >= sessionend; bar--)
{
if ((price >= Low[bar]) && (price <= High[bar]))
{
if ((MaxRange < range) || ((MaxRange == range) && (MathAbs(price - (SessionMin + (SessionMax - SessionMin) / 2)) < DistanceToCenter)))
{
MaxRange = range;
PriceOfMaxRange = price;
DistanceToCenter = MathAbs(price - (SessionMin + (SessionMax - SessionMin) / 2));
}
if (!DisableHistogram)
{
if (ColorBullBear)
{
if (Close[bar] == Open[bar]) CurrentBarDirection = Neutral;
else if (Close[bar] > Open[bar]) CurrentBarDirection = Bullish;
else if (Close[bar] < Open[bar]) CurrentBarDirection = Bearish;
if (bar == 0)
{
if (PreviousBarDirection == CurrentBarDirection) NeedToReviewColors = false;
else
{
NeedToReviewColors = true;
PreviousBarDirection = CurrentBarDirection;
}
}
}
if (!RightToLeft) PutDot(price, sessionstart, range, bar - sessionstart, rectangle_prefix);
else
{
converted_end_time = PutDot(price, sessionstart, range, bar - sessionstart, rectangle_prefix, converted_time);
if (converted_end_time < min_converted_end_time) min_converted_end_time = converted_end_time; // Find the leftmost time to use for the left border of the value area.
}
}
int index = (int)MathRound((price - SessionMin) / onetick);
TPOperPrice[index]++;
range++;
TotalTPO++;
}
}
if (ShowSinglePrint)
{
if (range == 1) PutSinglePrintMark(price, sessionstart, rectangle_prefix);
else if (range > 1) RemoveSinglePrintMark(price, sessionstart, rectangle_prefix); // Remove single print max if it exists.
}
if (SinglePrintRays)
{
int index = (int)MathRound((price - SessionMin) / onetick);
if (range == 1) SinglePrintTracking_array[index] = true; // Remember the single print's position relative to the price.
else SinglePrintTracking_array[index] = false;
}
}
if (SinglePrintRays)
{
color spr_color = SinglePrintColor; // Normal ray color.
if ((HideRaysFromInvisibleSessions) && (Time[WindowFirstVisibleBar()] >= Time[sessionstart])) spr_color = clrNONE; // Hide rays if behind the screen.
for (double price = SessionMax; price >= SessionMin; price -= onetick)
{
price = NormalizeDouble(price, DigitsM);
int index = (int)MathRound((price - SessionMin) / onetick);
if (SinglePrintTracking_array[index])
{
if (price == SessionMax) // Top of the session.
{
PutSinglePrintRay(price, sessionstart, rectangle_prefix, spr_color);
}
else
{
if (SinglePrintTracking_array[index + 1] == false) // Above is a non-single print.
{
PutSinglePrintRay(price, sessionstart, rectangle_prefix, spr_color);
}
else
{
RemoveSinglePrintRay(price, sessionstart, rectangle_prefix);
}
}
if (price == SessionMin) // Bottom of the session.
{
PutSinglePrintRay(price - onetick, sessionstart, rectangle_prefix, spr_color);
}
else
{
if (SinglePrintTracking_array[index - 1] == false) // Below is a non-single print.
{
PutSinglePrintRay(price - onetick, sessionstart, rectangle_prefix, spr_color);
}
else
{
RemoveSinglePrintRay(price - onetick, sessionstart, rectangle_prefix);
}
}
}
else
{
RemoveSinglePrintRay(price - onetick, sessionstart, rectangle_prefix);
}
}
}
if (EnableDevelopingPOC) CalculateDevelopingPOC(sessionstart, sessionend, rectangle); // Developing POC if necessary.
double TotalTPOdouble = TotalTPO;
int ValueControlTPO = (int)MathRound(TotalTPOdouble * ValueAreaPercentage_double);
int index = (int)((PriceOfMaxRange - SessionMin) / onetick);
if (index < 0) return false; // Data not yet ready.
int TPOcount = TPOperPrice[index];
int up_offset = 1;
int down_offset = 1;
while (TPOcount < ValueControlTPO)
{
double abovePrice = PriceOfMaxRange + up_offset * onetick;
double belowPrice = PriceOfMaxRange - down_offset * onetick;
index = (int)MathRound((abovePrice - SessionMin) / onetick);
int index2 = (int)MathRound((belowPrice - SessionMin) / onetick);
if (((belowPrice < SessionMin) || (TPOperPrice[index] >= TPOperPrice[index2])) && (abovePrice <= SessionMax))
{
TPOcount += TPOperPrice[index];
up_offset++;
}
else if (belowPrice >= SessionMin)
{
TPOcount += TPOperPrice[index2];
down_offset++;
}
else if (TPOcount < ValueControlTPO)
{
break;
}
}
string LastName = " " + TimeToString(Time[sessionstart]);
ObjectDelete(rectangle_prefix + "Median" + Suffix + LastName);
index = MathMax(sessionstart - MaxRange - 1, 0);
datetime time_start, time_end;
if ((RightToLeft) && ((sessionend == 0) || (Session == Rectangle)))
{
time_end = min_converted_end_time;
time_start = converted_time;
}
else
{
time_end = Time[index];
time_start = Time[sessionstart];
}
ObjectCreate(0, rectangle_prefix + "Median" + Suffix + LastName, OBJ_TREND, 0, time_start, PriceOfMaxRange, time_end, PriceOfMaxRange);
color mc = MedianColor;
if ((double)(sessionstart - index) / (double)Max_number_of_bars_in_a_session * 100 >= ProminentMedianPercentage)
{
mc = ProminentMedianColor;
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_WIDTH, ProminentMedianWidth);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_STYLE, ProminentMedianStyle);
}
else
{
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_WIDTH, MedianWidth);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_STYLE, MedianStyle);
}
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_COLOR, mc);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_BACK, false);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, rectangle_prefix + "Median" + Suffix + LastName, OBJPROP_RAY, false);
ObjectDelete(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName);
ObjectCreate(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJ_TREND, 0, time_start, PriceOfMaxRange + up_offset * onetick, time_start, PriceOfMaxRange - down_offset * onetick + onetick);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_COLOR, ValueAreaSidesColor);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_STYLE, ValueAreaSidesStyle);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_WIDTH, ValueAreaSidesWidth);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_BACK, false);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, rectangle_prefix + "VA_LeftSide" + Suffix + LastName, OBJPROP_RAY, false);
ObjectDelete(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName);
ObjectCreate(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJ_TREND, 0, time_end, PriceOfMaxRange + up_offset * onetick, time_end, PriceOfMaxRange - down_offset * onetick + onetick);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_COLOR, ValueAreaSidesColor);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_STYLE, ValueAreaSidesStyle);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_WIDTH, ValueAreaSidesWidth);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_BACK, false);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, rectangle_prefix + "VA_RightSide" + Suffix + LastName, OBJPROP_RAY, false);
ObjectDelete(0, rectangle_prefix + "VA_Top" + Suffix + LastName);
ObjectCreate(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJ_TREND, 0, time_start, PriceOfMaxRange + up_offset * onetick, time_end, PriceOfMaxRange + up_offset * onetick);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_COLOR, ValueAreaHighLowColor);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_STYLE, ValueAreaHighLowStyle);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_WIDTH, ValueAreaHighLowWidth);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_BACK, false);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, rectangle_prefix + "VA_Top" + Suffix + LastName, OBJPROP_RAY, false);
ObjectDelete(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName);
ObjectCreate(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJ_TREND, 0, time_start, PriceOfMaxRange - down_offset * onetick + onetick, time_end, PriceOfMaxRange - down_offset * onetick + onetick); // Adding onetick to put the value area bottom border to its real location as PriceOfMaxRange - down_offset * onetick puts it just below the bottom TPO, which itself is 1 tick deep.
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_COLOR, ValueAreaHighLowColor);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_STYLE, ValueAreaHighLowStyle);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_WIDTH, ValueAreaHighLowWidth);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_BACK, false);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, rectangle_prefix + "VA_Bottom" + Suffix + LastName, OBJPROP_RAY, false);
if (ShowKeyValues)
{
ENUM_ANCHOR_POINT anchor_poc = ANCHOR_RIGHT, anchor_va = ANCHOR_RIGHT;
if ((RightToLeft) && ((sessionend == 0) || (Session == Rectangle)))
{
time_start = time_end; // Inverting label display position.
if (((Session != Rectangle) && ((ShowValueAreaRays == All) || (ShowValueAreaRays == Current) || (ShowValueAreaRays == PreviousCurrent))) // For non-rectangle sessions, it is already known that it is the current session, so just check if current session uses rays.
|| ((Session == Rectangle) && ( // For rectangles, need to check whichПоказано первые 50% кода (символов: 82978)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.