English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
MQL5 프로그래밍 기본: 시간

MQL5 프로그래밍 기본: 시간

MetaTrader 5 | 2 9월 2021, 16:48
337 0
Dmitry Fedoseev
Dmitry Fedoseev

내용


소개

MQL5는 시간 작업을 위한 여러 가지 간단한 기능을 제공하며 이러한 기능에 익숙해지는 데 어려움이 없을 것입니다. 날짜와 시간을 사용해야 하는 작업의 범위는 매우 작습니다. 주요 작업은 다음과 같습니다.

  • 주어진 시간에 특정 작업을 수행하려면(그림 1). 이러한 작업은 매일 같은 시간에 수행되거나 주 단위로 주어진 시간과 요일에 수행되거나 단순히 주어진 날짜 및 시간에 수행될 수 있습니다.

    그림 1. 시점
    그림 1. 시점

  • 주어진 시간 범위(시간 세션) 내에서 특정 작업을 활성화하거나 비활성화합니다. 여기에는 하루 내의 시간 세션(매일 한 지점에서 다른 지점으로), 특정 요일의 특정 작업 사용/사용 안 함, 특정 요일의 특정 시간에서 다른 요일의 특정 시간 세션 및 지정된 날짜 및 시간 범위에 해당하는 작업만 포함될 수 있습니다.

    그림 2. 시간 범위.
    그림 2. 시간 범위.

실제로 시간 사용은 매우 복잡합니다. 어려움은 시간 측정의 특성과 Expert Advisors 및 지표가 작동하는 환경과 관련이 있습니다.

  • 가격 변동이 없기 때문에 차트에서 바가 누락되었습니다. M1, M5, 심지어 M15와 같이 더 짧은 시간 프레임에서 특히 두드러집니다. 누락된 바는 더 긴 시간 프레임에서도 관찰될 수 있습니다.

  • 일부 거래 센터의 호가에는 실제로 월요일에 속하는 일요일 바가 포함됩니다.

  • 주말. 월요일 이전 요일은 일요일이 아닌 금요일입니다. 금요일 다음에는 토요일이 아니라 월요일이 옵니다.

  • 일요일 바 외에도 일부 거래 센터는 주말 전체를 포함하여 지속적으로 호가를 제공합니다. 가격 활동은 평일에 비해 상당히 낮지만 주말 내내 나타납니다.

  • 거래 서버와 로컬 컴퓨터(거래자의 컴퓨터 및 거래 터미널) 간의 시간대 차이. 다른 거래 센터의 서버 시간은 다를 수 있습니다.

  • 일광 절약 시간.

이 글은 시간에 관한 몇 가지 일반적인 이론으로 시작합니다. 그런 다음 시간에 따라 작업하기 위한 표준 MQL5 기능을 검토하고 몇 가지 프로그래밍 기술을 동시에 고려하여 실용적인 문제를 처리하는 것으로 마무리합니다.

글이 너무 길어서 최근에 MQL5를 탐색하기 시작한 초보 프로그래머는 한 번에 모든 것을 관리하기 어려울 것입니다. 적어도 3일을 투자하는 것이 좋습니다.


시간 측정의 특징

잠시 주제에서 벗어나 천문학으로 넘어가 보겠습니다. 지구가 태양 주위를 공전하는 동시에 자전축을 중심으로 자전한다는 것은 알려진 사실입니다. 지구의 자전축은 태양 주위의 궤도에 대해 약간 기울어져 있습니다. 천문(천구, 지구) 좌표에서 축을 중심으로 지구를 완전히 한 바퀴 자전하는 데 필요한 시간을 천문 또는 항성일이라고 합니다.

항성일은 지구상의 일반 사람들에게 별 관심이 없습니다(천문학자와는 대조적으로). 더 중요한 것은 낮과 밤의 교대입니다. 낮과 밤이 순환하는 데 필요한 시간을 태양의 날이라고 합니다. 지구의 북극 위에서 태양계를 보면(그림 3) 지구가 축을 중심으로 회전하고 태양 주위를 반시계 방향으로 회전하는 것을 볼 수 있습니다. 따라서 태양에 대해 축을 완전히 한 바퀴 회전하려면 지구가 360도 조금 넘게 회전해야 합니다. 따라서 태양일은 항성일보다 약간 더 길게 되죠.

그림 3. 축과 태양 주위의 지구의 자전 방향(지구의 북극 위에서 볼 때).
그림 3. 축과 태양 주위의 지구의 자전 방향(지구의 북극 위에서 볼 때).

편의와 정확성을 위해 태양일을 시간 측정의 기초로 사용합니다. 태양절은 24개 부분으로 나뉘어 60분이 지속되는 1시간을 만들어냅니다. 항성일의 길이는 23시간 56분 4초입니다. 궤도면에 대해 지구 축이 약간 기울어지면 지구에 사는 생명체가 감지할 수 있는 계절의 변화가 나타납니다.

1년의 태양일 수는 정수가 아닙니다. 사실 365일 하고도 6시간이 조금 넘습니다. 그렇기 때문에 달력은 4년에 한 번(4년의 배수) 2월 29일(윤년)에 하루를 더하여 주기적으로 조정됩니다. 그러나 이 조정은 완전히 정확하지 않으므로(약간의 추가 시간이 더해짐) 일부 연도는 4의 배수이지만 윤년이 아닙니다. "00"(100의 배수)으로 끝나는 연도에는 달력 조정이 수행되지 않습니다. 하지만 그게 다가 아닙니다.

연도가 동시에 100과 400의 배수인 경우 해당 연도는 윤년으로 간주되어 달력을 조정해야 합니다. 1900년은 4와 100의 배수이지만 400의 배수가 아니므로 윤년이 아닙니다. 2000년은 4, 100, 400의 배수로 윤년이 됩니다. 4와 100의 배수인 다음 해는 2100년입니다. 그러나 400의 배수가 아니기 때문에 윤년이 되지는 않습니다. 이 글을 읽는 독자들은 매년 4의 배수가 되는 해가 윤년인 시대를 떠나게 되는 것으로 밝혀졌습니다. 100의 배수이면서 동시에 윤년인 다음 해는 2400년입니다.


시간대

지구는 자전축을 중심으로 자전하므로 낮과 밤이 바뀝니다. 낮이나 밤일 수도 있고, 지구상의 다른 장소에서 같은 시간에 하루 중 어느 시간일 수도 있습니다. 하루는 24시간이므로 지구의 둘레는 각각 15도의 24개 구역으로 나뉘며 각각을 시간대라고 합니다. 편의상 시간대의 경계는 항상 경도선을 따르지 않고 행정 구역의 경계(국가, 지역 등의 경계)를 따릅니다.

기준점은 그리니치 자오선이라고 하는 본초 자오선입니다. 그것은 그 이름을 얻은 그리니치의 런던 지구를 통과하고 있습니다. 그리니치 표준시는 그리니치 자오선의 양쪽에서 7.5도 확장됩니다. 그리니치 표준시(+1~+12)에서 동쪽으로 측정한 12개의 시간대와 그리니치 표준시(-1~-12)에서 서쪽으로 측정한 12개의 시간대가 있습니다. 실제로 시간대 -12와 +12의 너비는 15도가 아니라 7.5도에 불과합니다. 표준 시간대 -12 및 +12는 자오선 180의 오른쪽과 왼쪽, 즉 국제 날짜 표시선에 있습니다.

그리니치의 정오(12:00)일 때 00:00, 즉 시간대 -12 및 - 24:00의 시작 시간, 즉 시간대 +12의 다음 날 00:00이라고 가정합니다. 다른 시간도 마찬가지입니다. 시계의 시간은 동일하지만 달력의 날짜는 다릅니다. 시간대 -12는 실제로 사용되지 않으며 +12로 대체됩니다. 시간대 +13으로 대체된 시간대 -11도 마찬가지입니다. 이것은 아마도 경제 관계의 특성과 관련이 있을 것입니다. +13 시간대에 위치한 사모아 독립국은 일본과 강력한 경제 관계를 가지고 있으므로 일본 시간에 가까운 시간이 더 편리한 것으로 보입니다.

또한 -04:30, +05:45 등과 같은 특이한 시간대가 있습니다. 호기심이 많은 사람은 Windows 시간 설정에서 사용 가능한 모든 시간대 목록을 찾을 수 있습니다.


일광 절약 시간

세계의 많은 국가에서는 일광 및 에너지 절약을 보다 효율적으로 활용하기 위한 노력의 일환으로 일광 절약 시간제에 따라 시계를 1시간 앞당깁니다. 세계 80여 개국에서는 일광 절약 시간제를 준수하지만 다른 국가에서는 그렇지 않습니다. 일광 절약 시간제를 광범위하게 사용하는 일부 국가(미국 포함)에서는 지역별로 이를 사용하지 않는 곳도 있습니다. 일광 절약 시간제는 거의 모든 유럽 국가(독일, 영국, 스위스 포함), 미국(뉴욕, 시카고), 호주(시드니) 및 뉴질랜드(웰링턴)와 같이 경제적으로 발전된 주요 국가 및 지역에서 준수됩니다. 일본은 일광 절약 시간제를 준수하지 않습니다. 2011년 3월 27일, 러시아는 마지막으로 시계를 1시간 앞당겼고 10월에 다시 표준시로 바꾸지 않았습니다. 그 이후로 러시아는 공식적으로 일광 절약 시간제에서 제외되었습니다.

일광 절약 시간제로 변경하는 절차는 국가마다 다릅니다. 미국에서는 현지 시간으로 3월 두 번째 일요일 02:00에 시프트가 발생하고 11월 첫 번째 일요일 02:00에 시계가 뒤로 이동합니다. 유럽에서는 시계가 3월 마지막 일요일 02:00에 일광 절약 시간제로 바뀌고 10월 마지막 일요일 03:00에 표준 시간으로 돌아갑니다. 현지 시간으로 설정되지 않고 모든 유럽 국가에서 시프트가 한꺼번에 발생합니다. 시간대에 따라 런던은 02:00, 베를린은 03:00 등입니다. 시계는 런던의 경우 03:00, 베를린의 경우 04:00인 경우 표준 시간으로 뒤로 이동합니다.

