Организация пакетной обработки задачи по снятию изображений с экрана графика - страница 4

 
Kirill Belousov:

А какая последняя версия скрипта над которым работаете?

(возможно вносили правки с учетом замечаний)

Последний, но не окончательный, вариант такой

//+------------------------------------------------------------------+
//|                                                     WideShootrer |
//|                                           Copyright 2012,Karlson |
//+------------------------------------------------------------------+
#property copyright   "2012, Karlson."
#property link        "https://login.mql5.com/ru/users/Karlson"
#property description "WideShootrer"
#property version "1.00"
//-------------------------------------------------------------------+
#property script_show_inputs
//#define TOSTRING(A) #A + " = " + (string)(A) + "\n"

//input int Zoom=2;//Zoom на котором будет делатся скрин шот
enum ENUM_ZOOMWINDOWS_NAME
  {
ZoomWindows_100=0,
ZoomWindows_125=1,
Zoom_fxsaber=2,
Zoom_notShkala=3,
  };
input ENUM_ZOOMWINDOWS_NAME ZOOM=ENUM_ZOOMWINDOWS_NAME(3);

input double K_Proc=0.001;//Коэффициент расширения экрана для снятия скрина


//input string Data_ScreenStart="10.04.2018 10:00";      // - дата с которой будет делаться скриншот
//input string Data_ScreenStop="10.04.2018 22:00";       // - по какую дату будет делаться скриншот (ширина скриншота, фактически конвертированная в итоге в бары).
input int Data_ScreenStart_Shift=0;    // - смещение области для захвата экрана в барах, относительно указанной даты в правую часть графика
input int Data_ScreenStop_Shift=0;     // - смещение области для захвата экрана в барах, относительно указанной даты в левую часть графика
//-------------------------------------------------------------------+
double High[],Low[];
int bars=0;
string Data_ScreenStart="10.04.2018 10:00";      // - дата с которой будет делаться скриншот
string Data_ScreenStop="10.04.2018 22:00";       // - по какую дату будет делаться скриншот (ширина скриншота, фактически конвертированная в итоге в бары).
int Schkala=0;
//-------------------------------------------------------------------+
void OnStart()
  {
   //if(_Digits==5 || _Digits==3) {KF=10;} else {KF=1;}
   
  for (int x=0; x<17+1; x++)
  {
  Schkala=GetWidthScale();   
  Data_ScreenStart=StartDate(x);
  Data_ScreenStop=StopDate(x);
  
  Screen();
//  Print(TOSTRING(GetWidthScale()));
  }

  }

//+------------------------------------------------------------------+

