13 bejegyzés megtekintése - 1-13 / 13
  • Szerző
    Bejegyzés
  • Hornet
    Tag
    Bejegyzések száma: 1

    Szia Radu!

    A segítségedet szeretném kérni. A programom legelején minden megbízás számát lementem egy ticket nevű tömbbe, hogy később ebből tudjak dolgozni. Ha visszahívom a tömb értékét hiba nélkül fut a program. Azonban azt szeretném elérni, hogyha megszakad a szerverrel a kapcsolat, vagy újból a charthoz csatolom a EA-t akkor ismét mentse a tömbbe az adatokat. Ezt sikerült is kiviteleznem, azonban, ha ekkor vizsgálom a ticket tömböt az OrderSelect-tel, akkor false jelzést kapok vissza, pedig létezik a megbízás és a tömbben is megtalálható a megbízás száma. Mit javasolnál a problémára? Vagy próbálkozzak inkább globális változóval, az megoldaná a helyzetet?

    Ez lenne az érték visszaállító függvény:

    void Value_search(int j)
       {   
          ArrayInitialize(ticket,0);                                                                                     //Ticket tömb nullázása.
          ArrayInitialize(openprice,0);                                                                                  //Openprice tömb nullázása.
          ArrayInitialize(takeprofit,0);                                                                                 //Célártömb nullázása.
    
                for(int i=0; i<6; i++)                                                                                   //For ciklus indítása (ez számolja a ticket tömb második változóját)
                     {
                      for(int h=0; h<6; h++)                                                                             //For ciklus indítása (ez számolja a megbízásokat)
                         {                                                                                               //Kijelölöm a h pozíciójú megbízást, ami a devizapáron van, nem zárták le és nem 0:
                            if((OrderSelect(h,SELECT_BY_POS,MODE_TRADES)==true)&&(OrderSymbol()==devizapar[j])&&(OrderTicket()!=0)&&(OrderCloseTime()==0))
                               {                                                                                         //Ha a ticketnek még nincs értéke és nem egyenlő a korábbi ticketek értékével, akkor...
                                  if((ticket[j,i]==0)&&(OrderTicket()!=ticket[j,0])&&(OrderTicket()!=ticket[j,1])&&(OrderTicket()!=ticket[j,2])&&(OrderTicket()!=ticket[j,3])&&(OrderTicket()!=ticket[j,4])&&(OrderTicket()!=ticket[j,5]))
                                     {
                                        ticket[j,i]=OrderTicket();                                                       //A ticket megkapja a megbízás számát...
                                        openprice[j,i]=OrderOpenPrice();                                                 //Az openprice megkapja a megbízás nyitóárát...
                                        takeprofit[j,i]=OrderTakeProfit();                                               //A takeprofit megkapja a megbízás célárát.
                                        ObjectSetString(ChartID(),ticket_label[j,i],OBJPROP_TEXT,ticket[j,i]);           //Ticket felirat kiírása.
                                        ObjectSetString(ChartID(),openprice_label[j,i],OBJPROP_TEXT,openprice[j,i]);     //Nyitóár felirat kiírása.
                                        ObjectSetString(ChartID(),takeprofit_label[j,i],OBJPROP_TEXT,takeprofit[j,i]);   //Célár felirat kiírása.
                                        continue;                                                                        //Folytatjuk a következő megbízással.
                                     }                                                                                   //Ha a megbízás száma kissebb mint a korábbi ticket értéke (azaz korábban lett megnyitva), de nem egyenlő a korábbi ticketek értékével, akkor...
                                  if((OrderTicket()<ticket[j,i])&&(OrderTicket()!=ticket[j,0])&&(OrderTicket()!=ticket[j,1])&&(OrderTicket()!=ticket[j,2])&&(OrderTicket()!=ticket[j,3])&&(OrderTicket()!=ticket[j,4])&&(OrderTicket()!=ticket[j,5]))
                                     {
                                        ticket[j,i]=OrderTicket();                                                       //A ticket megkapja a megbízás számát...
                                        openprice[j,i]=OrderOpenPrice();                                                 //Az openprice megkapja a megbízás nyitóárát...
                                        takeprofit[j,i]=OrderTakeProfit();                                               //A takeprofit megkapja a megbízás célárát.
                                        ObjectSetString(ChartID(),ticket_label[j,i],OBJPROP_TEXT,ticket[j,i]);           //Ticket felirat kiírása.
                                        ObjectSetString(ChartID(),openprice_label[j,i],OBJPROP_TEXT,openprice[j,i]);     //Nyitóár felirat kiírása.
                                        ObjectSetString(ChartID(),takeprofit_label[j,i],OBJPROP_TEXT,takeprofit[j,i]);   //Célár felirat kiírása.
                                        continue;                                                                        //Folytatjuk a következő megbízással.
                                     }                                 
                               }
                         }
                   }
          return;
       }
    

    Ez pedig később, amikor OrderSelect-tel ki akarom jelölni:

                               else if((OrderSelect(ticket[j,0],SELECT_BY_TICKET,MODE_TRADES)==true)&&(OrderType()>1))         //Kijelöljük az elsőt, devizapáronként, ami függő megbízás...
                                     {
                                        ClosePending(j);                                                                          //Akkor lefuttatjuk a lezáró függvényt...
                                        continue;                                                                                 //Majd átadjuk a vezérlést a for ciklusnak.
                                     }      
                                  else if((OrderSelect(ticket[j,0],SELECT_BY_TICKET,MODE_HISTORY)==true)&&(OrderCloseTime()>0))   //Kijelöljük az elsőt, devizapáronként, a lezártak közül, ha van zárási ideje...
                                     {
                                        ClosePending(j);                                                                          //Akkor lefuttatjuk a lezáró függvényt...
                                        continue;                                                                                 //Majd átadjuk a vezérlést a for ciklusnak.
                                     }
    
    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Szia Hornet!

    A következő hibákat javítsd:

    • soha ne használj fix ciklust; használd a ciklusban az OrdersTotal() / OrdersHistoryTotal() -t; szerintem ez a bajaid fő forrása
    • a tömbökkel való munkában a lényeg a dinamikusság; írj ciklust arra, hogy keress egy kétdimenziós tömbben, mert ha 100 pozíciót akarsz kezelni akkor nem írhatod végig a 100 indexet a feltételekben
    • a continue használata a legtöbbször nem indokolt; építsd fel úgy az if feltételeket, hogy eleve továbbmenjen a ciklus
    • a kommentelés jó dolog, de használj konstansokat is, hogy olvasható legyen a kódod (1-es helyett OP_SELL használata); ha 1 hónap múlva megnézed majd, akkor is tudni kellene, hogy mit akartál egy-egy kódrészlettel
    • ha már ismered a ticket számokat, akkor OrderSelect-nél is használhatod azokat
    • az egymásba ágyazott ciklusok előnytelenül vannak elkészítve, ezért sokkal többször használod az erőforrásokat, mint az indokolt lenne; elég egyszer végigmenni minden pozíción, és körönként menteni a fontos adatokat a tömbbe
    • szükségtelen két külön OrderSelect(); a pozíciót ticket szám alapján válaszd ki, ekkor a program automatikusan ki fogja választani (nem neked kell döntened, hogy melyik pool-ban kell kotorásszon). A kiválasztás után az OrderCloseTime() alapján eldönthető, hogy lezárt vagy élő pozícióról van szó
    • a Számlatörténet fülön történő dátumkorlátozásra is figyelj, mert amennyiben a felhasználó lekorlátozza a számlatörténet megjelenített időszakát, az expertek sem férnek hozzá azokhoz a pozícióadatokhoz, amelyek nem látszanak
    • boolean vizsgálatnál szükségtelen a == true; elég pl. az if (OrderSelect(h, SELECT_BY_POS)) { }
    • az eredeti kérdés kapcsán pedig: írasd ki Print() segítségével hogy mely pozíciónál kapsz false -t vissza, így kiderül, hogy mi a hibás ticket szám amit ki akarsz választani – ennek alapján lehet majd tovább menni a nyomozásban. Lehet, hogy rossz / nem létező indexet akarsz kiválasztani, vagy nullát.
    BillyBill
    Tag
    Bejegyzések száma: 33

    Szia Radu!

    Ezt írtad: „ha már ismered a ticket számokat, akkor OrderSelect-nél is használhatod azokat”.
    Van valami más módja is az OrderTicket kinyerésének, vagy csak az, ha előbb lefuttatsz egy teljes ciklust az összes pozícióra, amiben egyesével megvizsgálod, hogy az adott order „érdekel-e” ( adott pár, adott magic stb..).
    Én is szívesen dolgoznék az OrderTicket-tel, nem akarok 2 ciklust futtani hozzá.

    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Legtöbbször mindenképpen ciklust kell futtatnod – én ezt teszem. Természetesen további lehetőségek is vannak: pl. eltárolod a számot egy változóban, globális változóban. De mindentől függetlenül a „végigmegyek a pozíciókon” módszer kikerülhetetlen.

    BillyBill
    Tag
    Bejegyzések száma: 33

    Ha jól értelek, akkor sajnos nincs más mód, csak ez:
    Lefuttatok egy teljes ciklust az összes pozíción, és megvizsgálom, hogy az adott order megfelel-e a kritériumaimnak. Ha igen, akkor pl. elmentem egy tömbbe. A teljes ciklus végén pedig lefuttatok egy második ciklust, amiben már csak a tömböm orderei szerepelnek. Jól értelek?
    Azért írtam, hogy sajnos, mert így két ciklust kell futtatni egy helyett, ami kicsit „drága ár” lehet, ha nagyszámú (akár többszáz) order van. (Globális változót itt fölöslegesnek érzem.)

    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Igen, jól érted. Okosan kell használni az erőforrásokat, én csak akkor használok tömböket, ha nincs más megoldás. Látatlanban nem tudom megmondani, hogy ez nálad egyáltalán szükséges-e.

    Ha több száz order van, akkor ez már valóban lehet gond – bár valós idejű futtatásnál én ilyen jellegű adatkezelésből nem tapasztaltam különösebb lassulást.

    Egyébként mi a projekt? Mihez tartozik több száz kötés?

    BillyBill
    Tag
    Bejegyzések száma: 33

    A többszáz kötés elvi lehetőség, de reális (már ahol a broki engedi).
    Az egészet a FIFO miatt vetettem fel. Sosem használtam OrderTicket alapú szelektálást, mindig pozíció alapján dolgoztam, de most felmerült egy (számomra) új szempont a zárásokat illetően. Eddig CloseAll esetén fordított sorrendben zártam az ordereket, mert ugye így biztonságos. De most felmerült, hogy a FIFO-ra is figyelnem kell, így átírtam az egészet aszerint, ahogy az előző posztomban írtam. Így már a második ciklusban biztonságosan tudom zárni az ordereket.

    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Szerintem olvasd el ezt a cikket és ezt a cikket, ezekben részletesen leírtam a témával kapcsolatos véleményemet.

    Én 5 éve gyakorlatilag sosem zárok indexelés, kizárólag ticket alapján. Minden robotomban van egy rutin, ami a pozíciószámlálást végzi – ebben megállapítom a robot logikájához tartozó fontos pozíciók ticket számát (legelső pozíció, legutolsó pozíció, vagy épp a szűrt pozíciókat elrakom tömbbe), és azok mindig rendelkezésre állnak. Index alapján szerintem csak egy pár hónapig zártam még 2010-ben, azonban ott kiderül az azzal kapcsolatos összes probléma, és váltottam a ticket szám alapú megoldásra.

    BillyBill
    Tag
    Bejegyzések száma: 33

    A cikkeidet el fogom olvasni.
    Atombiztos zárórutinom van (ez alapján írtam, kissé módosítva), de a FIFO-ra ugyen nem jó. Átírtam két ciklusosra, így már jó.

    BillyBill
    Tag
    Bejegyzések száma: 33

    Azonban, ha már itt tartunk, lenne még egy kérdésem: szerinted mi okozhatja, hogy egy CloseAll során (sima ciklus, a megfelelő order kiválasztása és zárása) a progi ERR_TOO_FREQUENT_REQUESTS errort dob? Én nem tudtam ezt reprodukálni, nálam mindig hibátlanul zárt, de egy fickó ilyen visszajelzést adott.

    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Ha fut mondjuk 15 robot egyszerre (különböző instrumentumokon), és a pozíciók állandóan nyílnak-záródnak egymástól függetlenül, akkor én az indexes megoldást biztosan nem látom jónak. Ezért fontos szerintem, hogy leszűrd a zárandó pozíciókat, és csak a konkrétakat zárd. Innentől kezdve abszolút nem érdekel, hogy közben megnyílt 50 pozíció és lezárult 22. Az indexes változatnál ezzel szemben a hatékonyság drasztikusan leesik az ilyen speciális esetekben.

    A ERR_TOO_FREQUENT_REQUESTS -et akkor kapod, ha túl sok kérést küldesz a bróker felé. Ellenőrizd, hogy mi a kérés oka (módosítás, zárás, esetleg nyitás) és használj Sleep() -et. Pl. 200 milliszekundum már sokat segít az ügyön :)

    BillyBill
    Tag
    Bejegyzések száma: 33

    A kérés egyértelműen OrderClose. Sosem hallottam még ilyet, hogy egy egyszer lefuttatott ciklus a zárásra ilyen errort adott volna. Csak arra tudok gondolni, hogy a broki szervere tetű lassú.

    Radulovic Attila
    Tag
    Bejegyzések száma: 653

    Ez is benne van a pakliban. Ha egy kérést küldesz, akkor ilyet nem szabadna kapnod. Ha több kérés megy egymás után, akkor viszont simán, ha gyorsan fut a ciklus és gyors egymásutánban akarsz zárni :)

13 bejegyzés megtekintése - 1-13 / 13
  • Be kell jelentkezni a hozzászóláshoz.