← К каталогу
Исходный код · ID 4345

valuearealevelsbhanucodelab.mq5

Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Индикатор для MetaTrader 5, рассчитывающий и отображающий уровни Value Area High (VAH), Point of Control (POC) и Value Area Low (VAL) для торговых сессий. Поддерживает расчёт текущей развивающейся зоны, предыдущей завершённой сессии и исторических профилей. Использует данные текущего таймфрейма графика для построения профилей на выбранном периоде.

Настройки программы

НастройкаОписание
Unique chart object prefix (InpObjectPrefix) Префикс объектов — Unique chart object prefix
Timeframe used to split profiles (InpProfilePeriod) Период профиля — Timeframe used to split profiles
Number of recent profiles to calculate (InpProfilesToDraw) Количество профилей — Number of recent profiles to calculate
Volume type used in profile calculation (InpVolumeMode) Режим объёма — Volume type used in profile calculation
Profile row size in symbol points (InpPriceStepPoints) Шаг цены в пунктах — Profile row size in symbol points
Value area percentage (InpValueAreaPercent) Процент зоны цены — Value area percentage
Keep completed profile levels unchanged (InpFreezeCompleted) Заморозка завершённых — Keep completed profile levels unchanged
Minimum seconds between live updates (InpUpdateSeconds) Интервал обновления — Minimum seconds between live updates
Show current developing VA levels (InpShowDevelopingValueArea) Показывать текущую зону — Show current developing VA levels
Show previous completed profile VA levels (InpShowPreviousValueArea) Показывать предыдущую зону — Show previous completed profile VA levels
Show older completed profile VA levels (InpShowHistoricalValueAreas) Показывать исторические зоны — Show older completed profile VA levels
Show older sessions' previous VA levels (InpShowHistoricalPreviousValueAreas) Показывать исторические предыдущие зоны — Show older sessions' previous VA levels
Previous-day label shift bars (InpPreviousLabelShiftBars) Сдвиг меток предыдущей — Previous-day label shift bars
Historical label shift bars (InpHistoricalLabelShiftBars) Сдвиг меток исторических — Historical label shift bars
Historical previous label shift bars (InpHistoricalPreviousLabelShiftBars) Сдвиг меток исторических предыдущих — Historical previous label shift bars
VAH and VAL line color (InpValueAreaLineColor) Цвет линий зоны — VAH and VAL line color
POC line color (InpPointOfControlLineColor) Цвет линии POC — POC line color
Level line width (InpLineWidth) Ширина линии — Level line width
Level line style (InpLineStyle) Стиль линии — Level line style
Show session break vertical line (InpShowSessionBreakLine) Показывать разделитель сессии — Show session break vertical line
Session break line color (InpSessionBreakColor) Цвет разделителя сессии — Session break line color
Session break line style (InpSessionBreakStyle) Стиль разделителя сессии — Session break line style
Session break line width (InpSessionBreakWidth) Ширина разделителя сессии — Session break line width
Show VAH/POC/VAL text labels (InpShowTextLabels) Показывать текстовые метки — Show VAH/POC/VAL text labels
Show price in label (InpShowPriceInLabel) Показывать цену в метке — Show price in label
Label font size (InpLabelFontSize) Размер шрифта метки — Label font size
Label shift from period start (InpLabelShiftBars) Сдвиг меток — Label shift from period start
Label offset unit (InpLabelOffsetUnit) Единица смещения метки — Label offset unit
Label offset above line (InpLabelOffsetValue) Значение смещения метки — Label offset above line
Minimum gap between stacked labels (InpLabelMinGapTicks) Минимальный зазор меток — Minimum gap between stacked labels
Show dashboard panel (InpShowDashboard) Показывать панель — Show dashboard panel
Dashboard corner (InpDashboardCorner) Угол панели — Dashboard corner
Dashboard X distance (InpDashboardX) X панели — Dashboard X distance
Dashboard Y distance (InpDashboardY) Y панели — Dashboard Y distance
Dashboard width (InpDashboardWidth) Ширина панели — Dashboard width
Dashboard font size (InpDashboardFontSize) Размер шрифта панели — Dashboard font size
Dashboard background (InpDashboardBgColor) Фон панели — Dashboard background
Dashboard border (InpDashboardBorderColor) Рамка панели — Dashboard border
Dashboard text (InpDashboardTextColor) Текст панели — Dashboard text
Dashboard header text (InpDashboardHeaderColor) Заголовок панели — Dashboard header text
Получить полный код