void Screen()
{
int Shift_Start=iBarShift(Symbol(),PERIOD_CURRENT,StringToTime(Data_ScreenStart),false); 
int Shift_Stop=iBarShift(Symbol(),PERIOD_CURRENT,StringToTime(Data_ScreenStop),false); 
//Print(Shift_Start);
int BarsTotal=Bars(Symbol(),PERIOD_CURRENT);
//Shift_Start=100*(-1);
Shift_Start=Shift_Start*(-1);
Shift_Stop=Shift_Stop*(-1);
//--- получим handle текущего графика 
   long handle=ChartID(); 
   if(handle>0) // если получилось, дополнительно настроим 
     { 
     //Print ("handle=",handle);
      //--- отключим автопрокрутку 
      ChartSetInteger(handle,CHART_AUTOSCROLL,false); 
      
      //---отображение сетки на графике
      ChartSetInteger(handle,CHART_SHOW_GRID,false); 

      //---Отображение значения Bid горизонтальной линией на графике      
      ChartSetInteger(handle,CHART_SHOW_BID_LINE,false);

      //---Отображение значения Ask горизонтальной линией на графике
      ChartSetInteger(handle,CHART_SHOW_ASK_LINE,false);
 
      //---Отображение значения Last горизонтальной линией на графике
      ChartSetInteger(handle,CHART_SHOW_LAST_LINE,false);
      
      //--- установим отступ правого края графика 
//      ChartSetInteger(handle,CHART_SHIFT,true); 
      //--- отобразим в виде свечей 
//      ChartSetInteger(handle,CHART_MODE,CHART_CANDLES); 
      //--- установить режим отображения тиковых объемов 
//      ChartSetInteger(handle,CHART_SHOW_VOLUMES,CHART_VOLUME_TICK);  
      //--- получим номер самого первого видимого на графике бара (нумерация как в таймсерии) 
      //long first_bar=ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0); 

int Zoom=(int)ChartGetInteger(handle,CHART_SCALE,0);
//Print(ChartGetInteger(handle,CHART_SCALE,0));

//--принудительный зум
//   ChartSetInteger(handle,CHART_SCALE,Zoom);

// зафиксируем шкалу и установим верх низ
   ChartSetInteger(handle,CHART_SCALEFIX,0,1);
   ChartSetInteger(handle,CHART_AUTOSCROLL,false);

// определяем сколько показывает на графике баров - потребуется для определения ширины скриншота
   int vis_bar=(int)ChartGetInteger(handle,CHART_VISIBLE_BARS);
   //Print("По ширине графика отображено баров=",vis_bar);

// сместим на нужный временной участок график
   ChartNavigate(handle,CHART_END,Shift_Start);
   int _SS=Shift_Start+vis_bar-3;   
   ChartNavigate(handle,CHART_END,_SS);

// определяем первый левый бар.От него будем делать скриншот
   int first_bar=(int)ChartGetInteger(handle,CHART_FIRST_VISIBLE_BAR);

// получаем цены баров в массив за период скрина для установки хай-лоу графика
   bars=Shift_Start*(-1)-Shift_Stop*(-1);
   if(first_bar<bars) {bars=first_bar;} // если график смещен менее чем требуется баров,тогда берем все что есть вправо до текущего времени
   int ch=CopyHigh(_Symbol,_Period,StringToTime(Data_ScreenStart),StringToTime(Data_ScreenStop),High);
   int cl=CopyLow(_Symbol,_Period,StringToTime(Data_ScreenStart),StringToTime(Data_ScreenStop),Low);

// определяем хай лоу на нашем промежутке и устанавливаем верх низ шкалы цены
   double max_price=High[ArrayMaximum(High,0,WHOLE_ARRAY)]*(1.00+K_Proc);
   double min_price=Low[ArrayMinimum(Low,0,WHOLE_ARRAY)]*(1.00-K_Proc);
   
// установим верх низ
   ChartSetDouble(handle,CHART_FIXED_MAX,max_price);
   ChartSetDouble(handle,CHART_FIXED_MIN,min_price);

// получим текущую дату в простом формате для фомирования имени файла
   MqlDateTime day;
   TimeToStruct(StringToTime(Data_ScreenStart),day);
   MqlDateTime dayEnd;
   TimeToStruct(StringToTime(Data_ScreenStop),dayEnd);
   string file=_Symbol+"_"+(string)day.year+"_"+(string)day.mon+"_"+(string)day.day+"_"+(string)day.hour+"_"+(string)day.min+
   "-"+(string)dayEnd.year+"_"+(string)dayEnd.mon+"_"+(string)dayEnd.day+"_"+(string)dayEnd.hour+"_"+(string)dayEnd.min+".png";

// определим высоту и ширину будущего скрина
   int scr_height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);


// Обозначим границы баров вертикальными линиями
   ObjectsDeleteAll(handle,"Shift",-1);
VLineCreate(handle,"Shift_Start",0,StringToTime(Data_ScreenStart),clrYellow,STYLE_SOLID,1,false, 
            false,true,false,0);
VLineCreate(handle,"Shift_Stop",0,StringToTime(Data_ScreenStop),clrYellow,STYLE_SOLID,1,false, 
            false,true,false,0);


// сделаем скриншот
int ZoomX=0;
if (ZOOM==ZoomWindows_100)
   {
      if (Zoom==0)ZoomX=52;
      if (Zoom==1)ZoomX=27;
      if (Zoom==2)ZoomX=15;
      if (Zoom==3)ZoomX=8;
      if (Zoom==4)ZoomX=5;
      if (Zoom==5)ZoomX=3;
   }
if (ZOOM==ZoomWindows_125)
   {
      if (Zoom==0)ZoomX=68;
      if (Zoom==1)ZoomX=35;
      if (Zoom==2)ZoomX=18;
      if (Zoom==3)ZoomX=10;
      if (Zoom==4)ZoomX=6;
      if (Zoom==5)ZoomX=4;
   }

int pp=GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1)+ZoomX);
//int pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+ZoomX);

if (ZOOM==Zoom_fxsaber)
   {
      //pp=GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1))+Schkala*1.3;
      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+2)+Schkala+3;
   }