호주와 뉴질랜드는 북반구에 겨울이 오면 여름이 시작되는 남반구에 위치하고 있습니다. 결과적으로 호주는 10월 첫 번째 일요일에 일광 절약 시간제로 시간을 변경하고 4월 첫 번째 일요일에 표준 시간으로 뒤로 이동합니다. 호주의 일광 절약 시간제에 관해서는 시작 날짜와 종료 날짜가 국가의 다른 지역에서 항상 일치하지 않기 때문에 더 정확하기 어렵습니다. 뉴질랜드에서 일광 절약 시간제로의 전환은 9월 마지막 일요일 02:00에 발생하고 4월 첫 번째 일요일 03:00에 뒤로 이동합니다.


표준 시간

앞에서 언급했듯이 태양일은 시간 측정의 기초로 사용되며 그리니치 표준시는 다른 모든 시간대에서 시간이 결정되는 시간 표준으로 사용됩니다. 그리니치 표준시는 종종 GMT로 약칭됩니다.

그러나 지구의 자전이 약간 불균일하다는 것이 확립되어 시간을 측정하는 데 원자 시계가 사용되어 UTC(협정 세계시)가 새로운 시간 표준이 되었습니다. 현재 UTC는 일광 절약 시간제에 필요한 조정과 함께 모든 시간대의 기본 시간 측정에 대한 전 세계의 기본 시간 표준 역할을 합니다. UTC에는 일광 절약 시간제가 적용되지 않습니다.

태양광 기반의 GMT는 원자시계 기반의 UTC와 완전히 일치하지 않기 때문에 UTC와 GMT 사이에는 약 500일마다 최대 1초 정도의 차이가 발생합니다. 이와 관련하여 6월 30일 또는 12월 31일에 때때로 1초 조정이 수행됩니다.


날짜 및 시간 형식

날짜 형식은 국가마다 다릅니다. 예를 들어 러시아에서는 일을 먼저 쓰고 월과 연도를 쓰는 것이 관례입니다. 날짜의 숫자는 점으로 구분됩니다. 2012년 12월 12일 - 2012년 12월 1일 미국에서 날짜 형식은 월/일/년이며 날짜의 숫자는 슬래시 "/"로 구분됩니다. 점 및 슬래시 "/" 외에도 일부 형식 표준에서는 대시 "-"를 사용하여 날짜의 숫자를 구분할 수 있습니다. 시간을 기록할 때 시, 분, 초는 콜론 ":"으로 구분됩니다. 12:15:30 - 12시간 15분 30초.

날짜 및 시간 형식을 지정하는 간단한 방법이 있습니다. 예를 들어, "dd.mm.yyyy"는 먼저 일(두 자리 숫자로 구성된 월의 일, 일이 1에서 9 사이의 숫자인 경우 시작 부분에 0을 추가함)을 작성한 다음 월을 쓰는 것을 의미합니다. (두 자리 숫자로 구성되어야 함) 및 네 자리 숫자로 구성된 연도. "d-m-yy"는 일(한 자리 숫자일 수 있음)이 먼저 나오고 월(한 자리 숫자가 허용됨)과 두 자리 숫자로 구성된 연도가 뒤따르는 것을 의미합니다. 12/12/12 - 2012년 12월 1일. 일, 월 및 연도 값은 대시 "-"로 구분됩니다.

시간은 공백을 사용하여 날짜와 구분됩니다. 시간 형식은 시간에 "h", 분에 "m", 초에 "s"를 사용하는 동시에 필요한 자릿수를 지정합니다. 예를 들어 "hh:mi:ss"는 먼저 시간(1에서 9 사이의 값 앞에 0을 추가해야 함)을 작성한 다음 분(2자리 필요) 및 초(2자리)를 작성한다는 의미입니다. 여기서 시간 값은, 분과 초는 콜론으로 구분됩니다.

프로그래머의 입장에서 가장 정확하다고 생각되는 날짜 및 시간 형식은 "yyyy.mm.dd hh:mi:ss"입니다. 이 표기법을 사용하여 작성된 날짜로 문자열을 정렬할 때 시간순으로 쉽게 정렬됩니다. 매일 텍스트 파일에 정보를 저장하고 같은 폴더에 보관한다고 가정합니다. 이 형식을 사용하여 파일 이름을 지정하면 폴더의 파일이 순서대로 편리하게 정렬되고 정렬됩니다.

이론적인 부분은 다 했으니 이제 구현을 해봅시다.


MQL5의 시간

MQL5에서 시간은 1970년 1월 1일에 시작된 이른바 유닉스 시대가 시작된 이후 경과된 초 단위로 측정됩니다. 시간을 저장하기 위해 datetime 유형의 변수를 사용합니다. datetime형 변수의 최소값은 0(epoch 시작 날짜에 해당)이고 최대값은 32 535 244 799(3000년 12월 31일 23:59:59에 해당)입니다.


현재 서버 시간 확인

현재 시간을 확인하기 위해 TimeCurrent() 함수를 사용합니다. 마지막으로 알려진 서버 시간을 반환합니다.

datetime tm=TimeCurrent();
//--- output result
Alert(tm);

동일한 서버 시간이 차트에서 바의 시간을 지정하는 데 사용됩니다. 마지막으로 알려진 서버 시간은 Market Watch 창에서 열린 기호의 가격이 마지막으로 변경된 시간입니다. Market Watch 창에 EURUSD만 있는 경우 TimeCurrent() 함수는 EURUSD의 마지막 가격 변경 사항을 반환합니다. Market Watch 창은 원칙적으로 상당한 수의 기호를 표시하므로 함수는 기본적으로 현재 서버 시간을 반환합니다. 그러나 주말에는 가격이 변하지 않기 때문에 함수가 반환하는 값은 실제 서버 시간과 많이 다릅니다.

특정 기호(최종 가격 변경 시간)로 서버 시간을 찾아야 하는 경우 SYMBOL_TIME 식별자와 함께 SymbolInfoInteger() 함수를 사용할 수 있습니다.

datetime tm=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
//--- output result
Alert(tm);


현재 현지 시간 확인

현지 시간(사용자의 PC 시계로 표시)은 TimeLocal() 함수에 의해 결정됩니다.

datetime tm=TimeLocal();
//--- output result
Alert(tm);

실제로 EA와 지표를 프로그래밍할 때 대부분 서버 시간을 사용하게 됩니다. 현지 시간은 경고 및 저널 항목에 유용합니다. 사용자가 메시지 또는 항목 타임스탬프를 PC 시계에 표시된 시간과 비교하여 이러한 메시지 또는 항목이 등록된 지 얼마나 되었는지 확인하는 것이 더 편리합니다. 그러나 MetaTrader 5 터미널은 Alert()Print() 기능을 사용하여 출력되는 메시지 및 저널 항목에 타임스탬프를 자동으로 추가합니다. 따라서 TimeLocal() 함수를 사용해야 하는 경우는 매우 드물게 발생할 수 있습니다.


시간 출력

위 코드에서 tm 변수의 값은 Alert() 함수를 사용하여 출력된다는 점에 유의하시기 바랍니다. 즉, 값은 읽기 쉬운 형식으로 표시됩니다. "2012.12.05 22:31:57". 이는 Alert() 함수가 전달된 인수를 string 유형으로 변환하기 때문입니다(Print() 및 Comment() 기능 및 텍스트 및 csv 파일로 출력할 때). datetime-type 변수의 값을 포함하는 문자 메시지를 생성할 때 유형 변환을 수행하는 것은 사용자의 책임입니다. 형식화된 시간을 가져와야 하는 경우 문자열 유형으로 변환하거나 숫자 값이 필요한 경우 문자열 유형 뒤에 오는 long 유형으로 변환합니다.

datetime tm=TimeCurrent();
//--- output result
Alert("Formatted: "+(string)tm+", in seconds: "+(string)(long)tm);

long형과 ulong형 변수의 값 범위는 datetime형 변수의 값 범위를 포함하므로 시간을 저장하는 데에도 사용할 수 있지만 이 경우 형식이 지정된 시간을 출력하려면 long 형식으로 변환해야 합니다. 숫자 값을 출력하려는 ​​경우 날짜/시간 유형으로 변환한 다음 문자열 유형으로 또는 문자열 유형 단독으로 합니다:

long tm=TimeCurrent();
//--- output result
Alert("Formatted: "+(string)(datetime)tm+", in seconds: "+(string)tm);


시간 형식

시간 형식은 다양한 변수를 문자열로 변환하는 데 사용되는 섹션의 "MQL5 프로그래밍 기본: 문자열"이라는 글에서 고려되었습니다. 여기에서 요점을 간략하게 설명하겠습니다. 유형을 변환하는 것 외에도 MQL5는 문자열로 변환할 때 날짜 및 시간 형식을 지정할 수 있는 기능인 TimeToString() 기능을 제공합니다.

datetime tm=TimeCurrent();
string str1="Date and time with minutes: "+TimeToString(tm);
string str2="Date only: "+TimeToString(tm,TIME_DATE);
string str3="Time with minutes only: "+TimeToString(tm,TIME_MINUTES);
string str4="Time with seconds only: "+TimeToString(tm,TIME_SECONDS);
string str5="Date and time with seconds: "+TimeToString(tm,TIME_DATE|TIME_SECONDS);
//--- output results
Alert(str1);
Alert(str2);
Alert(str3);
Alert(str4);
Alert(str5);

TimeToString() 함수는 datetime 유형의 변수, long 및 ulong 유형 변수 및 일부 다른 유형의 정수 변수에 적용할 수 있지만 시간을 저장하는 데 사용해서는 안 됩니다.