Поиск по коду файла

#property version   "1.0"
#property description "Draws developing, previous, and historical value area levels: VAH, POC, and VAL."
#property strict

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

#property indicator_label1  "VAH"
#property indicator_type1   DRAW_NONE
#property indicator_label2  "POC"
#property indicator_type2   DRAW_NONE
#property indicator_label3  "VAL"
#property indicator_type3   DRAW_NONE

enum ENUM_BCL_VOLUME_SOURCE
  {
   BCL_VOLUME_TICK = 0,   // Tick volume
   BCL_VOLUME_REAL = 1    // Real volume, fallback to tick volume if zero
  };

enum ENUM_BCL_LABEL_OFFSET_UNIT
  {
   BCL_LABEL_OFFSET_POINTS      = 0,  // Points
   BCL_LABEL_OFFSET_TICKS       = 1,  // Trade ticks
   BCL_LABEL_OFFSET_PRICE_STEPS = 2   // Profile price steps
  };

input string                    InpObjectPrefix                         = "ValueArea";       // Unique chart object prefix
input ENUM_TIMEFRAMES           InpProfilePeriod                       = PERIOD_D1;         // Timeframe used to split profiles
input int                       InpProfilesToDraw                      = 20;                // Number of recent profiles to calculate
input ENUM_BCL_VOLUME_SOURCE    InpVolumeMode                          = BCL_VOLUME_TICK;    // Volume type used in profile calculation
input int                       InpPriceStepPoints                     = 1;                 // Profile row size in symbol points
input double                    InpValueAreaPercent                    = 70.0;              // Value area percentage
input bool                      InpFreezeCompleted                     = true;              // Keep completed profile levels unchanged
input int                       InpUpdateSeconds                       = 5;                 // Minimum seconds between live updates
input bool                      InpShowDevelopingValueArea             = true;              // Show current developing VA levels
input bool                      InpShowPreviousValueArea               = true;              // Show previous completed profile VA levels
input bool                      InpShowHistoricalValueAreas            = true;              // Show older completed profile VA levels
input bool                      InpShowHistoricalPreviousValueAreas    = true;              // Show older sessions' previous VA levels
input int                       InpPreviousLabelShiftBars              = 8;                 // Previous-day label shift bars
input int                       InpHistoricalLabelShiftBars            = 1;                 // Historical label shift bars
input int                       InpHistoricalPreviousLabelShiftBars    = 8;                 // Historical previous label shift bars

input color                     InpValueAreaLineColor                  = clrGold;           // VAH and VAL line color
input color                     InpPointOfControlLineColor             = clrAqua;            // POC line color
input int                       InpLineWidth                           = 1;                 // Level line width
input ENUM_LINE_STYLE           InpLineStyle                           = STYLE_SOLID;       // Level line style

input bool                      InpShowSessionBreakLine                = true;              // Show session break vertical line
input color                     InpSessionBreakColor                   = clrDimGray;        // Session break line color
input ENUM_LINE_STYLE           InpSessionBreakStyle                   = STYLE_DOT;         // Session break line style
input int                       InpSessionBreakWidth                   = 1;                 // Session break line width