if (ZOOM==Zoom_notShkala)
   {
      ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
/*
//      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+4);
      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/((double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)-0.5)*((Shift_Start-Shift_Stop)*(-1)+0.5);
      ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
//      Print("Число баров - ", file, " - ",((Shift_Start-Shift_Stop)*(-1)+3)," - ",(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS));
   int vis_bar=(int)ChartGetInteger(handle,CHART_VISIBLE_BARS);
Print("Количество баров на графике, доступных для отображения - ",vis_bar);
Print("ширина графика в барах - ",ChartGetInteger(handle,CHART_WIDTH_IN_BARS));
//Количество баров на графике, доступных для отображения
//CHART_WIDTH_IN_BARS - ширина графика в барах
*/
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 
   //pp=LeftPixelOfBar+RightPixelOfBar+GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1)+2);
   pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2);

//Print("номер первого (левого) бара на экране - ",FirstBar, " количество видимых баров на экране - ",VisibleBars);
Print("номер первого (левого) бара на экране - ",FirstBar, " количество видимых баров на экране - ",Shift_Start);

   }


//Print((Shift_Start-Shift_Stop));
//ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу

   ChartScreenShot(handle,file,pp,scr_height,ALIGN_LEFT);
   if(GetLastError()>0) {Print("Error  (",GetLastError(),") ");} ResetLastError();

//---востановим настройки чарта
    ChartSetInteger(handle,CHART_SCALEFIX,0,0);
    ChartSetInteger(handle,CHART_SHOW_PRICE_SCALE ,1);

//---удалим созданные объекты
    ObjectsDeleteAll(handle,"Shift",-1);
     } 
}



//+------------------------------------------------------------------+ 
//| Получим iBarShift для заданного номера бара                      | 
//+------------------------------------------------------------------+    
/*
int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,const bool Exact=false)
  {
   static int Res=-1;
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static bool LastExact=false;
   static int PerSec=::PeriodSeconds(LastTimeFrame);
   
   if (LastTimeFrame!=TimeFrame) PerSec=::PeriodSeconds(TimeFrame);
   time-=time%PerSec;

   if((time!=LastTime) || (Symb!=LastSymb) || (TimeFrame!=LastTimeFrame) || (Exact!=LastExact))
     {
      Res=::Bars(Symb,TimeFrame,time,UINT_MAX)-1;
      if(Res<0) Res=0;

      LastTime = time;
      LastSymb = Symb;
      LastTimeFrame=TimeFrame;
      LastExact=Exact;
     }

   return(Res);
  }   
  */
