시스템트레이딩 게시글

MetaTrader 5에서 모든 심볼의 틱 이력 다운로드하기

첨부파일
56324.zip (3.28 KB, 다운로드 0회)

안녕하세요, 트레이더 여러분! 오늘은 MetaTrader 5를 사용하여 자신의 브로커에서 모든 심볼의 틱 데이터를 다운로드하는 방법에 대해 알아보겠습니다. 이 방법을 통해 백테스트를 위한 모든 심볼 이력을 다운로드하거나, 틱 데이터를 기반으로 커스텀 차트를 만들 수 있습니다.

우선, 틱 데이터가 저장될 데이터 폴더에 충분한 하드 드라이브 공간이 있는지 확인해야 합니다. 그리고 심볼 다운로드를 쉽게 하기 위해 다운로드 매니저를 먼저 설정해야 해요.

CDownloadManager 구조체에는 필요한 모든 정보가 포함되어 있습니다.

struct CDownloadManager
{
bool m_started, m_finished;
string m_symbols[], m_current;
int m_index;
}

여기서 각 구성 요소는 다음과 같은 역할을 합니다:

  • 다운로드 상태 (시작/완료)
  • 스캔할 심볼 목록
  • 현재 심볼
  • 스캔 중인 심볼의 인덱스

또한 하드 드라이브에 읽고 쓸 수 있는 기능이 필요하므로, 심볼을 다루기 위해 문자열을 이진 파일에서 읽고 쓰는 두 가지 간단한 기능을 만들어야 합니다.

파일에 문자열 저장하기:

void writeStringToFile(int f, string thestring) {
// 심볼 문자열 저장
char sysave[];
int charstotal=StringToCharArray(thestring, sysave, 0, StringLen(thestring), CP_ACP);
FileWriteInteger(f, charstotal, INT_VALUE);
for(int i=0; i FileWriteInteger(f, sysave[i], CHAR_VALUE);
}
}

이 함수는 다음과 같은 인자를 받습니다:

  • 파일 핸들 f (쓰기 및 이진 플래그가 설정된 파일)
  • 파일에 쓸 문자열

이 함수는 문자열의 길이를 정수로 저장한 다음, 각 문자를 배열에 저장합니다.

파일에서 문자열 읽기:

string readStringFromFile(int f) {
string result="";
// 심볼 문자열 읽기
char syload[];
int charstotal=(int)FileReadInteger(f, INT_VALUE);
if(charstotal>&0) {
ArrayResize(syload, charstotal, 0);
for(int i=0; i syload[i]=(char)FileReadInteger(f, CHAR_VALUE);
}
result=CharArrayToString(syload, 0, charstotal,CP_ACP);
}
return(result);
}

이 함수는 다음과 같은 인자를 받습니다:

  • 파일 핸들 f (읽기 전용 이진 파일)

이 함수는 파일에서 예상되는 문자 길이를 정수로 읽고, 각 문자를 char 배열로 읽어 문자열로 변환하여 반환합니다.

이제 CDownloadManager 구조체를 초기화하고 시장 감시에서 데이터를 가져오는 방법을 알아봐야 해요.

//+------------------------------------------------------------------+
//| 시장 감시에서 심볼 가져오기 |
//+------------------------------------------------------------------+
void grab_symbols() {
//! 오직 시장 감시에서만!
int s=SymbolsTotal(true);
ArrayResize(m_symbols, s, 0);
for(int i=0; i<ArraySize(m_symbols); i++) {
m_symbols[i]=SymbolName(i, true);
}
}

구조는 간단합니다:

  • 시장 감시에서 활성 심볼 수 요청
  • m_symbols 배열 크기를 조정하여 심볼 수 수용
  • 각 심볼의 이름 요청

이제 심볼 데이터 다운로드를 관리하기 위한 기능이 필요합니다. 이 기능은 본질적으로 매니저 역할을 합니다:

