Próbuję uporać się z takim automatem-pomocnikiem, który wystawiałby automatyczne zlecenia oczekujące do każdego, które jest już otwarte na rynku, lub które dopiero otworzę. Dodatkowym warunkiem jest sprawdzanie wolumenu przeciwstawnych zależnie od preferencji. Powinien również skanować zlecenia na bieżąco - niezależnie od tego w którym momencie go włączę (z czystą listą zleceń, czy z już otwartymi przed jego włączeniem).
Założeniem wyjściowym było "dopisywanie" komentarza do wysyłanego zlecenia oczekującego z numerem kontr-zlecenia dla którego zostało ono złożone. Miał to być znak rozpoznawczy, że zlecenie jest już "obsłużone". Może to siermiężna metoda, ale lepszej logicznej i praktycznej nie znalazłem...
W kodzie jest kilka "nic nie robiących" funkcji piszących tylko numery zleceń - póki nie uporam się z poprawną selekcją to sporo ułatwia by nie pogubić się w kodzie i w śledzeniu logów EA.
Przykład:
1. jest na rynku zlecenie BUY z ticketem 111111
2. jest na rynku zlecenie SELL z ticketem 999999
3. jest zlecenie oczekujące z ticketem 333333
4. skanuje listę zleceń i usuwam pending order, gdyż jego wolumen nie odpowiada moim założeniom z EA
5. usuwa oczekujące, zostają dwa aktywne
6. do zlecenia BUY sprawdza (na podstawie komentarza) czy nie istnieje dla niego już kontra
6a. jeśli nie istnieje to wrzuca na rynek oczekujące z komentarzem "Kontra dla 111111" - to znak rozpoznawczy
6b. jeśli istnieje - przechodzę do kolejnego aktywnego zlecenia
7. do zlecenia SELL sprawdza czy nie istnieje kontra
7a. jeśli nie istnieje to wrzuca na rynek oczekujące z komentarzem "Kontra dla 999999" - to znak rozpoznawczy
7b. jeśli istnieje - przechodzę do kolejnego aktywnego zlecenia
8. brak innych zleceń - koniec pętli
9. wrzucam z ręki kolejny SELL z ticketem 5555555
10. pętla sprawdza wszystkie zlecenia czy posiadają kontr-zlecenia, jeśli nie mają to wysyła kolejne oczekujące z komentarzem "Kontra dla 555555"
itd.
Tak to mniej więcej powinno wyglądać wg moich założeń, jednak podczas wielokrotnego multiskanowania mieszają się w kodzie aktualnie wybrane zlecenia przez OrderSelect() - przez co EA nie potrafi przeskanować wszystkiego poprawnie
Czy znalazłby się ktoś, kto poprawiłby mój kod?
PS. W rezultacie będzie to przydatne narzędzie nie tylko dla mnie
Oto moja próbka kodu:
Kod: Zaznacz cały
//+------------------------------------------------------------------+
//| auto pending position.mq4 |
//| 2015 - Jacek |
//+------------------------------------------------------------------+
#property copyright "2015 Jacek"
extern int auto_pending_distance = 250;
extern string vol_przeciwstawnej_pozycji = "!!! w procentach %%% !!!";
extern int oposite_order_volumen = 100;
extern string maxymalny_volumen = "MAXYMALNY DOPUSZCZALNY VOLUMEN ?";
extern double max_vol = 0.1;
//extern bool ignoreOtherEA=true;
// INICJALIZACJA EXPERTA
int init() {
Print("KONTO: ", AccountInfoDouble(ACCOUNT_BALANCE) );
return(0);
}
// DE-INICJALIZACJA EXPERTA
int deinit() {
return(0);
}
// FUNKCJA GŁÓWNA
int start()
{
double poziom_wejscia,pre_pending_order;
// JEŚLI JEST TYLKO 1 ZLECENIE OTWARTE :
if (OrdersTotal()==1)
{
for(int i=0;i<OrdersTotal();i++)
{ if(!OrderSelect(i,SELECT_BY_POS)) continue;
//double v = NormalizeDouble(OrderLots()+ (OrderLots()*2),2);
if(OrderType()==OP_BUY) // jeśli aktualne zlecenie to BUY
{ poziom_wejscia=OrderOpenPrice();
pre_pending_order = poziom_wejscia-(auto_pending_distance*Point);
if(OrderSend(Symbol(),OP_SELLSTOP,vol(OrderLots()),pre_pending_order,0,0,0,"Kontra do zlecenia "+OrderTicket())) continue;
Print(OrderComment());
}
if(OrderType()==OP_SELL) // jeśli aktualne zlecenie to SELL
{ poziom_wejscia=OrderOpenPrice();
pre_pending_order = poziom_wejscia+(auto_pending_distance*Point);
if(OrderSend(Symbol(),OP_BUYSTOP,vol(OrderLots()),pre_pending_order,0,0,0,"Kontra do zlecenia "+OrderTicket())) continue;
}
// ZAMYKANIE POZYCJI OCZEKUJĄCYCH, JEŚLI NIE MA INNYCH
if(OrdersTotal()==1 && (OrderType()==OP_BUYSTOP ||
OrderType()==OP_SELLSTOP ||
OrderType()==OP_BUYLIMIT ||
OrderType()==OP_SELLLIMIT))
{ if(OrderDelete(OrderTicket())) continue;
Print("OrderDelete ostatni error jest: ",GetLastError() + ", A TICKET TO: " + DoubleToString(OrderTicket(),8));
}
//Print("Pozycja: "+ DoubleToStr(i,0)+" - "+ DoubleToStr(NormalizeDouble(pre_pending_order,Digits),Digits));
}
}
// JEŚLI JEST WIĘCEJ NIŻ 1 ZLECENIE OTWARTE :
int order_ticket = 0;
if (OrdersTotal()>2)
{
for(int k=0;k<OrdersTotal();k++)
{ //if(!OrderSelect(k,SELECT_BY_POS)) continue;
if(OrderSelect(k, SELECT_BY_POS)==true)
{order_ticket=OrderTicket();
// PROCEDURA SPRAWDZENIA CZY ISTNIEJE JUŻ PRZECIWSTAWNE ZLECENIE
Print("OrderSelect wybrał zlecenie nr ",order_ticket);
czy_ticket_istnieje(OrderTicket());
} else
Print("OrderSelect failed error code is ",GetLastError());
if(OrderType()==OP_BUY) // jeśli aktualne zlecenie to BUY
{ poziom_wejscia=OrderOpenPrice();
pre_pending_order = poziom_wejscia-(auto_pending_distance*Point);
//OrderSend(Symbol(),OP_SELLSTOP,vol(OrderLots()),pre_pending_order,0,0,0,NULL);
}
if(OrderType()==OP_SELL) // jeśli aktualne zlecenie to SELL
{ poziom_wejscia=OrderOpenPrice();
pre_pending_order = poziom_wejscia+(auto_pending_distance*Point);
//OrderSend(Symbol(),OP_BUYSTOP,vol(OrderLots()),pre_pending_order,0,0,0,NULL);
}
// ZAMYKANIE POZYCJI OCZEKUJĄCYCH, JEŚLI NIE MA INNYCH
if(OrdersTotal()==1 && (OrderType()==OP_BUYSTOP ||
OrderType()==OP_SELLSTOP ||
OrderType()==OP_BUYLIMIT ||
OrderType()==OP_SELLLIMIT))
{ //OrderDelete(OrderTicket());
}
//Print("Pozycja: "+ DoubleToStr(i,0)+" - "+ DoubleToStr(NormalizeDouble(pre_pending_order,Digits),Digits));
}
}
// USUWANIE POZYCJI PRZECIWSTAWNYCH ZE ZŁYM VOLUMENEM W STOSUNKU DO POZYCJI AKTYWNEJ
if (OrdersTotal()>=2)
{
double pos_active_vol, pos_pending_vol;
int pos_active_ticket, pos_pending_ticket;
string koment;
for(int j=0;j<OrdersTotal();j++)
{ if(OrderSelect(j,SELECT_BY_POS)==True);
if(OrderType()==OP_BUY || OrderType()==OP_SELL) {
pos_active_vol=OrderLots();
pos_active_ticket=OrderTicket();
}
if(OrderType()==OP_BUYLIMIT || OrderType()==OP_BUYSTOP || OrderType()==OP_SELLLIMIT || OrderType()==OP_SELLSTOP) {
pos_pending_vol=OrderLots();
pos_pending_ticket=OrderTicket();
koment=OrderComment();
//}
}
Print("Activ VOL: ",pos_active_vol,", Pend VOL: ",pos_pending_vol,", Activ TICKET: ",pos_active_ticket,", Pending TICKET: ",pos_pending_ticket," Komentarz: ",koment);
//}
if((pos_pending_vol != vol(pos_active_vol)))
{
//OrderSelect(pos_pending_ticket,SELECT_BY_TICKET);
OrderDelete(pos_pending_ticket);
OrderPrint();
Print("OrderDelete ostatni error jest: ",GetLastError() + ", A TICKETssss TO: " + DoubleToString(OrderTicket(),0));
}
}
}
return(0);
}
// FUNKCJA WYLICZAJĄCA VOLUMEN DLA POZ. PRZECIWSTAWNEJ (zależnie od aktywnej na rynku)
double vol(double current_v)
{
double vol_multiply;
if(current_v>max_vol)
vol_multiply = NormalizeDouble(2*current_v,2);
else
vol_multiply = NormalizeDouble(current_v+(current_v*oposite_order_volumen)/100,2);
return(vol_multiply);
}
// PROCEDURA SPRAWDZENIA CZY ISTNIEJE JUŻ PRZECIWSTAWNE ZLECENIE
bool czy_ticket_istnieje(string tick)
{
string komentarz = "Kontra do zlecenia ";
StringAdd(komentarz,tick);
for(int m=0;m<OrdersTotal();m++)
{
if(OrderSelect(m,SELECT_BY_POS)==True)
if(OrderComment()==komentarz)
{
Print("Zlecenie istnieje: "+OrderComment()+" z ticketem: "+tick + komentarz );
return(True);
break;
}
else
{ Print("Chyba brak zlecenia - "+komentarz);
return(false);
break;
}
}
if(OrderSelect(tick,SELECT_BY_TICKET)==True)
{Print("Wybrano ticketaaaaaaa: ",tick); }
}