mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-08-13 20:38:05 +00:00
refactor: UTF-8
This commit is contained in:
@@ -1,78 +1,78 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| AccountInfoDisplayInit.mqh |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//--- Enum to define the row index for each piece of information
|
||||
// This makes the code readable and robust against reordering.
|
||||
enum ENUM_ACCOUNT_INFO_ROWS
|
||||
{
|
||||
ROW_HEADING_BASIC,
|
||||
ROW_LOGIN,
|
||||
ROW_NAME,
|
||||
ROW_SERVER,
|
||||
ROW_COMPANY,
|
||||
ROW_CURRENCY,
|
||||
ROW_CURRENCY_DIGITS,
|
||||
ROW_HEADING_FINANCIAL,
|
||||
ROW_BALANCE,
|
||||
ROW_CREDIT,
|
||||
ROW_PROFIT,
|
||||
ROW_EQUITY,
|
||||
ROW_HEADING_MARGIN,
|
||||
ROW_MARGIN,
|
||||
ROW_MARGIN_FREE,
|
||||
ROW_MARGIN_LEVEL,
|
||||
ROW_MARGIN_CALL,
|
||||
ROW_MARGIN_STOPOUT,
|
||||
ROW_HEADING_RULES,
|
||||
ROW_TRADE_MODE,
|
||||
ROW_LEVERAGE,
|
||||
ROW_MARGIN_MODE,
|
||||
ROW_STOPOUT_MODE,
|
||||
ROW_FIFO_CLOSE,
|
||||
ROW_HEDGE_ALLOWED,
|
||||
ROW_HEADING_PERMISSIONS,
|
||||
ROW_TRADE_ALLOWED,
|
||||
ROW_TRADE_EXPERT,
|
||||
//---
|
||||
ROW_TOTAL_COUNT // Always keep this last to get the total count
|
||||
};
|
||||
|
||||
//--- Array of strings for the labels, matching the enum order
|
||||
const string g_init_labels[ROW_TOTAL_COUNT] =
|
||||
{
|
||||
"I. Basic Info",
|
||||
"Login:",
|
||||
"Name:",
|
||||
"Server:",
|
||||
"Company:",
|
||||
"Currency:",
|
||||
"Currency Digits:",
|
||||
"II. Financials",
|
||||
"Balance:",
|
||||
"Credit:",
|
||||
"Profit:",
|
||||
"Equity:",
|
||||
"III. Margin",
|
||||
"Margin:",
|
||||
"Free Margin:",
|
||||
"Margin Level:",
|
||||
"Margin Call:",
|
||||
"Margin Stopout:",
|
||||
"IV. Rules",
|
||||
"Trade Mode:",
|
||||
"Leverage:",
|
||||
"Margin Mode:",
|
||||
"Stopout Mode:",
|
||||
"FIFO Close:",
|
||||
"Hedge Allowed:",
|
||||
"V. Permissions",
|
||||
"Trade Allowed:",
|
||||
"Expert Advisor:",
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| AccountInfoDisplayInit.mqh |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//--- Enum to define the row index for each piece of information
|
||||
// This makes the code readable and robust against reordering.
|
||||
enum ENUM_ACCOUNT_INFO_ROWS
|
||||
{
|
||||
ROW_HEADING_BASIC,
|
||||
ROW_LOGIN,
|
||||
ROW_NAME,
|
||||
ROW_SERVER,
|
||||
ROW_COMPANY,
|
||||
ROW_CURRENCY,
|
||||
ROW_CURRENCY_DIGITS,
|
||||
ROW_HEADING_FINANCIAL,
|
||||
ROW_BALANCE,
|
||||
ROW_CREDIT,
|
||||
ROW_PROFIT,
|
||||
ROW_EQUITY,
|
||||
ROW_HEADING_MARGIN,
|
||||
ROW_MARGIN,
|
||||
ROW_MARGIN_FREE,
|
||||
ROW_MARGIN_LEVEL,
|
||||
ROW_MARGIN_CALL,
|
||||
ROW_MARGIN_STOPOUT,
|
||||
ROW_HEADING_RULES,
|
||||
ROW_TRADE_MODE,
|
||||
ROW_LEVERAGE,
|
||||
ROW_MARGIN_MODE,
|
||||
ROW_STOPOUT_MODE,
|
||||
ROW_FIFO_CLOSE,
|
||||
ROW_HEDGE_ALLOWED,
|
||||
ROW_HEADING_PERMISSIONS,
|
||||
ROW_TRADE_ALLOWED,
|
||||
ROW_TRADE_EXPERT,
|
||||
//---
|
||||
ROW_TOTAL_COUNT // Always keep this last to get the total count
|
||||
};
|
||||
|
||||
//--- Array of strings for the labels, matching the enum order
|
||||
const string g_init_labels[ROW_TOTAL_COUNT] =
|
||||
{
|
||||
"I. Basic Info",
|
||||
"Login:",
|
||||
"Name:",
|
||||
"Server:",
|
||||
"Company:",
|
||||
"Currency:",
|
||||
"Currency Digits:",
|
||||
"II. Financials",
|
||||
"Balance:",
|
||||
"Credit:",
|
||||
"Profit:",
|
||||
"Equity:",
|
||||
"III. Margin",
|
||||
"Margin:",
|
||||
"Free Margin:",
|
||||
"Margin Level:",
|
||||
"Margin Call:",
|
||||
"Margin Stopout:",
|
||||
"IV. Rules",
|
||||
"Trade Mode:",
|
||||
"Leverage:",
|
||||
"Margin Mode:",
|
||||
"Stopout Mode:",
|
||||
"FIFO Close:",
|
||||
"Hedge Allowed:",
|
||||
"V. Permissions",
|
||||
"Trade Allowed:",
|
||||
"Expert Advisor:",
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
+116
-116
@@ -1,116 +1,116 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HA_Tools.mqh |
|
||||
//| A toolkit for Heiken Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
#include <Object.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHA_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heiken Ashi |
|
||||
//| candle values from standard OHLC data. This class |
|
||||
//| manages its own data buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHA_Calculator : public CObject
|
||||
{
|
||||
public:
|
||||
//--- Public Data Members ---
|
||||
// These buffers store the calculated Heiken Ashi values and are
|
||||
// publicly accessible for indicators to use in their calculations.
|
||||
double ha_open[];
|
||||
double ha_high[];
|
||||
double ha_low[];
|
||||
double ha_close[];
|
||||
|
||||
public:
|
||||
//--- Constructor and Destructor
|
||||
CHA_Calculator(void);
|
||||
~CHA_Calculator(void);
|
||||
|
||||
//--- Public Interface
|
||||
bool Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHA_Calculator::CHA_Calculator(void)
|
||||
{
|
||||
//--- No specific initialization required in the constructor
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHA_Calculator::~CHA_Calculator(void)
|
||||
{
|
||||
//--- No specific deinitialization required in the destructor
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heiken Ashi values for the entire history. |
|
||||
//| INPUT: rates_total - The total number of bars available. |
|
||||
//| prev_calculated - The number of bars calculated previously.|
|
||||
//| open[], high[], low[], close[] - Standard price arrays. |
|
||||
//| RETURN: true if calculation was successful, false otherwise. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHA_Calculator::Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[])
|
||||
{
|
||||
//--- Ensure internal buffers are sized correctly
|
||||
if(ArrayResize(ha_open, rates_total) < 0 ||
|
||||
ArrayResize(ha_high, rates_total) < 0 ||
|
||||
ArrayResize(ha_low, rates_total) < 0 ||
|
||||
ArrayResize(ha_close, rates_total) < 0)
|
||||
{
|
||||
Print("CHA_Calculator: Error resizing Heiken Ashi buffers!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//--- Determine the starting bar for calculation to optimize performance
|
||||
int start_pos = 0;
|
||||
if(prev_calculated > 1)
|
||||
{
|
||||
// On subsequent calls, only calculate new bars
|
||||
start_pos = prev_calculated - 1;
|
||||
}
|
||||
|
||||
//--- Calculate the very first HA bar (index 0) on the first run
|
||||
if(start_pos == 0)
|
||||
{
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
// For the first bar, HA High/Low are the same as the regular High/Low
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
start_pos = 1; // Set the starting position for the main loop to the next bar
|
||||
}
|
||||
|
||||
//--- Main loop to calculate all subsequent HA bars
|
||||
for(int i = start_pos; i < rates_total; i++)
|
||||
{
|
||||
// HA Open is the midpoint of the previous HA bar's body
|
||||
ha_open[i] = (ha_open[i-1] + ha_close[i-1]) / 2.0;
|
||||
// HA Close is the average price of the current regular bar
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
// HA High is the maximum of the current regular High, HA Open, and HA Close
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
// HA Low is the minimum of the current regular Low, HA Open, and HA Close
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| HA_Tools.mqh |
|
||||
//| A toolkit for Heiken Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
#include <Object.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHA_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heiken Ashi |
|
||||
//| candle values from standard OHLC data. This class |
|
||||
//| manages its own data buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHA_Calculator : public CObject
|
||||
{
|
||||
public:
|
||||
//--- Public Data Members ---
|
||||
// These buffers store the calculated Heiken Ashi values and are
|
||||
// publicly accessible for indicators to use in their calculations.
|
||||
double ha_open[];
|
||||
double ha_high[];
|
||||
double ha_low[];
|
||||
double ha_close[];
|
||||
|
||||
public:
|
||||
//--- Constructor and Destructor
|
||||
CHA_Calculator(void);
|
||||
~CHA_Calculator(void);
|
||||
|
||||
//--- Public Interface
|
||||
bool Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHA_Calculator::CHA_Calculator(void)
|
||||
{
|
||||
//--- No specific initialization required in the constructor
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHA_Calculator::~CHA_Calculator(void)
|
||||
{
|
||||
//--- No specific deinitialization required in the destructor
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heiken Ashi values for the entire history. |
|
||||
//| INPUT: rates_total - The total number of bars available. |
|
||||
//| prev_calculated - The number of bars calculated previously.|
|
||||
//| open[], high[], low[], close[] - Standard price arrays. |
|
||||
//| RETURN: true if calculation was successful, false otherwise. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHA_Calculator::Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[])
|
||||
{
|
||||
//--- Ensure internal buffers are sized correctly
|
||||
if(ArrayResize(ha_open, rates_total) < 0 ||
|
||||
ArrayResize(ha_high, rates_total) < 0 ||
|
||||
ArrayResize(ha_low, rates_total) < 0 ||
|
||||
ArrayResize(ha_close, rates_total) < 0)
|
||||
{
|
||||
Print("CHA_Calculator: Error resizing Heiken Ashi buffers!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//--- Determine the starting bar for calculation to optimize performance
|
||||
int start_pos = 0;
|
||||
if(prev_calculated > 1)
|
||||
{
|
||||
// On subsequent calls, only calculate new bars
|
||||
start_pos = prev_calculated - 1;
|
||||
}
|
||||
|
||||
//--- Calculate the very first HA bar (index 0) on the first run
|
||||
if(start_pos == 0)
|
||||
{
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
// For the first bar, HA High/Low are the same as the regular High/Low
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
start_pos = 1; // Set the starting position for the main loop to the next bar
|
||||
}
|
||||
|
||||
//--- Main loop to calculate all subsequent HA bars
|
||||
for(int i = start_pos; i < rates_total; i++)
|
||||
{
|
||||
// HA Open is the midpoint of the previous HA bar's body
|
||||
ha_open[i] = (ha_open[i-1] + ha_close[i-1]) / 2.0;
|
||||
// HA Close is the average price of the current regular bar
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
// HA High is the maximum of the current regular High, HA Open, and HA Close
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
// HA Low is the minimum of the current regular Low, HA Open, and HA Close
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HeikinAshiCalculator.mqh |
|
||||
//| A toolkit for Heikin Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heikin Ashi |
|
||||
//| candle values from standard OHLC data. This class is |
|
||||
//| stateless and operates on external buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_Calculator
|
||||
{
|
||||
public:
|
||||
//--- Public Interface
|
||||
void Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi values for the entire history. |
|
||||
//| This method performs a full recalculation for maximum stability. |
|
||||
//| INPUT: rates_total - The total number of bars available. |
|
||||
//| open[], high[], low[], close[] - Standard price arrays. |
|
||||
//| OUTPUT: ha_open[], ha_high[], ha_low[], ha_close[] - Result arrays.|
|
||||
//+------------------------------------------------------------------+
|
||||
void CHeikinAshi_Calculator::Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[])
|
||||
{
|
||||
//--- Not enough data for calculation
|
||||
if(rates_total < 1)
|
||||
return;
|
||||
|
||||
//--- Calculate the very first Heikin Ashi bar (index 0)
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
// For the first bar, HA High/Low are the same as the regular High/Low
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
|
||||
//--- Main loop to calculate all subsequent Heikin Ashi bars
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
// HA Open is the midpoint of the previous HA bar's body
|
||||
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2.0;
|
||||
// HA Close is the average price of the current regular bar
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
// HA High is the maximum of the current regular High, HA Open, and HA Close
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
// HA Low is the minimum of the current regular Low, HA Open, and HA Close
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| HeikinAshiCalculator.mqh |
|
||||
//| A toolkit for Heikin Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heikin Ashi |
|
||||
//| candle values from standard OHLC data. This class is |
|
||||
//| stateless and operates on external buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_Calculator
|
||||
{
|
||||
public:
|
||||
//--- Public Interface
|
||||
void Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi values for the entire history. |
|
||||
//| This method performs a full recalculation for maximum stability. |
|
||||
//| INPUT: rates_total - The total number of bars available. |
|
||||
//| open[], high[], low[], close[] - Standard price arrays. |
|
||||
//| OUTPUT: ha_open[], ha_high[], ha_low[], ha_close[] - Result arrays.|
|
||||
//+------------------------------------------------------------------+
|
||||
void CHeikinAshi_Calculator::Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[])
|
||||
{
|
||||
//--- Not enough data for calculation
|
||||
if(rates_total < 1)
|
||||
return;
|
||||
|
||||
//--- Calculate the very first Heikin Ashi bar (index 0)
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
// For the first bar, HA High/Low are the same as the regular High/Low
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
|
||||
//--- Main loop to calculate all subsequent Heikin Ashi bars
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
// HA Open is the midpoint of the previous HA bar's body
|
||||
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2.0;
|
||||
// HA Close is the average price of the current regular bar
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
// HA High is the maximum of the current regular High, HA Open, and HA Close
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
// HA Low is the minimum of the current regular Low, HA Open, and HA Close
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HeikinAshi_Tools.mqh |
|
||||
//| A toolkit for various Heikin Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//+==================================================================+
|
||||
//| |
|
||||
//| CLASS 1: CHeikinAshi_Calculator |
|
||||
//| |
|
||||
//+==================================================================+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heikin Ashi |
|
||||
//| candle values from standard OHLC data. This class is |
|
||||
//| stateless and operates on external buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_Calculator
|
||||
{
|
||||
public:
|
||||
//--- Public Interface
|
||||
void Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi values for the entire history. |
|
||||
//+------------------------------------------------------------------+
|
||||
void CHeikinAshi_Calculator::Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[])
|
||||
{
|
||||
if(rates_total < 1)
|
||||
return;
|
||||
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2.0;
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//+==================================================================+
|
||||
//| |
|
||||
//| CLASS 2: CHeikinAshi_RSI_Calculator |
|
||||
//| |
|
||||
//+==================================================================+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_RSI_Calculator |
|
||||
//| Purpose: Calculates RSI based on Heikin Ashi data. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_RSI_Calculator
|
||||
{
|
||||
protected:
|
||||
CHeikinAshi_Calculator m_ha_calculator; // Internal HA calculator
|
||||
|
||||
public:
|
||||
bool Calculate(const int rates_total,
|
||||
const int rsi_period,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &rsi_buffer[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi based RSI |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHeikinAshi_RSI_Calculator::Calculate(const int rates_total,
|
||||
const int rsi_period,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &rsi_buffer[])
|
||||
{
|
||||
if(rates_total <= rsi_period)
|
||||
return false;
|
||||
|
||||
//--- Intermediate buffers
|
||||
double ha_open[], ha_high[], ha_low[], ha_close[];
|
||||
ArrayResize(ha_open, rates_total);
|
||||
ArrayResize(ha_high, rates_total);
|
||||
ArrayResize(ha_low, rates_total);
|
||||
ArrayResize(ha_close, rates_total);
|
||||
|
||||
//--- Step 1: Calculate Heikin Ashi
|
||||
m_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close);
|
||||
|
||||
//--- Step 2: Calculate RSI on HA Close
|
||||
double pos_buffer[], neg_buffer[];
|
||||
ArrayResize(pos_buffer, rates_total);
|
||||
ArrayResize(neg_buffer, rates_total);
|
||||
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
double diff = ha_close[i] - ha_close[i-1];
|
||||
double positive_change = (diff > 0) ? diff : 0;
|
||||
double negative_change = (diff < 0) ? -diff : 0;
|
||||
|
||||
if(i == rsi_period)
|
||||
{
|
||||
double sum_pos=0, sum_neg=0;
|
||||
for(int j=1; j<=rsi_period; j++)
|
||||
{
|
||||
double p_diff = ha_close[j] - ha_close[j-1];
|
||||
sum_pos += (p_diff > 0) ? p_diff : 0;
|
||||
sum_neg += (p_diff < 0) ? -p_diff : 0;
|
||||
}
|
||||
pos_buffer[i] = sum_pos / rsi_period;
|
||||
neg_buffer[i] = sum_neg / rsi_period;
|
||||
}
|
||||
else
|
||||
if(i > rsi_period)
|
||||
{
|
||||
pos_buffer[i] = (pos_buffer[i-1] * (rsi_period - 1) + positive_change) / rsi_period;
|
||||
neg_buffer[i] = (neg_buffer[i-1] * (rsi_period - 1) + negative_change) / rsi_period;
|
||||
}
|
||||
|
||||
if(i >= rsi_period)
|
||||
{
|
||||
if(neg_buffer[i] > 0)
|
||||
{
|
||||
double rs = pos_buffer[i] / neg_buffer[i];
|
||||
rsi_buffer[i] = 100.0 - (100.0 / (1.0 + rs));
|
||||
}
|
||||
else
|
||||
{
|
||||
rsi_buffer[i] = 100.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| HeikinAshi_Tools.mqh |
|
||||
//| A toolkit for various Heikin Ashi calculations |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
//+==================================================================+
|
||||
//| |
|
||||
//| CLASS 1: CHeikinAshi_Calculator |
|
||||
//| |
|
||||
//+==================================================================+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_Calculator. |
|
||||
//| Purpose: Encapsulates the logic for calculating Heikin Ashi |
|
||||
//| candle values from standard OHLC data. This class is |
|
||||
//| stateless and operates on external buffers. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_Calculator
|
||||
{
|
||||
public:
|
||||
//--- Public Interface
|
||||
void Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi values for the entire history. |
|
||||
//+------------------------------------------------------------------+
|
||||
void CHeikinAshi_Calculator::Calculate(const int rates_total,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &ha_open[],
|
||||
double &ha_high[],
|
||||
double &ha_low[],
|
||||
double &ha_close[])
|
||||
{
|
||||
if(rates_total < 1)
|
||||
return;
|
||||
|
||||
ha_open[0] = (open[0] + close[0]) / 2.0;
|
||||
ha_close[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0;
|
||||
ha_high[0] = high[0];
|
||||
ha_low[0] = low[0];
|
||||
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2.0;
|
||||
ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
|
||||
ha_high[i] = MathMax(high[i], MathMax(ha_open[i], ha_close[i]));
|
||||
ha_low[i] = MathMin(low[i], MathMin(ha_open[i], ha_close[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//+==================================================================+
|
||||
//| |
|
||||
//| CLASS 2: CHeikinAshi_RSI_Calculator |
|
||||
//| |
|
||||
//+==================================================================+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHeikinAshi_RSI_Calculator |
|
||||
//| Purpose: Calculates RSI based on Heikin Ashi data. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHeikinAshi_RSI_Calculator
|
||||
{
|
||||
protected:
|
||||
CHeikinAshi_Calculator m_ha_calculator; // Internal HA calculator
|
||||
|
||||
public:
|
||||
bool Calculate(const int rates_total,
|
||||
const int rsi_period,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &rsi_buffer[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates Heikin Ashi based RSI |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHeikinAshi_RSI_Calculator::Calculate(const int rates_total,
|
||||
const int rsi_period,
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
double &rsi_buffer[])
|
||||
{
|
||||
if(rates_total <= rsi_period)
|
||||
return false;
|
||||
|
||||
//--- Intermediate buffers
|
||||
double ha_open[], ha_high[], ha_low[], ha_close[];
|
||||
ArrayResize(ha_open, rates_total);
|
||||
ArrayResize(ha_high, rates_total);
|
||||
ArrayResize(ha_low, rates_total);
|
||||
ArrayResize(ha_close, rates_total);
|
||||
|
||||
//--- Step 1: Calculate Heikin Ashi
|
||||
m_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close);
|
||||
|
||||
//--- Step 2: Calculate RSI on HA Close
|
||||
double pos_buffer[], neg_buffer[];
|
||||
ArrayResize(pos_buffer, rates_total);
|
||||
ArrayResize(neg_buffer, rates_total);
|
||||
|
||||
for(int i = 1; i < rates_total; i++)
|
||||
{
|
||||
double diff = ha_close[i] - ha_close[i-1];
|
||||
double positive_change = (diff > 0) ? diff : 0;
|
||||
double negative_change = (diff < 0) ? -diff : 0;
|
||||
|
||||
if(i == rsi_period)
|
||||
{
|
||||
double sum_pos=0, sum_neg=0;
|
||||
for(int j=1; j<=rsi_period; j++)
|
||||
{
|
||||
double p_diff = ha_close[j] - ha_close[j-1];
|
||||
sum_pos += (p_diff > 0) ? p_diff : 0;
|
||||
sum_neg += (p_diff < 0) ? -p_diff : 0;
|
||||
}
|
||||
pos_buffer[i] = sum_pos / rsi_period;
|
||||
neg_buffer[i] = sum_neg / rsi_period;
|
||||
}
|
||||
else
|
||||
if(i > rsi_period)
|
||||
{
|
||||
pos_buffer[i] = (pos_buffer[i-1] * (rsi_period - 1) + positive_change) / rsi_period;
|
||||
neg_buffer[i] = (neg_buffer[i-1] * (rsi_period - 1) + negative_change) / rsi_period;
|
||||
}
|
||||
|
||||
if(i >= rsi_period)
|
||||
{
|
||||
if(neg_buffer[i] > 0)
|
||||
{
|
||||
double rs = pos_buffer[i] / neg_buffer[i];
|
||||
rsi_buffer[i] = 100.0 - (100.0 / (1.0 + rs));
|
||||
}
|
||||
else
|
||||
{
|
||||
rsi_buffer[i] = 100.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
@@ -1,140 +1,140 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| IndicatorExporter.mqh |
|
||||
//| A toolkit for exporting indicator buffer data to CSV |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
#include <Object.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| IndicatorExporter.mqh |
|
||||
//| A toolkit for exporting indicator buffer data to CSV |
|
||||
//| Copyright 2025, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, xxxxxxxx"
|
||||
#property link ""
|
||||
|
||||
#include <Object.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Reference in New Issue
Block a user