Forex programozás › Fórum › Kérdések az MQL4 programozási nyelvvel kapcsolatban › Instrumentum lista lekérdezése
Címkézve: globális változó, instrumentum lista, tömb
-
SzerzőBejegyzés
-
Elsőként szeretném elmondani, hogy rengeteget tanultam az általad közétett posztokból és könyvből. Köszönöm szépen!
A kérdésem az lenne, hogy:
1. Le tudom-e valahogy kérdezni a terminálom által kezelt instrumentumok listáját?
2. MT4 terminál által kezelt globális változó csak double típusú lehet?
3. HA (2.kérdés == igen) akkor {Egy instrumentumra csak a nevével tudok hivatkozni? (pl.: „EURUSD”) Nincs vmilyen azonosító száma is a terminálon belül.}Röviden leírom miért érdekelne:
Szeretném megoldani, hogy egy több charton futatott expert egyik példánya kitüntetett szerepet kapjon és adatokat szolgátasson – a terminálban definiált globális változókon keresztül a többi expertnek .
Pl:
– lenne egy G_MasterSymbol nevű változó értéke: „EURUSD” >>(2. kérdés)Utána az „alárendelt” expertekben használnám fel pl:
if (Symbol() != G_MasterSymbol) x=MarketInfo(G_MasterSymbol,MODE_BID); formában.Ami lenginkább érdekel az hogy a 3.kérdésre mi a válasz. Köszi.
Ha nincs más akkor a szimbólum névből lesz UID. :)
double Symbol_ID (string sym=””)
{
int strl=StringLen(sym);
string uid=””;
for (int i=0; i<strl; i++) uid=StringConcatenate(uid,StringGetChar(sym, i));
return (StrToDouble(uid));
}Örülök, hogy segíthettem! :)
1. kérdésedre a válasz:
void LoadSymbols (string &SymbolsArray[]) { int ElementCount; string Row; int fileHandle = FileOpenHistory("symbols.sel", FILE_BIN|FILE_READ); if (fileHandle >= 0) { ElementCount = (FileSize(fileHandle) - 4) / 128; ArrayResize(SymbolsArray, ElementCount); FileSeek(fileHandle, 4, SEEK_SET); for (int k = 0; k < ElementCount; k++) { Row = FileReadString(fileHandle, 12); SymbolsArray[k] = Row; FileSeek(fileHandle, 116, SEEK_CUR); } FileClose(fileHandle); } } /* Használat: */ string Szimbolumok[]; LoadSymbols (Szimbolumok);
Miután a Szimbolumok tömb feltöltődött, felhasználhatod az elemeit.
2. Igen, a globális változók csak double típusúak lehetnek. Ellenben a nevükkel is lehet trükközni: csinálsz egy prefixet (_kiskutya_) és mögé rakod az értékes(ebb) adatokat is. Példa:
_kiskutya_EURUSD_
_kiskutya_GBPUSD_Amikor szükséged van az adatokra, beolvasod az összes GV-t, és kiszűröd belőle a prefix-szeiddel rendelkezőeket. Aztán kiszeded a változónévből a hasznos adatot, plusz az értéket és kész.
Bonyolultabb példa:
_kiskutya|EURUSD|1|1.0455|1.0055
Itt természetesen a | jel szeparátor feladatát tölti be.
3. Igen, csak a nevével tudsz rá hivatkozni. Illetve, ha te készítesz valamilyen háttértámogatást egy tömb formájában, akkor hivatkozhatsz a Szimbolumok kulcsával is.
Egyébként a te megoldásod is jópofa :)
Ui: a kódformázást trükközéssel csináltam, sajna még egyelőre nem érhető el a fórumposztokon keresztül
Köszönöm a kódot. Pontosan erre van szükségem.
A _prefix-es névadás is jó ötletnek tűnik, pláne most hogy jobban megnéztem; a GlobalVariablesDeleteAll() függvény is mintha direkt ehhez lenne kitalálva.A kódott elnézve mindjárt felvetődött bennem a kérdés, hogy instrumentumtípusonként szeparálva (forex, commodities,stb.) is le lehetne kérdezni a szimbólumokat, mondjuk egy két dimenziós tömbbe?
A Row változónak van vmilyen gyakorlati jelentősége, vagy inkább csak a jobb olvashatóság miatt van a kódban?
A GlobalVariablesDeleteAll() -t még írni is akartam, csak elfelejtettem!:)
Az instrumentumtípusonkénti szeparalást passzolom, én anno már annak is örültem, hogy ezt az alap megoldást sikerült meglelni. Nyilván a symbols.sel -ben a kategorizálás is benne van, de hogy hogy szedjük ki az számomra ismeretlen kérdés.
A Row változónak ott volt jelentősége, hogy a korábbi tesztelés során Printtel kiírattam a sorokat, nem szeretem duplán elvégezni azt, amit elég egyszer – és benne hagytam a kódban. Amúgy persze, kiveheted.
Sebaj. Ez is tuti.
A fentebb levő Symbol_ID függvénynek leginkább akkor van értelme, ha az általa generált double értékből újból ki lehet nyerni az eredeti stringet. Ide bigyesztem azt is hátha vkit érdekel:
string SydToName(double syd=0)
{
int karakterdb = StringLen(DoubleToStr(syd,0))/2;
int charcode=0;
string symbol_name=””;
for (int i=1; i<=karakterdb; i++) {//az utolsó két számjegy kinyerése maradékos osztással
charcode=MathMod(syd,100);//összerakjuk a szimbólumnevet karaktereneként
symbol_name=StringConcatenate(CharToStr(charcode),symbol_name);// megrövidítjük két számjeggyel a következő ciklushoz
syd=(syd-charcode)/100;
}
return(symbol_name);
}Max 8 karakter hosszúságú neveket lehet vele helyesen átalakítnai. Tehát pl. a FxPro-n elérhető SILVEREURO szimbólumnevet nem. Ehhez tovább kéne fejleszteni, a tizedesjegyeket is bevonva a karakterábrázolásba.
Persze nem csak szimbólumnevek hanem bármilyen NAGYBETŰS(!) ill. két számjeggyel kódolt (ASCII)karaktereket tartalmazó string is átadható vele.Mivel igen rövid előéletem van a programozást tekintve, ha bárki hibát talál az áltlam leírt kód(okban) vagy tud egy hatékonyabb megoldást és megírja, azt örömmel veszem.
Instrumentum lista lekérdezése – az oroszok így csinálják :) :
http://codebase.mql4.com/6134
http://codebase.mql4.com/source/18718 (SymbolsLib.mq4)Akkor csak meglett a csoportosítás is, ugye ? ;) Köszi a tippet!
A CHART_WINDOW_HANDLE is le lehet kérdezni így azonos szimbólumú, és idősíkú chartoknak különböző globális változó nevet lehet adni (bár általában erre ritkán van szükség). Az egyértelmű azonosításhoz CHART_WINDOW_HANDLE 5 jegyű szám elég (súgóban még egy függvény forráskódja is van ennek a lekérdezéséhez), de a könnyebb értelmezhetőség miatt a globális változók nevébe a szimbólumot és idősíkot érdemes bele tenni.
Az MT4 build 900 következő problémával találkoztam, egy chartra 2 indikátort raktam fel, az egyik létre hozta a globális változót, GBP JPY60 67338 valami néven, a név generáláshoz a _Symbol MQL4 előredefiniált változót használtam, ez rakta bele a szóközt. A másik indikátor lekérdezte a globális változót, de nem létezett. A hiba az volt, hogy amit kérdezett:
GBPJPY60 67338 valami volt, de a _Symbol itt nem rakta bele a szóközt. Tehát _Symbol kénye kedve szerint vagy belerakja vagy kihagyja a szóközt. Kénytelen leszek szóköztelenítő függvényt írni, és át nézni az összes forráskódom van-e benne _Symbolra kényes rész.Elnézést, de az előző bejegyzésem második bekezdése fals. Kiderül, hogy a _Symbol nem rak bele szóközt, csak nem proporcinális a betű típus és úgy néz ki van benne szóköz P és J betű között pedig nincs. Más instrumentumnál nem tűnne úgy.
Mi értelme van letölteni a szimbólum listát?
Gondolkoztam rajta, aztán írtam egy scriptet a LoadSymbols függvényhez. Az orosz módszert nem néztem meg, mert az bonyolultabbnak tűnt. Vigyázni kell, hogy legyen valamilyen profil a MetaTraderben mert, 100 ablakot elég nehéz kézzel, egyenként bezárni, persze lehetne arra is írni scriptet. Sok időt lehet spórolni ezzel a programmal.#property description "A piacfigyelő által megjelenített szimbólumok csv fileba írása, és/vagy megnyitása" #property description "Csak korlátozott számban: maximum 100 nyitható meg, a már megnyitottakkal együtt" #property script_show_inputs #property strict //+------------------------------------------------------------------+ #include <stdlib.mqh> //ErrorDescription-hoz kell //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ enum boole {nem,igen}; input boole FileWriting=nem;//fileba írás input boole AllSymbolOpen=igen;//az összes szimbolum megnyitása maximum 100 input int TimeFrame=PERIOD_H1;//Idősík void OnStart() { string Szimbolumok[]; int i; int db=0; int filehandle=INVALID_HANDLE; int Error; //+--- if(!FileWriting && !AllSymbolOpen) { Alert("A script ezzel a beállítással nem csinál semmit"); } else { LoadSymbols (Szimbolumok); db=ArraySize(Szimbolumok); if(db) { if(FileWriting) { filehandle=FileOpen("Symbollist.csv",FILE_WRITE|FILE_CSV); } for(i=0;i<db;i++ ) { if(FileWriting && filehandle!=INVALID_HANDLE) { FileWrite(filehandle,Szimbolumok[i]); } if(AllSymbolOpen && db<CHARTS_MAX) { if(!ChartOpen(Szimbolumok[i],TimeFrame)) { Error=GetLastError(); Print(__FUNCTION__," ",__LINE__," Error code = ",Error," ",ErrorDescription(Error)); } } } if(filehandle!=INVALID_HANDLE) { FileClose(filehandle); } } } }
Apró hiba van a kódban, nem mindig működik,
if(AllSymbolOpen && i<CHARTS_MAX) kell a if(AllSymbolOpen && db<CHARTS_MAX) helyett a 43 sorbanA for(i=0;i<db;i++ ) helyett a for(i=0;i<db-1;i++ ) jobbnak tűnik, mert különben egy plussz instrumentumot jelenit meg, de ha 2-nél kevesebb az instrumentum azt nem tudom kipróbálni, mert van nyitott pozícióm és azokat nem engedi az MT4 kitörölni a piacfigyelőből.
Köszönöm mások nevében, hogy megosztottad!
Az alábbi meglátásaim vannak (köszönöm az e-mailt, amit küldtél):
A db értékét ne csökkentsd eggyel, az jó úgy ahogy van; ehelyett ellenőrizd hogy az a chart, amely épp nyitva van (vagyis amiről a szkriptet indítottad) ne legyen kinyitva még egyszer. Ezt ezzel a kódsorral megteheted:
if (Szimbolumok[i] != Symbol()) { }
Természetesen ha pontosak szeretnénk lenni, akkor meg lehetne nézni, hogy a jelenleg nyitott chartok közül van-e olyan amit nem kellene még egyszer megnyitni. Legyen ez a házi feladat :)
Egy int() típusváltást beraktam, hogy a warning is eltűnjön.
Csatolom a módosított kódot, még egyszer köszi hogy megosztottad!
#property description "A piacfigyelő által megjelenített szimbólumok csv fileba írása, és/vagy megnyitása" #property description "Csak korlátozott számban: maximum 100 nyitható meg, a már megnyitottakkal együtt" #property script_show_inputs #property strict //+------------------------------------------------------------------+ #include
//ErrorDescription-hoz kell //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ enum boole {nem,igen}; input boole FileWriting=nem;//fileba írás input boole AllSymbolOpen=igen;//az összes szimbolum megnyitása maximum 100 input int TimeFrame=PERIOD_H1;//Idősík void OnStart() { string Szimbolumok[]; int i; int db=0; int filehandle=INVALID_HANDLE; int Error; //+--- if(!FileWriting && !AllSymbolOpen) { Alert("A script ezzel a beállítással nem csinál semmit"); } else { LoadSymbols (Szimbolumok); db=ArraySize(Szimbolumok); if(db) { if(FileWriting) { filehandle=FileOpen("Symbollist.csv",FILE_WRITE|FILE_CSV); } for(i=0;i = 0) { ElementCount = (int(FileSize(fileHandle)) - 4) / 128; ArrayResize(SymbolsArray, ElementCount); FileSeek(fileHandle, 4, SEEK_SET); for (int k = 0; k < ElementCount; k++) { Row = FileReadString(fileHandle, 12); SymbolsArray[k] = Row; FileSeek(fileHandle, 116, SEEK_CUR); } FileClose(fileHandle); } } -
SzerzőBejegyzés
- Be kell jelentkezni a hozzászóláshoz.