input bool                      InpShowTextLabels                      = true;              // Show VAH/POC/VAL text labels
input bool                      InpShowPriceInLabel                    = true;              // Show price in label
input int                       InpLabelFontSize                       = 8;                 // Label font size
input int                       InpLabelShiftBars                      = 1;                 // Label shift from period start
input ENUM_BCL_LABEL_OFFSET_UNIT InpLabelOffsetUnit                    = BCL_LABEL_OFFSET_TICKS; // Label offset unit
input int                       InpLabelOffsetValue                    = 25;                // Label offset above line
input int                       InpLabelMinGapTicks                    = 20;                // Minimum gap between stacked labels

input bool                      InpShowDashboard                       = true;              // Show dashboard panel
input ENUM_BASE_CORNER          InpDashboardCorner                    = CORNER_LEFT_UPPER; // Dashboard corner
input int                       InpDashboardX                         = 10;                // Dashboard X distance
input int                       InpDashboardY                         = 25;                // Dashboard Y distance
input int                       InpDashboardWidth                     = 310;               // Dashboard width
input int                       InpDashboardFontSize                  = 8;                 // Dashboard font size
input color                     InpDashboardBgColor                   = C'18,18,18';       // Dashboard background
input color                     InpDashboardBorderColor               = clrDimGray;        // Dashboard border
input color                     InpDashboardTextColor                 = clrWhite;          // Dashboard text
input color                     InpDashboardHeaderColor               = clrGold;           // Dashboard header text

double g_value_area_high_buffer[];
double g_point_of_control_buffer[];
double g_value_area_low_buffer[];

string   g_prefix = "";
datetime g_current_profile_start = 0;
datetime g_last_update_time = 0;
datetime g_last_tester_chart_bar_time = 0;
bool     g_force_full_redraw = true;
bool     g_refresh_historical = true;
bool     g_is_tester = false;
bool     g_is_visual_tester = false;

double   g_current_vah = EMPTY_VALUE;
double   g_current_poc = EMPTY_VALUE;
double   g_current_val = EMPTY_VALUE;
datetime g_current_start_for_dashboard = 0;
bool     g_has_current_values = false;

double   g_previous_vah = EMPTY_VALUE;
double   g_previous_poc = EMPTY_VALUE;
double   g_previous_val = EMPTY_VALUE;
datetime g_previous_start_for_dashboard = 0;
bool     g_has_previous_values = false;

bool AllowChartObjects()
  {
   return (!g_is_tester || g_is_visual_tester);
  }

bool IsProfilePeriodCompatible()
  {
   ENUM_TIMEFRAMES profile_period = InpProfilePeriod;

   if(profile_period == PERIOD_CURRENT)
      profile_period = (ENUM_TIMEFRAMES)_Period;

   int source_seconds = PeriodSeconds((ENUM_TIMEFRAMES)_Period);
   int profile_seconds = PeriodSeconds(profile_period);

   if(source_seconds <= 0 || profile_seconds <= 0)
      return true;

   return (source_seconds <= profile_seconds);
  }

datetime GetProfileStart(datetime bar_time)
  {
   ENUM_TIMEFRAMES profile_period = InpProfilePeriod;

   if(profile_period == PERIOD_CURRENT)
      profile_period = (ENUM_TIMEFRAMES)_Period;

   MqlDateTime parts;

   if(!TimeToStruct(bar_time, parts))
      return 0;

   if(profile_period == PERIOD_MN1)
     {
      parts.day = 1;
      parts.hour = 0;
      parts.min = 0;
      parts.sec = 0;
      return StructToTime(parts);
     }

   parts.hour = 0;
   parts.min = 0;
   parts.sec = 0;
   datetime day_start = StructToTime(parts);

   if(profile_period == PERIOD_W1)
     {
      int days_from_monday = (parts.day_of_week == 0) ? 6 : parts.day_of_week - 1;
      return day_start - (datetime)(days_from_monday * 86400);
     }

   int profile_seconds = PeriodSeconds(profile_period);

   if(profile_seconds <= 0)
      profile_seconds = PeriodSeconds((ENUM_TIMEFRAMES)_Period);

   if(profile_seconds <= 0)
      profile_seconds = 60;

   if(profile_seconds >= 86400)
      return day_start;

   MqlDateTime original_parts;

   if(!TimeToStruct(bar_time, original_parts))
      return day_start;

   int seconds_from_midnight = original_parts.hour * 3600 +
                               original_parts.min * 60 +
                               original_parts.sec;
   int bucket_start = (seconds_from_midnight / profile_seconds) * profile_seconds;

   return day_start + (datetime)bucket_start;
  }