int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=Bars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==Bars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
datetime iTime(string symbol,int tf,int index)
  {
   if(index < 0) return(-1);
//   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT;
   datetime Arr[];
   if(CopyTime(symbol,timeframe,index,1,Arr)>0)
      return(Arr[0]);
   else return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+  
int GetBarSize( const ulong Chart = 0 )
{
  return(1 << (int)ChartGetInteger(Chart, CHART_SCALE));
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+ 
bool VLineCreate(const long            chart_ID=0,        // ID графика 
                 const string          name="VLine",      // имя линии 
                 const int             sub_window=0,      // номер подокна 
                 datetime              time=0,            // время линии 
                 const color           clr=clrRed,        // цвет линии 
                 const ENUM_LINE_STYLE style=STYLE_SOLID, // стиль линии 
                 const int             width=1,           // толщина линии 
                 const bool            back=false,        // на заднем плане 
                 const bool            selection=true,    // выделить для перемещений 
                 const bool            ray=true,          // продолжение линии вниз 
                 const bool            hidden=true,       // скрыт в списке объектов 
                 const long            z_order=0)         // приоритет на нажатие мышью 
  { 
//--- если время линии не задано, то проводим ее через последний бар 
   if(!time) 
      time=TimeCurrent(); 
//--- сбросим значение ошибки 
   ResetLastError(); 
//--- создадим вертикальную линию 
   if(!ObjectCreate(chart_ID,name,OBJ_VLINE,sub_window,time,0)) 
     { 
      Print(__FUNCTION__, 
            ": не удалось создать вертикальную линию! Код ошибки = ",GetLastError()); 
      return(false); 
     } 
//--- установим цвет линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- установим стиль отображения линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); 
//--- установим толщину линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width); 
//--- отобразим на переднем (false) или заднем (true) плане 
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- включим (true) или отключим (false) режим перемещения линии мышью 
//--- при создании графического объекта функцией ObjectCreate, по умолчанию объект 
//--- нельзя выделить и перемещать. Внутри же этого метода параметр selection 
//--- по умолчанию равен true, что позволяет выделять и перемещать этот объект 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- включим (true) или отключим (false) режим отображения линии в подокнах графика 
   ObjectSetInteger(chart_ID,name,OBJPROP_RAY,ray); 
//--- скроем (true) или отобразим (false) имя графического объекта в списке объектов 
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- установим приоритет на получение события нажатия мыши на графике 
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- успешное выполнение 
   return(true); 
  } 
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+   
string StartDate(int i)
  {
   string Date[18]=
     {
      "23.03.2018 10:30",
      "09.02.2018 10:30",
      "15.12.2017 10:30",
      "27.10.2017 10:30",
      "15.09.2017 10:30",
      "28.07.2017 10:30",
      "16.06.2017 10:30",
      "28.04.2017 10:30",
      "24.03.2017 10:30",
      "03.02.2017 10:30",
      "16.12.2016 10:30",
      "28.10.2016 10:30",
      "16.09.2016 10:30",
      "29.07.2016 10:30",
      "10.06.2016 10:30",
      "29.04.2016 10:30",
      "18.03.2016 10:30",
      "29.01.2016 10:30",
     };
   return (Date[i] );
  }
string StopDate(int i)
  {
   string Date[18]=
     {
      "23.03.2018 23:30",
      "09.02.2018 23:30",
      "15.12.2017 23:30",
      "27.10.2017 23:30",
      "15.09.2017 23:30",
      "28.07.2017 23:30",
      "16.06.2017 23:30",
      "28.04.2017 23:30",
      "24.03.2017 23:30",
      "03.02.2017 23:30",
      "16.12.2016 23:30",
      "28.10.2016 23:30",
      "16.09.2016 23:30",
      "29.07.2016 23:30",
      "10.06.2016 23:30",
      "29.04.2016 23:30",
      "18.03.2016 23:30",
      "29.01.2016 23:30",
     };
   return (Date[i] );
  }
//+------------------------------------------------------------------+

// Ширина вертикальной шкалы графика
int GetWidthScale(const long chartID=0)
  {
   const string Name=__FUNCTION__+(string)MathRand();

//   int _Zoom=(int)ChartGetInteger(chartID,CHART_SCALE,0);

   ObjectCreate(chartID,Name,OBJ_CHART,0,0,0);
   ObjectSetInteger(chartID,Name,OBJPROP_XDISTANCE,-1e3);

   const long chart=ObjectGetInteger(chartID,Name,OBJPROP_CHART_ID);
/*
   //--принудительный зум
   ChartSetInteger(chart,CHART_SCALE,_Zoom);
   // зафиксируем шкалу и установим верх низ
   ChartSetInteger(chart,CHART_SCALEFIX,0,1);
   ChartSetInteger(chart,CHART_AUTOSCROLL,false);
*/   
   
   const int Res=(int)(ChartGetInteger(chart,CHART_WIDTH_IN_PIXELS) -
                  (ChartSetInteger(chart,CHART_SHOW,false) ? ChartGetInteger(chart,CHART_WIDTH_IN_PIXELS) : 0));

   ObjectDelete(chartID,Name);

   return(-Res);
  }
 
Скрипт не рекомендуется использовать при подключении к брокеру, так-как может не корректно происходить смещение из-за синхронизации, на которую влияют тики.
 
Aleksey Vyazmikin:
Скрипт не рекомендуется использовать при подключении к брокеру, так-как может не корректно происходить смещение из-за синхронизации, на которую влияют тики.

Это понятно. 

Посмотрим что за ребус )

 

Сделал тупую подгонку в пикселях под свой понитор и настройки Windows, поэтому прошу сообщить, если что-то работает не корректно.

Добавил возможность включения и отключения шкалы при захвате экрана

input bool Use_Shakala=true;//Скриншот со шкалой цен или без шкалы цен

Пока такой черновой вариант

//+------------------------------------------------------------------+
//|                                                     WideShootrer |
//|                                           Copyright 2012,Karlson |
//+------------------------------------------------------------------+
#property copyright   "2012, Karlson."
#property link        "https://login.mql5.com/ru/users/Karlson"
#property description "WideShootrer"
#property version "1.00"
//-------------------------------------------------------------------+
#property script_show_inputs
//#define TOSTRING(A) #A + " = " + (string)(A) + "\n"

//input int Zoom=2;//Zoom на котором будет делатся скрин шот
enum ENUM_ZOOMWINDOWS_NAME
  {
ZoomWindows_100=0,
ZoomWindows_125=1,
Zoom_fxsaber=2,
Zoom_notShkala=3,
  };
input ENUM_ZOOMWINDOWS_NAME ZOOM=ENUM_ZOOMWINDOWS_NAME(3);

input double K_Proc=0.001;//Коэффициент расширения экрана для снятия скрина
input bool Use_Shakala=true;//Скриншот со шкалой цен или без шкалы цен

//input string Data_ScreenStart="10.04.2018 10:00";      // - дата с которой будет делаться скриншот
//input string Data_ScreenStop="10.04.2018 22:00";       // - по какую дату будет делаться скриншот (ширина скриншота, фактически конвертированная в итоге в бары).
input int Data_ScreenStart_Shift=0;    // - смещение области для захвата экрана в барах, относительно указанной даты в правую часть графика
input int Data_ScreenStop_Shift=0;     // - смещение области для захвата экрана в барах, относительно указанной даты в левую часть графика
//-------------------------------------------------------------------+
double High[],Low[];
int bars=0;
string Data_ScreenStart="10.04.2018 10:00";      // - дата с которой будет делаться скриншот
string Data_ScreenStop="10.04.2018 22:00";       // - по какую дату будет делаться скриншот (ширина скриншота, фактически конвертированная в итоге в бары).
int Schkala=0;
//-------------------------------------------------------------------+
void OnStart()
  {
   //if(_Digits==5 || _Digits==3) {KF=10;} else {KF=1;}
   
  for (int x=0; x<17+1; x++)
  {
  if (Use_Shakala==true)Schkala=GetWidthScale();   
  Data_ScreenStart=StartDate(x);
  Data_ScreenStop=StopDate(x);
  
  Screen();
//  Print(TOSTRING(GetWidthScale()));
  }

  }

//+------------------------------------------------------------------+

void Screen()
{
int Shift_Start=iBarShift(Symbol(),PERIOD_CURRENT,StringToTime(Data_ScreenStart),false); 
int Shift_Stop=iBarShift(Symbol(),PERIOD_CURRENT,StringToTime(Data_ScreenStop),false); 
//Print(Shift_Start);
int BarsTotal=Bars(Symbol(),PERIOD_CURRENT);
//Shift_Start=100*(-1);
Shift_Start=Shift_Start*(-1);
Shift_Stop=Shift_Stop*(-1);
//--- получим handle текущего графика 
   long handle=ChartID(); 
   if(handle>0) // если получилось, дополнительно настроим 
     { 
     //Print ("handle=",handle);
      //--- отключим автопрокрутку 
      ChartSetInteger(handle,CHART_AUTOSCROLL,false); 
      
      //---отображение сетки на графике
      ChartSetInteger(handle,CHART_SHOW_GRID,false); 

      //---Отображение значения Bid горизонтальной линией на графике      
      ChartSetInteger(handle,CHART_SHOW_BID_LINE,false);

      //---Отображение значения Ask горизонтальной линией на графике
      ChartSetInteger(handle,CHART_SHOW_ASK_LINE,false);
 
      //---Отображение значения Last горизонтальной линией на графике
      ChartSetInteger(handle,CHART_SHOW_LAST_LINE,false);
      
      //--- установим отступ правого края графика 
//      ChartSetInteger(handle,CHART_SHIFT,true); 
      //--- отобразим в виде свечей 
//      ChartSetInteger(handle,CHART_MODE,CHART_CANDLES); 
      //--- установить режим отображения тиковых объемов 
//      ChartSetInteger(handle,CHART_SHOW_VOLUMES,CHART_VOLUME_TICK);  
      //--- получим номер самого первого видимого на графике бара (нумерация как в таймсерии) 
      //long first_bar=ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0); 

int Zoom=(int)ChartGetInteger(handle,CHART_SCALE,0);
//Print(ChartGetInteger(handle,CHART_SCALE,0));

//--принудительный зум
//   ChartSetInteger(handle,CHART_SCALE,Zoom);

// зафиксируем шкалу и установим верх низ
   ChartSetInteger(handle,CHART_SCALEFIX,0,1);
   ChartSetInteger(handle,CHART_AUTOSCROLL,false);

// определяем сколько показывает на графике баров - потребуется для определения ширины скриншота
   int vis_bar=(int)ChartGetInteger(handle,CHART_VISIBLE_BARS);
   //Print("По ширине графика отображено баров=",vis_bar);

// сместим на нужный временной участок график
   ChartNavigate(handle,CHART_END,Shift_Start);
   int _SS=Shift_Start+vis_bar-3;   
   ChartNavigate(handle,CHART_END,_SS);

// определяем первый левый бар.От него будем делать скриншот
   int first_bar=(int)ChartGetInteger(handle,CHART_FIRST_VISIBLE_BAR);

// получаем цены баров в массив за период скрина для установки хай-лоу графика
   bars=Shift_Start*(-1)-Shift_Stop*(-1);
   if(first_bar<bars) {bars=first_bar;} // если график смещен менее чем требуется баров,тогда берем все что есть вправо до текущего времени
   int ch=CopyHigh(_Symbol,_Period,StringToTime(Data_ScreenStart),StringToTime(Data_ScreenStop),High);
   int cl=CopyLow(_Symbol,_Period,StringToTime(Data_ScreenStart),StringToTime(Data_ScreenStop),Low);

// определяем хай лоу на нашем промежутке и устанавливаем верх низ шкалы цены
   double max_price=High[ArrayMaximum(High,0,WHOLE_ARRAY)]*(1.00+K_Proc);
   double min_price=Low[ArrayMinimum(Low,0,WHOLE_ARRAY)]*(1.00-K_Proc);
   
// установим верх низ
   ChartSetDouble(handle,CHART_FIXED_MAX,max_price);
   ChartSetDouble(handle,CHART_FIXED_MIN,min_price);

// получим текущую дату в простом формате для фомирования имени файла
   MqlDateTime day;
   TimeToStruct(StringToTime(Data_ScreenStart),day);
   MqlDateTime dayEnd;
   TimeToStruct(StringToTime(Data_ScreenStop),dayEnd);
   string file=_Symbol+"_"+(string)day.year+"_"+(string)day.mon+"_"+(string)day.day+"_"+(string)day.hour+"_"+(string)day.min+
   "-"+(string)dayEnd.year+"_"+(string)dayEnd.mon+"_"+(string)dayEnd.day+"_"+(string)dayEnd.hour+"_"+(string)dayEnd.min+".png";

// определим высоту и ширину будущего скрина
   int scr_height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);


// Обозначим границы баров вертикальными линиями
   ObjectsDeleteAll(handle,"Shift",-1);
VLineCreate(handle,"Shift_Start",0,StringToTime(Data_ScreenStart),clrYellow,STYLE_SOLID,1,false, 
            false,true,false,0);
VLineCreate(handle,"Shift_Stop",0,StringToTime(Data_ScreenStop),clrYellow,STYLE_SOLID,1,false, 
            false,true,false,0);


// сделаем скриншот
int ZoomX=0;
if (ZOOM==ZoomWindows_100)
   {
      if (Zoom==0)ZoomX=52;
      if (Zoom==1)ZoomX=27;
      if (Zoom==2)ZoomX=15;
      if (Zoom==3)ZoomX=8;
      if (Zoom==4)ZoomX=5;
      if (Zoom==5)ZoomX=3;
   }
if (ZOOM==ZoomWindows_125)
   {
      if (Zoom==0)ZoomX=68;
      if (Zoom==1)ZoomX=35;
      if (Zoom==2)ZoomX=18;
      if (Zoom==3)ZoomX=10;
      if (Zoom==4)ZoomX=6;
      if (Zoom==5)ZoomX=4;
   }

int pp=GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1)+ZoomX);
//int pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+ZoomX);