StringFormat() 함수를 사용하여 텍스트 메시지의 형식을 지정할 때 유형 변환을 처리해야 합니다.

  • datetime형 변수에 시간을 저장할 때:

    datetime tm=TimeCurrent();
    //--- generating a string
    string str=StringFormat("Formatted: %s, in seconds: %I64i",(string)tm,tm);
    //--- output result
    Alert(str);
  • 긴 유형 변수에 시간을 저장할 때:

    long tm=TimeCurrent();
    //--- generating a string
    string str=StringFormat("Formatted: %s, in seconds: %I64i",(string)(datetime)tm,tm);
    //--- output result
    Alert(str);
  • 또는 TimeToString() 함수를 사용하여:

    datetime tm=TimeCurrent();
    //--- generating a string
    string str=StringFormat("Date: %s",TimeToString(tm,TIME_DATE));
    //--- output result
    Alert(str);


시간을 숫자로 변환. 시간 더하기 및 빼기

형식이 지정된 날짜(문자열)를 숫자(에포크 시작 이후 경과된 초 수)로 변환하려면 StringToTime() 함수가 사용됩니다.

datetime tm=StringToTime("2012.12.05 22:31:57");
//--- output result
Alert((string)(long)tm);

위 코드의 결과 초 단위로 출력되는 시간은 "2012.12.05 22:31:57"과 같이 날짜에 해당하는 "1354746717"이 됩니다.

시간을 숫자로 나타내면 다양한 조작이 쉽고 편리해집니다. 과거 또는 미래의 날짜와 시간을 찾을 수 있습니다. 시간은 초 단위로 측정되므로 초 단위로 표시되는 시간 기간을 추가해야 합니다. 1분이 60초이고 1시간이 60분 또는 3600초라는 것을 알면 시간의 지속 시간을 계산하는 데 많은 노력이 필요하지 않습니다.

현재 시간에서 1시간(3600초)을 빼거나 더하면 1시간 전 또는 1시간 후의 시간을 얻을 수 있습니다.

datetime tm=TimeCurrent();
datetime ltm=tm-3600;
datetime ftm=tm+3600;
//--- output result
Alert("Current: "+(string)tm+", an hour ago: "+(string)ltm+", in an hour: "+(string)ftm);

StringToTime() 함수에 전달된 날짜는 완전할 필요가 없습니다. 또한 시간 없이 날짜를 전달하거나 날짜 없이 시간을 전달할 수 있습니다. 시간 없이 날짜를 전달하면 함수는 지정된 날짜의 00:00:00에 값을 반환합니다.

datetime tm=StringToTime("2012.12.05");
//--- output result
Alert(tm);

시간만 전달하면 함수는 현재 날짜의 지정된 시간에 해당하는 값을 반환합니다.

datetime tm=StringToTime("22:31:57");
//--- output result
Alert((string)tm);

시간은 초 없이도 지나갈 수 있습니다. 날짜를 전달하면 전달할 수 있는 유일한 시간 구성 요소는 시간입니다. 이것은 실제로 거의 필요하지 않을 것입니다. 하지만 궁금하시다면 직접 실험해 보시기 바랍니다.


날짜 및 시간 구성요소

개별 날짜 및 시간 구성 요소(년, 월, 날짜 등)의 값을 결정하기 위해 TimeToStruct() 함수와 MqlDateTime 구조를 사용합니다. 구조는 참조에 의해 함수에 전달됩니다. 함수를 실행한 후 구조는 전달된 날짜의 구성 요소 값으로 채워집니다.

datetime    tm=TimeCurrent();
MqlDateTime stm;
TimeToStruct(tm,stm);
//--- output date components
Alert("Year: "        +(string)stm.year);
Alert("Month: "      +(string)stm.mon);
Alert("Day: "      +(string)stm.day);
Alert("Hour: "        +(string)stm.hour);
Alert("Minute: "     +(string)stm.min);
Alert("Second: "    +(string)stm.sec);
Alert("Day of the week: "+(string)stm.day_of_week);
Alert("Day of the year: "  +(string)stm.day_of_year);

날짜 구성 요소 외에도 구조에는 요일(day_of_week 필드) 및 요일(day_of_year)과 같은 몇 가지 추가 필드가 포함되어 있습니다. 요일은 0부터 계산됩니다(0 - 일요일, 1 - 월요일 등). 연도의 날짜도 0부터 계산됩니다. 다른 값은 일반적으로 허용되는 계산 순서를 따릅니다(월은 일과 마찬가지로 1부터 계산).

TimeCurrent() 함수를 호출하는 또 다른 방법이 있습니다. MqlDateTime 유형의 구조는 참조로 함수에 전달됩니다. 함수 실행 후 구조는 현재 날짜 구성 요소로 채워집니다.

MqlDateTime stm;
datetime tm=TimeCurrent(stm);
//--- output date components
Alert("Year: "        +(string)stm.year);
Alert("Month: "      +(string)stm.mon);
Alert("Day: "      +(string)stm.day);
Alert("Hour: "        +(string)stm.hour);
Alert("Minute: "     +(string)stm.min);
Alert("Second: "    +(string)stm.sec);
Alert("Day of the week: "+(string)stm.day_of_week);
Alert("Day of the year: "  +(string)stm.day_of_year);

The TimeLocal() function can also be called in this manner.


구성 요소에서 날짜 생성

MqlDateTime 구조를 날짜/시간 유형으로 역변환할 수도 있습니다. 이를 위해 StructToTime() 함수를 사용합니다.

정확히 한 달 전의 시간을 구해봅시다. 한 달의 일 수는 다양합니다. 30일 또는 31일이 있는 달이 있고 2월이 28일 또는 29일일 수 있습니다. 따라서 앞에서 고려한 시간 뺄셈과 덧셈의 방법은 적절하지 않습니다. 따라서 날짜를 구성 요소로 나누고 월 값을 1로 줄이고 월 값이 1이면 12로 설정하고 연도 값을 1로 줄입니다.

datetime tm=TimeCurrent();
MqlDateTime stm;
TimeToStruct(tm,stm);
if(stm.mon==1)
  {
   stm.mon=12;
   stm.year--;
  }
else
  {
   stm.mon--;
  }
datetime ltm=StructToTime(stm);
//--- output result
Alert("Current: "+(string)tm+", a month ago: "+(string)ltm);


바 시간 결정하기

지표를 개발할 때 MetaEditor는 OnCalculate() 함수의 두 가지 버전 중 하나를 자동으로 생성합니다.

버전 1:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   return(rates_total);
  }

버전 2:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   return(rates_total);
  }

함수의 첫 번째 버전의 매개변수에는 요소에 모든 바의 시간이 포함된 time[] 배열이 포함됩니다.

두 번째 버전을 사용할 때뿐만 아니라 EA를 프로그래밍하고 지표에서 다른 시간 프레임의 바 시간으로 액세스를 정렬할 때 항상 CopyTime() 함수를 사용합니다. 이 기능은 세 가지 버전이 있습니다. 모든 버전에서 처음 두 개의 함수 매개변수는 기호와 바 시간이 결정되는 차트 시간 프레임을 정의합니다. 마지막 매개변수는 반환된 값을 저장하는 배열을 정의하고 두 개의 중간 매개변수는 사용된 함수 버전에 따라 다릅니다.

카피타임 - 버전 1. 바 인덱스와 복제할 요소 수를 지정해야 합니다.

//--- variables for function parameters
int start = 0; // bar index
int count = 1; // number of bars
datetime tm[]; // array storing the returned bar time
//--- copy time 
CopyTime(_Symbol,PERIOD_D1,start,count,tm);
//--- output result
Alert(tm[0]);

이 예제는 D1 시간 프레임에서 마지막 바의 시간을 복제하는 구현을 보여줍니다. 우리가 사용하는 함수 버전은 전달된 매개변수의 유형에 따라 다릅니다. 위의 예는 int 유형 변수의 사용을 특징으로 합니다. 즉, 지정된 바 수에 대해 바 번호로 시간을 가져와야 함을 의미합니다.

CopyTime() 함수를 사용할 때 바는 오른쪽에서 왼쪽으로 0에서 계산됩니다. 얻은 값(마지막 매개변수)에 사용되는 동적 배열은 CopyTime() 함수 자체에 의해 필요한 크기로 조정됩니다. 정적 배열을 사용할 수도 있지만 이 경우 배열 크기는 요청된 요소의 수(4번째 매개변수의 값)와 엄격하게 일치해야 합니다.

한 번에 여러 바에서 시간을 가져올 때 반환된 배열의 요소 순서를 이해하는 것이 중요합니다. 차트의 바는 지정된 바부터 시작하여 오른쪽에서 왼쪽으로 계산되지만 배열 요소는 왼쪽에서 오른쪽으로 정렬됩니다.

//--- variables for function parameters
int start = 0; // bar index
int count = 2; // number of bars
datetime tm[]; // array storing the returned bar time
//--- copy time 
CopyTime(_Symbol,PERIOD_D1,start,count,tm);
//--- output result
Alert("Today: "+(string)tm[1]+", yesterday: "+(string)tm[0]);

이 코드의 결과로 어제 바의 시간은 tm 배열의 0 요소에 저장되고 첫 번째 요소는 오늘 바의 시간을 포함합니다.

어떤 경우에는 차트에서 바를 세는 순서와 같은 순서로 배열에 시간을 배치하는 것이 더 편리해 보일 수 있습니다. 여기서 ArraySetAsSeries() 함수가 트릭을 수행할 수 있습니다.

//--- variables for function parameters
int start = 0; // bar index
int count = 2; // number of bars
datetime tm[]; // array storing the returned bar time
ArraySetAsSeries(tm,true); // specify that the array will be arranged in reverse order
//--- copy time 
CopyTime(_Symbol,PERIOD_D1,start,count,tm);
//--- output result
Alert("Today: "+(string)tm[0]+", yesterday: "+(string)tm[1]);

이제 오늘 바의 시간은 인덱스 0인 요소에 있고 어제 바의 시간은 인덱스 1인 요소에 있습니다.

