Nagyon rég volt már programozással kapcsolatos poszt, úgyhogy illik már ez ügyben is tennem valamit. Innentől kezdve kisebb-nagyobb posztokban fogok foglalkozni mindenki számára hasznos, gyakorta felmerülő funkciók megosztásával és részletesebb tárgyalásával.
Mai áldozatunk: hogyan kérdezhető le a nyitott pozíciók vagy a számlatörténet pozíciói közül a legutolsó pozíció ? Hogyan lehet lekérdezni a nyitott pozíciók darabszámát általunk megadott feltételek alapján? Sajnálatos tény, hogy az mql4 nyelvben nincsen egyetlen olyan beépített függvény sem, amely az életünket ilyen szempontból megkönnyítené. Hozzunk hát létre párat!
Mi számít legutolsó pozíciónak?
Természetesen ez is jelenthet mindenkinek mást, szóval definiáljuk: a legutolsó pozíció az időben legfiatalabb, azaz a legújabb pozíciót jelenti.
Amennyiben a legelső (legkorábban nyitott) pozícióra vagyunk kíváncsiak, az megint más kérdés – abban az esetben ugyanis a legrégebben nyitott pozícióra gondolunk.
A legutolsó pozíciót egyébként nagyon könnyű azonosítani: mindig, minden körülmények között neki a legnagyobb a ticket száma. Ezt a tényt fogjuk használni a probléma megoldásához.
Ticket szám
A ticket szám a pozíció bróker által kiadott, egyértelmű és egyedi azonosító száma. Egy pozíció ticket száma soha nem változhat meg! A ticket számok a Számlatörténet és a Kereskedés panelen az első oszlopban láthatóak.
A függő megbízások (buy stop, buy limit, sell stop és sell limit) ticket számai nem változnak meg akkor, amikor a bróker teljesíti azt nekünk. Így a teljesült buy vagy sell pozíciók „öröklik” azon függő megbízás ticket számát, amelyből születtek.
Fontos továbbá, hogy amikor a függő pozícióból élő pozíció lesz, a pozícióhoz tartozó nyitóidőpont a kihelyezési dátumról a teljesülés dátumára fog változni. Ezért a nyitóidőpont alapján történő rendezés során úgy tűnhet, hogy a bróker felborította a ticket számok sorrendjét; ez azonban csak abból a tényből ered, hogy az adott pozíció függő típusként lett korábban létrehozva. Az alábbi képpel illusztrálom a helyzetet: jól látszik, hogy ticket szám ugyanaz, míg a nyitóidőpont és a típus természetesen eltérnek egymástól.
Szűrés egyéb feltételek alapján, pozíciók megkülönböztetése
Ömlesztett pozíciók közül történő horgászás esetén nyilván ezernyi szűrési feltételünk van. Ilyen lehet például a magic szám, pozíciótípus, nyitott-e még a pozíció, stb. Ezekre ki kell térnünk a programkódban is – én melegen ajánlom azt, hogy előre elkészített függvényeket használjunk és mindig, minden körülmények között szűrjünk magic számra. Ha most nem is futtattok több robotot, vagy kevertek kézi kötéseket a robot kötései mellé, a jövőben szükségetek lehet a pozíciók elkülönítésére. A magic szám használata mindenképpen fontos! A backtesztben ugyanis minden tökéletesen működik, hiszen ott alap esetben csak egy stratégia pozíciói léteznek. Nincsen kézi kötés, nincs másik futtatott robot. Ez azonban a valós idejű futtatásnál nincs mindig így – elég egyszer elfeledkeznünk arról, hogy nem voltunk elég körültekintőek! Elég egy kézi kötés, és az OrdersTotal() -ra épülő feltételeink azonnal elhasalnak.
Emiatt a beépített OrdersTotal() és OrdersHistoryTotal() függvényt is csak a pozíciók végignyálazása során használjuk majd – ebben a cikkben egy egyéni pozíciószámláló függvényt is létrehozunk majd.
Pozíciók listája
A pozíciók listájára kettő lista (tár, queue, „fiók”) áll rendelkezésünkre: az egyik az aktív pozíciók listája (MODE_TRADES), a másik pedig a már lezártaké (MODE_HISTORY).
Pozíciók kiválasztásához az OrderSelect() függvény használható, amelynek három paramétere van:
- egy szám, amely lehet az adott lista numerikus indexe, illetve konkrét ticket szám
- a kiválasztás módja (lásd lentebb)
- a lista, ahonnan dolgozni szeretnénk (MODE_TRADES vagy MODE_HISTORY; ha nem adunk meg semmit, az alapértelmezés a MODE_TRADES).
Hivatkozás egy konkrét pozícióra
Mindenképpen számmal lehet hivatkozni egy pozícióra, azonban erre két különböző mód létezik:
- hivatkozás a queue indexével (SELECT_BY_POS)
- hivatkozás konkrét ticket számmal (SELECT_BY_TICKET)
Amennyiben az utóbbit használjuk, nem szükséges megadni azt, hogy mely pozíciólistából guberálunk, hisz’ a ticket szám egyértelműen azonosítja a pozíciót. Nyissunk egy tetszőleges pozíciót (kézzel), és a ticket számát (1234567) helyettesítsük be az alábbi kódba:
OrderSelect (1234567, SELECT_BY_TICKET); Print (OrderTicket(), " pozíció nyitóára: ", OrderOpenPrice()); |
Az OrderSelect() -nek megadtuk a konkrét pozíció ticket számát (1234567), valamint azt hogy ticket alapján szeretnénk azonosítani őt (SELECT_BY_TICKET). Abban az esetben (tehát majdnem mindig), ha nem tudjuk a konkrét ticket számot, a numerikus index alapján fogunk dolgozni.
OrderSelect (0, SELECT_BY_POS); Print (OrderTicket(), " pozíció nyitóára: ", OrderOpenPrice()); |
A számlatörténet és az aktív pozíciók numerikus indexe mindig nullától indul, tehát az index legmagasabb értéke mindig OrdersTotal() – 1 vagy OrdersHistoryTotal() – 1. Amennyiben olyan indexű pozíciót akarunk kiválasztani amely nem létezik, hibaüzenetet fogunk kapni. Természetesen ez a nem létező ticket számokra is igaz!
Amennyiben sikeresen kiválasztottunk egy pozíciót, az adott pozíció minden adatához hozzáférünk mindaddig, amely más pozíciót nem választunk ki. Erre érdemes különös figyelmet fordítani: ha kiválasztottunk egy pozíciót, akkor a későbbiekben – pláne ha függvényeket használunk – előfordulhat, hogy egy függvényünk szintén OrderSelect() segítségével megváltoztatja az aktív kiválasztott pozíciót. Ekkor hirtelen olyan adatokkal fogunk dolgozni, amelyek nem passzolnak az adott helyzethez és káoszt okozhatnak. Mindig figyeljünk oda, hogy éppen mikor és melyik pozíciót választjuk ki!
A nem létező pozíciókkal kapcsolatban: az OrderSelect() függvény visszatérési értéke csak akkor true, ha sikerült kiválasztani az adott pozíciót.
if (OrderSelect(0, SELECT_BY_POS)) { Print ("Pozíció sikeresen kiválasztva!"); } else { Print ("Pozíció kiválasztása sikertelen: ", GetLastError()); } |
A GetLastError() segít a hiba megállapításában: egy nullánál nagyobb számot ad vissza, amennyiben valamilyen hiba történt. A hibakódokat itt olvashatjátok.
Pozíciók „átnyálazása”
Ahhoz, hogy biztonsággal megállapítsuk a számunkra fontos pozíciók ticket számait, mindig végig kell futni a számlatörténet/aktív pozíciólista pozícióit (vagylagosan!). Ez azt jelenti, hogy ha csak egy pozíció ticket számára van szükségünk, akkor is ki kell választanunk az összes pozíciót az adott listában. A kiválasztás mindenképpen szükséges, hiszen csak ezután tudjuk eldönteni, hogy az adott pozíció adatai alapján beleesik-e az általunk definiált kondíciókba.
Írassuk ki az összes BUY típusú EURUSD pozíciót!
(Megjegyzés: a továbbiakban nem fogom külön kérni, hogy nyissatok több pozíciót; legyen nyitva több pozíciótok vegyesen buy, sell, EURUSD, GBPUSD, tetszőleges instrumentumokon!)
for (int i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS)) { if (OrderSymbol() == "EURUSD" && OrderType() == OP_BUY) { Print (OrderTicket()); } } } |
A fenti kód egymás alá fogja kiírni az összes buy típusú EURUSD instrumentumon nyitott pozíciót. A ciklus nullától indul és addig fut, ameddig i < OrdersTotal() feltétel igaz. Ha tehát 5 pozíciónk van, akkor a pozíciók indexe 0-tól 4-ig terjed. A ciklus minden körben eggyel növeli i értékét. Ötször fut le tehát ciklusunk, ebből azonban csak annyiszor fogunk „bejutni” a második if feltételen belülre, ha EURUSD instrumentumú buy pozíció van éppen terítéken.
Mivel a pozícióindex folyamatosan változhat, javaslom hogy minden esetben ticket alapján dolgozzunk. Vagyis, ne reménykedjünk abban hogy az éppen nyitott pozíciónk 0-ás indexe sosem fog változni! Kérdezzük le a ticket számát, és későbbi hivatkozáskor is használjuk azt!
Nézzük meg, hogyan tudunk a fenti kódból egy egyszerű függvényt létrehozni!
void PozicioTipus (int Tipus, string Instrumentum = "") { // Ha nincs megadva az instrumentum, // az aktuális chart szimbólumát vesszük alapul if (Instrumentum == "") { Instrumentum = Symbol(); } for (int i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS)) { if (OrderSymbol() == Instrumentum && OrderType() == Tipus) { Print (OrderTicket()); } } } } |
A fenti függvényt a későbbiekben így használhatjuk:
PozicioTipus (OP_BUY); PozicioTipus (OP_BUY, "EURGBP"); |
Természetesen a kód egy kis módosításával pillanatokon belül megszületik első pozíciószámláló függvényünk is, mintegy az utolsó pozíció keresése során folytatott út melléktermékeként:
int PozicioSzamlalo (int Tipus, int MagicNumber = 0, string Instrumentum = "") { int Darabszam = 0; // Ha nincs megadva az instrumentum, // az aktuális chart szimbólumát vesszük alapul if (Instrumentum == "") { Instrumentum = Symbol(); } for (int i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS)) { if (OrderSymbol() == Instrumentum && OrderType() == Tipus && OrderMagicNumber() == MagicNumber) { Darabszam++; } } } return (Darabszam); } // Használat: // 5-ös magic számú buy pozíciók megszámlálása Print (PozicioSzamlalo (OP_BUY, 5)); // Magic szám nélküli sell pozíciók megszámlása Print (PozicioSzamlalo (OP_SELL)); // Magic szám nélküli, EURGBP -n nyitott buy limit pozíciók megszámlása Print (PozicioSzamlalo (OP_BUYLIMIT, 0, "EURGBP")); |
A függvény visszatérési értéke egy egész szám – az érintett pozíciók darabszáma. Természetesen a kódot érdemes kiegészíteni egy olyan feltétellel, hogy amennyiben Tipus értéke egy általunk definiált konstans (pl. OP_ALL), akkor az összes pozíciót számolja, ne csak egy konkrét típust. Ekkor már készen is vagyunk egy egyéni pozíciószámláló függvénnyel, de újabb konstansokat is létrehozhatunk, amely saját kényelmünket szolgálja: például OP_BUYSELL – buy és sell pozíciók „begyűjtésére”.
#define OP_ALL 6 // Minden pozíció int PozicioSzamlalo (int Tipus = OP_ALL, int MagicNumber = 0, string Instrumentum = "") { int Darabszam = 0; // Ha nincs megadva az instrumentum, // az aktuális chart szimbólumát vesszük alapul if (Instrumentum == "") { Instrumentum = Symbol(); } for (int i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS)) { if (OrderSymbol() == Instrumentum && (Tipus == OP_ALL || OrderType() == Tipus) && OrderMagicNumber() == MagicNumber) { Darabszam++; } } } return (Darabszam); } |
Megjegyzés: idegen kódokban konstansok helyett gyakran találkozhatunk a konstansok értékeinek megfelelő számokkal (pl.: OP_BUY = 0, OP_SELL = 1, stb.). Habár ez is jó megoldás, véleményem szerint a későbbi kódolvasást megkönnyítendő érdemesebb inkább a konstansokat használni, hiszen így egy pillanat alatt egyértelmű hogy mely pozíciókra gondoltunk anno.
A legutolsó pozíció megkeresése
A megfelelő feltételek alapján már képesek vagyunk csak azon pozíciókkal foglalkozni, amelyek beleesnek az általunk fontosnak tartott halmazba. Innen már csak egy dolgunk van: a halmaz lehető legnagyobb ticket számának megállapítása!
#define OP_ALL 6 // Minden pozíció int UtolsoPozicio (int Tipus = OP_ALL, int MagicNumber = 0, string Instrumentum = "") { int UtolsoTicket = 0; // Ha nincs megadva az instrumentum, // az aktuális chart szimbólumát vesszük alapul if (Instrumentum == "") { Instrumentum = Symbol(); } for (int i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS)) { if (OrderSymbol() == Instrumentum && (Tipus == OP_ALL || OrderType() == Tipus) && OrderMagicNumber() == MagicNumber) { UtolsoTicket = MathMax (UtolsoTicket, OrderTicket()); } } } return (UtolsoTicket); } |
Lássuk, mi történik: a függvény kezdetekor létrehoztunk egy UtolsoTicket nevű változót. A cikluson belül a MathMax() függvénnyel megnézzük, hogy az aktuális pozíció ticket száma – OrderTicket() – nagyobb-e, mint az UtolsoTicket változó értéke. Amennyiben igen, átállítjuk az UtolsoTicket változó értékét a MathMax() által visszaadott, magasabb számértékre. A függvény visszatérési értéke így a halmazunkon belüli legmagasabb ticket számot fogja visszaadni: az időben legkésőbb nyílt, azaz a legutolsó pozíciót.
Ha a számlatörténetben is szeretnénk ugyanezt a keresést elvégezni, még egy kis bonyolítás szükséges: tegyük állíthatóvá azt, hogy for ciklusunk mely pozíciókon szaladjon végig!
int UtolsoPozicio (int Tipus = OP_ALL, int MagicNumber = 0, int Lista = MODE_TRADES, string Instrumentum = "") { int UtolsoTicket = 0, Darabszam = 0; // Ha nincs megadva az instrumentum, // az aktuális chart szimbólumát vesszük alapul if (Instrumentum == "") { Instrumentum = Symbol(); } if (Lista == MODE_TRADES) { Darabszam = OrdersTotal(); } else { Darabszam = OrdersHistoryTotal(); } for (int i = 0; i < Darabszam; i++) { if (OrderSelect(i, SELECT_BY_POS, Lista)) { if (OrderSymbol() == Instrumentum && (Tipus == OP_ALL || OrderType() == Tipus) && OrderMagicNumber() == MagicNumber) { UtolsoTicket = MathMax (UtolsoTicket, OrderTicket()); } } } return (UtolsoTicket); } |
Függvényünk Lista nevű paramétere alapesetben a MODE_TRADES értéket kapja meg, azaz ha az aktív pozíciók közül kukázunk, akkor szükségtelen megadni. Ha a számlatörténet a kívánt cél, adjunk meg MODE_HISTORY -t! A Darabszam nevű változó a Lista alapján kapja meg értékét, és az OrderSelect() függvényt is kibővítettük a Lista nevű változóval. Így kerek a világ, most már tudunk az aktív és lezárt pozíciók között is keresgélni!
// Az utolsó BUY pozíció // az aktív tradek közül UtolsoPozicio (OP_BUY); // Az utolsó 23-as magic számú // BUY pozíció az aktív tradek közül UtolsoPozicio (OP_BUY, 23); // Az utolsó 23-as magic számú // EURGBP BUY pozíció az aktív tradek közül UtolsoPozicio (OP_BUY, 23, MODE_TRADES, "EURGBP"); // Az utolsó 23-as magic számú // EURGBP BUY pozíció a lezárt tradek közül UtolsoPozicio (OP_BUY, 23, MODE_HISTORY, "EURGBP"); // Az utolsó 23-as magic számú // EURGBP pozíció a lezárt tradek közül UtolsoPozicio (OP_ALL, 23, MODE_HISTORY, "EURGBP"); |
A függvény lefutásakor nem ír ki semmit, visszatérési értéke pedig a keresett ticket azonosító lesz. Ezt már elrakhatjuk egy változóba, felhasználhatjuk if feltételekben, kiírathatjuk a Print() függvénnyel. Ha visszatérési értéke nulla, akkor vagy nem talált megfelelő pozíciót a feltételek alapján, vagy nincs nyitott pozíció, stb.
A legelső pozíció megkeresése
Házi feladat: létrehozni a legelső pozíció kikeresésére vonatkozó függvényt. Talán már el sem kell árulnom, hogy a MathMin() függvényt érdemes használni a MathMax() helyett. Mivel azonban a ticket számot tároló változónk kiindulási értéke nulla, így mindenképpen értéket kell neki adnunk, hiszen a nulla egészen biztos, hogy minden ticket számnál kisebb lesz. A ciklus megfelelő if feltételén belül tehát hozzunk létre egy újabbat, ami csak arra figyel, hogy a végeredményt tároló változónk értéke nulla-e. Amennyiben igen, beállítjuk neki az első ciklusfordulóban érintett pozíció ticket számát – a többi ciklusfordulóban pedig ehhez képest keressük a kisebb ticket számot.
A számlatörténet korlátjai
Fontos figyelembe venni, hogy az OrdersHistoryTotal() figyelembe veszi a Metatrader terminálban a felhasználó által beállított múltbéli adatok mennyiségét. Azaz ha a Számlatörténet panelen az „Utolsó hónap” opció van beállítva, akkor semmilyen módon nem férhetünk hozzá az aktuális hónapnál régebben lezárt pozíciókhoz.
Az aktuális pozícióadatok pontossága
Felmerülhet a kérdés, hogy mi van akkor, ha az éppen aktuális tick-re elindult programunk futása közben a pozícióindex változik – azaz megszűnik vagy épp születik egy új pozíció. Megnyugtatásként: egy tickre éppen futó példány futási ideje alatt nem változik a pozíciódarabszám. Ha egy pozíció bróker által megszületik vagy lezárul, ez a történés hamarabb történik meg, mint a program futásának kezdete.
Természetesen ha mi zárunk vagy nyitunk (piacon, azaz mintha kézzel tevékenykednénk) egy pozíciót, a pozícióindex természetesen azonnal megváltozik. Ezeket a tényeket a program tervezésénél mindenféleképpen figyelembe kell venni! Főleg zárásnál okozhat ez problémát – de erről majd legközelebb.
Egyéb információk lekérdezése
A fenti for ciklussal megépített függvények egyértelműen sok más feladatra is használhatóak. Mivel már képesek vagyunk szűrni a számunkra fontos pozíciókat, megtudhatjuk például a pozíciótömeg átlagárát, összlotját, stb. Ezen funkciókra javallott létrehozni egy-egy specifikus függvényt, kialakítva ezzel egy alapvető támogatást későbbi munkáinkhoz.
Zárszó
Remélem, tudtam segíteni új információkkal! Amennyiben úgy érzed, kihagytam egy olyan információt ami nélkül nem lehet élni, jelezd!
És persze lájkolj és/vagy kommentelj, ha szeretnél még több ilyen cikket:)
Köszönjük a bejegyzést, a gyakorlatban is alkalmazható tudást ad, rendkívül hasznos és személy szerint én örülnék további hasonlóaknak is.
Köszi Povi
Igyekszem, lesz még ilyesmi ;)
A „while” ciklus operátor fejlécében lehet két feltételt használni? Pl.: while (feltétel1 || feltétel2).
Köszönöm
Igen, lehet! A while addig fog futni, ameddig a két feltétel közül legalább egy igaz. (|| esetén; && esetén nyilván mindkettő feltételnek igaznak kell lennie!)
Válaszodat köszönöm, ám újabb kérdésem lenne:
kijelölök egy ordert majd elvégzem a szükséges lekérdezést. Ha később újabb adatra van szükség erről a poziról -de még nem lett másik order kiválasztva- meg marad a kijelölés vagy minden lekérdezés előtt OrderSelect kell?
Üdv Povi
A kijelölés megmarad. Ennek ellenére a pozíció záródása, illetve megnyíló pending order esetén mindenképpen javaslok egy újabb OrderSelectet.
Kedves Radu!
Kérlek írd le nekem, hogy hogy tudom meg az Utolsó Tickethez tartozó OrderType-ot és OrderProfit-ot a legutolsó példánál, ahol a függvény visszatérési értéke az UtolsóTicket.
Köszönöm előre is.
Mivel már tudod a ticket számát, egyszerűen kiválasztod – utána azt kérdezel le, amit szeretnél.
Hello,
Próbáltam szkripttel, programmal (EA) több devizapárra pozit nyitni, de azt válaszolja, hogy „ismeretlen devizapár”. Csak olyan blogbejegyzéseket olvastam, amiben azt írják, hogy ez nem lehetséges, de akkor meg minek megadni az OrderSend() függvénynél a Symbol() -t, ha az ugysem lehet más, mint az aktuális chart instrumentuma?
A kérdésem inkább az, hogy te tudsz-e valami megoldást a problémára?
Csak kíváncsiságból írtam egy programot, ami randomszerűen választ devizapárt (tömbből), irányt és pl. +/-50 pippel pozit nyit(na).
Kézzel egyszer próbáltam, találomra nyitottam 5 pozit 5 véletlenül kiválasztott devizapáron, véletlen irányba (dobókockával:-), 100 pip TP és stop távolsággal, és 4 nyert. Érdekelt volna robottal ugyanez, de nem engedi az MT4, illetve a brókercégek,…többet is próbáltam.
Üdv.Attila
Az OrderSend() függvénnyel bármilyen olyan instrumentumra tudsz nyitni pozit, amelyet az adott bróker elfogad – viszont mindenképpen meg kell adni. Tehát a minimum a Symbol() (vagy egy változó, amibe korábban a függvény értékét átadtad), de megadhatod szövegesen is, ha több instrumentumot kezelsz egyidőben.
Írasd ki a Symbol() függvénnyel az instrumentum nevét, és hasonlítsd össze azzal, amelyet megadsz az OrderSend() -nek. Sok brókernél van egy pont, alulvonás vagy egyéb karakter pluszban az instrumentum neve előtt/után.
Amennyiben olyan instrumentumon próbálsz nyitni, amelyen nem engedélyezett a kereskedés, szintén futhatsz ilyesmi problémába.
A végkövetkeztetés tehát az, hogy valamilyen kisebb-nagyobb hibát vétettél a kódban, és ez okozza a problémádat. Ha megosztod a kódot, akkor igyekszem segíteni benne.
Illetve fontos még azt megjegyezni, hogy visszatesztben bajos az egyszerre több instrumentum kezelése. Bár a problémád úgy érzem nem ez!
Hello,
Kösz a választ, amúgy 4106-os hibát adott, ami ismeretlen szimbólum, de amikor írtam egy kis scriptet, ami köt 5 különféle instrumentumot, hogy megmutassam a hibát, és azonnal rájöttem, hogy mindenhol a Close[0]-val adtam meg az árat -:)), ami nem az adott instrumentumé, hanem az adott charton lévőé. Ennek ellenére nem volt szép, hogy a program nem az árak kifogásolta, hanem a szimbol nevét.
üdv. Attila
Általában a ticket szám, mindig egyre nagyobb. Bár mindig így lenne, könnyebb lenne a programozók dolga. Sajnos néha van kivétel. Mint nálam IronFx demoszámlán. Program fejlesztés közben vette észre, különben szabad szemmel nehéz az ilyesmit észrevenni. A havi összesítő programot készítettem, a programom kimutatta a rossz sorrendet, a hónapok végénél. Kénytelen voltam egy 2 dimenziós tömbe eltárolni az OrderSelect()- el lekérdezett múltbeli adatokat, legalább a dátumot és ticket számot, majd rendezni és csak utána felhasználni. A rendezéshez külön függvényt (quicksort) használtam, mert a beépített ArraySort-tal nem lehet, csak egy dimenziós tömböt rendezni, struktúra tömb, meg nincs.
Egyébként rengeteget segítséget jelent nekem ez a blog köszönöm.
A ticket szám mindig növekszik, legalábbis én ennek ellenkezőjét még nem tapasztaltam. Ha mutatnál egy számlakivonatot, azt megköszönném.
Szerintem maximum rendszerhibáról lehet szó, demónál ennél cifrább dolgok is előfordulhatnak.
A quicksort rendben van, én is használom – de kizárólag olyan esetben, amikor nem a ticket szám alapján szeretnék rendezni.
http://data.hu/get/7249351/DetailedStatement.rar
Ennél az IronFx demo számlánál a #25097984 től találni néhány rossz sorrendűt. A #25167162 is. Megadhatom a jelszót is, amúgy is ezt a számlát lenulláztam. Egyébként így is úgy is rendezni kellet, mert az orderek záró dátuma és nem a nyító dátuma szerint kellett a sorrend.
A megoldás – ahogy már e-mailben leírtam – az, hogy a STOP/LIMIT megbízások ticket száma és kihelyezési dátuma a kihelyezéskor korrelál, míg a teljesüléskor (vagyis amikor a STOP/LIMIT -ből élő pozícióvá válnak) a teljesülés dátumát veszi fel a pozíció. Így fordulhat elő az általad leírt jelenség.
Tényleg, mivel a robotom amit teszteltem, csak függő megbízással dolgozott. Backteszttel ellentétben, itt a MetaTrader elrejtette a függő megbízásokat a listában, ezért elkerülte a figyelmem.
Jó kis írás!
Annyit fűznék hozzá, hogy a függvények „fejlécébe” is bele lehetne tenni a szimbólumot, pl.
void PozicioTipus (int Tipus, string Instrumentum = Symbol())
így már nincs szükség erre:
if (Instrumentum == „”) {
Instrumentum = Symbol();
Kicsit rövidebb, kicsit gyorsabb így.
Az általad javasolt megoldás nem működik sem a régi, sem az új MQL4 nyelvben.
Való igaz, úgy baromság, ahogy van. Fáradt voltam már. Bocsi a beleokvetetlenkedésért.
Szia Radu!
Milyen módszerrel lehet az utolsó előtti ticketszámot megkapni?
Szia Glacc!
A meglévő rutin módosításával egyszerűen meg tudod oldani: hozz létre egy változót, amelynek az utolsó pozíciót cikluson belüli „ideiglenes” értékét adod át, amikor azt frissíted. Ennyi. Nyilván ez csak akkor fontos, ha legalább két nyitott pozíció van.
Köszönöm szépen!