You don't need to add the path yourself.
string screenshot_path = "Screenshots\\" + file_name;
Here is the updated script:
//+------------------------------------------------------------------+ //| Expert Advisor Template.mq5 | //| | //+------------------------------------------------------------------+ // Include necessary files #include <Files/File.mqh> #include <Files/FileBin.mqh> #include <Arrays/ArrayString.mqh> #include <Arrays/ArrayObj.mqh> input string FileName = "test.csv"; // CSV file name input string SymbolName = "GBPUSD"; // Symbol name input string StartTime = "1999.01.15 20:45:00"; // Start time for the visualizer input string EndTime = "2022.06.02 05:00:00"; // End time for the visualizer input string ScreenshotFolder = "Screenshots"; // Folder name for storing screenshots // Declare your custom structure for the data struct Data { datetime sample_time; datetime ht_time; double ht_open; double ht_high; double ht_low; double ht_close; double ht_bollinger_mid; double ht_OHLC_max; double ht_OHLC_min; int ht_liq_type; datetime lt_time; double lt_open; double lt_high; double lt_low; double lt_close; double lt_bollinger_mid; double lt_OHLC_max; double lt_OHLC_min; double lt_valid_range; double lt_tap_range; string dist_prox; datetime tapped_by; double sl; double entry; double tp; string dir; bool FromCSVLine(string line) { StringReplace(line, "\"", ""); // Remove double quotes from the line string parts[]; StringSplit(line, ',', parts); // Split the line using comma as a delimiter if(ArraySize(parts) != 27) // Check that there are 27 fields in the line return false; // Parse and populate the data structure sample_time = StringToTime(parts[1]); ht_time = StringToTime(parts[2]); ht_open = StringToDouble(parts[3]); ht_high = StringToDouble(parts[4]); ht_low = StringToDouble(parts[5]); ht_close = StringToDouble(parts[6]); ht_bollinger_mid = StringToDouble(parts[7]); ht_OHLC_max = StringToDouble(parts[8]); ht_OHLC_min = StringToDouble(parts[9]); ht_liq_type = int(StringToInteger(parts[10])); lt_time = StringToTime(parts[11]); lt_open = StringToDouble(parts[12]); lt_high = StringToDouble(parts[13]); lt_low = StringToDouble(parts[14]); lt_close = StringToDouble(parts[15]); lt_bollinger_mid = StringToDouble(parts[16]); lt_OHLC_max = StringToDouble(parts[17]); lt_OHLC_min = StringToDouble(parts[18]); lt_valid_range = StringToDouble(parts[19]); lt_tap_range = StringToDouble(parts[20]); dist_prox = parts[21]; tapped_by = StringToTime(parts[22]); sl = StringToDouble(parts[23]); entry = StringToDouble(parts[24]); tp = StringToDouble(parts[25]); dir = parts[26]; return true; } }; int getCsvLines(const string fName, string &l[], int flag = 0, ushort sepLine = '\n') { uchar Bytes[]; int numLines = FileLoad(fName, Bytes, flag) ? StringSplit(CharArrayToString(Bytes), sepLine, l) : 0; Print("getCsvLines: Read ", numLines, " lines from file: ", fName); return numLines; } bool ReadCSVFile(const string filename, Data &data[], uint &count) { string lines[]; int numLines = getCsvLines(filename, lines); if (numLines <= 0) { Print("Error reading file: ", filename); return false; } Print("Header: ", lines[0]); count = 0; for (int i = 1; i < numLines; i++) { string line = lines[i]; if (StringLen(line) == 0) { Print("Skipping empty line ", i); continue; } Data newData; if (newData.FromCSVLine(line)) { ArrayResize(data, count + 1); data[count] = newData; count++; } else { Print("Failed to parse line ", i, ": ", line); break; } } Print("ReadCSVFile: Parsed ", count, " lines successfully."); return count > 0; } // GetCandleInformation function definition void GetCandleInformation(string symbol, ENUM_TIMEFRAMES sample_time_tf, ENUM_TIMEFRAMES ht_time_tf, ENUM_TIMEFRAMES lt_time_tf, int index, Data& data) { data.sample_time = iTime(symbol, sample_time_tf, index); data.ht_time = iTime(symbol, ht_time_tf, index); data.ht_open = iOpen(symbol, ht_time_tf, index); data.ht_high = iHigh(symbol, ht_time_tf, index); data.ht_low = iLow(symbol, ht_time_tf, index); data.ht_close = iClose(symbol, ht_time_tf, index); double ht_bollinger_mid[]; int ht_bands_handle = iBands(symbol, ht_time_tf, 20, 2, 0, PRICE_CLOSE); if(CopyBuffer(ht_bands_handle, 1, 0, 1, ht_bollinger_mid) != 1) { Print("Failed to get bollinger mid value for HT at index ", index); return; } data.ht_bollinger_mid = ht_bollinger_mid[0]; data.ht_OHLC_max = MathMax(MathMax(data.ht_open, data.ht_high), MathMax(data.ht_low, data.ht_close)); data.ht_OHLC_min = MathMin(MathMin(data.ht_open, data.ht_high), MathMin(data.ht_low, data.ht_close)); data.ht_liq_type = (data.ht_close > data.ht_bollinger_mid) ? 1 : 2; data.lt_time = iTime(symbol, lt_time_tf, index); data.lt_open = iOpen(symbol, lt_time_tf, index); data.lt_high = iHigh(symbol, lt_time_tf, index); data.lt_low = iLow(symbol, lt_time_tf, index); data.lt_close = iClose(symbol, lt_time_tf, index); double lt_bollinger_mid[]; int lt_bands_handle = iBands(symbol, lt_time_tf, 20, 2, 0, PRICE_CLOSE); if(CopyBuffer(lt_bands_handle, 1, 0, 1, lt_bollinger_mid) != 1) { Print("Failed to get bollinger mid value for LT at index ", index); return; } data.lt_bollinger_mid = lt_bollinger_mid[0]; data.lt_OHLC_max = MathMax(MathMax(data.lt_open, data.lt_high), MathMax(data.lt_low, data.lt_close)); data.lt_OHLC_min = MathMin(MathMin(data.lt_open, data.lt_high), MathMin(data.lt_low, data.lt_close)); data.lt_valid_range = data.lt_close - data.lt_open; data.lt_tap_range = MathAbs(data.ht_close - data.lt_close) / (data.ht_OHLC_max - data.ht_OHLC_min); data.dist_prox = (data.ht_liq_type == 1) ? "far" : "close"; data.tapped_by = (data.ht_close > data.lt_close) ? data.ht_time : data.lt_time; data.sl = (data.ht_liq_type == 1) ? data.lt_low : data.lt_high; data.entry = (data.ht_liq_type == 1) ? data.lt_close - data.lt_valid_range * 2 : data.ht_close + data.lt_valid_range * 2; data.tp = (data.ht_liq_type == 1) ? data.lt_close - data.lt_tap_range * data.lt_valid_range : data.ht_close + data.lt_tap_range * data.lt_valid_range; data.dir = (data.ht_close > data.lt_close) ? "long" : "short"; } void DrawMarkersAndLines(Data &data) { datetime chartTime = iTime(SymbolName, PERIOD_M15, iBarShift(SymbolName, PERIOD_M15, data.sample_time)); if (chartTime != WRONG_VALUE) { // Create BuyArrow if (data.dir == "long") { ObjectCreate(ChartID(), "BuyArrow", OBJ_ARROW, 0, chartTime, data.entry); ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_ARROWCODE, 233); // Up arrow ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_COLOR, clrBlue); ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_WIDTH, 2); Print("Buy Arrow created at ", TimeToString(chartTime)); } // Create SellArrow if (data.dir == "short") { ObjectCreate(ChartID(), "SellArrow", OBJ_ARROW, 0, chartTime, data.entry); ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_ARROWCODE, 234); // Down arrow ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_COLOR, clrRed); ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_WIDTH, 2); Print("Sell Arrow created at ", TimeToString(chartTime)); } // Create StopLoss ObjectCreate(ChartID(), "StopLoss", OBJ_HLINE, 0, chartTime, data.sl); ObjectSetInteger(ChartID(), "StopLoss", OBJPROP_COLOR, clrOrange); ObjectSetInteger(ChartID(), "StopLoss", OBJPROP_WIDTH, 1); ObjectSetString(ChartID(), "StopLoss", OBJPROP_TEXT, "SL"); Print("Stop Loss created at ", TimeToString(chartTime)); // Create TakeProfit ObjectCreate(ChartID(), "TakeProfit", OBJ_HLINE, 0, chartTime, data.tp); ObjectSetInteger(ChartID(), "TakeProfit", OBJPROP_COLOR, clrGreen); ObjectSetInteger(ChartID(), "TakeProfit", OBJPROP_WIDTH, 1); ObjectSetString(ChartID(), "TakeProfit", OBJPROP_TEXT, "TP"); Print("Take Profit created at ", TimeToString(chartTime)); // Add marker for sample_time candle ObjectCreate(ChartID(), "SampleTime", OBJ_VLINE, 0, data.sample_time,0); ObjectSetInteger(ChartID(), "SampleTime", OBJPROP_COLOR, clrYellow); ObjectSetInteger(ChartID(), "SampleTime", OBJPROP_WIDTH, 1); Print("Sample Time marker created at ", TimeToString(data.sample_time)); // Add marker for ht_time candle ObjectCreate(ChartID(), "HtTime", OBJ_VLINE, 0, data.ht_time,0); ObjectSetInteger(ChartID(), "HtTime", OBJPROP_COLOR, clrPurple); ObjectSetInteger(ChartID(), "HtTime", OBJPROP_WIDTH, 1); Print("HT Time marker created at ", TimeToString(data.ht_time)); } else { Print("Invalid chart index for sample_time=", TimeToString(data.sample_time)); } } // SaveScreenshot function definition bool save_screenshot(string screenshot_path, datetime sample_time) { Print("Attempting to save screenshot: ", screenshot_path); int chartIndex = iBarShift(_Symbol, PERIOD_M15, sample_time); if(chartIndex == -1) { Print("Failed to find the chart index for sample_time=", TimeToString(sample_time)); return false; } ChartNavigate(ChartID(), CHART_BEGIN, chartIndex); // Navigate to the specific chart index Sleep(5000); // Add a delay of 3 seconds before taking the screenshot if (ChartScreenShot(ChartID(), screenshot_path, 800, 600, ALIGN_RIGHT)) { Print("Screenshot saved: ", screenshot_path); return true; } else { Print("Failed to save screenshot: ", screenshot_path); Print("Error: ", GetLastError()); return false; } } // OnStart function int OnInit() { Print("OnInit Checkpoint: Initialization started"); Print("Using file name: ", FileName); Data data[]; uint count = 0; if (ReadCSVFile(FileName, data, count)) { Print("CSV file read successfully. Number of data rows: ", count); } else { Print("Error reading CSV file."); } datetime start_time = StringToTime(StartTime); datetime end_time = StringToTime(EndTime); for (uint i = 0; i < count; i++) { if (data[i].sample_time < start_time || data[i].sample_time > end_time) { continue; } Print("Current index: ", i); Print("Sample time: ", TimeToString(data[i].sample_time)); int chartIndex = iBarShift(_Symbol, PERIOD_M15, data[i].sample_time); Print("Chart index: ", chartIndex); GetCandleInformation(SymbolName, PERIOD_M15, PERIOD_H4, PERIOD_M15, chartIndex, data[i]); Sleep(3000); ChartNavigate(ChartID(), CHART_BEGIN, chartIndex - 10); DrawMarkersAndLines(data[i]); ChartRedraw(); string file_name = StringFormat("s_t_%s_%s_%d.jpg", FileName, TimeToString(data[i].sample_time, TIME_DATE | TIME_SECONDS), i); StringReplace(file_name, ":", "_"); // Replace colons with underscores StringReplace(file_name, " ", "_"); // Replace spaces with underscores string screenshot_path = ScreenshotFolder + "\\" + file_name; if (!save_screenshot(screenshot_path, data[i].sample_time)) { Print("Failed to save screenshot: ", screenshot_path); Print("Failed to save screenshot for index: ", i); } } return(INIT_SUCCEEDED); }
Screenshots are now being sucesfully saved and created. I have a new problem. The screenshot is always taken in the real time chart, and doesn't go back to the sample data where all the markers are created.
Here is the updated script:
Did you try to search the forum before asking ?
- 2020.07.25
- www.mql5.com
Yes.
I used ALLIGN_LEFT before but it still doesn't take screenshots at the exact sample data in my script. It takes screenshots in different places but wrong places.
I want it to go to the chart index of the sample data.
int chartIndex = iBarShift(_Symbol, PERIOD_M15, data[i].sample_time);
ChartNavigate(ChartID(), CHART_BEGIN, chartIndex); // Navigate to the specific chart index
But it doesn't go there.
Yes.
I used ALLIGN_LEFT before but it still doesn't take screenshots at the exact sample data in my script. It takes screenshots in different places but wrong places.
I want it to go to the chart index of the sample data.
But it doesn't go there.
You said you used ALIGN_LEFT but your posted code show something else.
We don't know what you are doing, what you are expecting ?
Show the values used (index, datetime...) and the screenshot you get.
Otherwise it's just waste of time.
You said you used ALIGN_LEFT but your posted code show something else.
We don't know what you are doing, what you are expecting ?
Show the values used (index, datetime...) and the screenshot you get.
Otherwise it's just waste of time.
You're right. I'm sorry. I figured it out and now screenshots are being taken perfectly. I have one last issue.
I need to build a period separator. So if lower timeframe is M15 and higher timeframe is H4, draw a shaded region (like in the photo attached) on the lower timeframe candles to separate every H4 candle. So 1 H4 candle is 1 shaded region on M15. Basically dividing M15 candles into H4 regions. For example: if 1999.01.19 20:00:00 is the higher timeframe candle, the left-most candle in the shaded region is 1999.01.19 20:00:00, and the right-most candle that should be marked (with the same colour) is 1999.01.19 23:45:00.
Need to add this background for all M15 candles. (image.png attached)
I want to use this indicator https://www.mql5.com/en/code/86 for the background object.
I'm not even sure where I should start and how to do it, can someone give me a suggestion?
Here's the updated code:
//+------------------------------------------------------------------+ //| Expert Advisor Template.mq5 | //| | //+------------------------------------------------------------------+ // Include necessary files #include <Files/File.mqh> #include <Files/FileBin.mqh> #include <Arrays/ArrayString.mqh> #include <Arrays/ArrayObj.mqh> input string FileName = "test.csv"; // CSV file name input string SymbolName = "GBPUSD"; // Symbol name input string StartTime = "1999.01.15 20:45:00"; // Start time for the visualizer input string EndTime = "2022.06.02 05:00:00"; // End time for the visualizer input string ScreenshotFolder = "Screenshots"; // Folder name for storing screenshots // Declare your custom structure for the data struct Data { datetime sample_time; datetime ht_time; double ht_open; double ht_high; double ht_low; double ht_close; double ht_bollinger_mid; double ht_OHLC_max; double ht_OHLC_min; int ht_liq_type; datetime lt_time; double lt_open; double lt_high; double lt_low; double lt_close; double lt_bollinger_mid; double lt_OHLC_max; double lt_OHLC_min; double lt_valid_range; double lt_tap_range; string dist_prox; datetime tapped_by; double sl; double entry; double tp; string dir; bool FromCSVLine(string line) { StringReplace(line, "\"", ""); // Remove double quotes from the line string parts[]; StringSplit(line, ',', parts); // Split the line using comma as a delimiter if(ArraySize(parts) != 27) // Check that there are 27 fields in the line return false; // Parse and populate the data structure sample_time = StringToTime(parts[1]); ht_time = StringToTime(parts[2]); ht_open = StringToDouble(parts[3]); ht_high = StringToDouble(parts[4]); ht_low = StringToDouble(parts[5]); ht_close = StringToDouble(parts[6]); ht_bollinger_mid = StringToDouble(parts[7]); ht_OHLC_max = StringToDouble(parts[8]); ht_OHLC_min = StringToDouble(parts[9]); ht_liq_type = int(StringToInteger(parts[10])); lt_time = StringToTime(parts[11]); lt_open = StringToDouble(parts[12]); lt_high = StringToDouble(parts[13]); lt_low = StringToDouble(parts[14]); lt_close = StringToDouble(parts[15]); lt_bollinger_mid = StringToDouble(parts[16]); lt_OHLC_max = StringToDouble(parts[17]); lt_OHLC_min = StringToDouble(parts[18]); lt_valid_range = StringToDouble(parts[19]); lt_tap_range = StringToDouble(parts[20]); dist_prox = parts[21]; tapped_by = StringToTime(parts[22]); sl = StringToDouble(parts[23]); entry = StringToDouble(parts[24]); tp = StringToDouble(parts[25]); dir = parts[26]; return true; } }; int getCsvLines(const string fName, string &l[], int flag = 0, ushort sepLine = '\n') { uchar Bytes[]; int numLines = FileLoad(fName, Bytes, flag) ? StringSplit(CharArrayToString(Bytes), sepLine, l) : 0; Print("getCsvLines: Read ", numLines, " lines from file: ", fName); return numLines; } bool ReadCSVFile(const string filename, Data &data[], uint &count) { string lines[]; int numLines = getCsvLines(filename, lines); if (numLines <= 0) { Print("Error reading file: ", filename); return false; } Print("Header: ", lines[0]); count = 0; for (int i = 1; i < numLines; i++) { string line = lines[i]; if (StringLen(line) == 0) { Print("Skipping empty line ", i); continue; } Data newData; if (newData.FromCSVLine(line)) { ArrayResize(data, count + 1); data[count] = newData; count++; } else { Print("Failed to parse line ", i, ": ", line); break; } } Print("ReadCSVFile: Parsed ", count, " lines successfully."); return count > 0; } // GetCandleInformation function definition void GetCandleInformation(string symbol, ENUM_TIMEFRAMES sample_time_tf, ENUM_TIMEFRAMES ht_time_tf, ENUM_TIMEFRAMES lt_time_tf, int index, Data& data) { data.sample_time = iTime(symbol, sample_time_tf, index); data.ht_open = iOpen(symbol, ht_time_tf, index); data.ht_high = iHigh(symbol, ht_time_tf, index); data.ht_low = iLow(symbol, ht_time_tf, index); data.ht_close = iClose(symbol, ht_time_tf, index); double ht_bollinger_mid[]; int ht_bands_handle = iBands(symbol, ht_time_tf, 20, 2, 0, PRICE_CLOSE); if(CopyBuffer(ht_bands_handle, 1, 0, 1, ht_bollinger_mid) != 1) { Print("Failed to get bollinger mid value for HT at index ", index); return; } data.ht_bollinger_mid = ht_bollinger_mid[0]; data.ht_OHLC_max = MathMax(MathMax(data.ht_open, data.ht_high), MathMax(data.ht_low, data.ht_close)); data.ht_OHLC_min = MathMin(MathMin(data.ht_open, data.ht_high), MathMin(data.ht_low, data.ht_close)); data.ht_liq_type = (data.ht_close > data.ht_bollinger_mid) ? 1 : 2; data.lt_time = iTime(symbol, lt_time_tf, index); data.lt_open = iOpen(symbol, lt_time_tf, index); data.lt_high = iHigh(symbol, lt_time_tf, index); data.lt_low = iLow(symbol, lt_time_tf, index); data.lt_close = iClose(symbol, lt_time_tf, index); double lt_bollinger_mid[]; int lt_bands_handle = iBands(symbol, lt_time_tf, 20, 2, 0, PRICE_CLOSE); if(CopyBuffer(lt_bands_handle, 1, 0, 1, lt_bollinger_mid) != 1) { Print("Failed to get bollinger mid value for LT at index ", index); return; } data.lt_bollinger_mid = lt_bollinger_mid[0]; data.lt_OHLC_max = MathMax(MathMax(data.lt_open, data.lt_high), MathMax(data.lt_low, data.lt_close)); data.lt_OHLC_min = MathMin(MathMin(data.lt_open, data.lt_high), MathMin(data.lt_low, data.lt_close)); data.lt_valid_range = data.lt_close - data.lt_open; data.lt_tap_range = MathAbs(data.ht_close - data.lt_close) / (data.ht_OHLC_max - data.ht_OHLC_min); data.dist_prox = (data.ht_liq_type == 1) ? "far" : "close"; data.tapped_by = (data.ht_close > data.lt_close) ? data.ht_time : data.lt_time; data.sl = (data.ht_liq_type == 1) ? data.lt_low : data.lt_high; data.entry = (data.ht_liq_type == 1) ? data.lt_close - data.lt_valid_range * 2 : data.ht_close + data.lt_valid_range * 2; data.tp = (data.ht_liq_type == 1) ? data.lt_close - data.lt_tap_range * data.lt_valid_range : data.ht_close + data.lt_tap_range * data.lt_valid_range; data.dir = (data.ht_close > data.lt_close) ? "long" : "short"; } void DrawMarkersAndLines(Data &data) { datetime chartTime = iTime(SymbolName, PERIOD_M15, iBarShift(SymbolName, PERIOD_M15, data.sample_time)); if (chartTime != WRONG_VALUE) { // Create BuyArrow if (data.dir == "long") { ObjectCreate(ChartID(), "BuyArrow", OBJ_ARROW, 0, chartTime, data.entry); ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_ARROWCODE, 233); // Up arrow ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_COLOR, clrBlue); ObjectSetInteger(ChartID(), "BuyArrow", OBJPROP_WIDTH, 1); Print("Buy Arrow created at ", TimeToString(chartTime)); } // Create SellArrow if (data.dir == "short") { double sellArrowPrice = data.lt_close + data.lt_valid_range * 2; // Calculate the correct price for Sell Arrow ObjectCreate(ChartID(), "SellArrow", OBJ_ARROW, 0, chartTime, sellArrowPrice); ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_ARROWCODE, 234); // Down arrow ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_COLOR, clrRed); ObjectSetInteger(ChartID(), "SellArrow", OBJPROP_WIDTH, 1); Print("Sell Arrow created at ", TimeToString(chartTime)); } // Create StopLoss ObjectCreate(ChartID(), "StopLoss", OBJ_HLINE, 0, chartTime, data.sl); ObjectSetInteger(ChartID(), "StopLoss", OBJPROP_COLOR, clrOrange); ObjectSetInteger(ChartID(), "StopLoss", OBJPROP_WIDTH, 1); ObjectSetString(ChartID(), "StopLoss", OBJPROP_TEXT, "SL"); Print("Stop Loss created at ", TimeToString(chartTime)); // Create TakeProfit ObjectCreate(ChartID(), "TakeProfit", OBJ_HLINE, 0, chartTime, data.tp); ObjectSetInteger(ChartID(), "TakeProfit", OBJPROP_COLOR, clrGreen); ObjectSetInteger(ChartID(), "TakeProfit", OBJPROP_WIDTH, 1); ObjectSetString(ChartID(), "TakeProfit", OBJPROP_TEXT, "TP"); Print("Take Profit created at ", TimeToString(chartTime)); // Create Entry Line ObjectCreate(ChartID(), "Entry", OBJ_HLINE, 0, chartTime, data.entry); ObjectSetInteger(ChartID(), "Entry", OBJPROP_COLOR, clrAqua); ObjectSetInteger(ChartID(), "Entry", OBJPROP_WIDTH, 1); ObjectSetString(ChartID(), "Entry", OBJPROP_TEXT, "Entry"); Print("Entry line created at ", TimeToString(chartTime)); } else { Print("Invalid chart index for sample_time=", TimeToString(data.sample_time)); } } // SaveScreenshot function definition bool save_screenshot(string screenshot_path, int chartShift) { Print("Attempting to save screenshot: ", screenshot_path); int centeredChartShift = chartShift - 70; // Adjust the number '10' to shift the desired number of candles before the chartShift if (centeredChartShift < 0) { centeredChartShift = 0; } ChartNavigate(ChartID(), CHART_BEGIN, centeredChartShift); // Navigate to the specific chart shift Sleep(1000); if (ChartScreenShot(ChartID(), screenshot_path, 1024, 768, ALIGN_LEFT)) { Print("Screenshot saved: ", screenshot_path); return true; } else { Print("Failed to save screenshot: ", screenshot_path); Print("Error: ", GetLastError()); return false; } } // OnStart function int OnInit() { Print("OnInit Checkpoint: Initialization started"); Print("Using file name: ", FileName); Data data[]; uint count = 0; if (ReadCSVFile(FileName, data, count)) { Print("CSV file read successfully. Number of data rows: ", count); } else { Print("Error reading CSV file."); } datetime start_time = StringToTime(StartTime); datetime end_time = StringToTime(EndTime); int totalBars = iBars(_Symbol, PERIOD_M15); for (uint i = 0; i < count; i++) { if (data[i].sample_time < start_time || data[i].sample_time > end_time) { continue; } Print("Current index: ", i); Print("Sample time: ", TimeToString(data[i].sample_time)); int chartIndex = iBarShift(_Symbol, PERIOD_M15, data[i].sample_time); Print("Chart index: ", chartIndex); GetCandleInformation(SymbolName, PERIOD_M15, PERIOD_H4, PERIOD_M15, chartIndex, data[i]); Sleep(1000); ChartNavigate(ChartID(), CHART_BEGIN, chartIndex - 10); DrawMarkersAndLines(data[i]); string file_name = StringFormat("s_t_%s_%s_%d.jpg", FileName, TimeToString(data[i].sample_time, TIME_DATE | TIME_SECONDS), i); StringReplace(file_name, ":", "_"); // Replace colons with underscores StringReplace(file_name, " ", "_"); // Replace spaces with underscores string screenshot_path = ScreenshotFolder + "\\" + file_name; // Calculate the chart shift value to navigate from the oldest to the most recent bar int chartShift = totalBars - chartIndex - 1; if (!save_screenshot(screenshot_path, chartShift)) { Print("Failed to save screenshot: ", screenshot_path); Print("Failed to save screenshot for index: ", i); } ChartRedraw(); } return(INIT_SUCCEEDED); }
- www.mql5.com
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
In the following Expert Advisor the screenshots aren't being saved in the given path. I've tried changing the path and it keeps not creating the screenshot.
In the terminal upon adding the script to the chart I get:
2023.04.14 15:20:20.328 mt5_chart_marker (GBPUSD,M15) Attempting to save screenshot: C:\Users\manu_\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Files\Screenshots\s_t_2022.05.24_11_30_00_24.jpg
But when I go to the folder there is no screenshot. What might be the issue?