int BuildProfileStarts(const datetime &time[],
                       int rates_total,
                       int requested_count,
                       datetime &profile_starts[])
  {
   ArrayResize(profile_starts, 0);

   if(rates_total <= 0 || requested_count <= 0)
      return 0;

   datetime last_start = 0;
   int count = 0;

   for(int bar = 0; bar < rates_total && count < requested_count; bar++)
     {
      if(IsStopped())
         break;

      datetime profile_start = GetProfileStart(time[bar]);

      if(profile_start <= 0)
         continue;

      if(count == 0 || profile_start != last_start)
        {
         ArrayResize(profile_starts, count + 1);
         profile_starts[count] = profile_start;
         last_start = profile_start;
         count++;
        }
     }

   return count;
  }

int GetSafePeriodSeconds(ENUM_TIMEFRAMES tf)
  {
   int sec = PeriodSeconds(tf);

   if(sec <= 0)
      sec = PeriodSeconds(_Period);

   if(sec <= 0)
      sec = 60;

   return sec;
  }

string TimeframeToString(ENUM_TIMEFRAMES tf)
  {
   switch(tf)
     {
      case PERIOD_CURRENT: return "CURRENT";
      case PERIOD_M1:      return "M1";
      case PERIOD_M2:      return "M2";
      case PERIOD_M3:      return "M3";
      case PERIOD_M4:      return "M4";
      case PERIOD_M5:      return "M5";
      case PERIOD_M6:      return "M6";
      case PERIOD_M10:     return "M10";
      case PERIOD_M12:     return "M12";
      case PERIOD_M15:     return "M15";
      case PERIOD_M20:     return "M20";
      case PERIOD_M30:     return "M30";
      case PERIOD_H1:      return "H1";
      case PERIOD_H2:      return "H2";
      case PERIOD_H3:      return "H3";
      case PERIOD_H4:      return "H4";
      case PERIOD_H6:      return "H6";
      case PERIOD_H8:      return "H8";
      case PERIOD_H12:     return "H12";
      case PERIOD_D1:      return "D1";
      case PERIOD_W1:      return "W1";
      case PERIOD_MN1:     return "MN1";
      default:             return "TF";
     }
  }

double GetProfilePriceStep()
  {
   int points_count = MathMax(1, InpPriceStepPoints);
   return _Point * points_count;
  }

double GetSymbolTickSize()
  {
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

   if(tick_size <= 0.0)
      tick_size = _Point;

   if(tick_size <= 0.0)
      tick_size = 0.00001;

   return tick_size;
  }

double GetLabelOffsetPrice()
  {
   int value = MathMax(1, InpLabelOffsetValue);

   if(InpLabelOffsetUnit == BCL_LABEL_OFFSET_TICKS)
      return value * GetSymbolTickSize();

   if(InpLabelOffsetUnit == BCL_LABEL_OFFSET_PRICE_STEPS)
      return value * GetProfilePriceStep();

   return value * _Point;
  }

double GetLabelMinGapPrice()
  {
   int ticks = MathMax(1, InpLabelMinGapTicks);
   return ticks * GetSymbolTickSize();
  }

double NormalizeSymbolPrice(double price)
  {
   return NormalizeDouble(price, _Digits);
  }

double RoundPriceDownToStep(double price, double step)
  {
   if(step <= 0.0)
      return price;

   return MathFloor(price / step) * step;
  }