카피타임 - 버전 2. 여기에서 CopyTime() 함수를 호출할 때 복제가 시작되는 마디의 시간과 복제할 마디의 수를 지정해야 합니다. 이 버전은 더 낮은 시간 프레임의 바를 포함하는 더 높은 시간 프레임의 시간을 결정하는 데 적합합니다.

//--- get the time of the last bar on M5
int m5_start=0; 
int m5_count=1;
datetime m5_tm[];
CopyTime(_Symbol,PERIOD_M5,m5_start,m5_count,m5_tm);
//--- determine the bar time on H1 that contains the bar on M5
int h1_count=1;
datetime h1_tm[];
CopyTime(_Symbol,PERIOD_H1,m5_tm[0],h1_count,h1_tm);
//--- output result
Alert("The bar on М5 with the time "+(string)m5_tm[0]+" is contained in the bar on H1 with the time "+(string)h1_tm[0]);

더 낮은 시간 프레임에서 바의 시간을 결정해야 하는 경우 더 복잡해지며 더 높은 시간 프레임에서 바의 시작입니다. 더 높은 시간 프레임에 있는 바의 시간과 같은 시간을 가진 바는 더 낮은 시간 프레임에 누락될 수 있습니다. 이러한 경우 더 높은 시간 프레임의 이전 바에 포함된 더 낮은 시간 프레임의 마지막 바 시간을 얻습니다. 따라서 우리는 더 낮은 시간 프레임의 바 수를 결정하고 다음 바의 시간을 얻어야 합니다.

다음은 사용할 준비가 된 함수의 형태로 위의 구현입니다.

bool LowerTFFirstBarTime(string aSymbol,
                         ENUM_TIMEFRAMES aLowerTF,
                         datetime aUpperTFBarTime,
                         datetime& aLowerTFFirstBarTime)
  {
   datetime tm[];
//--- determine the bar time on a lower time frame corresponding to the bar time on a higher time frame 
   if(CopyTime(aSymbol,aLowerTF,aUpperTFBarTime,1,tm)==-1)
     {
      return(false);
     }
   if(tm[0]<aUpperTFBarTime)
     {
      //--- we got the time of the preceding bar
      datetime tm2[];
      //--- determine the time of the last bar on a lower time frame
      if(CopyTime(aSymbol,aLowerTF,0,1,tm2)==-1)
        {
         return(false);
        }
      if(tm[0]<tm2[0])
        {
         //--- there is a bar following the bar of a lower time frame  that precedes the occurrence of the bar on a higher time frame
         int start=Bars(aSymbol,aLowerTF,tm[0],tm2[0])-2;
         //--- the Bars() function returns the number of bars from the bar with time tm[0] to
         //--- the bar with time tm2[0]; since we need to determine the index of the bar following 
         //--- the bar with time tm2[2], subtract 2
         if(CopyTime(aSymbol,aLowerTF,start,1,tm)==-1)
           {
            return(false);
           }
        }
      else
        {
         //--- there is no bar of a lower time frame contained in the bar on a higher time frame
         aLowerTFFirstBarTime=0;
         return(true);
        }
     }
//--- assign the obtained value to the variable 
   aLowerTFFirstBarTime=tm[0];
   return(true);
  }

기능 매개변수:

  • aSymbol - 기호;
  • aLowerTF - 더 낮은 기간;
  • aUpperTFBarTime - 더 높은 시간 프레임의 바 시간;
  • aLowerTFFirstBarTime - 더 낮은 시간 프레임의 값을 반환합니다.

코드 전체에서 함수는 CopyTime() 함수의 호출이 성공했는지 여부를 확인하고 오류가 발생하면 함수는 false를 반환합니다. 바 시간은 aLowerTFFirstBarTime 매개변수를 통해 참조로 반환됩니다.

기능을 사용하는 예는 다음과 같습니다.

//--- time of the bar on the higher time frame H1
   datetime utftm=StringToTime("2012.12.10 15:00");
//--- variable for the returned value
   datetime val;
//--- function call
   if(LowerTFFirstBarTime(_Symbol,PERIOD_M5,utftm,val))
     {
      //--- output result in case of successful function operation
      Alert("val = "+(string)val);
     }
   else
     {
      //--- in case of an error, terminate the operation of the function from which the LowerTFFirstBarTime() function is called
      Alert("Error copying the time");
      return;
     }

함수가 더 높은 시간 프레임의 존재하지 않는 바의 시간을 수신하는 경우 더 높은 시간 프레임의 바에 포함된 더 낮은 시간 프레임에 바가 없는 상황이 발생할 수 있습니다. 이 경우 함수는 true를 반환하고 시간 값 0이 aLowerTFFirstBarTime 변수에 기록됩니다. 더 높은 시간 프레임의 바가 존재하는 경우 낮은 시간 프레임 각각에 항상 하나 이상의 해당 바가 있습니다.

더 높은 시간 프레임의 바에 포함된 더 낮은 시간 프레임의 마지막 바 시간을 찾는 것이 약간 더 쉽습니다. 우리는 더 높은 시간 프레임에서 다음 바의 시간을 계산하고 얻은 값을 사용하여 더 낮은 시간 프레임에서 해당 바의 시간을 결정합니다. 결과 시간이 더 높은 시간 프레임의 계산된 시간과 같으면 더 낮은 시간 프레임에서 이전 바의 시간을 결정해야 합니다. 결과 시간이 더 짧으면 적절한 시간을 얻은 것입니다.

다음은 사용할 준비가 된 함수의 형태로 위의 구현입니다.

bool LowerTFLastBarTime(string aSymbol,
                        ENUM_TIMEFRAMES aUpperTF,
                        ENUM_TIMEFRAMES aLowerTF,
                        datetime aUpperTFBarTime,
                        datetime& aLowerTFFirstBarTime)
  {
//--- time of the next bar on a higher time frame
   datetime NextBarTime=aUpperTFBarTime+PeriodSeconds(aUpperTF);
   datetime tm[];
   if(CopyTime(aSymbol,aLowerTF,NextBarTime,1,tm)==-1)
     {
      return(false);
     }
   if(tm[0]==NextBarTime)
     {
      //--- There is a bar on a lower time frame corresponding to the time of the next bar on a higher time frame.
      //--- Determine the time of the last bar on a lower time frame
      datetime tm2[];
      if(CopyTime(aSymbol,aLowerTF,0,1,tm2)==-1)
        {
         return(false);
        }
      //--- determine the preceding bar index on a lower time frame
      int start=Bars(aSymbol,aLowerTF,tm[0],tm2[0]);
      //--- determine the time of this bar
      if(CopyTime(aSymbol,aLowerTF,start,1,tm)==-1)
        {
         return(false);
        }
     }
//--- assign the obtain value to the variable 
   aLowerTFFirstBarTime=tm[0];
   return(true);
  }

기능 매개변수:

  • aSymbol - 기호;
  • aUpperTF - 더 높은 시간 프레임
  • aLowerTF - 더 낮은 기간;
  • aUpperTFBarTime - 더 높은 시간 프레임의 바 시간;
  • aLowerTFFirstBarTime - 더 낮은 시간 프레임의 값을 반환합니다.

코드 전체에서 함수는 CopyTime() 함수의 호출이 성공했는지 여부를 확인하고 오류가 발생하면 함수는 false를 반환합니다. 바 시간은 aLowerTFFirstBarTime 매개변수를 통해 참조로 반환됩니다.

기능을 사용하는 예는 다음과 같습니다.

//--- time of the bar on the higher time frame H1
datetime utftm=StringToTime("2012.12.10 15:00");
//--- variable for the returned value
datetime val;
//--- function call
if(LowerTFLastBarTime(_Symbol,PERIOD_H1,PERIOD_M5,utftm,val))
  {
//--- output result in case of successful function operation
   Alert("val = "+(string)val);
  }
else
  {
//--- in case of an error, terminate the operation of the function from which the LowerTFFirstBarTime() function is called
   Alert("Error copying the time");
   return;
  }

주의! 함수에 전달된 시간은 더 높은 시간 프레임의 정확한 시간이라고 가정합니다. 바의 정확한 시간을 알 수 없고 해당 바의 특정 틱 또는 더 높은 시간 프레임의 바에 포함된 더 낮은 시간 프레임의 바만 알고 있는 경우 시간 정규화가 필요합니다. MetaTrader 5 터미널에서 사용되는 시간 프레임은 하루를 정수 바로 나눕니다. Epoch 시작 이후의 바 번호를 결정하고 바 길이(초)를 곱합니다.

datetime BarTimeNormalize(datetime aTime,ENUM_TIMEFRAMES aTimeFrame)
  {
   int BarLength=PeriodSeconds(aTimeFrame);
   return(BarLength*(aTime/BarLength));
  }

기능 매개변수:

  • aTime - 시간;
  • aTimeFrame - 시간대.

기능을 사용하는 예는 다음과 같습니다.

//--- the time to be normalized
datetime tm=StringToTime("2012.12.10 15:25");
//--- function call
datetime tm1=BarTimeNormalize(tm,PERIOD_H1);
//--- output result
Alert(tm1);

그러나 이것은 시간 정규화 방법일 뿐만 아니라 더 낮은 시간 프레임의 시간으로 높은 시간 프레임의 시간을 결정하는 또 다른 방법입니다.

카피타임 - 버전 3. 이 경우 CopyTime() 함수를 호출할 때 시간을 복제해야 하는 바에 대한 시간 범위를 지정합니다. 이 방법을 사용하면 더 높은 시간 프레임의 바에 포함된 더 낮은 시간 프레임의 모든 바를 쉽게 얻을 수 있습니다.

//--- time of the bar start on H1
datetime TimeStart=StringToTime("2012.12.10 15:00");
//--- the estimated time of the last bar on
//--- M5
datetime TimeStop=TimeStart+PeriodSeconds(PERIOD_H1)-PeriodSeconds(PERIOD_M5);
//--- copy time
datetime tm[];
CopyTime(_Symbol,PERIOD_M5,TimeStart,TimeStop,tm);
//--- output result 
Alert("Bars copied: "+(string)ArraySize(tm)+", first bar: "+(string)tm[0]+", last bar: "+(string)tm[ArraySize(tm)-1]);


