Sari la conținut

Problema Buffere MQL4


Postări Recomandate

Salut,

Problema este legata de un indicator pe care vreau sa-l folosesc intr-un expert.<-- Este prima mea intersectie cu limbaju MQL -->

In mare indicatorul da semnale de buy/sell prin sageti atasate chart-ului, concomitent cu alerte. Prin urmare pentru a folosi in expert semnalele indicatorului trebuie sa:

 

-adaug inca un buffer in indicator si sa-i atribui un index in cadrul init();

 

double my_buff[];
int init()
SetIndexBuffer(7, my_buff);

-adaug langa linia de cod a alertei ceva de genu

my_buff[i]=k //unde k=1 pentru buy sau k=2 pentru sell

Acum rezultatul, evident, este altul. Verific my_buff imediat dupa ce ii atribui valoarea prin

Alert("valoare buffer=", my_buff[i]);
si este 0 mereu. De ce, nu stiu!!??

 

Iar daca folosesc variabila my_buff ca un simplu array, adica sterg linia "SetIndexBuffer(7, my_buff);" , stocheaza valoarea care trebuie dar merge doar daca am si linia asta: ArrayResize(my_buff, Bars); in init(). Inca un paradox pentru mine.

 

Intrebarea mea este de ce nu i se atribuie nicio valoare variabilei my_buff? Trebuie folosita o alta abordare?

Link spre comentariu
Distribuie pe alte site-uri

  • Răspunsuri 10
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Moderators

o grămadă de necunoscute, care trebuie luate prin deductie, ar trebui să fii un pic mai clar, well, prima deductie care se poate face este că indicatorul foloseste deja 7 buffere, numerotate de la 0 la 6, odata ce tu vrei sa il folosesti pe al optulea (spui setindexbuffer(7...)), deci pe undeva ai o linie de properties care spune "#property indicator_buffers 7" şi trebuie modificata in "8". Apoi mai sunt necesare ceva setari in functia init, nu stiu ce ai pe acolo, vezi in help functiile de tipul "SetIndexXXXXX" unde XXXXX este ceea ce vrei sa faca functia. Pe urma, cine este i-ul ala? Adică, folosesti undeva IndicatorCounted() să pictezi bare pe istorie? Pentru că altfel trebuie sa pictezi doar bara curenta, care are indexul 0, nu iti trebuie acel i, şi trebuie sa fii atent ca aceste buffere nu sunt matrici, vectori, adică sunt, dar sunt dinamici, in sensul că dacă spui v[7]=5 si citesti peste o bucata de vreme, v[7] nu mai este 5, pentru ca chartul s-a deplasat spre stanga cu un numar de bare.

 