if (ZOOM==Zoom_fxsaber)
   {
      //pp=GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1))+Schkala*1.3;
      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+2)+Schkala+3;
   }
if (ZOOM==Zoom_notShkala)
   {
 if (Use_Shakala==false)
 
 {
  ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
/*
//      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)*((Shift_Start-Shift_Stop)*(-1)+4);
      pp=(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/((double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS)-0.5)*((Shift_Start-Shift_Stop)*(-1)+0.5);
      ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
//      Print("Число баров - ", file, " - ",((Shift_Start-Shift_Stop)*(-1)+3)," - ",(double)ChartGetInteger(handle,CHART_WIDTH_IN_PIXELS)/(double)ChartGetInteger(handle,CHART_WIDTH_IN_BARS));
   int vis_bar=(int)ChartGetInteger(handle,CHART_VISIBLE_BARS);
Print("Количество баров на графике, доступных для отображения - ",vis_bar);
Print("ширина графика в барах - ",ChartGetInteger(handle,CHART_WIDTH_IN_BARS));
//Количество баров на графике, доступных для отображения
//CHART_WIDTH_IN_BARS - ширина графика в барах
*/
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 
   //pp=LeftPixelOfBar+RightPixelOfBar+GetBarSize(0)*((Shift_Start-Shift_Stop)*(-1)+2);
      if (Zoom==0)ZoomX=6;
      if (Zoom==1)ZoomX=5;
      if (Zoom==2)ZoomX=5;
      if (Zoom==3)ZoomX=4;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;

  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2)+ZoomX;
}

  if (Use_Shakala==true)
  {
   ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,1);//Показывать или нет ценовую шкалу
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_WIDTH_IN_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 

      if (Zoom==0)ZoomX=1;
      if (Zoom==1)ZoomX=1;
      if (Zoom==2)ZoomX=1;
      if (Zoom==3)ZoomX=3;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;    
  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2-0.5)+ZoomX+Schkala;
  
  }