하루 시작 시간 및 하루 시작 이후 경과 시간 결정

주어진 시간으로 하루 시작 시간을 결정하는 가장 확실한 방법은 시간을 구성 요소로 나누고 시, 분, 초를 0으로 만들고 다시 더하는 것입니다. 그러나 더 쉬운 방법이 있습니다. 하루는 86400초입니다. 하루의 초 수로 시간을 나눈 ​​결과로 정수를 얻고 여기에 하루의 초 수를 곱해야 합니다.

datetime tm=TimeCurrent();
tm=(tm/86400)*86400;
//--- output result
Alert("Day start time: "+(string)tm);

주의! 이 트릭은 정수 변수에만 효과적입니다. double 및 float 유형의 변수가 계산에 나타나면 MathFloor() 함수를 사용하여 소수 부분을 잘라야 합니다.

MathFloor(tm/86400)*86400

곱셈 후에 값은 NormalizeDouble() 함수를 사용하여 정규화되어야 합니다. 결과 값은 정수여야 하므로 반올림 함수인 MathRound()를 사용할 수 있습니다.

MathRound(MathFloor(tm/86400)*86400)

정수 변수를 사용할 때 나머지는 자동으로 삭제됩니다. 시간을 다룰 때 double 또는 float 유형의 변수는 거의 필요하지 않으며 사용은 근본적으로 잘못된 접근 방식을 나타낼 가능성이 큽니다.

하루가 시작된 후 경과된 시간(초)을 결정하려면 시간을 86400으로 나눈 나머지 부분만 취하면 됩니다.

datetime tm=TimeCurrent();
long seconds=tm%86400;
//--- output result
Alert("Time elapsed since the day start: "+(string)seconds+" sec.");

유사한 방법을 사용하여 초 단위로 얻은 시간을 시, 분, 초로 변환할 수 있습니다. 함수로 구현:

int TimeFromDayStart(datetime aTime,int &aH,int &aM,int &aS)
  {
//--- Number of seconds elapsed since the day start (aTime%86400),
//--- divided by the number of seconds in an hour is the number of hours
   aH=(int)((aTime%86400)/3600);
//--- Number of seconds elapsed since the last hour (aTime%3600),
//--- divided by the number of seconds in a minute is the number of minutes 
   aM=(int)((aTime%3600)/60);
//--- Number of seconds elapsed since the last minute 
   aS=(int)(aTime%60);
//--- Number of seconds since the day start
   return(int(aTime%86400));
  }

첫 번째로 전달된 매개변수는 시간입니다. 반환된 값에 다른 매개변수가 사용됩니다. aH - 시간, aM - 분, aS - 초. 함수 자체는 하루가 시작된 이후의 총 시간(초)을 반환합니다. 기능을 확인해보자:

datetime tm=TimeCurrent();
int t,h,m,s;
t=TimeFromDayStart(tm,h,m,s);
//--- output result
Alert("Time elapsed since the day start ",t," s, which makes ",h," h, ",m," m, ",s," s ");

하루 시작의 바를 결정하기 위한 지표에 사용할 날짜 수를 계산할 수도 있습니다.

bool NewDay=(time[i]/86400)!=(time[i-1]/86400);

바는 왼쪽에서 오른쪽으로 인덱싱된다고 가정합니다. 여기서 time[i]는 현재 바의 시간이고 time[i-1]은 이전 바의 시간입니다.


주 시작 시간 및 주 시작 이후 경과 시간 결정

주 시작 시간을 결정하는 것은 요일 시작을 결정하는 것보다 조금 더 복잡합니다. 한 주의 일 수는 일정하고 한 주의 지속 시간을 초(604800초) 단위로 계산할 수 있지만 신기원의 시작부터 경과한 주의 정수를 단순히 계산하고 해당 주의 기간으로 곱하는 것만으로는 충분하지 않습니다.

문제는 대부분의 국가에서 한 주가 월요일에 시작하는 반면 일부 다른 국가(미국, 캐나다, 이스라엘 및 기타)에서는 일요일에 시작한다는 것입니다. 그러나 우리가 기억하는 것처럼 시간 측정의 시대는 목요일에 시작됩니다. 목요일이 주의 첫 번째 요일이었다면 그 간단한 계산으로 충분했을 것입니다.

편의상 0 값에 해당하는 첫 번째 epoch day의 예를 통해 주 시작을 결정하는 특성을 고려합니다. 우리는 시간을 추가할 때 0에서 계산된 신기원의 첫 번째 날(1970.01.01 00:00)을 네 번째 날로 변경하는 값을 찾아야 합니다. 즉, 4일의 기간을 추가해야 합니다. 한 주가 월요일에 시작하는 경우 목요일은 4일이 되어야 하므로 3일의 기간을 추가해야 합니다. 그러나 주가 일요일에 시작하는 경우 목요일은 다섯 번째 날이어야 하므로 4일의 기간을 추가해야 합니다.

주 수를 계산하는 함수를 작성해 보겠습니다.

long WeekNum(datetime aTime,bool aStartsOnMonday=false)
  {
//--- if the week starts on Sunday, add the duration of 4 days (Wednesday+Tuesday+Monday+Sunday),
//    if it starts on Monday, add 3 days (Wednesday, Tuesday, Monday)
   if(aStartsOnMonday)
     {
      aTime+=259200; // duration of three days (86400*3)
     }
   else
     {
      aTime+=345600; // duration of four days (86400*4)  
     }
   return(aTime/604800);
  }

이 기능은 새로운 주의 첫 번째 바를 결정하는 지표에서 유용할 수 있습니다.

bool NewWeek=WeekNum(time[i])!=WeekNum(time[i-1]);

바는 왼쪽에서 오른쪽으로 인덱싱된다고 가정합니다. 여기서 time[i]는 현재 바의 시간이고 time[i-1]은 이전 바의 시간입니다.

이제 한 주의 시작 시간을 계산할 수 있습니다. 요일을 계산하기 위해 에포크가 3일(또는 4일) 일찍 시작된다고 가정했기 때문에 이제 역 시간 수정을 수행해야 합니다.

long WeekStartTime(datetime aTime,bool aStartsOnMonday=false)
  {
   long tmp=aTime;
   long Corrector;
   if(aStartsOnMonday)
     {
      Corrector=259200; // duration of three days (86400*3)
     }
   else
     {
      Corrector=345600; // duration of four days (86400*4)
     }
   tmp+=Corrector;
   tmp=(tmp/604800)*604800;
   tmp-=Corrector;
   return(tmp);
  }  

첫 번째 주의 값이 음수일 수 있기 때문에 이 함수는 long 유형의 값을 반환합니다(epoch 시작 3-4일 전). 함수의 두 번째 매개변수는 한 주가 일요일에 시작하는지 월요일에 시작하는지 결정할 수 있습니다.

이제 주 시작 시간이 있으므로 주 시작 이후 경과된 시간(초)을 계산할 수 있습니다.

long SecondsFromWeekStart(datetime aTime,bool aStartsOnMonday=false)
  {
   return(aTime-WeekStartTime(aTime,aStartsOnMonday));
  }

초는 일, 시, 분, 초로 변환할 수 있습니다. 하루가 시작된 후 시간, 분, 초를 계산하는 것은 어렵지 않았지만 이 경우에는 TimeToStruct() 함수를 사용하는 것이 더 쉬울 것입니다.

long sfws=SecondsFromWeekStart(TimeCurrent());
MqlDateTime stm;
TimeToStruct(sfws,stm);
stm.day--;
Alert("Time elapsed since the week start "+(string)stm.day+" d, "+(string)stm.hour+" h, "+(string)stm.min+" m, "+(string)stm.sec+" s");

stm.day 값이 1 감소합니다. 전체 일 수를 결정해야 하므로 월의 일 수는 1부터 계산됩니다. 이 섹션의 기능이 실용적인 관점에서 쓸모없다고 생각하는 사람도 있을 수 있지만 이러한 기능에 대한 이해는 시간 작업의 경험으로 큰 가치가 있을 것입니다.


주어진 날짜, 연도 시작 또는 월 시작 이후 주 번호 확인

MqlDateTime 구조의 필드, 특히 day_of_year 필드를 보면 연초와 월 시작 이후의 주 수를 결정하는 함수를 만드는 것과 같은 느낌이 듭니다. 주어진 날짜 이후의 주 수를 결정하는 일반 함수를 작성하는 것이 좋습니다. 함수 연산의 원리는 신기원의 시작 이후 주 수를 결정하는 데 사용되는 원리와 유사합니다.

long WeekNumFromDate(datetime aTime,datetime aStartTime,bool aStartsOnMonday=false)
  {
   long Time,StartTime,Corrector;
   MqlDateTime stm;
   Time=aTime;
   StartTime=aStartTime;
//--- determine the beginning of the reference epoch
   StartTime=(StartTime/86400)*86400;
//--- determine the time that elapsed since the beginning of the reference epoch
   Time-=StartTime;
//--- determine the day of the week of the beginning of the reference epoch
   TimeToStruct(StartTime,stm);
//--- if the week starts on Monday, numbers of days of the week are decreased by 1,
//    and the day with number 0  becomes a day with number 6
   if(aStartsOnMonday)
     {
      if(stm.day_of_week==0)
        {
         stm.day_of_week=6;
        }
      else
        {
         stm.day_of_week--;
        }
     }
//--- calculate the value of the time corrector 
   Corrector=86400*stm.day_of_week;
//--- time correction
   Time+=Corrector;
//--- calculate and return the number of the week
   return(Time/604800);
  }