double RoundPriceUpToStep(double price, double step)
  {
   if(step <= 0.0)
      return price;

   return MathCeil(price / step) * step;
  }

int GetFloorPriceIndex(double price, double low_price, double step)
  {
   if(step <= 0.0)
      return 0;

   return (int)MathFloor((price - low_price) / step + 0.000000001);
  }

int GetCeilPriceIndex(double price, double low_price, double step)
  {
   if(step <= 0.0)
      return 0;

   return (int)MathCeil((price - low_price) / step - 0.000000001);
  }

double GetPriceFromIndex(int index, double low_price, double step)
  {
   return NormalizeDouble(low_price + index * step, _Digits);
  }

double GetArraySum(const double &values[])
  {
   double total = 0.0;
   int size = ArraySize(values);

   for(int i = 0; i < size; i++)
      total += values[i];

   return total;
  }

int FindPointOfControlIndex(const double &profile[])
  {
   int size = ArraySize(profile);

   if(size <= 0)
      return -1;

   double max_value = profile[0];

   for(int i = 1; i < size; i++)
     {
      if(profile[i] > max_value)
         max_value = profile[i];
     }

   double center = (size - 1) / 2.0;
   int best_index = -1;
   double best_distance = DBL_MAX;

   for(int i = 0; i < size; i++)
     {
      if(MathAbs(profile[i] - max_value) <= 0.0000001)
        {
         double distance = MathAbs(i - center);

         if(distance < best_distance)
           {
            best_distance = distance;
            best_index = i;
           }
        }
     }

   return best_index;
  }

void CalculateValueArea(const double &profile[],
                        int poc_index,
                        double value_area_percent,
                        int &val_index,
                        int &vah_index)
  {
   int size = ArraySize(profile);
   val_index = -1;
   vah_index = -1;

   if(size <= 0 || poc_index < 0 || poc_index >= size)
      return;

   double total = GetArraySum(profile);

   if(total <= 0.0)
     {
      val_index = poc_index;
      vah_index = poc_index;
      return;
     }

   double percent = MathMax(1.0, MathMin(value_area_percent, 100.0));
   double target = total * percent / 100.0;

   int low_index = poc_index;
   int high_index = poc_index;
   double included = profile[poc_index];

   while(included < target && (low_index > 0 || high_index < size - 1))
     {
      double below = (low_index > 0) ? profile[low_index - 1] : -1.0;
      double above = (high_index < size - 1) ? profile[high_index + 1] : -1.0;

      if(above > below)
        {
         high_index++;
         included += profile[high_index];
        }
      else if(below > above)
        {
         low_index--;
         included += profile[low_index];
        }
      else
        {
         if(low_index > 0)
           {
            low_index--;
            included += profile[low_index];
           }

         if(included >= target)
            break;

         if(high_index < size - 1)
           {
            high_index++;
            included += profile[high_index];
           }
        }
     }

   val_index = low_index;
   vah_index = high_index;
  }

void DisableObject(const string name)
  {
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_SELECTED, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
  }

void DeleteObjectsByPrefix(const string prefix)
  {
   if(!AllowChartObjects())
      return;

   int total = ObjectsTotal(0, -1, -1);

   for(int i = total - 1; i >= 0; i--)
     {
      string name = ObjectName(0, i, -1, -1);

      if(StringFind(name, prefix) == 0)
         ObjectDelete(0, name);
     }
  }

void DrawSeparator(const string profile_prefix, datetime separator_time)
  {
   if(!AllowChartObjects() || !InpShowSessionBreakLine)
      return;

   string name = profile_prefix + "SEP";
   ObjectDelete(0, name);

   if(!ObjectCreate(0, name, OBJ_VLINE, 0, separator_time, 0.0))
      return;

   ObjectSetInteger(0, name, OBJPROP_COLOR, InpSessionBreakColor);
   ObjectSetInteger(0, name, OBJPROP_STYLE, InpSessionBreakStyle);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, InpSessionBreakWidth);
   ObjectSetInteger(0, name, OBJPROP_BACK, true);

   DisableObject(name);
  }

