Ordine, pozitii si tranzactii incheiate. Partea a II-a
[English version] [MQLmagazine.com in english] [Editia romaneasca]
In articolul precedent am vorbit despre cum sistemul pozitional difera de vechiul sistem de ordine folosit in MT4. In acest articol vom continua cu functiile care se ocupa de noul sistem.
Asa cum probabil stiai, ca si programator MetaTrader, singurul element care-i permite traderului sa-si cunoasca profiturile, pierderile si expunerea pe fiecare instrument este ordinul. Adica, totul incepe cu selectia si analiza fiecarui ordin, fie el ordin curent, sau ordin trecut, selectabil cu OrderSelect(). Sigur, numarul total de ordine este obtinut cu OrdersTotal() si OrdersHistoryTotal(). Deoarece MT4 are o foarte accentuata orientare monoasset, data aproape in intregime de limitarea monoasset pe care o are Strategy Tester, nici macar nu era nevoie pentru functii de pozitie, intrucat traderii aveau posibilitati limitate de a crea experti multiasset.
Incepem cu ce era deja cunoscut din MQL4, si anume lucrul cu ordine. Mai intai de toate, toata paleta de functii de ordine din MQL4 se restrange la cateva:
- OrdersTotal(), care intoarce numarul de ordine;
- OrderSelect(), functia obisnuita de selectie;
- OrderGetDouble(), OrderGetInteger(), OrderGetString(), care sa intoarca informatiile despre ordine;
- OrderGetTicket(), care este o versiune imbunatatita a lui OrderTicket() din MQL4; OrderTicket() din MQL4 intoarce tichetul ordinului selectat; pe cand OrderGetTicket() din MQL5 primeste indexul ordinului ca parametru, si-l mai si selecteaza, facand redundanta aplicarea lui OrderSelect() asupra rezultatului.
- si, desigur, OrderSend() ; apropo, era sa uit : nu mai exista OrderClose().
Functia OrdersTotal() intoarce numarul de ordine; desigur, numai numarul celor pending, pentru ca acestea sunt singurele ramase; orice ordin care este piata sau pending si este executat este incorporat in pozitie si dispare.
Functia OrderSelect() are urmatorul prototip:
1 2 3 4 | bool OrderSelect( ulong ticket // Tichetul ordinului uint timeout=0 // Timeout in millisecunde ); |
Poti vedea diferentele majore cand e comparata cu vechea OrderSelect() din MQL4. Acea OrderSelect() functiona atat cu tichete cat si cu indecsi, pentru ordine curente cat si pentru ordine trecute. Acum functia solicita numarul de tichet, de unde rezulta ca vechiul mod de adresare:
OrderSelect(index,SELECT_BY_POS,MODE_TRADES)
este inlocuit de
OrderGetTicket(index)
Intoarcerea proprietatilor ordinului selectat se face cu OrderGetDouble(), OrderGetInteger(), OrderGetString(), urmarind regula generala stabilita de MQL5, ca functiile care intorc proprietati sa fie centralizate in mai putine functii, cate una pe fiecare tip principal de date.
Fiecare dintre cele trei functii are doua prototipuri, depinzand de cum sunt apelate, Un prototip le permite sa fie apelate ca si functii, admitand ca parametru doar proprietatea care este chestionta; celalalt prototip le permite sa fie apelate ca proceduri, admitand ca parametru proprietatea, si totodata o variabila de acelasi tip ca cel inclus in numele functiei. De exemplu, ai putea apela OrderGetDouble ca
sl=OrderGetDouble(ORDER_SL);
sau
OrderGetDouble(ORDER_SL,sl);
(desigur, cu sl previously declarat ca double). Un comportament similar se aplica celorlalte doua functii.
Proprietatea care este primita ca parametru de functia OrderGetDouble este de tip ENUM_ORDER_PROPERTY_DOUBLE:
| Identificator | Descriere | Tipul rezultatului |
| ORDER_VOLUME_INITIAL | Volumul initial al ordinului | double |
| ORDER_VOLUME_CURRENT | Volumul curent al ordinului | double |
| ORDER_PRICE_OPEN | Pretul specificat in ordin | double |
| ORDER_SL | Valoarea Stop Loss | double |
| ORDER_TP | Valoarea Take Profit | double |
| ORDER_PRICE_CURRENT | Pretul curent al simbolului | double |
| ORDER_PRICE_STOPLIMIT | Pretul Limita pentru un ordin StopLimit | double |
Toate acestea sunt cunoscute. Nu vad nimic in tabela care ar trebui ne ridice sprancenele.
La fel se intampla si cu OrderGetString(), care admite parametri de tip
ENUM_ORDER_PROPERTY_STRING:
| Identifier | Descriere | Tipul rezultatului |
| ORDER_SYMBOL | Simbolul ordinului | string |
| ORDER_COMMENT | Comentariul ordinului | string |
Dar cu adevarat interesanta este functia OrderGetInteger(). Pentru ca analiza lui OrderGetInteger(), ca si de altfel a lui OrderSend(), dezvaluie intentiile MetaQuotes in legatura cu MetaTrader5.
Parametrii admisibili sunt de tip ENUM_ORDER_PROPERTY_INTEGER:
| Identificator | Descriere | Tip rezultat |
| ORDER_TIME_SETUP | Momentul la care ordinul intra in vigoare | datetime |
| ORDER_TYPE | Tipul ordinului | ENUM_ORDER_TYPE |
| ORDER_STATE | Starea ordinului | ENUM_ORDER_STATE |
| ORDER_TIME_EXPIRATION | Timpul expirarii ordinului | datetime |
| ORDER_TIME_DONE | Momentul executiei sau anularii | datetime |
| ORDER_TYPE_FILLING | Felul executiei | ENUM_ORDER_TYPE_FILLING |
| ORDER_TYPE_TIME | Durata de viata a ordinului | ENUM_ORDER_TYPE_TIME |
| ORDER_MAGIC | ID-ul unui expert care a plasat ordinul (proiectat ca fie EA sa-si puna un numar unic) | long |
Mai intai, poti vedea ca nu toate tipurile sunt int, caci int e de fapt o familie de tipuri. Tipurile ENUM sunt tipuri care contin constante numerice speciale, care sunt constante intregi, deci compatibile cu int. Astfel avem ORDER_TYPE, care este destul de clar, similar cu cel din MQL4, cu diferenta ca doua tipuri de ordine sunt adaugate (sigur, constantele se scriu diferit ca cele din MQL4, dar descrierea e aceeasi):
ENUM_ORDER_TYPE:
| Identificator | Descriere |
| ORDER_TYPE_BUY | Ordin de cumparare la piata |
| ORDER_TYPE_SELL | Ordin de vanzare la piata |
| ORDER_TYPE_BUY_LIMIT | Ordin de cumparare Limita |
| ORDER_TYPE_SELL_LIMIT | Ordin de vanzare Limita |
| ORDER_TYPE_BUY_STOP | Ordin de cumparare Stop |
| ORDER_TYPE_SELL_STOP | Ordin de vanzare stop |
| ORDER_TYPE_BUY_STOP_LIMIT | Dupa atingerea pretului ordinului, un ordin de cumparare Limita este lansat la pretul StopLimit (*Nou in MQL5*) |
| ORDER_TYPE_SELL_STOP_LIMIT | Dupa atingerea pretului ordinului, un ordin de vanzare limita este lansat la pretul StopLimit (*Nou in MQL5*) |
ENUM_ORDER_TRADE_TYPE specifica tipul ordinului in termeni de expirare:
| Identifier | Description |
| ORDER_TIME_GTC | Bun pana la anulare |
| ORDER_TIME_DAY | Bun pe parcursul zilei de trading |
| ORDER_TIME_SPECIFIED | Cu timp specificat |
Chestia care chiar ne ridica sprancenele aici e ENUM_ORDER_TYPE_FILLING:
ENUM_ORDER_TYPE_FILLING:
| Identificator | Descriere |
| ORDER_FILLING_AON | Tranzactia se executa exclusv la volumul specificat, cu un pret egal sau mai bun decat cel specificat in ordin. Dca nu exista suficient volum de oferta pentru simbol, ordinul nu va fi executat. |
| ORDER_FILLING_CANCEL | O intelegere de executie a ordinului cu un volum maxim posibil la un pret egal sau mai bun ca cel specificat in ordin. In acest caz, un ordin aditional pentru volumul neexecutat nu va fi plasat. |
| ORDER_FILLING_RETURN | O intelegere de executie a ordinului la volumul maxim posibil la un pret egal sau mai bun decat cel specificat in ordin. In acest caz va fi plasat un ordin aditional pentru volumul neexecutat. |
De ce nevoia pentru un parametru de executie intr-o platforma de retail ? Asta ne spune ca MetaQuotes pregateste MetaTrader5 pentru Nivelul II. “Pret mai bun” ? Nu specificam cumva cat de rau putea fi pretul acceptat prin parametrul Slippage ? Daca executia va fi controlata ca sa fie mai buna pentru trader, inclusiv spargerea ordinului in piese mai mici care raman pending, e sigur de nivel II. Pentru ca in contextul tradingului de retail de Nivel I nu ar avea sens. De ce? Datorita latentei. Ori pretul este mai bun si ordinul este executat in intregime la noul pret, ori pretul este mai rau, si avem o toleranta la asta, definita de Slippage. Daca noua cotatie ar fi un stream binar, 50% mai buna, 50% mai rea, atunci ai avea preturi mai bune in 50% din situatii, si nu ai avea o executie in celelalte 50%. Dar Slippage iti defineste o toleranta mai mare, asa ca admiti, in probabil 70% din cele 50% cazuri mai rele, ca esti multumit cu executie mai proasta. Noul tip de executie poate fi numai un semn al Nivelului II. Tradusa in Nivel I, inseamna ca brokerul permite sa ai ordinul partial/total executat la pretul specificat (plus/minus noul slippage, numit “deviatie”). In Nivelul II nu exista deviatie. Tradingul de nivel II nu admite executii mai proaste. Traderii pot fi avea executiile ordinelor totale, partiale sau deloc. Noul parametru de executie va da brokerilor posibilitatea de a organiza piata de Nivel II pentru trader. Deci ai putea aveao cumparare pending la Bid, sau o vanzare pending la Ask si chiar sa ai aceste ordine executate de alti participanti in ECN. Traderul de Nivel I, chiar daca scrie acelasi cod ca cel de Nivel II, va experimenta primele executii cand pretul ajunge la Ask pentru ordinul de cumparare sua cand pretul ajunge la Bid pentru ordinul de vanzare, ceea ce inseamna mult mai tarziu decat cerinta pentru Nivelul II. Totusi, pe Nivelul II, executia este jocul pietei, pe cand la Nivelul I, executia este obligatia brokerului. Aceste schimbari sunt confirmate de constantele din ENUM_ORDER_STATE, dar descriu cu acuratete starea ordinului, chiar si dinamica procesului de acceptare. Toate astea ar fi fost un nonsens in MT4, unde un ordin ar putea fi executat integral sau deloc:
ENUM_ORDER_STATE:
| Identificator | Descriere |
| ORDER_STATE_STARTED | Ordin verificat, dar neacceptat inca de broker |
| ORDER_STATE_PLACED | Ordin acceptat |
| ORDER_STATE_CANCELED | Ordin anulat de client |
| ORDER_STATE_PARTIAL | Ordin partial executat |
| ORDER_STATE_FILLED | Ordin executat integral |
| ORDER_STATE_REJECTED | Ordin respins |
| ORDER_STATE_EXPIRED | Ordin expirat |
O nota interesanta despre ORDER_MAGIC. MetaQuotes inca impinge ideea ca magicul sa fie utilizat ca used as identificator de expert. Initial, MQL5 avea acest ORDER_EXPERT_ID in loc de ORDER_MAGIC, dar apoi s-au intors la conceptul de numar magic. Sigur, numarul magic poate fi folosit ca identificator de expert, dar expert_id ar fi fost un nume inselator, indicand ca acesta ar fi fost singurul uz al numarului magic. Asa cum ati vazut in articolul nostru Trading Orientat pe Obiecte : o abordare POO a tradingului sunt destule moduri de a construi numere magice folositoare cu descrieri intentionale, care pot avea un inteles chiar pentru expert si care poate fi folosit ca eveniment de actiune.
Functia OrderSend() are urmatorul prototip:
1 2 3 4 | bool OrderSend( MqlTradeRequest& request // structura tranzactiei MqlTradeResult& result // structura raspunsului ); |
E mai elegant decat OrderSend() din MQL4. Functia accepta parametrii intr-o structura MqlTradeRequest, si raspunde intr-o structura MqlTradeResult. Lucru care e mai bun comparativ cu MQL4, unde o functie intoarce doar tichetul ordinului, si seteaza eroarea intr-o variabil de sistem MT4, care este interogata de trader cu functia GetLastError(). Acum structura MqlTradeResult contine toate raspunsurile in acelasi loc.
Membrii MqlTradeRequest:
| Camp | Tip | Descriere |
| action | ENUM_TRADE_REQUEST_ACTIONS | Tipul operatiunii |
| magic | ulong | Numar care identifica expertual sau specifica un inteles al ordinului. |
| order | ulong | Tichetul ordinului. Este folosit pentru modificarea ordinelor pending. |
| symbol | string | Simbolul ordinului. Nu este necesar pentru operatiile de modificare a ordinului si de inchidere a pozitiei. |
| volume | double | Volumul solicitat, in loturi. De notat ca volumul real al afacerii va depinde de tipul executiei. |
| price | double | Pretul la care trebuie sa se ajunga ca ordinul sa fie executat. Pentru ordinele de piata se foloseste tipul TRADE_ACTION_DEAL, si nu e necesara definirea unui pret. |
| stoplimit | double | valoarea pretului, la care ordinul pending stopLimit va fi plasat, cand pretul atinge valoarea price (aceasta conditie este obligatorie). Pana atunci ordinul nu este plasat. |
| sl | double | Pretul Stop Loss in caz de evolutie nefavorabila a pretului. |
| tp | double | Pretul Take Profit in caz de evolutie favorabila a pretului. |
| deviation | ulong | Valoarea maxima a deviatiei pretului, specificata in puncte |
| type | ENUM_ORDER_TYPE | Tipul ordinului |
| type_filling | ENUM_ORDER_TYPE_FILLING | Tipul executiei ordinului |
| type_time | ENUM_ORDER_TYPE_TIME | Timpul executiei ordinului |
| expiration | datetime | Momentul expirarii ordinului (pentru ordinele de tip ORDER_TIME_SPECIFIED) |
| comment | string | Comentariul ordinului |
Dupa cum se vede, o noutate in T5 este tichetul facut de utilizator, spre deosebire de MT4 unde serverul asigna tichete ordinelor. Pana la un punct, tichetul poate juca rol de magic secundar, sau chiar isi poate inversa rolul cu magicul, dar totusi sugerez folosirea momentului lansarii pe post de tichet.
Membrii MqlTradeResult:
| Identificator | Tip | Descriere |
| retcode | uint | Codul rezultant intors de la server |
| deal | ulong | Tichetul afacerii, daca afacerea a fost confirmata. Este disponibil pentru tranzactiile de tip TRADE_ACTION_DEAL. |
| order | ulong | Tichetul ordinului, daca un tichet a fost plasat. Este disponibil pentru tranzactiile de tip TRADE_ACTION_PENDING |
| volume | double | Volumul afacerii, confirmat de broker. Depinde de tipul executiei ordinului |
| price | double | Pretul afacerii, confirmat de broker. Depinde de campul deviation si/sau de tipul tranzactiei. |
| bid | double | Pretul Bid de piata (recotat) |
| ask | double | Pretul Ask de piata (recotat) |
| comment | string | Comentariul brokerului la operatiune (de regula cuprinde descrierea operatiei) |
Cel mai important camp aici este retcode , care este raspunsul serverului. Acesta preia sarcinile de la functia GetLastError() din MQL4. Pe baza acestui retcode vom scrie versiuni “de incredere” ale lui OrderSend() cum am facut si in MQL4, tratand din ce in ce mai multe erori de executie. Urmeaza deal si order, care arata sistemul pozitional chiar din structura. Ordinele care sunt trimise ca TRADE_ACTION_DEAL, adica ordinele de piata, nu au o perioada de viata propriu-zisa, pentru ca exista doar pana cand sunt acceptate de broker, adica maximum 1-2 secunde (asta presupunand ca brokerul chiar te uraste). De aceea tichetul lor, specificat de trader in structura MqlTradeRequest se intoarce pe campul deal , nu pe campul order.
volume e un un camp chiar interesant. Volumul se comporta in functie de cum a fost setata executia. De xemplu, daca ordinul nu poate fi executat in intregime, si campul spune exact cat anume a fost executat. Intrebarea ramane, daca un ordin pending are o executie partiala, cum va fi ea raportata in timp real ? OnTrade() nu are parametri ca sa raporteze executiile. Deisgur un ordin pending nu ar trebui sa aiba o executie partiala, pe Nivelul I. Pentru ca ordinul era deja acolo cand piata l-a atins pe linia de executie. Dar daca am fi pe Nivelul II, o mare parte din executiile ordinelor pending (care sunt, asa cum am zis mai inainte, langa piata) executiile sunt in cea mai mare parte partiale. Si OnTrade() trebuie sa fie imbunatatit ca sa trimita datele de executie in timp real catre programul apelant.
Campul pret este folositor, continand pretul confirmat. In MQL4 ar fi trebuit sa selectezi ordinul si sa fi extras pretul real de deschidere cu OrderOpenPrince(), asa ca acest camp scurteaza cautarea.
Campurile bid si ask au roluri mai mult informationale, la fel ca si comment.
Pozitii
Nu voi explica din nou cum functioneaza pozitiile, pentru ca am facut asta in Partea I a articolului. Prima functie care trebuie sa fie cunoscuta este PositionsTotal() care intoarce numarul de pozitii deschise. Similar cu OrderSelect() si OrderGetTicket() avem acum functiile echivalente pentru pozitii PositionSelect() si PositionGetSymbol(). Amandoua selecteaza o pozitie cu care sa se lucreze mai departe.
Functia PositionSelect() are urmatorul prototip:
1 2 3 4 | bool PositionSelect( string symbol // Simbol uint timeout=0 // Timeout in milisecunde ); |
Chiar arata ca OrderSelect(), nu ? Solicita un simbol si un timeout. Similar si cu PositionGetSymbol(), care admite ca parametru index pozitiei in pozitiile curent deschise.
Apoi, urmeaza functiile de interogare a pozitiilor, pe acelasi model ca cele pentru ordine: PositionGetDouble(), PositionGetInteger(), PositionGetString(). Au cam acelasi prototip, cu diferenta ca parametrul principal e de tip
ENUM_POSITION_PROPERTY_DOUBLE, ENUM_POSITION_PROPERTY_STRING sau ENUM_POSITION_PROPERTY_INTEGER.
ENUM_POSITION_PROPERTY_DOUBLE
| Identificator | Descriere | Tip rezultat |
| POSITION_VOLUME | Volumul pozitiei | double |
| POSITION_PRICE_OPEN | Pretul de deschidere al pozitiei | double |
| POSITION_SL | Nivelul Stop Loss al pozitiei | double |
| POSITION_TP | Nivelul Take Profit al pozitiei | double |
| POSITION_PRICE_CURRENT | Pretul curent pentru instrumentul pozitiei | double |
| POSITION_COMMISSION | Comisionul | double |
| POSITION_SWAP | Swap (dobanda) cumulata | double |
| POSITION_PROFIT | Profitul curent | double |
Acum chiar trebuie sa intelegi de ce POSITION_PRICE_OPEN trebuie sa fie o medie ponderata. Sa zicem ca deschizi 1 lot de cumparare la 1.3000 si 3 loturi la 1.3300. Dupa ce faci asta, pozitia ta va fi de cumparare 4 loturi. Daca piata merge in jos 1.3100, vei fi in pierdere. Daca pozitia e de cumparare 4 loturi, cu deschidere la 1.3000, n-ar avea niciun sens sa fie in pierdere la 1.3100. De aceea pretul de deschidere trebuie sa fie o medie ponderata, pentru ca rezultatele sa aiba o interpretare corecta.
ENUM_POSITION_PROPERTY_INTEGER
| Identificator | Descriere | Tip rezultat |
| POSITION_TIME | Momentul deschiderii pozitiei | datetime |
| POSITION_TYPE | Tipul pozitiei | ENUM_POSITION_TYPE (poate fi POSITION_TYPE_BUY sau POSITION_TYPE_SELL) |
| POSITION_MAGIC | Numarul magic al pozitiei | long |
ENUM_POSITION_PROPERTY_STRING
| Identificator | Descriere | Tip rezultat |
| POSITION_SYMBOL | Simbolul pozitiei | string |
| POSITION_COMMENT | Comentariul pozitiei | string |
Dintre aceste proprietati, cele mai ciudate par a fi POSITION_MAGIC si POSITION_COMMENT. Aceste sunt proprietati legate de ordine, pentru ca fiecare ordin are propriul lui sens. Pozitia in sine este un rezultat al ordinelor. De unde rezulta ca POSITION_MAGIC si POSITION_COMMENT coincid cu ultima executie a unui ordin pe simbolul respectiv.
Istoric
MetaQuotes a inclus doua cai de citire a istoricului : afacerile (tranzactii incheiate), insemnand modificari trecute ale pozitiei, la fel ca si vechiul stil MQL4, istoricul ordinelor. Spre deosebire de istoricul ordinelor in MQL4, acum perioada studiata trebuie sa fie selectata cu HistorySelect(). Functia primeste doi parametri datetime: date_from and date_to. Asta face ca functia sa fie folositoare pentru cazul in care OnTrade() nu va fi modificat si nu va raporta care ordin este executat, pentru ca masa ordinelor care trebuie sa fie scanate devine foarte mica. Desigur, from_date poate fi zero, de unde rezulta ca tot istoricul va fi selectat. Dar e mai bine sa se tina o evidenta cu timpul cand s-a facut ultima scanare, astfel ca numai noile executii sa fie scanate, poate chiar dupa ultima executie. Pe de alta parte, to_date are un inteles interesant acum, pentru ca sunt doua functii care se ocupa cu timpul serverului. Una este din MQL4, si anume TimeCurrent(), care intoarce ultimul timp cunoscut al serverului, si una noua, TimeTradeServer(), care face acelasi lucru, dar are rezultate mai precise, pentru ca foloseste timpul local al computerului, dar da rezultate pe acelasi fus orar ca si TimeCurrent().
Odata ce selectia s-a facut, avem: numarul total de tranzactii incheiate, ce poate fi extras cu HistoryDealsTotal(), tichetul per index, selectabil cu HistoryDealGetTicket(), si functia obisnuita de selectie HistoryDealSelect() ; aceastea doua au aceeasi sintaxa ca OrderGetTicket() si OrderSelect(). Functiile de solicitare de date sunt similare cu functiile de la ordine, si astfel avem HistoryDealGetDouble, HistoryDealGetInteger(), HistoryDealGetString().
ENUM_DEAL_PROPERTY_DOUBLE
| Identificator | Descriere | Tipul rezultatului |
| DEAL_VOLUME | Volumul tranzactiei | double |
| DEAL_PRICE | Pretul tranzactiei | double |
| DEAL_COMMISSION | Comisionul tranzactiei | double |
| DEAL_SWAP | Swapul cumulativ la inchidere | double |
| DEAL_PROFIT | Profitul tranzactiei | double |
ENUM_DEAL_PROPERTY_INTEGER
| Identificator | Descriere | Tipul rezultatului |
| DEAL_ORDER | Numarul ordinului tranzactiei | long |
| DEAL_TIME | Momentul tranzactiei | datetime |
| DEAL_TYPE | Tipul tranzactiei | ENUM_DEAL_TYPE (poate fi DEAL_TYPE_ ..BUY, ..SELL, ..BALANCE, ..CREDIT, ..CHARGE, ..CORRECTION) |
| DEAL_ENTRY | Intrarea pozitiei | ENUM_DEAL_ENTRY (poate fi DEAL_ENTRY_ ..IN, ..OUT, ..INOUT, ..STATE |
| DEAL_MAGIC | Numarul magic al pozitiei (vezi ORDER_MAGIC) | long |
ENUM_DEAL_PROPERTY_STRING
| Identificator | Descriere | Tipul rezultatului |
| DEAL_SYMBOL | Simbolul tranzactiei | string |
| DEAL_COMMENT | Comentariul tranzactiei | string |
De exemplu, dupa ce am lansat urmatoarele ordine (manual) pe contul demo:
Sell EURUSD 0.1 lots @ 1.41548
Sell EURUSD 0.3 lots @ 1.41600
Buy EURUSD 0.5 lots @ 1.41647
Sell EURUSD 0.1 lots @ 1.41648
am rulat urmatorul script ca sa vad ce e in istoricul tranzactiilor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | //+------------------------------------------------------------------+ //| History Test.mq5 | //| Copyright Bogdan Caramalac | //| http://mqlmagazine.com | //+------------------------------------------------------------------+ #property copyright "Bogdan Caramalac" #property link "http://mqlmagazine.com" #property version "1.02" #property script_show_inputs //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string EnumDealEntry(long e) { switch(e) { case DEAL_ENTRY_IN: return("DEAL_ENTRY_IN "); case DEAL_ENTRY_INOUT: return("DEAL_ENTRY_INOUT "); case DEAL_ENTRY_OUT: return("DEAL_ENTRY_OUT "); case DEAL_ENTRY_STATE: return("DEAL_ENTRY_STATE "); default: return("DEAL ENTRY UNKNOWN"); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string EnumDealType(long t) { switch(t) { case DEAL_TYPE_BUY: return("DEAL_TYPE_BUY "); case DEAL_TYPE_SELL: return("DEAL_TYPE_SELL "); case DEAL_TYPE_BALANCE: return("DEAL_TYPE_BALANCE "); case DEAL_TYPE_CREDIT: return("DEAL_TYPE_CREDIT "); case DEAL_TYPE_CORRECTION: return("DEAL_TYPE_CORRECTION"); default: return("DEAL TYPE UNKNOWN "); } } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { long ticket; int deals=HistoryDealsTotal(); datetime from_date=0; datetime to_date=TimeTradeServer(); HistorySelect(from_date,to_date); deals=HistoryDealsTotal(); Print("Total history deals=",HistoryDealsTotal()); for(int i=deals-1;i>=0;i--) { ticket=HistoryDealGetTicket(i); Print(" ",i," ",DoubleToString(HistoryDealGetDouble(ticket,DEAL_VOLUME),2)," ", EnumDealType(HistoryDealGetInteger(ticket,DEAL_TYPE))," ", DoubleToString(HistoryDealGetDouble(ticket,DEAL_PRICE),SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))," ", EnumDealEntry(HistoryDealGetInteger(ticket,DEAL_ENTRY))," ", DoubleToString(HistoryDealGetDouble(ticket,DEAL_PROFIT),2)); } Print("Index Volume Type Price Entry Profit"); } //+------------------------------------------------------------------+ |
Si rezultatul este:

Desigur, cum am spus mai devreme, vechiul stil al istoricului a fost pastrat. Functiile care lucreaza cu istoricul ordinelor sunt: HistoryOrdersTotal(), HistoryOrderSelect(), HistoryOrderGetTicket(), HistoryOrderGetDouble(), HistoryOrderGetInteger(), HistoryOrderGetString(). Toate se supun functiei HistorySelect(), exceptie facand HistoryOrderSelect(). Parametrii functiilor sunt aceiasi ca la functiile care lucreaza cu ordinele curente.