이 함수를 기반으로 연초 이후의 주 수와 월 시작 이후의 주 수를 결정하는 두 가지 함수를 작성해 보겠습니다. 이렇게 하려면 먼저 연도 시작 시간과 월 시작 시간을 결정해야 합니다. 시간을 구성 요소로 나누고 일부 필드의 값을 조정하고 구성 요소를 시간 표기법으로 다시 변환합니다.

  • 시작 시간을 결정하는 기능:

    datetime YearStartTime(datetime aTime)
          {
           MqlDateTime stm;
           TimeToStruct(aTime,stm);
           stm.day=1;
           stm.mon=1;
           stm.hour=0;
           stm.min=0;
           stm.sec=0;
           return(StructToTime(stm));
          }
  • 월 시작 시간을 결정하는 기능:

    datetime MonthStartTime(datetime aTime)
          {
           MqlDateTime stm;
           TimeToStruct(aTime,stm);
           stm.day=1;
           stm.hour=0;
           stm.min=0;
           stm.sec=0;
           return(StructToTime(stm));
          }

이제 다음은 연도 시작 및 월 시작 이후의 주 수를 판별하는 함수입니다.

  • 연초부터:

    long WeekNumYear(datetime aTime,bool aStartsOnMonday=false)
          {
           return(WeekNumFromDate(aTime,YearStartTime(aTime),aStartsOnMonday));
          }
  • 월 시작 이후:

    long WeekNumMonth(datetime aTime,bool aStartsOnMonday=false)
          {
           return(WeekNumFromDate(aTime,MonthStartTime(aTime),aStartsOnMonday));
          }

마지막으로, 우리는 순전히 실용적인 작업으로 넘어갑니다.


실험 도구 세트 만들기

이미 언급했듯이 호가에 일요일 바가 포함되어 있고 주말 내내 지속적으로 호가를 제공하는 거래 센터가 있습니다. 모든 경우에 필요한 기능이 제대로 작동하는지 확인해야 합니다. 물론 인터넷에서 적절한 거래 센터를 찾고 데모 계정의 호가를 사용하여 기능의 작동을 테스트할 수 있습니다. 그러나 올바른 거래 센터를 찾는 것 외에도 차트에서 필요한 테스트를 실행하기 위해 적절한 포지션을 검색해야 합니다.

기능 테스트를 위한 자체 테스트 영역을 만들어 보겠습니다. 금요일, 주말 및 월요일이 특히 중요합니다. 필요에 따라 금요일, 월요일 및 주말 바의 시간을 포함하는 배열을 만듭니다. 총 4가지 옵션이 있습니다.

  1. 주말 바가 없습니다.
  2. 일요일이 끝날 때 일부 바, 예를 들어 4.
  3. 연속 주말 호가.
  4. 토요일 바는 있지만 일요일 바는 없습니다.

배열이 너무 커지지 않도록 하기 위해 H1 시간 프레임을 사용합니다. 최대 배열 크기는 96개 요소(하루 24개, 4일)이며 배열 자체는 그래픽 개체를 사용하여 그릴 때 차트에 맞습니다. 따라서 시간이 있는 지표 버퍼와 같은 것을 얻고 지표를 시작할 때 OnCalculate() 함수의 첫 번째 실행과 유사한 방식으로 루프에서 배열을 반복합니다. 따라서 함수 연산을 시각화할 수 있습니다.

이 도구는 이 글에 첨부된 스크립트(sTestArea.mq5 파일)의 형태로 구현됩니다. 준비는 스크립트의 OnStart() 함수에서 수행됩니다. 함수 코드의 맨 처음에 있는 Variant 변수를 사용하면 위에 나열된 네 가지 옵션 중 하나를 선택할 수 있습니다. OnStart() 함수 아래에는 지표의 OnCalculate() 함수와 유사한 LikeOnCalculate() 함수를 볼 수 있습니다. 이 함수에는 두 개의 매개변수가 있습니다. Rates_total - 바의 수 및 time[] - 바의 시간이 있는 배열입니다.

또한 지표를 작성하는 것처럼 이 함수에서 계속 작업합니다. SetMarker() 함수를 호출하여 함수에서 마커를 설정할 수 있습니다. SetMarker() 함수에 전달되는 매개변수는 바 인덱스, 버퍼 인덱스(마커가 표시되는 행) 및 마커 색상입니다.

그림 4는 스크립트 성능 결과를 보여줍니다. Variant 변수는 2이고 각 바 아래에 두 개의 마커 행이 설정되어 있습니다(바는 관련 타임스탬프로 표시됨). 모든 차트 요소에 설정된 색상은 보이지 않습니다.

그림 4. sTestArea.mq5 스크립트 성능.
그림 4. sTestArea.mq5 스크립트 성능.

바 타임스탬프는 요일에 따라 색상이 지정됩니다: 금요일 - 빨간색, 토요일 - 자홍색, 일요일 - 녹색, 월요일 - 파란색. 이제 주말 바에 대한 특별한 접근이 필요한 다양한 기능을 작성하여 작업을 시각적으로 모니터링할 수 있습니다.


피벗 지표 - 옵션 1

먼저 간단한 피벗 지표를 만들어 보겠습니다. 피벗선을 계산하려면 어제의 종가와 어제의 최고가와 최저 가격을 알아야 합니다. 지표 값은 이 세 값의 평균으로 계산됩니다. 우리는 하루 동안 새로운 최고점과 최저점을 식별하고, 새로운 하루가 시작될 때 Pivot 값을 계산하고, 하루 종일 수준을 더 그려서 표시합니다.

지표 작업의 두 가지 버전을 제공합니다.

  1. 피벗은 새로운 날마다 계산됩니다(주말 바가 없다고 가정). 주말 바가 있는 경우 토요일과 일요일 바는 다르게 취급됩니다.
  2. 토요일 바는 금요일에 속하고 일요일 바는 월요일에 속합니다(이는 주말 내내 지속적으로 호가가 제공되고 일요일 바만 있는 경우에 적용됨). 여기서 주말에는 술집이 없을 수도 있다는 점을 염두에 두어야 합니다.

첫 번째 버전에서는 새 날의 시작만 결정하는 것으로 충분합니다. 현재 시간(aTimeCur)과 이전 시간(aTimePre)을 함수에 전달하고 에포크 시작 이후의 날짜 수를 계산하고 일치하지 않으면 새 날짜가 시작되었다고 추론합니다.

bool NewDay1(datetime aTimeCur,datetime aTimePre)
  {
   return((aTimeCur/86400)!=(aTimePre/86400));
  }

