diff --git a/Include/MyIncludes/IndicatorExporter.mqh b/Include/MyIncludes/IndicatorExporter.mqh new file mode 100644 index 0000000..cf2ca32 --- /dev/null +++ b/Include/MyIncludes/IndicatorExporter.mqh @@ -0,0 +1,140 @@ +//+------------------------------------------------------------------+ +//| IndicatorExporter.mqh | +//| A toolkit for exporting indicator buffer data to CSV | +//| Copyright 2025, xxxxxxxx | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, xxxxxxxx" +#property link "" + +#include + +//+------------------------------------------------------------------+ +//| Class CIndicatorExporter. | +//| Purpose: Encapsulates all logic for exporting indicator data | +//| to a CSV file. It handles file opening, writing, and | +//| closing operations. | +//+------------------------------------------------------------------+ +class CIndicatorExporter : public CObject + { +private: + int m_file_handle; // Stores the handle of the currently open file + string m_delimiter; // Stores the delimiter character for the CSV + +public: + //--- Constructor and Destructor + CIndicatorExporter(void); + ~CIndicatorExporter(void); + + //--- Public Interface + bool OpenFile(const string file_name, const string delimiter=","); + void CloseFile(void); + bool WriteHeader(const string &header_fields[]); + bool WriteRow(const datetime time_val, const double &data_values[]); + }; + +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CIndicatorExporter::CIndicatorExporter(void) : m_file_handle(INVALID_HANDLE), m_delimiter(",") + { +//--- Initializes member variables to default states + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CIndicatorExporter::~CIndicatorExporter(void) + { +//--- Ensures the file is closed when the object is destroyed + if(m_file_handle != INVALID_HANDLE) + FileClose(m_file_handle); + } + +//+------------------------------------------------------------------+ +//| Opens a file for writing in the MQL5/Files/ directory. | +//| INPUT: file_name - The name of the file to create. | +//| delimiter - The character to use for separating values. | +//| RETURN: true if the file was opened successfully, false otherwise.| +//+------------------------------------------------------------------+ +bool CIndicatorExporter::OpenFile(const string file_name, const string delimiter=",") + { + m_delimiter = delimiter; + ResetLastError(); + +//--- Open the file with write, CSV, and ANSI flags + char separator = (char)StringGetCharacter(m_delimiter, 0); + m_file_handle = FileOpen(file_name, FILE_WRITE | FILE_CSV | FILE_ANSI, separator); + +//--- Check for errors + if(m_file_handle == INVALID_HANDLE) + { + PrintFormat("CIndicatorExporter: Error opening file '%s'. Error code: %d", file_name, GetLastError()); + return false; + } + return true; + } + +//+------------------------------------------------------------------+ +//| Closes the currently open file. | +//+------------------------------------------------------------------+ +void CIndicatorExporter::CloseFile(void) + { + if(m_file_handle != INVALID_HANDLE) + { + FileClose(m_file_handle); + m_file_handle = INVALID_HANDLE; // Reset handle to prevent accidental reuse + } + } + +//+------------------------------------------------------------------+ +//| Writes the header row to the CSV file. | +//| INPUT: header_fields - A string array containing the column names.| +//| RETURN: true on success, false on failure. | +//| NOTE: This version is hardcoded for 4 header fields. | +//+------------------------------------------------------------------+ +bool CIndicatorExporter::WriteHeader(const string &header_fields[]) + { + if(m_file_handle == INVALID_HANDLE) + return false; + +//--- Check array size before writing + if(ArraySize(header_fields) == 4) + { + FileWrite(m_file_handle, header_fields[0], header_fields[1], header_fields[2], header_fields[3]); + } + else + { + Print("CIndicatorExporter: WriteHeader currently supports exactly 4 header fields."); + return false; + } + return true; + } + +//+------------------------------------------------------------------+ +//| Writes a single row of data to the file. | +//| INPUT: time_val - The datetime for the current row. | +//| data_values - A double array with the indicator values. | +//| RETURN: true on success, false on failure. | +//| NOTE: This version is hardcoded for 3 data values. | +//+------------------------------------------------------------------+ +bool CIndicatorExporter::WriteRow(const datetime time_val, const double &data_values[]) + { + if(m_file_handle == INVALID_HANDLE) + return false; + +//--- Convert datetime to a standard string format + string time_str = TimeToString(time_val, TIME_DATE | TIME_MINUTES | TIME_SECONDS); + +//--- Check array size before writing + if(ArraySize(data_values) == 3) + { + FileWrite(m_file_handle, time_str, data_values[0], data_values[1], data_values[2]); + } + else + { + Print("CIndicatorExporter: WriteRow currently supports exactly 3 data values."); + return false; + } + return true; + } +//+------------------------------------------------------------------+ +//+------------------------------------------------------------------+