Met deze Expert Advisor code kun je de markten van je broker scannen en alle beschikbare ticks van symbolen downloaden, of ticks tot een bepaalde datum.
Dit kan handig zijn om de gehele historie van een symbool te downloaden voor je backtest of om een aangepast grafiek te maken op basis van die ticks.
Vergeet niet dat de terminals de ticks opslaan in de gegevensmap, dus zorg ervoor dat je voldoende schijfruimte hebt.
Om de symbolen te downloaden, hebben we eerst een downloadmanager nodig.
struct CDownloadManager { bool m_started,m_finished; string m_symbols[],m_current; int m_index; }
In deze structuur houden we het volgende bij:
- De status van de download (gestart/voltooid)
- De lijst van symbolen die gescand moeten worden
- Het huidige symbool
- De index van het gescande symbool
Daarnaast zullen we ook naar de harde schijf moeten lezen en schrijven. Aangezien we met symbolen werken, creëren we twee eenvoudige functies om strings naar binaire bestanden te schrijven en te lezen.
De functie om een string naar een bestand te schrijven:
void writeStringToFile(int f,string thestring) { // sla symbol string op 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); } }
Deze functie ontvangt:
- Bestandshandle f, van een bestand dat geopend is voor schrijven met binaire vlaggen FILE_WRITE|FILE_BIN
- De string die naar het bestand geschreven moet worden
Het schrijft een geheel getal dat aangeeft hoeveel karakters er in de string staan en slaat daarna elk karakter in de string op.
De functie om een string uit een bestand te lezen:
string readStringFromFile(int f) { string result=""; // laad symbol string 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); }
Deze functie ontvangt:
- Bestandshandle f van een bestand dat geopend is voor lezen met binaire vlaggen, FILE_READ|FILE_BIN
Het leest een geheel getal dat aangeeft hoeveel karakters er op dat moment in het bestand verwacht worden. Vervolgens leest het elk karakter in een char-array en maakt daar een string van, die als resultaat wordt teruggegeven.
Terug naar de CDownloadManager structuur. We moeten een manier hebben om de manager te initialiseren en deze te vullen vanuit de marktmonitor:
//+------------------------------------------------------------------+ //| pak symbolen van de marktmonitor | //+------------------------------------------------------------------+ void grab_symbols() { //! alleen van de 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); } }
Dit is vrij rechttoe rechtaan:
- Vraag hoeveel symbolen er in de marktmonitor (actief) zijn
- Pas onze m_symbols array aan om ze te ontvangen
- Loop door de totale symbolen en vraag de naam van het symbool aan
We zijn ook verantwoordelijk voor het beheren van het downloaden van de symboldgegevens, dus we hebben een functie nodig die in wezen de manager is:
//+------------------------------------------------------------------+ //| Beheer het downloadproces van symbolen | //+------------------------------------------------------------------+ void manage(string folder,string filename) { // dit start of navigeert naar het volgende symbool // als ingesteld if(ArraySize(m_symbols)>0) { // als niet gestart if(!m_started) { m_started=true; // ga naar het eerste symbool 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; } // als gestart 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("Voltooid"); ExpertRemove(); return; } } } else { Print("Pak eerst de symbolen"); } // als ingesteld eindigt hier }
Hoe het systeem werkt:
- De grafiek opent, we hebben 1 grafiek nodig en een timer wordt ingesteld.
- Die timer voert de actie uit, we annuleren de timer
- We controleren of dit een nieuwe download is of een voortzetting van een download
- Als het een nieuwe download is, stellen we het in door alle symbolen te pakken
- Als het een voortzetting van een download is, downloaden we gegevens voor het huidige symbool
Dit is het deel van de code dat de download op de timer uitvoert:
//+------------------------------------------------------------------+ //| Timer | //+------------------------------------------------------------------+ void OnTimer() { //--- als gesynchroniseerd if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1) { EventKillTimer(); //--- laad het systeem hier if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE)) { //--- systeem geladen, dus we zijn een symbool aan het scannen Comment("Systeem geladen en we verwerken "+MANAGER.m_current); //--- tick laden //--- vind de oudste tick die beschikbaar is bij de broker 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("PleaseWait"); 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("Oudste Tick : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" Cursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+") Pogingen("+IntegerToString(attempts)+") Wacht alstublieft op antwoord..."); } //--- op dit punt hebben we de oudste tick //--- begin met het aanvragen van ticks van de oudste naar de nieuwste if(oldest!=LONG_MAX) { ArrayFree(receiver); datetime newest_tick=0; //--- ontvang de tijd van de laatste tick voor dit symbool opgeslagen in symbol_time datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME); while(newest_tick<most_recent_candle) { //--- vraag een nieuwe batch aan, beginnend vanaf de oudste tijd met de gespecificeerde ticks-limiet int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets); if(pulled>0) { //--- als we een nieuwe batch binnenhalen, werken we onze gedownloade tijden bij newest_tick=receiver[pulled-1].time; oldest=receiver[pulled-1].time_msc; ArrayFree(receiver); } //--- time-out server aanvragen, wijzig het als je dat wilt Sleep(44); Comment("Tot nu toe tot "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" gehaald"); } } else { Alert("Sluit de terminal alstublieft ga naar de ticks-map en verwijder de lege mappen"); ExpertRemove(); } //--- werk de manager bij en ga verder MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } else { //--- pak de symbolen van de marktmonitor om de download te starten Comment("Symbolen pakken en starten"); MANAGER.grab_symbols(); MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } } }
Gerelateerde berichten
- MQL5 Wizard: Creëer Handelsstrategieën met Bullish en Bearish Engulfing Candlestick Patronen en Stochastic
- MQL5 Wizard: Handelsignalen Geïnspireerd Door Morning/Evening Stars + MFI voor MetaTrader 5
- MQL5 Wizard: Handelsignalen Geïnspireerd door Morning/Evening Stars en RSI voor MetaTrader 5
- Efficiënt Trendvolgend Handelsysteem met Exp_X2MA_JFatl voor MetaTrader 5
- Close Cross MA: Efficiënt Orders Sluiten met MetaTrader 4