void DrawLevelLine(const string profile_prefix,
                   const string tag,
                   datetime from_time,
                   datetime to_time,
                   double price,
                   color line_color)
  {
   if(!AllowChartObjects())
      return;

   if(to_time <= from_time)
      to_time = from_time + GetSafePeriodSeconds(_Period);

   string name = profile_prefix + tag + "_LINE";
   ObjectDelete(0, name);

   if(!ObjectCreate(0, name, OBJ_TREND, 0, from_time, price, to_time, price))
      return;

   ObjectSetInteger(0, name, OBJPROP_RAY_LEFT, false);
   ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
   ObjectSetInteger(0, name, OBJPROP_COLOR, line_color);
   ObjectSetInteger(0, name, OBJPROP_STYLE, InpLineStyle);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, InpLineWidth);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);

   DisableObject(name);
  }

datetime LabelTime(datetime base_time, int shift_bars)
  {
   return base_time + MathMax(0, shift_bars) * GetSafePeriodSeconds(_Period);
  }

string BuildLabelText(const string display_tag, double price)
  {
   if(InpShowPriceInLabel)
      return display_tag + " " + DoubleToString(price, _Digits);

   return display_tag;
  }

void DrawLevelLabel(const string profile_prefix,
                    const string object_tag,
                    const string display_tag,
                    datetime label_time,
                    double line_price,
                    double label_price,
                    color label_color)
  {
   if(!AllowChartObjects() || !InpShowTextLabels)
      return;

   string name = profile_prefix + object_tag + "_LABEL";
   ObjectDelete(0, name);

   if(!ObjectCreate(0, name, OBJ_TEXT, 0, label_time, NormalizeSymbolPrice(label_price)))
      return;

   ObjectSetString(0, name, OBJPROP_TEXT, BuildLabelText(display_tag, line_price));
   ObjectSetString(0, name, OBJPROP_FONT, "Arial");
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, InpLabelFontSize);
   ObjectSetInteger(0, name, OBJPROP_COLOR, label_color);
   ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);

   DisableObject(name);
  }

void DrawSessionLevels(const string profile_prefix,
                       const string display_prefix,
                       datetime separator_time,
                       datetime line_start_time,
                       datetime line_end_time,
                       double vah,
                       double poc,
                       double val,
                       int label_shift_bars)
  {
   if(!AllowChartObjects())
      return;

   if(separator_time > 0)
      DrawSeparator(profile_prefix, separator_time);

   DrawLevelLine(profile_prefix, "VAH", line_start_time, line_end_time, vah, InpValueAreaLineColor);
   DrawLevelLine(profile_prefix, "POC", line_start_time, line_end_time, poc, InpPointOfControlLineColor);
   DrawLevelLine(profile_prefix, "VAL", line_start_time, line_end_time, val, InpValueAreaLineColor);

   datetime label_time = LabelTime(line_start_time, label_shift_bars);
   double offset = GetLabelOffsetPrice();
   double minimum_gap = MathMax(GetLabelMinGapPrice(), offset);

   double val_label = val + offset;
   double poc_label = poc + offset;
   double vah_label = vah + offset;

   if(poc_label < val_label + minimum_gap)
      poc_label = val_label + minimum_gap;

   if(vah_label < poc_label + minimum_gap)
      vah_label = poc_label + minimum_gap;

   DrawLevelLabel(profile_prefix, "VAH", display_prefix + "VAH", label_time, vah, vah_label, InpValueAreaLineColor);
   DrawLevelLabel(profile_prefix, "POC", display_prefix + "POC", label_time, poc, poc_label, InpPointOfControlLineColor);
   DrawLevelLabel(profile_prefix, "VAL", display_prefix + "VAL", label_time, val, val_label, InpValueAreaLineColor);
  }