//Print("номер первого (левого) бара на экране - ",FirstBar, " количество видимых баров на экране - ",VisibleBars);
//Print("номер первого (левого) бара на экране - ",FirstBar, " количество видимых баров на экране - ",Shift_Start);

   }


//Print((Shift_Start-Shift_Stop));
//ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу

   ChartScreenShot(handle,file,pp,scr_height,ALIGN_LEFT);
   if(GetLastError()>0) {Print("Error  (",GetLastError(),") ");} ResetLastError();

//---востановим настройки чарта
    ChartSetInteger(handle,CHART_SCALEFIX,0,0);
    ChartSetInteger(handle,CHART_SHOW_PRICE_SCALE ,1);

//---удалим созданные объекты
    ObjectsDeleteAll(handle,"Shift",-1);
     } 
}



//+------------------------------------------------------------------+ 
//| Получим iBarShift для заданного номера бара                      | 
//+------------------------------------------------------------------+    
/*
int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,const bool Exact=false)
  {
   static int Res=-1;
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static bool LastExact=false;
   static int PerSec=::PeriodSeconds(LastTimeFrame);
   
   if (LastTimeFrame!=TimeFrame) PerSec=::PeriodSeconds(TimeFrame);
   time-=time%PerSec;

   if((time!=LastTime) || (Symb!=LastSymb) || (TimeFrame!=LastTimeFrame) || (Exact!=LastExact))
     {
      Res=::Bars(Symb,TimeFrame,time,UINT_MAX)-1;
      if(Res<0) Res=0;

      LastTime = time;
      LastSymb = Symb;
      LastTimeFrame=TimeFrame;
      LastExact=Exact;
     }

   return(Res);
  }   
  */
