Halo, trader! Kali ini kita akan membahas tentang cara mendownload semua riwayat tick dari simbol yang ada di MetaTrader 5 dengan menggunakan Expert Advisor (EA). Dengan EA ini, kamu bisa mengambil semua tick yang tersedia dari broker yang kamu gunakan, atau hingga tanggal tertentu yang kamu inginkan.
Ini sangat berguna untuk melakukan backtest atau membuat grafik kustom dari tick yang sudah diambil. Pastikan juga kamu memiliki ruang penyimpanan yang cukup di hard drive, karena terminal akan menyimpan tick di folder data.
Sebelum mulai mendownload simbol, kita perlu menyiapkan download manager terlebih dahulu. Struktur CDownloadManager akan berisi semua informasi yang kita butuhkan.
struct CDownloadManager
{
bool m_started,m_finished;
string m_symbols[],m_current;
int m_index;
}
- Status download (mulai/selesai)
- Daftar simbol yang akan dipindai
- Simbol saat ini
- Indeks simbol yang sedang dipindai
Kita juga perlu membaca dan menulis ke hard drive. Karena kita bekerja dengan simbol, kita akan membuat dua fungsi cepat untuk menulis dan membaca string dari file biner.
Fungsi untuk menyimpan string ke file:
void writeStringToFile(int f,string thestring)
{
//menyimpan string simbol
char sysave[];
int charstotal=StringToCharArray(thestring,sysave,0,StringLen(thestring),CP_ACP);
FileWriteInteger(f,charstotal,INT_VALUE);
for(int i=0;i<charstotal;i++)
{
FileWriteInteger(f,sysave[i],CHAR_VALUE);
}
}
Fungsi ini menerima:
- Handle file f, dari file yang dibuka untuk menulis dengan bendera biner FILE_WRITE|FILE_BIN
- String yang akan ditulis ke file
Fungsi ini menulis integer yang menunjukkan berapa banyak karakter yang ada dalam string dan kemudian menyimpan setiap karakter dalam string tersebut.
Fungsi untuk memuat string dari file:
string readStringFromFile(int f)
{
string result="";
//memuat string simbol
char syload[];
int charstotal=(int)FileReadInteger(f,INT_VALUE);
if(charstotal>0)
{
ArrayResize(syload,charstotal,0);
for(int i=0;i<charstotal;i++)
{
syload[i]=(char)FileReadInteger(f,CHAR_VALUE);
}
result=CharArrayToString(syload,0,charstotal,CP_ACP);
}
return(result);
}
Fungsi ini menerima:
- Handle file f dari file yang dibuka untuk membaca sebagai biner, dengan bendera FILE_READ|FILE_BIN
Fungsi ini membaca integer yang menunjukkan berapa banyak karakter yang diharapkan pada titik tersebut dalam file. Kemudian, ia melanjutkan untuk membaca setiap karakter ke dalam array char dan kemudian membuat string dari array char tersebut yang dikembalikan sebagai hasil pemuatan.
Kembali ke struktur CDownloadManager. Kita perlu cara untuk menginisialisasi manager dan mengisinya dari market watch:
//+------------------------------------------------------------------+
//| Mengambil simbol dari market watch |
//+------------------------------------------------------------------+
void grab_symbols()
{
//! hanya dari mw !
int s=SymbolsTotal(true);
ArrayResize(m_symbols,s,0);
for(int i=0;i<ArraySize(m_symbols);i++)
{
m_symbols[i]=SymbolName(i,true);
}
}
Cukup sederhana:
- Meminta berapa banyak simbol yang ada di market watch (aktif)
- Mengubah ukuran array m_symbols untuk menerima simbol-simbol tersebut
- Melakukan loop untuk semua simbol dan meminta nama simbolnya
Kita juga bertanggung jawab untuk mengelola proses download data simbol, jadi kita memerlukan fungsi yang pada dasarnya adalah manajernya:
//+------------------------------------------------------------------+
//| Mengelola proses download simbol |
//+------------------------------------------------------------------+
void manage(string folder,string filename)
{
// pada dasarnya ini memulai atau navigasi ke simbol berikutnya
// jika sudah diatur
if(ArraySize(m_symbols)>0)
{
// jika belum dimulai
if(!m_started)
{
m_started=true;
// pergi ke simbol pertama
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;
}
// jika sudah dimulai
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("Selesai");
ExpertRemove();
return;
}
}
else
{
Print("Silakan ambil simbol terlebih dahulu");
}
// jika sudah diatur berakhir di sini
}
Bagaimana sistem ini bekerja:
- Chart terbuka, kita memerlukan 1 chart, dan timer diatur.
- Timer tersebut dieksekusi, kita batalkan timer
- Kita memeriksa apakah ini adalah download baru atau download yang berlanjut
- Jika ini adalah download baru, kita siapkan dengan mengambil semua simbol
- Jika ini adalah download yang berlanjut, kita download data untuk simbol saat ini
Ini adalah bagian dari kode yang melakukan download berdasarkan timer:
//+------------------------------------------------------------------+
//|Timer |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- jika disinkronkan
if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1)
{
EventKillTimer();
//--- memuat sistem di sini
if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE))
{
//--- sistem dimuat jadi kita memindai simbol di sini
Comment("Sistem dimuat dan kita sedang memproses "+MANAGER.m_current);
//--- pemuatan tick
//--- temukan tick tertua yang tersedia di broker terlebih dahulu
int attempts=0;
int ping=-1;
datetime cursor=flatten(TimeTradeServer());
long cursorMSC=((long)cursor)*1000;
long jump=2592000000;//60*60*24*30*1000;
MqlTick receiver[];
long oldest=LONG_MAX;
Comment("Silakan tunggu");
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)
{
oldest=receiver[0].time_msc;
}
cursorMSC-=jump;
if(limitDate&&receiver[0].time<=oldestLimit)
{
break;
}
}
else
{
attempts++;
}
Sleep(44);
Comment("Tick Tertua : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"\nCursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")\nAttempts("+IntegerToString(attempts)+")\nSilakan tunggu untuk respon...");
}
//--- pada titik ini kita memiliki tick tertua
//--- mulai meminta tick dari yang tertua ke yang terbaru
if(oldest!=LONG_MAX)
{
ArrayFree(receiver);
datetime newest_tick=0;
//--- terima waktu tick terakhir untuk simbol ini yang disimpan dalam symbol_time
datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
while(newest_tick<most_recent_candle)
{
//--- meminta batch baru mulai dari waktu tertua dengan batas tick yang ditentukan
int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets);
if(pulled>0)
{
//--- jika kita menarik batch baru, perbarui waktu yang diunduh
newest_tick=receiver[pulled-1].time;
oldest=receiver[pulled-1].time_msc;
ArrayFree(receiver);
}
//--- batas waktu untuk permintaan server, ubah jika perlu
Sleep(44);
Comment("Ditarik hingga "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" sejauh ini");
}
}
else
{
Alert("Silakan tutup terminal pergi ke folder ticks dan hapus folder kosong");
ExpertRemove();
}
//--- perbarui manager dan lanjutkan
MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
}
else
{
//--- ambil simbol dari market watch untuk mulai download
Comment("Mengambil MW dan memulai");
MANAGER.grab_symbols();
MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
}
}
Postingan terkait
- MQL5 Wizard: Membuat EA dengan Sinyal Trading Berdasarkan Pola Morning/Evening Stars dan Stochastic
- MQL5 Wizard: Membuat EA Berdasarkan Pola 3 Black Crows/3 White Soldiers dan Stochastic
- Menggunakan MQL5 Wizard untuk Sinyal Trading Berdasarkan Pola Candlestick dan CCI
- MQL5 Wizard: Menggunakan Sinyal Trading Berbasis Morning/Evening Stars dan RSI untuk MetaTrader 5
- MQL5 Wizard: Membuat Expert Advisor dengan Sinyal Trading 3 Black Crows/3 White Soldiers dan MFI