//+------------------------------------------------------------------+
//| CustomTicksAdd.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#define CUSTOM_SYMBOL_NAME Symbol()+".C" // 사용자 지정 심볼명
#define CUSTOM_SYMBOL_PATH "Forex" // 심볼을 생성할 그룹 명
#define CUSTOM_SYMBOL_ORIGIN Symbol() // 사용자 정의 심볼의 기반이 되는 심볼 명
#define DATATICKS_TO_COPY UINT_MAX // 복사 되는 틱의 수
#define DATATICKS_TO_PRINT 20 // 저널에 보내진 틱의 수
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 사용자 정의 심볼을 생성할 때 오류 코드를 가져옵니다.
int create=CreateCustomSymbol(CUSTOM_SYMBOL_NAME, CUSTOM_SYMBOL_PATH, CUSTOM_SYMBOL_ORIGIN);
//--- 오류 코드가 0(심볼 생성 성공)도 아니고 5304(심볼이 이미 생성됨)도 아닌 경우 - 그대로 둠
if(create!=0 && create!=5304)
return;
//--- 표준 심볼 틱 데이터를 MqlTick 배열로 가져옵니다.
MqlTick array[]={};
if(!GetTicksToArray(CUSTOM_SYMBOL_ORIGIN, DATATICKS_TO_COPY, array))
return;
//--- 표준 심볼의 첫 번째 및 마지막 수신 틱 시간을 출력합니다.
int total=(int)array.Size();
PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
TimeToString(array[0].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
TimeToString(array[total-1].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
//--- 저널에 있는 표준 심볼의 마지막 틱 DATATICKS_TO_PRINT를 출력합니다.
PrintFormat("\nThe last %d ticks for the standard symbol '%s':", DATATICKS_TO_PRINT, CUSTOM_SYMBOL_ORIGIN);
for(int i=total-DATATICKS_TO_PRINT; i<total; i++)
{
if(i<0)
continue;
PrintFormat(" %dth Tick: %s", i, GetTickDescription(array[i]));
}
//--- 종합 시세 창에 사용자 정의 심볼을 추가합니다.
ResetLastError();
if(!SymbolSelect(CUSTOM_SYMBOL_NAME, true))
{
Print("SymbolSelect() failed. Error ", GetLastError());
return;
}
//--- 사용자 지정 심볼 가격 히스토리에 틱 배열 데이터를 추가합니다.
Print("...");
uint start=GetTickCount();
PrintFormat("Start of adding %u ticks to the history of the custom symbol '%s'", array.Size(), CUSTOM_SYMBOL_NAME);
int added=CustomTicksAdd(CUSTOM_SYMBOL_NAME, array);
PrintFormat("Added %u ticks to the history of the custom symbol '%s' in %u ms", added, CUSTOM_SYMBOL_NAME, GetTickCount()-start);
//--- 사용자 정의 심볼 틱 데이터를 MqlTick 배열로 가져옵니다.
Print("...");
if(!GetTicksToArray(CUSTOM_SYMBOL_NAME, array.Size(), array))
return;
//--- 사용자 정의 심볼의 첫 번째 및 마지막 수신 틱 시간을 출력합니다.
total=(int)array.Size();
PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
TimeToString(array[0].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
TimeToString(array[total-1].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
//--- 저널에 있는 사용자 정의 심볼의 마지막 틱 DATATICKS_TO_PRINT를 출력합니다.
PrintFormat("\nThe last %d ticks for the custom symbol '%s':", DATATICKS_TO_PRINT, CUSTOM_SYMBOL_NAME);
for(int i=total-DATATICKS_TO_PRINT; i<total; i++)
{
if(i<0)
continue;
PrintFormat(" %dth Tick: %s", i, GetTickDescription(array[i]));
}
//--- 차트 주석에 스크립트 종료 키에 대한 힌트를 표시합니다.
Comment(StringFormat("Press 'Esc' to exit or 'Del' to delete the '%s' symbol and exit", CUSTOM_SYMBOL_NAME));
//--- Esc 또는 Del 키를 눌러 무한 루프를 종료할 때까지 기다립니다.
while(!IsStopped() && TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)==0)
{
Sleep(16);
//--- Del 키를 누르면 생성된 사용자 정의 심볼 및 해당 데이터가 삭제됩니다.
if(TerminalInfoInteger(TERMINAL_KEYSTATE_DELETE)<0)
{
//--- 바 데이터 삭제
int deleted=CustomRatesDelete(CUSTOM_SYMBOL_NAME, 0, LONG_MAX);
if(deleted>0)
PrintFormat("%d history bars of the custom symbol '%s' were successfully deleted", deleted, CUSTOM_SYMBOL_NAME);
//--- 틱 데이터 삭제
deleted=CustomTicksDelete(CUSTOM_SYMBOL_NAME, 0, LONG_MAX);
if(deleted>0)
PrintFormat("%d history ticks of the custom symbol '%s' were successfully deleted", deleted, CUSTOM_SYMBOL_NAME);
//--- 심볼 삭제
if(DeleteCustomSymbol(CUSTOM_SYMBOL_NAME))
PrintFormat("Custom symbol '%s' deleted successfully", CUSTOM_SYMBOL_NAME);
break;
}
}
//--- 종료하기 전에 차트를 삭제
Comment("");
/*
결과:
Requested 4294967295 ticks to download tick history for the symbol 'EURUSD'
The tick history for the 'EURUSD' symbol is received in the amount of 351183943 ticks in 56454 ms
First tick time: 2011.12.19 00:00:08.000, Last tick time: 2024.06.20 21:18:12.010
The last 20 ticks for the standard symbol 'EURUSD':
351183923th Tick: 2024.06.20 21:17:46.380 Bid=1.07124 (Info tick)
351183924th Tick: 2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
351183925th Tick: 2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
351183926th Tick: 2024.06.20 21:17:49.481 Ask=1.07125 (Info tick)
351183927th Tick: 2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
351183928th Tick: 2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
351183929th Tick: 2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
351183930th Tick: 2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
351183931th Tick: 2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
351183932th Tick: 2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
351183933th Tick: 2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
351183934th Tick: 2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
351183935th Tick: 2024.06.20 21:18:00.102 Bid=1.07126 (Info tick)
351183936th Tick: 2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
351183937th Tick: 2024.06.20 21:18:03.699 Bid=1.07129 (Info tick)
351183938th Tick: 2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
351183939th Tick: 2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
351183940th Tick: 2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
351183941th Tick: 2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
351183942th Tick: 2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (Info tick)
...
Start of adding 351183943 ticks to the history of the custom symbol 'EURUSD.C'
Added 351183943 ticks to the history of the custom symbol 'EURUSD.C' in 269890 ms
...
Requested 351183943 ticks to download tick history for the symbol 'EURUSD.C'
The tick history for the 'EURUSD.C' symbol is received in the amount of 351183943 ticks in 116407 ms
First tick time: 2011.12.19 00:00:08.000, Last tick time: 2024.06.20 21:18:12.010
The last 20 ticks for the custom symbol 'EURUSD.C':
351183923th Tick: 2024.06.20 21:17:46.380 Ask=1.07124 Bid=1.07124 (Info tick)
351183924th Tick: 2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
351183925th Tick: 2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
351183926th Tick: 2024.06.20 21:17:49.481 Ask=1.07125 Bid=1.07125 (Info tick)
351183927th Tick: 2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
351183928th Tick: 2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
351183929th Tick: 2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
351183930th Tick: 2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
351183931th Tick: 2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
351183932th Tick: 2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
351183933th Tick: 2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
351183934th Tick: 2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
351183935th Tick: 2024.06.20 21:18:00.102 Ask=1.07126 Bid=1.07126 (Info tick)
351183936th Tick: 2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
351183937th Tick: 2024.06.20 21:18:03.699 Ask=1.07129 Bid=1.07129 (Info tick)
351183938th Tick: 2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
351183939th Tick: 2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
351183940th Tick: 2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
351183941th Tick: 2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
351183942th Tick: 2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (Info tick)
*/
}
//+------------------------------------------------------------------+
//| 사용자 지정 심볼 생성, 에러 코드 반환 |
//+------------------------------------------------------------------+
int CreateCustomSymbol(const string symbol_name, const string symbol_path, const string symbol_origin=NULL)
{
//--- 사용자 정의 심볼의 기반이 될 심볼명을 정의합니다.
string origin=(symbol_origin==NULL ? Symbol() : symbol_origin);
//--- 사용자 정의 심볼 생성에 실패했고 오류 5304가 아닌 경우 저널에 이를 보고합니다.
ResetLastError();
int error=0;
if(!CustomSymbolCreate(symbol_name, symbol_path, origin))
{
error=GetLastError();
if(error!=5304)
PrintFormat("CustomSymbolCreate(%s, %s, %s) failed. Error %d", symbol_name, symbol_path, origin, error);
}
//--- 성공
return(error);
}
//+------------------------------------------------------------------+
//| 사용자 정의 심볼 삭제 |
//+------------------------------------------------------------------+
bool DeleteCustomSymbol(const string symbol_name)
{
//--- 종합시세 창에서 심볼 숨기기
ResetLastError();
if(!SymbolSelect(symbol_name, false))
{
PrintFormat("SymbolSelect(%s, false) failed. Error %d", GetLastError());
return(false);
}
//--- 사용자 정의 심볼 삭제에 실패한 경우 이를 저널에 보고하고 'false'를 반환합니다.
ResetLastError();
if(!CustomSymbolDelete(symbol_name))
{
PrintFormat("CustomSymbolDelete(%s) failed. Error %d", symbol_name, GetLastError());
return(false);
}
//--- 성공
return(true);
}
//+------------------------------------------------------------------+
//| 배열에서 지정된 틱 수를 가져옵니다. |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbol, const uint count, MqlTick &array[])
{
//--- 히스토리 데이터 로딩의 시작을 알립니다.
PrintFormat("Requested %u ticks to get tick history for the symbol '%s'", count, symbol);
//--- 틱 수신을 위해 3번 시도합니다.
int attempts=0;
while(attempts<3)
{
//--- 틱을 받기 전에 시작 시간을 측정합니다.
uint start=GetTickCount();
//--- 1970.01.01 00:00.001 이후의 틱 내역을 요청합니다(매개변수 =1ms)
int received=CopyTicks(symbol, array, COPY_TICKS_ALL, 1, count);
if(received!=-1)
{
//--- 틱 수 및 소요 시간에 대한 정보 표시
PrintFormat("The tick history for the '%s' symbol is received in the amount of %u ticks in %d ms", symbol, received, GetTickCount()-start);
//--- 틱 히스토리가 동기화되면 오류 코드는 0과 같습니다. - 'true'를 반환합니다.
if(GetLastError()==0)
return(true);
PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d",
symbol, received, GetTickCount()-start, GetLastError());
}
//--- 카운트 시도
attempts++;
//--- 틱 데이터베이스 동기화가 끝날 때까지 기다리기 위한 1초 일시 중지
Sleep(1000);
}
//--- 3번의 시도에서 틱 복사에 실패했습니다.
return(false);
}
//+------------------------------------------------------------------+
//| 틱의 문자열 설명을 반환합니다. |
//+------------------------------------------------------------------+
string GetTickDescription(MqlTick &tick)
{
string desc=StringFormat("%s.%03u ", TimeToString(tick.time, TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick.time_msc%1000);
//--- 틱 플래그 체크
bool buy_tick = ((tick.flags &TICK_FLAG_BUY) == TICK_FLAG_BUY);
bool sell_tick = ((tick.flags &TICK_FLAG_SELL) == TICK_FLAG_SELL);
bool ask_tick = ((tick.flags &TICK_FLAG_ASK) == TICK_FLAG_ASK);
bool bid_tick = ((tick.flags &TICK_FLAG_BID) == TICK_FLAG_BID);
bool last_tick = ((tick.flags &TICK_FLAG_LAST) == TICK_FLAG_LAST);
bool volume_tick= ((tick.flags &TICK_FLAG_VOLUME)== TICK_FLAG_VOLUME);
//--- 우선 거래 플래그에 대한 체크를 확인하십시오(CustomTicksAdd()에는 플래그가 없습니다).
if(buy_tick || sell_tick)
{
//--- 거래 틱에 대한 출력 형성
desc += (buy_tick ? StringFormat("Buy Tick: Last=%G Volume=%d ", tick.last, tick.volume) : "");
desc += (sell_tick? StringFormat("Sell Tick: Last=%G Volume=%d ",tick.last, tick.volume) : "");
desc += (ask_tick ? StringFormat("Ask=%G ", tick.ask) : "");
desc += (bid_tick ? StringFormat("Bid=%G ", tick.ask) : "");
desc += "(Trade tick)";
}
else
{
//--- 정보 틱에 대한 출력을 약간 다르게 구성
desc += (ask_tick ? StringFormat("Ask=%G ", tick.ask) : "");
desc += (bid_tick ? StringFormat("Bid=%G ", tick.ask) : "");
desc += (last_tick ? StringFormat("Last=%G ", tick.last) : "");
desc += (volume_tick? StringFormat("Volume=%d ",tick.volume): "");
desc += "(Info tick)";
}
//--- 틱 설명 반환
return(desc);
}
|