int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=Bars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==Bars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
datetime iTime(string symbol,int tf,int index)
  {
   if(index < 0) return(-1);
//   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT;
   datetime Arr[];
   if(CopyTime(symbol,timeframe,index,1,Arr)>0)
      return(Arr[0]);
   else return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+  
int GetBarSize( const ulong Chart = 0 )
{
  return(1 << (int)ChartGetInteger(Chart, CHART_SCALE));
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+ 
bool VLineCreate(const long            chart_ID=0,        // ID графика 
                 const string          name="VLine",      // имя линии 
                 const int             sub_window=0,      // номер подокна 
                 datetime              time=0,            // время линии 
                 const color           clr=clrRed,        // цвет линии 
                 const ENUM_LINE_STYLE style=STYLE_SOLID, // стиль линии 
                 const int             width=1,           // толщина линии 
                 const bool            back=false,        // на заднем плане 
                 const bool            selection=true,    // выделить для перемещений 
                 const bool            ray=true,          // продолжение линии вниз 
                 const bool            hidden=true,       // скрыт в списке объектов 
                 const long            z_order=0)         // приоритет на нажатие мышью 
  { 
//--- если время линии не задано, то проводим ее через последний бар 
   if(!time) 
      time=TimeCurrent(); 
//--- сбросим значение ошибки 
   ResetLastError(); 
//--- создадим вертикальную линию 
   if(!ObjectCreate(chart_ID,name,OBJ_VLINE,sub_window,time,0)) 
     { 
      Print(__FUNCTION__, 
            ": не удалось создать вертикальную линию! Код ошибки = ",GetLastError()); 
      return(false); 
     } 
//--- установим цвет линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); 
//--- установим стиль отображения линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); 
//--- установим толщину линии 
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width); 
//--- отобразим на переднем (false) или заднем (true) плане 
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); 
//--- включим (true) или отключим (false) режим перемещения линии мышью 
//--- при создании графического объекта функцией ObjectCreate, по умолчанию объект 
//--- нельзя выделить и перемещать. Внутри же этого метода параметр selection 
//--- по умолчанию равен true, что позволяет выделять и перемещать этот объект 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); 
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); 
//--- включим (true) или отключим (false) режим отображения линии в подокнах графика 
   ObjectSetInteger(chart_ID,name,OBJPROP_RAY,ray); 
