概述
结构是一种方便的工具,用于存储、记录和检索属于单个变量的任何定义的逻辑相关数据。
MqlDateTime 结构
数据结构包含八个int类型的字段。
struct MqlDateTime
{
int year; // year
int mon; // month
int day; // day
int hour; // hour
int min; // minutes
int sec; // seconds
int day_of_week; // day of the week (0-Sunday, 1-Monday, ... ,6-Saturday)
int day_of_year; // number of a day in the year (1st of January has number 0)
};
标准函数TimeCurrent()、TimeGMT()、TimeLocal()、TimeTradeServer()和TimeToStruct()用于填充结构字段。
前四个函数,除了返回当前日期、GMT日期、本地计算机时间和交易服务器日期外,每个函数都有一个重载函数。在函数的形式参数中,可以通过引用将日期结构传递给它。执行函数后,传递给函数的结构字段将填充函数返回的日期数据。
TimeToStruct()函数专门用于将datetime值类型(自1970年1月1日起的秒数)中的结构填充到MqlDateTime结构类型变量中。
bool TimeToStruct(
datetime dt, // date and time
MqlDateTime& dt_struct // structure for accepting values
);
如果成功,返回true,否则-false。操作后,日期结构将填充在datetime类型的变量中第一个参数中传递的时间数据。
我们的日期结构已经完整了,但我们如何打印它?有一个标准的TimeToString()函数,它将包含自1970年1月1日以来以秒为单位的时间的值转换为“yyyy.mm.dd hh:min:sec”格式的字符串。
但是该函数不适用于MqlDateTime结构,而是适用于datetime日期。那么,我们应该将结构转换回时间值吗?当然不要。每个函数都有其自身的用途。我们可以从日期结构中单独提取日期和时间的任何组成部分——一年、一个月、一小时、一分钟、一周中的一天等等。。。但是我们怎样才能显示所有的结构数据呢?
ArrayPrint()函数适用于此任务,该函数记录简单类型或简单结构的数组。它以表的形式显示数据,其中列是结构的字段,行表示数组单元。换句话说,为了只显示一个日期的结构,我们需要一个1的数组。对于一个交易周,如果数据来自D1图表,数组大小通常为5个交易日。
MqlDateTime, 打印方法
这样的脚本使用ArrayPrint()打印从日志中的当前时间获得的日期结构:
void OnStart()
{
//--- Declare a date structure variable
MqlDateTime time;
//--- Get the current time and at the same time fill in the date structure
TimeCurrent(time);
//--- Declare an array with the MqlDateTime type and write the data of the filled structure into it
MqlDateTime array[1];
array[0]=time;
//--- Display the header and time using the standard ArrayPrint()
Print("Time current (ArrayPrint):");
ArrayPrint(array);
/* Sample output:
Time current (ArrayPrint):
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2023 7 17 12 8 37 1 197
*/
}
相应地,采用日期结构并将其打印在日志中的函数将如下所示:
//+------------------------------------------------------------------+
//| Take a date structure and display its data to the journal. |
//| Use ArrayPrint() for display |
//+------------------------------------------------------------------+
void MqlDateTimePrint(const MqlDateTime& time_struct)
{
//--- Declare an array with the MqlDateTime type and write the data of the obtained structure into it
MqlDateTime array[1];
array[0]=time_struct;
//--- Print the array
ArrayPrint(array);
/* Sample output:
Time current (ArrayPrint):
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2023 7 17 12 8 37 1 197
*/
}
该函数允许在日志中打印time_struct变量中传递给它的一个日期。
使用上述函数记录单个日期结构的脚本:
void OnStart()
{
//--- Declare a date structure variable
MqlDateTime time;
//--- Get the current time and at the same time fill in the date structure
TimeCurrent(time);
//--- Display the header and time using the standard ArrayPrint()
Print("Time current (ArrayPrint):");
MqlDateTimePrint(time);
/* Sample output:
Time current (ArrayPrint):
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2023 7 17 12 8 37 1 197
*/
}
如果我们需要打印一个日期数组(毕竟这是ArrayPrint()的主要目标),那么我们需要将数据数组传递给datetime函数,填写MqlDateTime数组并打印它。
接受日期时间数组并打印MqlDateTime数组的函数:
//+------------------------------------------------------------------+
//| Accept the datetime array, convert it into MqlDateTime and |
//| display converted data into the journal. |
//| Use ArrayPrint() for display |
//+------------------------------------------------------------------+
void MqlDateTimePrint(const datetime& array_time[])
{
//--- Declare a dynamic array of the MqlDateTime type
MqlDateTime array_struct[];
//--- Get the size of the array passed to the function
int total=(int)array_time.Size();
//--- If an empty array is passed, report on that and leave the function
if(total==0)
{
PrintFormat("%s: Error. Empty array.",__FUNCTION__);
return;
}
//--- Change the size of the MqlDateTime array to match the size of the datetime array
ResetLastError();
if(ArrayResize(array_struct,total)!=total)
{
PrintFormat("%s: ArrayResize() failed. Error %s",__FUNCTION__,(string)GetLastError());
return;
}
//--- Convert dates from the datetime array into the date structure in the MqlDateTime array
for(int i=0;i<total;i++)
{
ResetLastError();
if(!TimeToStruct(array_time[i],array_struct[i]))
PrintFormat("%s: [%s] TimeToStruct() failed. Error %s",__FUNCTION__,(string)i,(string)GetLastError());
}
//--- Print the filled MqlDateTime array
ArrayPrint(array_struct);
/* Sample output:
Time data of the last 10 bars GBPUSD H1 (ArrayPrint):
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2023 7 17 7 0 0 1 197
[1] 2023 7 17 8 0 0 1 197
[2] 2023 7 17 9 0 0 1 197
[3] 2023 7 17 10 0 0 1 197
[4] 2023 7 17 11 0 0 1 197
[5] 2023 7 17 12 0 0 1 197
[6] 2023 7 17 13 0 0 1 197
[7] 2023 7 17 14 0 0 1 197
[8] 2023 7 17 15 0 0 1 197
[9] 2023 7 17 16 0 0 1 197
*/
}
因此,使用上述函数打印日志中datetime数组的脚本将如下所示:
void OnStart()
{
//--- Declare a time array
datetime array[];
//--- Copy the time of the last 10 bars to the array
ResetLastError();
if(CopyTime(Symbol(),Period(),0,10,array)<0)
{
PrintFormat("CopyTime() failed. Error %s",(string)GetLastError());
return;
}
//--- Display the header and the time data array of the last 10 bars using the standard ArrayPrint()
PrintFormat("Time data of the last 10 bars %s %s (ArrayPrint):",Symbol(),StringSubstr(EnumToString(Period()),7));
MqlDateTimePrint(array);
/* Sample output:
Time data of the last 10 bars GBPUSD H1 (ArrayPrint):
[year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
[0] 2023 7 17 7 0 0 1 197
[1] 2023 7 17 8 0 0 1 197
[2] 2023 7 17 9 0 0 1 197
[3] 2023 7 17 10 0 0 1 197
[4] 2023 7 17 11 0 0 1 197
[5] 2023 7 17 12 0 0 1 197
[6] 2023 7 17 13 0 0 1 197
[7] 2023 7 17 14 0 0 1 197
[8] 2023 7 17 15 0 0 1 197
[9] 2023 7 17 16 0 0 1 197
*/
}
用于处理MqlDateTime结构数据的函数。
上面测试的一切都是方便、实用和简洁的。但有时需要更完整的信息,最好是在同样简洁的陈述中。或者,相反,我们可能需要更详细的描述,减少数据呈现的简洁和枯燥。例如,仅一天的数字就可能令人困惑。但如果写的是“星期四”,那么我们马上就明白我们说的是星期四。一个月的数字也是如此——有时看到“07(七月)”比回忆哪个月是第七个要好。。。当然,这可能有些夸张,但这些小的改进仍然增加了便利性。当分析程序日志中的大量条目时,这些小便利加起来会带来非常明显的时间增益。
为了增加这些便利性,我们必须编写您自己的函数,以MqlDateTime格式返回日期描述。
该函数将:
以短格式显示数据(星期几、月、日、年、时间);
在表格视图中显示数据(数据头值);
在我们开始创建返回结构字段描述的函数之前,我们将创建返回周、日和月名称的辅助函数。
辅助函数
要获得一星期中某一天的名称,让我们编写一个简单的函数,根据以数字格式存储星期天的结构字段中的值返回星期天的文本:
//+------------------------------------------------------------------+
//| Return the name of a week day |
//+------------------------------------------------------------------+
string DayWeek(MqlDateTime &date_time)
{
//--- Define a week day name
string dw=EnumToString((ENUM_DAY_OF_WEEK)date_time.day_of_week);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital
if(dw.Lower())
dw.SetChar(0,ushort(dw.GetChar(0)-0x20));
//--- Return a resulting string
return dw;
/* Sample output:
Wednesday
*/
}