두 번째 버전. 토요일이 시작된 경우 하루 시작을 무시해야 합니다. 일요일이 시작되면 하루 시작을 정의합니다(이는 당연히 다른 날임). 일요일 다음으로 월요일이 시작되면 하루 시작을 건너뜁니다. 월요일이 다른 요일보다 앞서는 경우(예: 토요일 또는 금요일, 시작일을 정의합니다. 우리가 얻는 것은 다음과 같은 함수입니다:

bool NewDay2(datetime aTimeCur,datetime aTimePre)
  {
   MqlDateTime stm;
//--- new day
   if(NewDay1(aTimeCur,aTimePre))
     {
      TimeToStruct(aTimeCur,stm);
      switch(stm.day_of_week)
        {
         case 6: // Saturday
            return(false);
            break;
         case 0: // Sunday
            return(true);
            break;
         case 1: // Monday
            TimeToStruct(aTimePre,stm);
            if(stm.day_of_week!=0)
              { // preceded by any day of the week other than Sunday
               return(true);
              }
            else
              {
               return(false);
              }
            break;
         default: // any other day of the week
            return(true);
        }
     }
   return(false);
  }

버전에 따른 일반적인 기능은 다음과 같습니다.

bool NewDay(datetime aTimeCur,datetime aTimePre,int aVariant=1)
  {
   switch(aVariant)
     {
      case 1:
         return(NewDay1(aTimeCur,aTimePre));
         break;
      case 2:
         return(NewDay2(aTimeCur,aTimePre));
         break;
     }
   return(false);
  }

"sTestArea" 도구(첨부된 sTestArea_Pivot1.mq5 파일, 시작 날짜는 갈색으로 표시됨)를 사용하여 기능 작동을 테스트해 보겠습니다. 8개의 테스트를 실행해야 합니다. 4개의 바 생성 옵션에 대한 2개의 기능 버전. 기능이 제대로 작동하는지 확인한 후에는 지표 개발을 안전하게 시작할 수 있습니다. 그러나 지표 개발은 이 글의 초점이 아니므로 개발의 가장 어려운 부분을 자세히 고려하여 준비된 지표(Pivot1.mq5 파일)를 여기에 첨부했습니다.


시간 세션 결정

Expert Advisor가 하루 중 지정된 시간 범위 내에서 매일 같은 간격으로 거래할 수 있도록 해야 합니다. 우리는 거래 세션이 시작되는 시간과 분뿐만 아니라 거래 세션이 끝나는 시간과 분을 지정합니다. "14:00"으로 지정된 시간의 문자열 변수가 아니라 별도로 지정된 시간과 분을 사용하면 Expert Advisor에서 기능을 사용하는 경우 Strategy Tester에서 최적화를 수행할 수 있습니다.

시간 세션을 결정하려면 다음과 같이 하세요.

  1. 시작 시점에 대해 하루가 시작된 이후의 시간을 초 단위로 계산하고 종료 시점에 대해서도 동일하게 수행합니다.
  2. 하루가 시작된 후 현재 시간을 초 단위로 계산합니다.
  3. 현재 시간을 시작 및 종료 시간과 비교합니다.

거래 세션이 어느 날 시작되어 다른 날 종료되는 것은 불가능하지 않습니다. 즉, 거래 세션이 자정을 넘을 때 하루 시작 이후 계산된 종료 시간이 시작 시간보다 짧은 것으로 판명됩니다. 따라서 두 가지 검사를 수행해야 합니다. 우리가 얻는 함수는 다음과 같습니다.

bool TimeSession(int aStartHour,int aStartMinute,int aStopHour,int aStopMinute,datetime aTimeCur)
  {
//--- session start time
   int StartTime=3600*aStartHour+60*aStartMinute;
//--- session end time
   int StopTime=3600*aStopHour+60*aStopMinute;
//--- current time in seconds since the day start
   aTimeCur=aTimeCur%86400;
   if(StopTime<StartTime)
     {
      //--- going past midnight
      if(aTimeCur>=StartTime || aTimeCur<StopTime)
        {
         return(true);
        }
     }
   else
     {
      //--- within one day
      if(aTimeCur>=StartTime && aTimeCur<StopTime)
        {
         return(true);
        }
     }
   return(false);
  }

세션이 자정을 초과하는 경우 현재 시간은 세션 시작 시간보다 크거나 같아야 하거나 세션 종료 시간보다 작아야 합니다. 세션이 하루 내에 발생하는 경우 현재 시간은 시작 시간보다 크거나 같아야 하고 종료 시간보다 작아야 합니다.

기능 작동을 테스트하기 위해 생성된 지표는 글 끝에 첨부되어 있습니다(Session.mq5 파일). 응용 프로그램의 다른 지표와 마찬가지로 테스트뿐만 아니라 다른 실용적인 목적으로도 사용할 수 있습니다.


하루 중 시점 결정

틱이 일정한 간격으로 발생하지 않고 몇 초에서 몇 분의 지연이 있을 수 있으므로 지정된 시간과 동일한지 간단한 확인이 제대로 작동하지 않습니다. 시장에서 지정된 시간에 틱이 없을 가능성이 매우 높습니다. 주어진 타임스탬프의 교차점을 확인해야 합니다.

현재 시간은 지정된 시간보다 크거나 같아야 하고 이전 시간은 지정된 시간보다 작아야 합니다. 하루 중 특정 시점을 결정해야 하므로 현재 시간(및 이전 시간)을 하루가 시작된 이후의 초로 변환해야 합니다. 유사하게, 주어진 시간 매개변수(시 및 분)는 초로 변환되어야 합니다. 이전 시간은 전날에 해당할 수 있습니다. 즉, 하루 시작 이후 초로 변환하면 현재 시간보다 클 수 있습니다. 이 경우 시간 세션을 결정할 때와 동일한 방식으로 진행합니다. 두 가지 검사를 수행합니다.

우리가 얻는 함수는 다음과 같습니다.

bool TimeCross(int aHour,int aMinute,datetime aTimeCur,datetime aTimePre)
  {
//--- specified time since the day start
   datetime PointTime=aHour*3600+aMinute*60;
//--- current time since the day start
   aTimeCur=aTimeCur%86400;
//--- previous time since the day start
   aTimePre=aTimePre%86400;
   if(aTimeCur<aTimePre)
     {
      //--- going past midnight
      if(aTimeCur>=PointTime || aTimePre<PointTime)
        {
         return(true);
        }
     }
   else
     {
      if(aTimeCur>=PointTime && aTimePre<PointTime)
        {
         return(true);
        }
     }
   return(false);
  }

이 기능을 기반으로 생성된 지표가 있습니다(글에 첨부된 TimePoint.mq5 파일).


피벗 지표 - 옵션 2

이제 시점을 결정하는 방법을 배웠으므로 Pivot 지표를 정교하게 만들어 보겠습니다. 평소의 00:00 대신 하루가 이제 주어진 시간에 시작됩니다. 우리는 그것을 사용자 정의 날이라고 부를 것입니다. 사용자 정의 날짜의 시작을 결정하기 위해 앞에서 설명한 TimeCross() 함수를 사용합니다. 주말에는 다양한 바 생성 옵션으로 인해 일부 날짜를 생략해야 합니다. 현재로서는 모든 점검 규칙을 마련하기가 어려우므로 한 번에 한 단계씩 진행해 나가도록 하겠습니다. 중요한 것은 시작해야 할 것이 있고 진행 방법에 대한 옵션이 있다는 것입니다. 테스트 스크립트인 sTestArea.mq5가 있으므로 실험적으로 올바른 솔루션을 찾을 수도 있습니다.

"주말 바 없음"의 경우가 가장 간단합니다. 새로운 날은 주어진 타임스탬프의 교차점에서 시간이 시작됩니다.

일요일이 끝날 때 바가 몇 개 없는 경우 TimeCross() 함수는 함수 매개변수가 주어지면 첫 번째 일요일 바를 요일 시작으로 정의합니다. 주말에는 따옴표가 없다고 가정하므로(일요일 바는 월요일에 속함) 일요일은 무시해야 합니다. 주어진 시간이 일련의 일요일 바 중간 어딘가에 있는 경우 새 날 시작이 이미 금요일에 등록되었으므로 무시해야 합니다.

연속 주말 따옴표: 사용자 정의 날짜의 시작이 달력 날짜의 중간에 있는 경우(그림 5),

그림 5. 사용자 정의 요일은 달력의 중간에 시작됩니다. 금요일 - 레드, 토요일 - 마젠타, 일요일 - 그린, 월요일 - 블루.
그림 5. 사용자 정의 요일은 달력의 중간에 시작됩니다.
금요일 - 레드, 토요일 - 마젠타, 일요일 - 그린, 월요일 - 블루.

토요일의 반은 금요일로 처리되고 일요일의 반은 월요일로 처리될 수 있습니다. 그러나 토요일 중반부터 일요일 중반까지 어디에도 속하지 않는 바가 있습니다. 물론 토요일에서 일요일까지의 간격을 동일한 부분으로 나누고 절반은 금요일로, 나머지 절반은 월요일로 처리할 수 있습니다. 주말 호가가 그렇게 중요하지 않더라도 이것은 매우 간단한 지표를 상당히 복잡하게 만듭니다.

가장 합리적인 솔루션은 모든 토요일 및 일요일 바를 금요일부터 월요일까지 지속되는 사용자 정의 요일로 간주하는 것입니다. 즉, 토요일과 일요일에 시작하는 사용자 정의 요일은 건너뜁니다.

우리가 얻는 함수는 다음과 같습니다.

bool NewCustomDay(int aHour,int aMinute,datetime aTimeCur,datetime aTimePre)
  {
   MqlDateTime stm;
   if(TimeCross(aHour,aMinute,aTimeCur,aTimePre))
     {
      TimeToStruct(aTimeCur,stm);
      if(stm.day_of_week==0 || stm.day_of_week==6)
        {
         return(false);
        }
      else
        {
         return(true);
        }
     }
   return(false);
  }

이 기능을 기반으로 생성된 지표가 있습니다(글에 첨부된 Pivot2.mq5 파일).


요일의 거래일 결정

Expert Advisor가 특정 날짜에만 거래할 수 있도록 하는 것은 매우 쉽습니다. TimeToStruct() 함수를 사용하여 시간을 구성 요소로 나누고 Expert Advisor의 매개 변수에서 각 요일에 대한 bool 유형 변수를 선언합니다. 요일에 따라 함수는 해당 변수의 값을 반환합니다.

이것은 보다 최적의 방법으로 수행될 수 있습니다. Expert Advisor 또는 지표를 초기화할 때 특정 날짜에 거래를 허용하거나 허용하지 않는 변수 값으로 배열을 채우십시오. 그런 다음 요일에 해당하는 배열 요소의 값을 확인합니다. 우리는 두 개의 함수를 얻습니다. 하나는 초기화 중에 호출되고 다른 하나는 필요에 따라 호출됩니다.

변수:

input bool Sunday   =true; // Sunday
input bool Monday   =true; // Monday
input bool Tuesday  =true; // Tuesday 
input bool Wednesday=true; // Wednesday
input bool Thursday =true; // Thursday
input bool Friday   =true; // Friday
input bool Saturday =true; // Saturday

bool WeekDays[7];

초기화 기능:

void WeekDays_Init()
  {
   WeekDays[0]=Sunday;
   WeekDays[1]=Monday;
   WeekDays[2]=Tuesday;
   WeekDays[3]=Wednesday;
   WeekDays[4]=Thursday;
   WeekDays[5]=Friday;
   WeekDays[6]=Saturday;
  }

주요 기능:

bool WeekDays_Check(datetime aTime)
  {
   MqlDateTime stm;
   TimeToStruct(aTime,stm);
   return(WeekDays[stm.day_of_week]);
  }

이 기능을 기반으로 생성된 지표는 글 말미(TradeWeekDays.mq5 파일)에 첨부되어 있습니다.


주간 거래 시간 결정

우리는 요일의 주어진 시간에서 다른 요일의 주어진 시간까지의 거래 세션을 결정해야 합니다. 이 함수는 TimeSession() 함수와 유사하지만 계산이 주 시작 이후 경과된 시간을 기반으로 한다는 점만 다릅니다. 우리가 얻는 함수는 다음과 같습니다.

bool WeekSession(int aStartDay,int aStartHour,int aStartMinute,int aStopDay,int aStopHour,int aStopMinute,datetime aTimeCur)
  {
//--- session start time since the week start
   int StartTime=aStartDay*86400+3600*aStartHour+60*aStartMinute;
//--- session end time since the week start
   int StopTime=aStopDay*86400+3600*aStopHour+60*aStopMinute;
//--- current time in seconds since the week start
   long TimeCur=SecondsFromWeekStart(aTimeCur,false);
   if(StopTime<StartTime)
     {
      //--- passing the turn of the week
      if(TimeCur>=StartTime || TimeCur<StopTime)
        {
         return(true);
        }
     }
   else
     {
      //--- within one week
      if(TimeCur>=StartTime && TimeCur<StopTime)
        {
         return(true);
        }
     }
   return(false);
  }

이 기능을 기반으로 생성된 지표는 글 말미(SessionWeek.mq5 파일)에 첨부되어 있습니다.

우리는 가장 일반적인 시간 관련 작업을 거의 모두 고려하고 관련 프로그래밍 기술과 이를 해결하는 데 필요한 표준 MQL5 기능을 검토했습니다.


추가 MQL5 기능

시간 작업을 위한 MQL5 함수가 몇 가지 더 있습니다. TimeTradeServer(), TimeGMT(), TimeDaylightSavings()TimeGMTOffset(). 이러한 기능의 주요 특징은 사용자 PC의 시계 및 시간 설정에서 사용된다는 것입니다.

TimeTradeServer() 함수. TimeCurrent() 함수가 주말(금요일의 마지막 가격 변경 시간)에 잘못된 시간을 표시한다고 글 앞부분에서 언급했습니다. TimeTradeServer() 함수는 올바른 서버 시간을 계산합니다.

datetime tm=TimeTradeServer();
//--- output result
Alert(tm);

TimeGMT() 함수. 이 기능은 사용자 컴퓨터의 시계 값과 시간 설정(시간대 및 일광 절약 시간제)을 기반으로 GMT 시간을 계산합니다.

datetime tm=TimeGMT();
//--- output result
Alert(tm);

더 정확하게 말하면 이 함수는 UTC 시간을 반환합니다.

TimeDaylightSavings() 함수. 이 기능은 사용자의 컴퓨터 설정에서 일광 절약 시간제에 대한 수정 값을 반환합니다.

int val=TimeDaylightSavings();
//--- output result
Alert(val);

Daylight Saving Time에 대한 보정 값이 없는 시간을 얻으려면 현지 시간에 보정 값을 추가해야 합니다.

TimeGMTOffset() 함수. 이 기능을 사용하면 사용자 컴퓨터의 시간대를 얻을 수 있습니다. 값은 GMT 시간을 얻기 위해 현지 시간에 추가되는 초 단위로 반환됩니다.

int val=TimeGMTOffset();
//--- output result
Alert(val);

사용자 컴퓨터의 시간은 TimeGMT()-TimeGMTOffset()-TimeDaylightSavings()입니다.

datetime tm1=TimeLocal();
datetime tm2=TimeGMT()-TimeGMTOffset()-TimeDaylightSavings();
//--- output result
Alert(tm1==tm2);


시간 처리를 위한 몇 가지 더 유용한 기능

윤년 결정 함수

bool LeapYear(datetime aTime)
  {
   MqlDateTime stm;
   TimeToStruct(aTime,stm);
//--- a multiple of 4 
   if(stm.year%4==0)
     {
      //--- a multiple of 100
      if(stm.year%100==0)
        {
         //--- a multiple of 400
         if(stm.year%400==0)
           {
            return(true);
           }
        }
      //--- not a multiple of 100 
      else
        {
         return(true);
        }
     }
   return(false);
  }

윤년을 결정하는 원리는 위의 시간 측정의 특성 섹션에 설명되어 있습니다.

한 달의 일 수를 결정하는 함수

int DaysInMonth(datetime aTime)
  {
   MqlDateTime stm;
   TimeToStruct(aTime,stm);
   if(stm.mon==2)
     {
      //--- February
      if(LeapYear(aTime))
        {
         //--- February in a leap year 
         return(29);
        }
      else
        {
         //--- February in a non-leap year 
         return(28);
        }
     }
   else
     {
      //--- other months
      return(31-((stm.mon-1)%7)%2);
     }
  }

이 함수는 연도가 윤년인지 확인하여 2월에 적절한 값인 28 또는 29를 반환하고 다른 달의 일 수를 계산합니다. 처음 7개월의 일 수는 31, 30, 31, 30 등으로 변경되고 나머지 5개월의 일 수는 변경됩니다. 따라서 함수는 7로 나눈 나머지를 계산합니다. 그런 다음 홀수 패리티 검사를 수행하고 얻은 수정을 31에서 뺍니다.


전략 테스터에서 시간 함수 연산의 특성

전략 테스터는 자체 호가 스트림을 생성하고 TimeCurrent() 함수의 값은 전략 테스터의 호가 스트림에 해당합니다. TimeTradeServer() 함수 값은 TimeCurrent() 값에 해당합니다. 마찬가지로 TimeLocal() 함수 값은 TimeCurrent() 값에 해당합니다. Strategy Tester의 TimeCurrent() 함수는 시간대와 Daylight Saving Time 수정을 고려하지 않습니다. Expert Advisors의 운용은 가격 변동을 기반으로 하므로 Expert Advisor가 시간 처리를 필요로 하는 경우 TimeCurrent() 함수를 사용하세요. 이를 통해 Strategy Tester에서 Expert Advisor를 안전하게 테스트할 수 있습니다.

TimeGMT(), TimeDaylightSavings() 및 TimeGMTOffset() 함수는 사용자 컴퓨터의 현재 설정을 기반으로 독점적으로 작동합니다(일광 절약 시간으로의 전환 및 뒤로는 전략 테스터에서 시뮬레이션되지 않음). Expert Advisor를 테스트할 때 일광 절약 시간제로 시간 변경을 시뮬레이션하고 표준 시간으로 되돌려야 하는 경우(정말 필요한 경우) 사용자가 직접 처리해야 합니다. 이를 위해서는 시계 이동을 위한 정확한 날짜와 시간에 대한 정보와 철저한 분석이 필요합니다.

이 문제에 대한 해결책은 단일 글의 범위를 훨씬 넘어서므로 여기에서 고려하지 않습니다. Expert Advisor가 유럽 또는 미국 세션 시간 내에 근무하고 거래 센터가 일광 절약 시간제를 준수하는 경우 아시아 세션과 달리 서버 시간과 이벤트 시간의 불일치가 없을 것입니다(일본은 일광 절약 시간제, 호주는 11월에 일광 절약 시간제로 시계를 변경함).


결론

이 글에서는 시간 작업을 위한 모든 표준 MQL5 기능을 다뤘습니다. 시간 관련 작업을 처리할 때 사용되는 프로그래밍 기술을 설명합니다. 이 글은 또한 작동 원리에 대한 자세한 설명과 함께 몇 가지 지표와 몇 가지 유용한 기능의 생성을 보여주었습니다.

시간 작업을 위한 모든 표준 함수는 여러 범주로 분류할 수 있습니다.

  1. TimeCurrent()TimeLocal()은 현재 시간을 결정하는 데 사용되는 주요 함수입니다.
  2. TimeToString(), StringToTime(), TimeToStruct()StructToTime()은 시간 처리 함수입니다.
  3. CopyTime()은 마디 시간으로 작업하기 위한 함수입니다.
  4. TimeTradeServer(), TimeGMT(), TimeDaylightSavings()TimeGMTOffset()은 사용자의 컴퓨터 설정.


첨부 파일

  • sTestArea.mq5 - 복잡한 시간 함수를 테스트하기 위한 스크립트입니다.
  • sTestArea_Pivot1.mq5 - Pivot1.mq5 지표의 시간 기능을 테스트하는 데 사용되는 sTestArea.mq5 스크립트.
  • Pivot1.mq5 - 표준 날짜를 사용하는 Pivot 지표(NewDay 기능).
  • Session.mq5 - 당일 거래 세션 지표(TimeSession 기능).
  • TimePoint.mq5 - 주어진 시점의 지표(TimeCross 기능).
  • Pivot2.mq5 - 사용자 정의 날짜를 사용하는 Pivot 지표(NewCustomDay 함수).
  • TradeWeekDays.mq5 - 주간 거래일 지표(WeekDays_Check 기능).
  • SessionWeek.mq5 - 주의 거래 세션 지표(WeekSession 기능).
  • TimeFunctions.mqh - 이 문서에서 제공하는 모든 시간 함수를 단일 파일로 제공합니다.

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/599

파일 첨부됨 |
stestarea.mq5 (4.96 KB)
pivot1.mq5 (4.5 KB)
session.mq5 (3.51 KB)
timepoint.mq5 (3.32 KB)
pivot2.mq5 (4.14 KB)
tradeweekdays.mq5 (3.59 KB)
sessionweek.mq5 (5.08 KB)
timefuncions.mqh (20.52 KB)
지표 배출 (Indicator Emissions)의 적분 특성 계산 지표 배출 (Indicator Emissions)의 적분 특성 계산
지표 배출은 시장 조사에서 거의 연구되지 않은 영역입니다. 이는 주로 시변 데이터의 매우 큰 배열 처리로 인한 분석의 어려움 때문입니다. 기존 그래픽 분석은 리소스 집약적이므로 시계열 배출을 사용하는 간결한 알고리즘 개발을 촉발했습니다. 이 글은 시각적(직관적인 이미지) 분석이 배출의 통합 특성 연구로 대체될 수 있는 방법을 보여줍니다. 자동 거래 시스템의 거래자와 개발자 모두에게 흥미로울 수 있습니다.
MetaTrader 4 및 MetaTrader 5의 신호 제공자가 되는 방법 MetaTrader 4 및 MetaTrader 5의 신호 제공자가 되는 방법
거래 시그널을 제공하고 수익을 내고 싶으시나요? MQL5.com 웹사이트에 판매자로 등록하고 거래 계정을 지정하고 트레이더들이 여러분의 거래를 복사할 수 있는 구독을 제공하세요.
MetaTrader 4 및 MetaTrader 5의 신호 거래에 대한 일반 정보 MetaTrader 4 및 MetaTrader 5의 신호 거래에 대한 일반 정보
MetaTrader 4 / MetaTrader 5 거래 신호는 거래자가 신호 제공자의 거래 작업을 복사할 수 있도록 하는 서비스입니다. 우리의 목표는 가입자를 보호하고 불필요한 비용을 덜어주는 새로운 대량 사용 서비스를 개발하는 것이었습니다.
매수하기 전에 거래 로봇을 테스트하는 방법 매수하기 전에 거래 로봇을 테스트하는 방법
MQL5 Market에서 거래 로봇을 매수하면 다른 모든 유사한 옵션에 비해 뚜렷한 이점이 있습니다. 제공되는 자동화 시스템은 MetaTrader 5 터미널에서 직접 철저히 테스트할 수 있습니다. 매수하기 전에 Expert Advisor는 시스템을 완전히 파악하기 위해 내장된 전략 테스터의 모든 불리한 모드에서 신중하게 실행할 수 있고 또 실행해야 합니다.