Wszystkie pytania dozwolone początkujących programistów

O jezykach programowania w platformach i nie tylko.
fievral
Stały bywalec
Stały bywalec
Posty: 28
Rejestracja: 17 maja 2011, 23:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: fievral »

Witam, w kwestii programowania to jest mój pierwszy post. Na razie zaczynam pisać jakieś bardzo proste rzeczy, żeby po prostu uczyć się i pisać, chciałem napisać banalny program, który będzie otwierał zlecenie kupna jeżeli poprzednia świeca była wzrostowa, sprzedawał kiedy poprzednia będzie spadkowa i tak przy starcie każdej godziny. Jednakże chciałem, żeby aktualnie było otwarte nie więcej niż dwie pozycje na raz i tu mam problem bo nie wiem jak to zrobić. Myślałem żeby zrobić to przy pomocy funkcji OrderTotal(), ale przy jednym zleceniu aktywnym działa a przy dwóch nie działa nie wiem. Jedyne moje jakieś podejrzenie, to to że powinienem użyć pętli ale też nie wiem za bardzo jak. Proszę o pomoc.


kod:

Kod: Zaznacz cały

#property copyright "Adrian"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern int     StartHour   = 0;
extern int     EndHour     = 20;
extern double  Lots        = 0.5;
extern double  StopLoss    = 40;
extern double  TakeProfit  = 40;


void OnTick()
{
   
   static bool IsFirstTick= true;
   static int  ticket= 0;
   double O1= Open[1];                          // cena otwarcia świecy
   double C1= Close[1];                         // cena zamknięcia świecy
   
  // if (Hour()>= StartHour&& Hour()<=EndHour)
  // {
      int Order=OrdersTotal();
       
    
      if(Order<=1)
      {
         if (IsFirstTick==true)
         {
            IsFirstTick= false;
         
            if (C1>O1)
            {
               ticket= OrderSend(Symbol(),OP_BUY,Lots,Ask,10*10,Bid-StopLoss*Point*10, Bid+TakeProfit*Point*10);
               if( ticket<0)
               {
                  Alert( " Błąd wysyłania zlecenia");
               }
            }
            else if (C1<O1)
            {
               ticket= OrderSend(Symbol(),OP_SELL,Lots,Bid,10*10,Ask+StopLoss*Point*10,Ask-TakeProfit*Point*10);
               if ( ticket<0)
               {
                  Alert( "Błąd wysyłania zlecenia");
               }
            }
        
         }
      }
     
      else
      {
         IsFirstTick= true;
      } 
}
//+------------------------------------------------------------------+

rookie2
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 29 wrz 2020, 00:10

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: rookie2 »

fievral pisze:
14 mar 2022, 20:56
Witam, w kwestii programowania to jest mój pierwszy post. Na razie zaczynam pisać jakieś bardzo proste rzeczy, żeby po prostu uczyć się i pisać, chciałem napisać banalny program, który będzie otwierał zlecenie kupna jeżeli poprzednia świeca była wzrostowa, sprzedawał kiedy poprzednia będzie spadkowa i tak przy starcie każdej godziny. Jednakże chciałem, żeby aktualnie było otwarte nie więcej niż dwie pozycje na raz i tu mam problem bo nie wiem jak to zrobić. Myślałem żeby zrobić to przy pomocy funkcji OrderTotal(), ale przy jednym zleceniu aktywnym działa a przy dwóch nie działa nie wiem. Jedyne moje jakieś podejrzenie, to to że powinienem użyć pętli ale też nie wiem za bardzo jak. Proszę o pomoc.


kod:

Kod: Zaznacz cały

#property copyright "Adrian"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern int     StartHour   = 0;
extern int     EndHour     = 20;
extern double  Lots        = 0.5;
extern double  StopLoss    = 40;
extern double  TakeProfit  = 40;


void OnTick()
{
   
   static bool IsFirstTick= true;
   static int  ticket= 0;
   double O1= Open[1];                          // cena otwarcia świecy
   double C1= Close[1];                         // cena zamknięcia świecy
   
  // if (Hour()>= StartHour&& Hour()<=EndHour)
  // {
      int Order=OrdersTotal();
       
    
      if(Order<=1)
      {
         if (IsFirstTick==true)
         {
            IsFirstTick= false;
         
            if (C1>O1)
            {
               ticket= OrderSend(Symbol(),OP_BUY,Lots,Ask,10*10,Bid-StopLoss*Point*10, Bid+TakeProfit*Point*10);
               if( ticket<0)
               {
                  Alert( " Błąd wysyłania zlecenia");
               }
            }
            else if (C1<O1)
            {
               ticket= OrderSend(Symbol(),OP_SELL,Lots,Bid,10*10,Ask+StopLoss*Point*10,Ask-TakeProfit*Point*10);
               if ( ticket<0)
               {
                  Alert( "Błąd wysyłania zlecenia");
               }
            }
        
         }
      }
     
      else
      {
         IsFirstTick= true;
      } 
}
//+------------------------------------------------------------------+
1. Ponieważ gdy wchodzi do tej funkcji OnTick, czyli robi pierwszy obrót pętli (pobranie ticków),
2. następnie sprawdza warunek if(Order<=1) następnie kolejny warunek if (IsFirstTick==true)
3. następnie jest ustawienie zmiennej globalnej IsFirstTick na false i przy kolejnym wykonaniu pętli przez onTick jest sprawdzeniu warunków z pkt 2 gdzie masz już ustawione IsFirstTick na false na zmiennej globalej, bo przy pierwszy obrocie pętli, przy pierwszym sprawdzeniu masz warunek <= (mniejsze lub równe), więc wystarczy że będzie 1 pozycja otwarta, i już warunek jest prawdziwy. Więc przechodzi do kolejnej części kodu. I tam już masz ustawione na false, gdzie jest warunek sprawdzający czy if (IsFirstTick==true)/ dlatego dalej nie przechodzi do wykonywania kolejnych instrukcji w ciele tej instrukcji warunkowej, ponieważ jest tam teraz wartość false. Gdy kolejny raz sprawdza ten warunek.

Może wywal te warunki isFirstTick, tylko ustaw tak jak dobrze kombinujesz OrdersTotal() <= 2

Kod: Zaznacz cały

#property copyright "Adrian"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern int     StartHour   = 0;
extern int     EndHour     = 20;
extern double  Lots        = 0.5;
extern double  StopLoss    = 40;
extern double  TakeProfit  = 40;


void OnTick()
{
   
   static bool IsFirstTick= true;
   static int  ticket= 0;
   double O1= Open[1];                          // cena otwarcia świecy
   double C1= Close[1];                         // cena zamknięcia świecy
   
  // if (Hour()>= StartHour&& Hour()<=EndHour)
  // {
      int Order=OrdersTotal();
       
    
      if(Order<=2)
      {
     
            if (C1>O1)
            {
               ticket= OrderSend(Symbol(),OP_BUY,Lots,Ask,10*10,Bid-StopLoss*Point*10, Bid+TakeProfit*Point*10);
               if( ticket<0)
               {
                  Alert( " Błąd wysyłania zlecenia");
               }
            }
            else if (C1<O1)
            {
               ticket= OrderSend(Symbol(),OP_SELL,Lots,Bid,10*10,Ask+StopLoss*Point*10,Ask-TakeProfit*Point*10);
               if ( ticket<0)
               {
                  Alert( "Błąd wysyłania zlecenia");
               }
            }
        
      }
     
 
}
//+------------------------------------------------------------------+
Można to na inne sposoby robić, np ustawić globalną zmienną int counter = 0 i wewnątrz warunku gdzie otwierasz zlecenie zwiększać ten licznik (inkrementować) czyli robić counter++. I wtedy sprawdzasz przed wejściem do tej inkrementacji czy licznik nie jest większy od 2 na przykład. W sumie to samo co OrdersTotal()...
https://www.myfxbook.com/members/rookie_t/pycha-kroczy-przed-upadkiem/7931743

fievral
Stały bywalec
Stały bywalec
Posty: 28
Rejestracja: 17 maja 2011, 23:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: fievral »

Super, rozumiem teraz o co chodzi :D , wielkie dzięki rookie2 za wyjaśnienia bo sam bym nad tym siedział nie wiadomo ile.

rookie2
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 29 wrz 2020, 00:10

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: rookie2 »

fievral pisze:
14 mar 2022, 21:29
Super, rozumiem teraz o co chodzi :D , wielkie dzięki rookie2 za wyjaśnienia bo sam bym nad tym siedział nie wiadomo ile.
Trochę chaotycznie to opisałem, ale chyba dojdziesz o co mi chodzi jak spojrzysz na kod i przejdziesz po kolejnych liniach tego kodu. Powinieneś zacząć od jakiegoś języka z intuicyjnym debugerem. Żeby sobie krokowo sprawdzać wykonanie kodu. I tak się uczyć jak wykonuje się kod instrukcja po instrukcji. mql to w c++. Dla c++ i c jest m.in. gdb. Tutaj jest widzę nawet online kompilator c++ i debuger gdb :)
https://www.onlinegdb.com/
https://www.youtube.com/watch?v=bWH-nL7v5F4

btw. int3, to breakpoint https://en.wikipedia.org/wiki/INT_(x86_instruction)

Kod: Zaznacz cały

/******************************************************************************

Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.

*******************************************************************************/
#include <iostream>

using namespace std;

int main()
{
    //cout<<"Hello World";
    
    asm("int3");

    return 0;
}
lista podstawowych instrukcji http://polishlinux.wikidot.com/gdb:komendy

Czyli jak wkleisz ten kod do tego komilatora online, i uruchomisz nie Run, z menu u góry tylko drugi guzik czyli Debug, następnie wpiszesz komendę "run" to program zatrzyma się na pierwszej instrukcji asm(int3)/ Gdybyś w pętli umieścił to asm(int3) to po każdym continue by się zatrzymywał na tym. I tym debugerem i krokowym wykonaniem sprawdzisz jak zachowują się instrukcje warunkowe itd. Alb zainstaluj Visual Studio https://visualstudio.microsoft.com/pl/
gbdonline.png
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
https://www.myfxbook.com/members/rookie_t/pycha-kroczy-przed-upadkiem/7931743

Awatar użytkownika
ninjaproject
Maniak
Maniak
Posty: 4944
Rejestracja: 30 lip 2019, 13:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: ninjaproject »

Może łatwiej tak, co?
Funkcja IsNewBar() pozwala włożyć całość kodu wykonalnego w warunek if(IsNewBar()) { } i twedy będzie wykonywać tylko raz przy każdym nowym słupku/świecy.

Kod: Zaznacz cały


//+------------------------------------------------------------------+
bool IsNewBar()
{ 
  static datetime Trend_Candle_prevTime1 = -1;
  
  if(Trend_Candle_prevTime1 != Time[6])
  { 
   Trend_Candle_prevTime1 = Time[6]; 
       
   return(true);  
  } 

  return(false); 
}
//+------------------------------------------------------------------+
Można to też przerobić na konkretny Tf stosując iTime() w miejsce Time[].

Funkcja OpenTradesForPair(int iType) policzy ile jest otwartych pozycji podanego rodzaju dla danego instrumentu.
Tak samo, użyta w warunku np. if(OpenTradesForPair(OP_BUY)==2) { } .

Kod: Zaznacz cały


//+------------------------------------------------------------------+
int OpenTradesForPair(int iType)
{
int icnt, itotal, retval;

retval=0;
itotal=OrdersTotal();

   for(icnt=0;icnt<itotal;icnt++) // for loop
     {
      if(OrderSelect(icnt, SELECT_BY_POS, MODE_TRADES))
       {
       // check for opened position, symbol & Magic_Number
       if (OrderSymbol()==_Symbol&&OrderMagicNumber()==Magic_Number)
        {
              if(OrderType()==iType) retval++;      
        } 
        }
     } // for loop

return(retval);
}
//+------------------------------------------------------------------+
Trejder, Mentor/trener, aka. Dadas, fx-technik, obecnie ninjaproject.
Programuję wskaźniki i EA do MetaTrader 4/5.

fievral
Stały bywalec
Stały bywalec
Posty: 28
Rejestracja: 17 maja 2011, 23:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: fievral »

Co Ty ja zrozumiałem, więc musi być zrozumiale :d . W ogóle to próbował coś ze static robić ale mi nie wychodziło. Ogólnie kiedyś trochę c++ się uczyłem (ale to takie podstawy podstaw) przed próbami z mql, a teraz po długiej przerwie próbuje na nowo i widzę, że mało co pamiętam i chyba słusznie tak jak piszesz muszę sobie to poodświeżać startując od c++.
rookie2 pisze:
14 mar 2022, 21:46
fievral pisze:
14 mar 2022, 21:29
Super, rozumiem teraz o co chodzi :D , wielkie dzięki rookie2 za wyjaśnienia bo sam bym nad tym siedział nie wiadomo ile.
Trochę chaotycznie to opisałem, ale chyba dojdziesz o co mi chodzi jak spojrzysz na kod i przejdziesz po kolejnych liniach tego kodu. Powinieneś zacząć od jakiegoś języka z intuicyjnym debugerem. Żeby sobie krokowo sprawdzać wykonanie kodu. I tak się uczyć jak wykonuje się kod instrukcja po instrukcji. mql to w c++. Dla c++ i c jest m.in. gdb. Tutaj jest widzę nawet online kompilator c++ i debuger gdb :)
https://www.onlinegdb.com/
https://www.youtube.com/watch?v=bWH-nL7v5F4

btw. int3, to breakpoint https://en.wikipedia.org/wiki/INT_(x86_instruction)

fievral
Stały bywalec
Stały bywalec
Posty: 28
Rejestracja: 17 maja 2011, 23:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: fievral »

Dzięki wielkie, bo nawet nie wiedziałem o tej funkcji, a właśnie czegoś takiego też szukałem po forum tyle, że po omacku to nic mi się nie udało :D .
ninjaproject pisze:
14 mar 2022, 22:13
Może łatwiej tak, co?
Funkcja IsNewBar() pozwala włożyć całość kodu wykonalnego w warunek if(IsNewBar()) { } i twedy będzie wykonywać tylko raz przy każdym nowym słupku/świecy.

Kod: Zaznacz cały


//+------------------------------------------------------------------+
bool IsNewBar()
{ 
  static datetime Trend_Candle_prevTime1 = -1;
  
  if(Trend_Candle_prevTime1 != Time[6])
  { 
   Trend_Candle_prevTime1 = Time[6]; 
       
   return(true);  
  } 

  return(false); 
}
//+------------------------------------------------------------------+
Można to też przerobić na konkretny Tf stosując iTime() w miejsce Time[].

Funkcja OpenTradesForPair(int iType) policzy ile jest otwartych pozycji podanego rodzaju dla danego instrumentu.
Tak samo, użyta w warunku np. if(OpenTradesForPair(OP_BUY)==2) { } .

Kod: Zaznacz cały


//+------------------------------------------------------------------+
int OpenTradesForPair(int iType)
{
int icnt, itotal, retval;

retval=0;
itotal=OrdersTotal();

   for(icnt=0;icnt<itotal;icnt++) // for loop
     {
      if(OrderSelect(icnt, SELECT_BY_POS, MODE_TRADES))
       {
       // check for opened position, symbol & Magic_Number
       if (OrderSymbol()==_Symbol&&OrderMagicNumber()==Magic_Number)
        {
              if(OrderType()==iType) retval++;      
        } 
        }
     } // for loop

return(retval);
}
//+------------------------------------------------------------------+

Szymon_P
Stały bywalec
Stały bywalec
Posty: 60
Rejestracja: 31 paź 2015, 22:35

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: Szymon_P »

Witam,
Czy jest możliwość ustawienia zmiennej(najlepiej bool), aby podczas wystąpienia na jednym instrumencie zadziałała także na innych, gdzie jest taka sama nazwa EA, ale inny magic number? Jeśli wystąpi dana zależność na jednym walorze to wykona zadanie na pozostałych walorach, gdzie EA o danej nazwie jest uruchomiony.
Przykład:
bool F1==false,F2==false; - dla wszystkich EA
Robot „XXX” (MagicNumber 1) ; F1==false;
Robot „XXX” (MagicNumber 2) ; F1==false;
Robot „XXX” (MagicNumber 3) ; F1==false;
Robot „XXX” (MagicNumber 4) ; F1==false;
Robot „XXX” (MagicNumber 5) ; F1==false;
W każdym EA miałbym warunek
If(F1==true) – obojętne dla którego EA o tej samej nazwie
{F2=true;} – we wszystkich EA o tej samej nazwie
następnie
If(F2==true)
{zrób coś tam;}

Awatar użytkownika
ninjaproject
Maniak
Maniak
Posty: 4944
Rejestracja: 30 lip 2019, 13:15

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: ninjaproject »

Szymon_P pisze:
06 kwie 2022, 18:33
Witam,
Czy jest możliwość ustawienia zmiennej(najlepiej bool), aby podczas wystąpienia na jednym instrumencie zadziałała także na innych, gdzie jest taka sama nazwa EA, ale inny magic number? Jeśli wystąpi dana zależność na jednym walorze to wykona zadanie na pozostałych walorach, gdzie EA o danej nazwie jest uruchomiony.
Przykład:
bool F1==false,F2==false; - dla wszystkich EA
Robot „XXX” (MagicNumber 1) ; F1==false;
Robot „XXX” (MagicNumber 2) ; F1==false;
Robot „XXX” (MagicNumber 3) ; F1==false;
Robot „XXX” (MagicNumber 4) ; F1==false;
Robot „XXX” (MagicNumber 5) ; F1==false;
W każdym EA miałbym warunek
If(F1==true) – obojętne dla którego EA o tej samej nazwie
{F2=true;} – we wszystkich EA o tej samej nazwie
następnie
If(F2==true)
{zrób coś tam;}
Tak, zapisać zmienną za pomocą: https://docs.mql4.com/globals/globalvariableset
Sprawdzić zmienną za pomocą: https://docs.mql4.com/globals/globalvariablecheck
Odczytać za pomocą: https://docs.mql4.com/globals/globalvariableget
No i pamiętać o usuwaniu: https://docs.mql4.com/globals/globalvariabledel

Tyle, że te zmienne zawsze mają charakter double, więc łatwiej dać F1=0; dla false i F1=1; dla true, na przykład.
Trejder, Mentor/trener, aka. Dadas, fx-technik, obecnie ninjaproject.
Programuję wskaźniki i EA do MetaTrader 4/5.

Mistyfikator
Pasjonat
Pasjonat
Posty: 932
Rejestracja: 05 lip 2021, 20:35

Re: Wszystkie pytania dozwolone początkujących programistów

Nieprzeczytany post autor: Mistyfikator »

Dlaczego wyświetla się komunikat "Zły TP i SL"?

Kod: Zaznacz cały


    if(Ask>SMAm1&&Ask>SMAm5&&Ask>SMAm15&&Ask>SMAm30&&Ask>SMAH1) { OrderSend(NULL,0,Ile,Ask,2.00,Tnij,Bierz,NULL,0,0,clrNONE);} 
    if(Bid<SMAm1&&Bid<SMAm5&&Bid<SMAm15&&Bid<SMAm30&&Bid<SMAH1) { OrderSend(NULL,1,Ile,Bid,2.00,Tnij,Bierz,NULL,0,0,clrNONE);} 
    
     
Dodam, że zmienne Tnij i Bierz mam zadeklarowane w inputs double, poza void, pod property.
Czy chodzi o to, żeby tą deklarowaną wartość dodatkowo odjąć/dodać od ceny otwarcia? Czy MQL4 sam to robi?

A może trzeba zadeklarować _Digits? Ja zrozumiałem, że jest to predefiniowalne...

Jak w takiej sytuacji deklaruje się SL? Bo widzę, że to jeden z argumentów OrderSend?
Czy służy do tego OrderStopLoss?

Będę potrzebował zapisać coś w tym stylu:

1. if ASK >= Ask + X, wtedy SL = OpenPrice+Y
2. if SL >= OpenPrice, wtedy OrderSend(NULL,0,Ile,Ask,2.00,Tnij,Bierz,NULL,0,0,clrNONE)


W ogóle jestem początkujący i tutaj pojawia się kolejne pytanie:

Strategia będzie umożliwiała otwarcie więcej niż jednej pozycji (coś w stylu piramidowania), czy w tej sytuacji konieczna jest identyfikacja każdej kolejnej pozycji przy pomocy jakiegoś Ticket, czy Magic Number?

Czy można to po prostu pominąć, jeśli parametry SL będą identyczne dla wszystkich otwartych pozycji (w zasadzie wszystkie parametry poza ceną otwarcia?)
Ostatnio zmieniony 27 kwie 2022, 14:50 przez Mistyfikator, łącznie zmieniany 1 raz.

ODPOWIEDZ