string FormatDashboardPrice(double price, bool valid)
  {
   if(!valid || price == EMPTY_VALUE)
      return "--";

   return DoubleToString(price, _Digits);
  }

string FormatDashboardTime(datetime time_value)
  {
   if(time_value <= 0)
      return "--";

   return TimeToString(time_value, TIME_DATE | TIME_MINUTES);
  }

string FormatDashboardWidth(double vah, double val, bool valid)
  {
   if(!valid || vah == EMPTY_VALUE || val == EMPTY_VALUE)
      return "--";

   double width_price = MathAbs(vah - val);
   double width_points = (_Point > 0.0) ? width_price / _Point : 0.0;

   return DoubleToString(width_price, _Digits) + " / " + DoubleToString(width_points, 0) + " pts";
  }

string PadRight(string text, int total_length)
  {
   while(StringLen(text) < total_length)
      text += " ";

   return text;
  }

string DashboardLine(string label, string value)
  {
   return PadRight(label, 9) + " : " + value;
  }

void GetDashboardBaseXY(int width, int height, int &base_x, int &base_y)
  {
   int chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0);
   int chart_height = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0);

   int margin_x = MathMax(0, InpDashboardX);
   int margin_y = MathMax(0, InpDashboardY);

   bool use_right = (InpDashboardCorner == CORNER_RIGHT_UPPER || InpDashboardCorner == CORNER_RIGHT_LOWER);
   bool use_lower = (InpDashboardCorner == CORNER_LEFT_LOWER || InpDashboardCorner == CORNER_RIGHT_LOWER);

   base_x = use_right ? chart_width - width - margin_x : margin_x;
   base_y = use_lower ? chart_height - height - margin_y : margin_y;

   if(base_x < 0)
      base_x = 0;

   if(base_y < 0)
      base_y = 0;

   if(chart_width > width && base_x + width > chart_width)
      base_x = chart_width - width;

   if(chart_height > height && base_y + height > chart_height)
      base_y = chart_height - height;
  }

void DrawDashboardBox(const string name,
                      int width,
                      int height,
                      int base_x,
                      int base_y)
  {
   if(!AllowChartObjects())
      return;

   ObjectDelete(0, name);

   if(!ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0))
      return;

   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, base_x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, base_y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, InpDashboardBgColor);
   ObjectSetInteger(0, name, OBJPROP_COLOR, InpDashboardBorderColor);
   ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);

   DisableObject(name);
  }

void DrawDashboardLabel(const string name,
                        int row,
                        const string text,
                        color text_color,
                        int base_x,
                        int base_y,
                        bool bold = false)
  {
   if(!AllowChartObjects())
      return;

   ObjectDelete(0, name);

   if(!ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0))
      return;

   int row_height = MathMax(14, InpDashboardFontSize + 6);
   int x = base_x + 10;
   int y = base_y + 8 + row * row_height;

   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
   ObjectSetString(0, name, OBJPROP_TEXT, text);
   ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial" : "Consolas");
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, InpDashboardFontSize);
   ObjectSetInteger(0, name, OBJPROP_COLOR, text_color);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);

   DisableObject(name);
  }

void DrawDashboard()
  {
   if(!AllowChartObjects())
      return;

   string dashboard_prefix = g_prefix + "DASH_";
   DeleteObjectsByPrefix(dashboard_prefix);

   if(!InpShowDashboard)
      return;

   int row_height = MathMax(14, InpDashboardFontSize + 6);
   int rows = 20;
   int height = 16 + rows * row_height;
   int width = MathMax(290, InpDashboardWidth);

   int chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0);
   int chart_height = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0);

   if(chart_width > 50 && width > chart_width - 10)
      width = chart_widt

Показано первые 50% кода (символов: 32385)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
3 238,50₽ ≈ $39.59