In plus, buferele trebuie folosite la rând, adică daca nu ai deja 7 buffere folosite, nu poti sa folosesti pe cel de al 8-ulea. Numarul de bufere pe care il folosesti trebuie musai declarat cu o linie de properties ca cea de mai sus, in care spui cate bufere folosesti, si daca sunt trei, de exemplu, atunci in init() va trebui sa explici cine e bufferul zero, bufferul 1 si bufferul 2, dar NU AI VOIE sa folosesti buffere cu numere 3, 4, 5, 6, 7 (adica ai voie, dar patesti ce ai patit tu :P). Altfel MQL nu are de unde stii care e buffer si care e matrice. Diferenta consta in faptul ca buferele sunt legate de chart, adica tot niste matrici, dar cresc odata cu chartul si se deplaseaza spre stanga, componenta v[0] devine v[1], si asa mai departe, v[n] devine v[n+1], iar in faţa lor se inserează o componentă nouă, care devine noul v[0], si care de obicei NU ESTE initializata, continutul ei este NaN. Trebuie sa ai grija tu ce pui acolo (de exemplu zero, sau pt indicatorii care trag linii trebuie sa copiezi valoarea lui v[1] plus sau minus ceva, etc.

Editat de tradelover
bolduit pe ici pe colo
Link spre comentariu
Distribuie pe alte site-uri

Multumesc Tradelover, prima deductie a fost si cea corecta. Nu stiu de ce aveam impreisa ca "#property indicator_buffers 7" este un comentariu.

 

In alta ordine de idei m-am lovit de un aspect pe care nu imi dau seama cum sa-l interpretez.

 

EA-ul la care lucrez proceseaza tranzactiile in functie de comentariul asignat la momentul deschiderii lor. Intrebarea mea este: Atunci cand EA-ul inchide partial o pozitie se reseteaza comentariul adaugat? (Spun asta bazandu-ma pe faptul ca in ST cand inchid partial o tranzactie, de 2 Loturi spre exemplu, imi arata ceva de genu CLOSE SIZE:1LOT, BUY SIZE 1LOT. Adica imi inchide jumate si deshide cealalta jumate cumva sa compenseze si astfel ma aleg cu o tranzactie noua care nu are comentariu).

Este adevarata supozitia sau e tot o problema de cod?

Link spre comentariu
Distribuie pe alte site-uri

  • Moderators

comentariul orderului se schimbă de fiecare dată când operezi orderul. Asta inseamnă că dacă modifici sl, tp, punctul de intrare (la pending), dacă faci inchideri partiale, ori dacă inchizi total sau partial ordere balansate (hedge total sau partial), margin call, inchidere in stop, inchidere in target, etc, acel comentariu se schimbă.

 

Câmpul de comentariu este ceva prin care sistemul te anunţă ori de câte ori se joacă cu orderele tale, de ce s-a jucat cu ele. De exemplu, dai in SL, o sa apară ceva de genul "SL/A: bla bla", când dai in TP vei avea "TP/A bla bla", dacă ai un order sell 1 lot, ticket 12345, si altul buy 0.3 loturi ticket 67890, si alegi "close by", cu cele doua ordere, vei avea două ordere inchise, la cel de sel "closed by 67890", la cel de buy "closed by 12345", şi un order nou (al treilea), care va fi un sell 0.7 (diferenta de expunere) şi comment "from hedge 12345 & 67890". Dacă faci inchidere partiala la orderul 32451, vei avea un order nou 76512, cu comentariul "from 32451", iar cel vechi se va inchide cu comentariul "to 76512".

 

Dacă ai nefericirea să dai in Margin Call, vei avea toate orderele inchise cu comentariul "Stopped Out: bla bla bla", sau "SO/A: bla bla".

 

Şi asa mai departe. Bineinteles că în toate cazurile, comentariul vechi se pierde.

 

Mesajele diferă de la broker la broker, dar ai prins ideea, câmpul ăla e pentru sistem, nu pt tine. Poţi să scrii in el dacă vrei, dar nu ai garanţia că mai găsesti ce trebuie acolo. Soluţia este să folosesti magic-numbere, pe care eventual să le asociezi cu comentariul, adică setezi magicul, setezi comentariu, dacă peste un timp un order care are magicul tău va avea alt comentariu, inseamnă că cineva s-a jucat cu el. O altă solutie e să memorezi ticketele, etc. Sunt o grămadă de posibilităţi, depinde ce vrei să faci.

Editat de tradelover
Link spre comentariu
Distribuie pe alte site-uri

Pana la urma se pare ca si in documentatie scrie ca ultima parte a comentariului poate fi modificata de server.

comment - Order comment text. Last part of the comment may be changed by server

In conditiile asta o sa aleg varianta cu memorarea ticketelor si a comentariilor in vectori independenti.

 

Si cum o problema nu vine singura urmatoarele linii de cod, atat de banale, dau un rezultat ciudat.

double MyNewSl = OrderStopLoss();
------------------------------
//Prelucrare/modificare MyNewSl
------------------------------
if(MyNewSl != OrderStopLoss())
{
Print ("sl=",MyNewSl,"odsl=",OrderStopLoss());
int MdfyOrder = OrderModify(OrderTicket(), OrderOpenPrice(), MyNewSl, NewTp, 0, Blue);
}

Evident primesc OrderModify error 1 pentru ca MyNewSl = OrderStopLoss(). Cum de intra in conditia if, ramane un paradox pentru mine.

Probabil trebuie sa aplic o functie gen doubleVal() lui MyNewSl...cum este in php FloatVal. Nu-mi dau seama. Poate are cineva vreo idee?!

Link spre comentariu
Distribuie pe alte site-uri

  • Moderators

haha, asta nu tine de mql, ci de programare in general :P, doua numere flotante nu sunt niciodata egale sau inegale. Ele sunt unul mai mare sa celalalt, sau invers. De exemplu, "if (1/10.0==0.1)" va fi intotdeauna false, iar "if (3*(1/3.0)==1)" va depinde de implementare (in MQL e true, in C++ poate fi true sau false). Asta pentru ca 0.1 in binar este o fractie infinita. Cand o dai ca constantă este altfel generată decat atunci cand rezultă din calcule. Pentru detalii, vezi aici. Ele diferă prin exact o singură ULP, deci nu sunt egale. Numerele reale nu se pot comparara niciodata cu simnul egal, rezultatele sunt imprevizibile. Adică "if (a==b)" unde a si b sunt double este gresit, in sensul ca nu poti sti care va fi rezultatul. Spre exemplu "if (0.010000000707805156707763671875 == 0.009999999776482582092285156250) va fi intotdeauna true pe un computer cu 32 de biti, dar va fi intotdeauna false pe 16 biti ori pe 64 de biti. Pentru detalii, vezi aici.

 

Ori le normalizezi, ori le compari cu inegalitate.

 

Revenind la problema ta, OrderStopLoss() intoarce un numar normalizat, care are intotdeauna 2, 3, 4, sau 5 zecimale, dependent de perechea valutara (2 pt jpy si 4 pt restul) si de broker (daca ai cont cu 5 zecimale, atunci 3 pt jpy, 5 pt restul), pe cand MyNewSL poate fi normalizat sau nu, depinde de felul cum il calculezi, si poate avea oricate zecimale, poate fi diferit la zecimala a 19-a. Exista posibilitatea ca ele sa fie egale teoretic, dar sa nu fie egale practic (reprezentarea lor in binar e diferita).

 

Solutia? Incearca să folosesti NormalizeDouble(). Ori incearca sa le compari cu inegalitate, nu cu egalitate.

 

Si daca vrei sa iti bagi nasul mai tare in aceste chestii, un articol foarte bun este aici (atentie, contine multa matematica, hihi).

Editat de tradelover
Link spre comentariu
Distribuie pe alte site-uri

  • Moderators

pai iti trebuie oricum NormalizeDouble() si in functia OrderModify(...)

 

Eu cred ca un cod de tipul urmator

 

if(NormalizeDouble(MyNewSl,Digits) != OrderStopLoss())
{
Print ("sl=",MyNewSl,"odsl=",OrderStopLoss());
int MdfyOrder = OrderModify(OrderTicket(), OrderOpenPrice(), 
   NormalizeDouble(MyNewSl, Digits), 
   NormalizeDouble(NewTp, Digits),
   0, Blue);
}

ar trebui sa mearga perfect, desi nu e solutia cea mai buna. Cel mai bine ar fi sa iti calculezi SL-ul deja normalizat, si sa folosesti inegalitati, pentru ca stopul nu se largeste niciodata, el doar se strânge, deci la stopul unui buy se mută doar in sus, cel al unui sell doar in jos.

 

//in locul unde il calculezi
MyNewSL=NormalizeDouble(....calcule...., Digits);

//in locul unde vrei sa il muti:
if (OrderType()==OP_SELL && MyNewSL<OrderStopLoss())
{  bla bla muta stopul }
else if (OrderType()==OP_BUY && MyNewSL>OrderStopLoss())
{  bla bla muta stopul }

functiile pe siruri sunt lente, in plus, oricum nu scapi de NormalizeDouble(), pt ca serverul nu accepta sa ii setezi noul stop daca nu are exact Digits zecimale (ori mai putine). Degeaba il faci string cand il compari, trebuie oricum sa il normalizezi, pt ca de exemplu nu poti seta un sl la 1.365725 daca cotatia are doar 5 sau 4 zecimale si atunci vei primi in mod cert eroare 1, sau 3, sau 130. La fel si pentru NewTP.

Editat de tradelover
Link spre comentariu
Distribuie pe alte site-uri

Ai dreptate cel mai cinstit,corect si etic este sa calculez SL-ul deja normalizat.

In schimb 'anomaliile' nu se opresc aici. Daca pana acum foloseam EA-ul la un broker cu 4 digits, cand l-am mutat pe 5 digits mi-a dat un rezultat cel putin ciudat. Exemplu:

 

MA = iMA(Symbol(), 0, Period_MA, 0, MODE_EMA, PRICE_CLOSE,0); 
//MA = 1.01234

Print ("MA nenormalizat=",MA); 
//Afiseaza MA nenormalizat = 1.0123

Print ("MA normalizat=",NormalizeDouble(MA,5)); 
//Afiseaza MA normalizat = 1.0123

Print ("MA in format string=",DoubleToStr(MA,5)); 
//Afiseaza MA in format string = 1.01234

Care este explicatia?De ce nu am MA-ul in format de 5 zecimale dupa ce normalizez? Mai mult, daca fortez nota si fac:

Print ("MA tricky calculation=",StrToDouble(DoubleToStr(MA,5),5)); 
//Afiseaza MA tricky calculation = 1.0123

WTF? E vreo conspiratie ceva?!?!?!?!

Link spre comentariu
Distribuie pe alte site-uri

Alătură-te conversației

Poți posta acum și să te înregistrezi mai târziu. Dacă ai un cont, autentifică-te acum pentru a posta cu contul tău.

Vizitator
Răspunde la acest subiect...

×   Alipit ca text avansat.   Alipește ca text simplu

  Doar 75 emoji sunt permise.

×   Linkul tău a fost încorporat automat.   Afișează ca link în schimb

×   Conținutul tău precedent a fost resetat.   Curăță editor

×   Nu poți lipi imagini direct. Încarcă sau inserează imagini din URL.

  • Navigare recentă   0 membri

    • Nici un utilizator înregistrat nu vede această pagină.

×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.