//+------------------------------------------------------------------+
//| 심볼 다운로드 프로세스 관리 |
//+------------------------------------------------------------------+
void manage(string folder, string filename) {
// 본질적으로 시작하거나 다음 심볼로 이동합니다.
if(ArraySize(m_symbols)>&0) {
// 시작하지 않았다면
if(!m_started) {
m_started=true;
m_current=m_symbols[0];
m_index=1;
save(folder, filename);
if(_Symbol!=m_current) {
ChartSetSymbolPeriod(ChartID(), m_current,_Period);
}
else {
ENUM_TIMEFRAMES new_period=PERIOD_M1;
for(int p=0; p<ArraySize(TFS); p++) {
if(_Period!=TFS[p]) {
new_period=TFS[p];
break;
}
}
ChartSetSymbolPeriod(ChartID(), m_current, new_period);
}
return;
}
// 시작한 경우
else {
m_index++;
if(m_index<=ArraySize(m_symbols)) {
m_current=m_symbols[m_index-1];
save(folder, filename);
if(_Symbol!=m_current) {
ChartSetSymbolPeriod(ChartID(), m_current, _Period);
}
return;
}
else {
m_finished=true;
FileDelete(folder+"\"+filename);
Print("완료되었습니다");
ExpertRemove();
return;
}
}
}
else {
Print("먼저 심볼을 가져오세요");
}
}

시스템 작동 방식:

  • 차트를 열고 타이머를 설정합니다.
  • 타이머가 실행되고, 타이머를 취소합니다.
  • 새 다운로드인지 계속하는 다운로드인지 확인합니다.
  • 새 다운로드라면 모든 심볼을 가져옵니다.
  • 계속하는 다운로드라면 현재 심볼에 대한 데이터를 다운로드합니다.

타이머에서 다운로드를 수행하는 코드 부분입니다:

//+------------------------------------------------------------------+
//| 타이머 |
//+------------------------------------------------------------------+
void OnTimer() {
//--- 동기화되었다면
if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1) {
EventKillTimer();
//--- 시스템을 여기서 로드합니다
if(MANAGER.load(MANAGER_FOLDER, MANAGER_STATUS_FILE)) {
//--- 시스템이 로드되었으므로 심볼을 스캔하고 있습니다
Comment("시스템이 로드되고 있습니다: "+MANAGER.m_current);
//--- 틱 로드
//--- 브로커에서 가장 오래된 틱을 찾습니다
int attempts=0;
int ping=-1;
datetime cursor=flatten(TimeTradeServer());
long cursorMSC=((long)cursor)*1000;
long jump=2592000000;
MqlTick receiver[];
long oldest=LONG_MAX;
Comment("잠시만 기다려 주세요");
while(attempts<5) {
ping=CopyTicks(_Symbol, receiver,COPY_TICKS_ALL, cursorMSC,1);
if(ping==1) {
if(receiver[0].time_msc==oldest) {
attempts++;
}
else {
attempts=0;
}
if(receiver[0].time_msc oldest=receiver[0].time_msc;
}
cursorMSC-=jump;
}
Sleep(44);
}
//--- 이제 가장 오래된 틱을 가지고 있습니다
//--- 가장 오래된 것부터 새로운 것까지 틱 요청을 시작합니다
if(oldest!=LONG_MAX) {
ArrayFree(receiver);
datetime newest_tick=0;
//--- 이 심볼에 대한 마지막 틱의 시간을 수신합니다
datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
while(newest_tick //--- 가장 오래된 시간부터 시작하여 틱 제한을 지정하여 새 배치를 요청합니다
int pulled=CopyTicks(_Symbol, receiver,COPY_TICKS_ALL, oldest, tick_packets);
if(pulled>&0) {
//--- 새로운 배치를 가져오면 다운로드된 시간을 업데이트합니다
newest_tick=receiver[pulled-1].time;
oldest=receiver[pulled-1].time_msc;
ArrayFree(receiver);
}
//--- 서버 요청에 대한 타임아웃, 원하신다면 변경 가능합니다
Sleep(44);
}
}
else {
Alert("터미널을 닫고 틱 폴더로 가서 빈 폴더를 삭제하세요");
ExpertRemove();
}
//--- 매니저 업데이트 후 진행합니다
MANAGER.manage(MANAGER_FOLDER, MANAGER_STATUS_FILE);
}
else {
//--- 시장 감시의 심볼을 가져와서 다운로드를 시작합니다
Comment("시장을 가져오고 시작합니다");
MANAGER.grab_symbols();
MANAGER.manage(MANAGER_FOLDER, MANAGER_STATUS_FILE);
}
}
}

이처럼, MetaTrader 5를 활용하여 쉽고 간편하게 모든 심볼의 틱 이력을 다운로드할 수 있습니다. 여러분도 이 방법을 통해 더 나은 트레이딩 결과를 얻으시길 바랍니다!

연관 포스트

댓글 (0)