Author: Copyright (c) 2021, Marketeer
0 Views
0 Downloads
0 Favorites
SubScaler
//+------------------------------------------------------------------+
//|                                                    SubScaler.mq5 |
//|                                               Copyright (c) 2021 |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2021, Marketeer"
#property link      "https://www.mql5.com/en/users/marketeer"
#property version   "1.0"
#property description "Subwindow scaler: use Up/Down arrow keys to scale up/down; hold Shift with arrow keys to move up/down.\n"
#property description "Scaling up means that picture becomes larger (zoom in, can be clipped), whereas scaling down means that picture becomes smaller (zoom out).\n"
#property description "SubScaler must be the 1-st indicator in subwindow; affected indicator must be the next and switched to 'inherited scale'; chart must have keyboard focus for the keys to take effect.\n"

#property indicator_separate_window
#property indicator_buffers 0
#property indicator_plots   0


input double FixedMaximum = 1000; // Initial Maximum
input double FixedMinimum = -1000; // Initial Minimum
input double _ScaleFactor = 0.1; // Scale Factor [0.01 ... 0.5]


#define VK_UP   38
#define VK_DOWN 40


double ScaleFactor;
int w = -1, n = -1;

void OnInit()
{
  ScaleFactor = _ScaleFactor;
  if(ScaleFactor < 0.01 || ScaleFactor > 0.5)
  {
    PrintFormat("ScaleFactor %f is adjusted to default value 0.1, valid range is [0.01, 0.5]", ScaleFactor);
    ScaleFactor = 0.1;
  }
  w = ChartWindowFind();
  n = ChartIndicatorsTotal(0, w);
}


void scale(const long cmd, const int shift)
{
  // PrintFormat("%lld %llx", cmd, shift);

  const double min = ChartGetDouble(0, CHART_PRICE_MIN, w);
  const double max = ChartGetDouble(0, CHART_PRICE_MAX, w);
  //PrintFormat("%f %f", min, max);
  
  if((shift & 0x10000000) == 0)
  {
    if(cmd == VK_UP)
    {
      IndicatorSetDouble(INDICATOR_MINIMUM, min / (1.0 + ScaleFactor));
      IndicatorSetDouble(INDICATOR_MAXIMUM, max / (1.0 + ScaleFactor));
      ChartRedraw();
    }
    else if(cmd == VK_DOWN)
    {
      IndicatorSetDouble(INDICATOR_MINIMUM, min * (1.0 + ScaleFactor));
      IndicatorSetDouble(INDICATOR_MAXIMUM, max * (1.0 + ScaleFactor));
      ChartRedraw();
    }
  }
  else
  {
    if(cmd == VK_UP)
    {
      const double d = (max - min) * ScaleFactor;
      IndicatorSetDouble(INDICATOR_MINIMUM, min - d);
      IndicatorSetDouble(INDICATOR_MAXIMUM, max - d);
      ChartRedraw();
    }
    else if(cmd == VK_DOWN)
    {
      const double d = (max - min) * ScaleFactor;
      IndicatorSetDouble(INDICATOR_MINIMUM, min + d);
      IndicatorSetDouble(INDICATOR_MAXIMUM, max + d);
      ChartRedraw();
    }
    
  }
}

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
  switch(id)
  {
    case CHARTEVENT_KEYDOWN:
      scale(lparam, TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT));
      break;
    case CHARTEVENT_CHART_CHANGE:
      if(ChartIndicatorsTotal(0, w) > n)
      {
        n = ChartIndicatorsTotal(0, w);
        const double min = ChartGetDouble(0, CHART_PRICE_MIN, w);
        const double max = ChartGetDouble(0, CHART_PRICE_MAX, w);
        PrintFormat("Change: %f %f %d", min, max, n);
        if(min == 0 && max == 0)
        {
          IndicatorSetDouble(INDICATOR_MINIMUM, FixedMinimum);
          IndicatorSetDouble(INDICATOR_MAXIMUM, FixedMaximum);
        }
      }
      break;
  }
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
  return rates_total;
}

Comments