//--- скроем (true) или отобразим (false) имя графического объекта в списке объектов 
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); 
//--- установим приоритет на получение события нажатия мыши на графике 
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); 
//--- успешное выполнение 
   return(true); 
  } 
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+   
string StartDate(int i)
  {
   string Date[18]=
     {
      "23.03.2018 10:30",
      "09.02.2018 10:30",
      "15.12.2017 10:30",
      "27.10.2017 10:30",
      "15.09.2017 10:30",
      "28.07.2017 10:30",
      "16.06.2017 10:30",
      "28.04.2017 10:30",
      "24.03.2017 10:30",
      "03.02.2017 10:30",
      "16.12.2016 10:30",
      "28.10.2016 10:30",
      "16.09.2016 10:30",
      "29.07.2016 10:30",
      "10.06.2016 10:30",
      "29.04.2016 10:30",
      "18.03.2016 10:30",
      "29.01.2016 10:30",
     };
   return (Date[i] );
  }
string StopDate(int i)
  {
   string Date[18]=
     {
      "23.03.2018 23:30",
      "09.02.2018 23:30",
      "15.12.2017 23:30",
      "27.10.2017 23:30",
      "15.09.2017 23:30",
      "28.07.2017 23:30",
      "16.06.2017 23:30",
      "28.04.2017 23:30",
      "24.03.2017 23:30",
      "03.02.2017 23:30",
      "16.12.2016 23:30",
      "28.10.2016 23:30",
      "16.09.2016 23:30",
      "29.07.2016 23:30",
      "10.06.2016 23:30",
      "29.04.2016 23:30",
      "18.03.2016 23:30",
      "29.01.2016 23:30",
     };
   return (Date[i] );
  }
//+------------------------------------------------------------------+

// Ширина вертикальной шкалы графика
int GetWidthScale(const long chartID=0)
  {
   const string Name=__FUNCTION__+(string)MathRand();

//   int _Zoom=(int)ChartGetInteger(chartID,CHART_SCALE,0);

   ObjectCreate(chartID,Name,OBJ_CHART,0,0,0);
   ObjectSetInteger(chartID,Name,OBJPROP_XDISTANCE,-1e3);

   const long chart=ObjectGetInteger(chartID,Name,OBJPROP_CHART_ID);
/*
   //--принудительный зум
   ChartSetInteger(chart,CHART_SCALE,_Zoom);
   // зафиксируем шкалу и установим верх низ
   ChartSetInteger(chart,CHART_SCALEFIX,0,1);
   ChartSetInteger(chart,CHART_AUTOSCROLL,false);
*/   
   
   const int Res=(int)(ChartGetInteger(chart,CHART_WIDTH_IN_PIXELS) -
                  (ChartSetInteger(chart,CHART_SHOW,false) ? ChartGetInteger(chart,CHART_WIDTH_IN_PIXELS) : 0));

   ObjectDelete(chartID,Name);

   return(-Res);
  }
 

А какие требования к соседним (стыкующимся) снимкам?

Вы хотите чтобы можно было сложить их все и не получить нигде нахлеста (повторения) баров?

А масштаб чтобы был максимально возможным для данного участка?
 
Kirill Belousov:

А какие требования к соседним (стыкующимся) снимкам?

Вы хотите чтобы можно было сложить их все и не получить нигде нахлеста (повторения) баров?

А масштаб чтобы был максимально возможным для данного участка?

Это независимые снимки, на которых может быть разное число баров, разный зум и так далее, главное это точность позиционирования.

Причина обращения: