Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools

Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools (http://www.expert-advisor.com/forum/index.php)
-   Programmierung MQL4 (http://www.expert-advisor.com/forum/forumdisplay.php?f=220)
-   -   Lotsize aus festgelegter Reihe - Array? (http://www.expert-advisor.com/forum/showthread.php?t=6025)

dundale 04.03.18 23:40

Lotsize aus festgelegter Reihe - Array?
 
Hallo,

ein Beispiel, ich kaufe den EURUSD bei 1,20, die Lotsize ist 0.03. Die Lotsize des nächsten Trade, egal ob Buy oder Sell, soll 0,12 sein. Die Lotsize soll nicht errechnet werden, sondern aus einer festgelegten Reihe kommen, bspw. einem Array.
Wie setzt man so etwas um, dass ich die Lotsize in einer EnterTrade()-Funktion dann weiterverwenden kann? Ist das Array dafür überhaupt sinnvoll?

Die Beispiel-Reihe könnte folgende Werte haben:
Trade 1: 0.03
Trade 2: 0.12
Trade 3: 0.18
Trade 4: 0.24

Das Thema Array und wie man sie ausliest, ist für mich einfach zu hoch.

Leopold 05.03.18 09:24

Du könntest einen Zähler verwenden, der bei Tradeeröffnung eins nach oben zählt. Und beim letzten wert auf 0 gesetzt wird.

Code:

double Array_LotSize[4];

Array_LotSize[0] = 0.03;
Array_LotSize[1] = 0.12;
Array_LotSize[2] = 0.18;
Array_LotSize[3] = 0.24;

int i = 0; (Zähler)
...
Tradeeröffnung mit LotSize[i] (i = 0)
i++;
....
Traderöffnung mit LotSize[i] (i = 1)
i++;
....

Hoffe das ist verständlich.


--- Leopold ---

next user 05.03.18 11:23

Wenn die Reihe sich immer um +6 fortsetzt, so kann die Zuweisung auch in eine Schleife.
Oder noch besser, gleich einfach eine einzige Variable die man nach jedem Trade entsprechend anhebt...

Leopold 05.03.18 11:35

Zitat:

Zitat von next user (Beitrag 40447)
Oder noch besser, gleich einfach eine einzige Variable die man nach jedem Trade entsprechend anhebt...

Wenn immer um den gleichen Wert erhöht wird ist das sicher die bessere Lösung.

---Leopold---

pascalper 05.03.18 12:16

Persönlich würde ich die Anzahl der offenen Positionen abfragen und die Lots davon abhängig machen, so ist auch eine manuell geöffnete Position (ohne Magic)mit in der Berechnung-wenn das erwünscht ist.

dundale 05.03.18 16:10

Vielen Dank für eure Anregungen. Die Idee mit der Abfrage des TotalOpenOrders-Wertes finde ich gut. Aber ich bekomme die Funktionen trotzdem nicht zusammen.

Ich habe eine fertige Funktion, welche mir die Anzahl der offenen Trades liefert: TotalOpenOrders().

Bitte nicht an die Decke gehen, über die folgende Funktion, die wahrscheinlich kompletter Nonsens ist.

Ich hole mir also den Wert der offenen Orders und versuche hier zu prüfen, ob dieser Wert größer ist als num_LotSize (Positionsnummer im Array), wenn ja wird num_LotSize erhöht, wenn nicht soll der erste Wert im Array verwendet werden.

Code:

double LotSize_Berechnung()
  {
  int num_lotsize=0;
  if(OrdersTotal()>0)
      for(int i=OrdersTotal()-1; i>=0; i--)
      {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
        if(OrderSymbol() == Symbol())
            {
            if(TotalOpenOrders() > num_lotsize)
            num_lotsize++;
            }   
            if(TotalOpenOrders() < num_lotsize)
            num_lotsize=1;
        } 
      }
  return (num_lotsize);
  }

Ich kann die Werte des Arrays nicht mit der Funktion verknüpfen und somit die LotSize nicht weitergeben.

pascalper 05.03.18 16:17

Auf die Schnelle (Fehler garantiert):

double lots=0.01;
if(TotalOpenOrders() = 2 {lots=0.06};
if(TotalOpenOrders() = 3 {lots=0.09};
if(TotalOpenOrders() = 4 {lots=0.12};
usw.

Wozu Array?

dundale 05.03.18 17:20

@pascalper
Du hast recht. Das klappt auf diese Weise super.
Danke.

next user 05.03.18 17:39

Zitat:

Zitat von dundale (Beitrag 40457)
Ich habe eine fertige Funktion, welche mir die Anzahl der offenen Trades liefert: TotalOpenOrders().

Ich nehme mal an, du hast OrdersTotal() nicht übersehen und nutzt TotalOpenOrders(), um die Pendings auszuschließen...

Zitat:

Zitat von dundale (Beitrag 40457)
Ich hole mir also den Wert der offenen Orders und versuche hier zu prüfen, ob dieser Wert größer ist als num_LotSize (Positionsnummer im Array), wenn ja wird num_LotSize erhöht, wenn nicht soll der erste Wert im Array verwendet werden.

Code:

double LotSize_Berechnung()
  {
  int num_lotsize=0;
  if(OrdersTotal()>0)
      for(int i=OrdersTotal()-1; i>=0; i--)
      {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
        if(OrderSymbol() == Symbol())
            {
            if(TotalOpenOrders() > num_lotsize)
            num_lotsize++;
            }   
            if(TotalOpenOrders() < num_lotsize)
            num_lotsize=1;
        } 
      }
  return (num_lotsize);
  }


  • Um die "num_lotsize" mit deiner totalen Orderanzahl (TotalOpenOrders()) zu vergleichen, brauchst du doch nicht
    jede einzelne Order in einer Schleife anzusprechen. Die Orders spielen hier auch überhaupt keine Rolle.
  • Du filterst hier die Orders nach Symbol, vergleichst im nächsten Schritt aber die TotalOpenOrders(), da kann doch was nicht stimmen.
  • Deine Filterung bzgl. Symbol schließt mit ihren Klammern nur den ersten Vergleich ein. Der zweite (if(TotalOpenOrders() < num_lotsize)) wird
    unabhängig vom Symbol behandelt.
  • Ist es wirklich so gewollt, bei geringerer Orderanzahl als "num_lotsize" auf die erste (bzw. wenn Array auf die zweite) Lotgröße zu setzen?
    Nicht das sich da ein (Denk)Fehler eingeschlichen hat.

Zitat:

Zitat von pascalper (Beitrag 40458)
Auf die Schnelle (Fehler garantiert):

double lots=0.01;
if(TotalOpenOrders() = 2 {lots=0.06};
if(TotalOpenOrders() = 3 {lots=0.09};
if(TotalOpenOrders() = 4 {lots=0.12};
usw.

Wozu Array?

Bei so einer Abfrage, wozu if's?
Code:

switch(TotalOpenOrders())
{
  case 1: ... break;
  case 2: ... break;
  ect. ...
}

Dann spart er sich auch doppelte Aufrufe von TotalOpenOrders() ;)

Zitat:

Zitat von pascalper (Beitrag 40458)
...(Fehler garantiert)...

Hab ihn gefunden (die fehlende, schließende Klammer bei den if's mal abgesehen). Zuweisung im Vergleich (nur ein Gleichheitszeichen im if) :D

============================================

@dundale
Wenn ich es richtig gesehen habe, so liefert dir TotalOpenOrders() NUR die aktiven und NICHT auch noch die Pending Orders.
Den Sinn dahinter verstehe ich nicht, aber dann hättest du doch sicherlich OrdersTotal() genutzt, oder?

Du könntest dann einfach einen Zähler beim Öffnen einer Order inkrementieren und diesen, um auch manuelle Trades zu integrieren,
z.B. in der OnTick() mit der aktuellen Anzahl vergleichen. Stimmen sie nicht überein, so anpassen.

Ein Beispiel könnte so aussehen:
Code:

double  lotArray[4] = {0.03, 0.12, 0.18, 0.24};
double  lotSize = lotArray[0];
int      count_lotSize = 0;

// Bei Ordereröffnung einfach die Lots vom Array holen...
OrderSend(...,lotArray[count_lotSize],...);
count_lotSize++;

// In der OnTick()
if(TotalOpenOrders() > count_lotSize)
  // Totale Anzahl größer als count_lotSize. Anpassen...
else if(TotalOpenOrders() < count_lotSize)
  // Totale Anzahl kleiner als count_lotSize...


dundale 05.03.18 20:05

@next user
Die fehlenden Klammern habe ich gefunden. Ich wollte mit TotalOpenOrders() wirklich nur die aktiven Order.

Tausend Dank für den Code mit dem Array.

Ich habe etwas gebraucht, aber erfolgreich in das Script integriert. Bei jedem neuen Trade wird die Lotsize aus dem Array geholt und verwendet.

Einzig habe ich jetzt ein "Array out of range"-Problem. Wie erreiche ich, dass der 5. Trade und alle folgenden die Lotsize Nr. 4 also 0.24 haben. Also den letzten Wert der Reihe?

next user 05.03.18 20:13

Zitat:

Zitat von dundale (Beitrag 40462)
Einzig habe ich jetzt ein "Array out of range"-Problem. Wie erreiche ich, dass der 5. Trade und alle folgenden die Lotsize Nr. 4 also 0.24 haben. Also den letzten Wert der Reihe?

Du vergist aber nicht, den index im Array -1 zu nehmen (also count_lotSize = 1 -->> lotArray[count_lotSize-1]).
Habe ich im Beispielcode vergessen.

Bezüglich den zweiten Teil, einfach eine Beschränkung z.B. so:
Code:

if(count_lotSize > 4)
    ...lotArray[3]...
else
    ...lotArray[count_lotSize-1]...


dundale 05.03.18 21:27

Also irgendwie bekomme ich es nicht hin. Ich habe bestimmt irgendwo ein Denkfehler und stehe dazu noch auf dem Schlauch.

Ich habe mal den Code eingefügt. Es geht ja nur um die Lotsize. Im Test macht er 4 Trades auf und schließt sie wieder. Aber er soll eigentlich 8 Trades eröffnen.

Kannst du bitte noch mal drüber schauen?
Sorry.

Code:

//+------------------------------------------------------------------+
//|                                                    Beispiel.mq4 |
//+------------------------------------------------------------------+
#property strict
#property icon "icon.ico"
#include <stderror.mqh>
#include <stdlib.mqh>

extern double TP                      = 100;
extern double SL                      = 100;
extern double LS                      = 0.02;
extern string MyComment              = "Beispiel";
extern bool  AutoTrade              = true;
double  lotArray[4]  = {0.03, 0.12, 0.18, 0.24};
double  lotSize      = lotArray[0];
int      count_lotSize = 0;
double pips;
//+------------------------------------------------------------------+
//| Expert initialization function                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
// Determine what a pip is.
  pips=Point; //.00001 or .0001. .001 .01.
  if(Digits==3 || Digits==5 || Digits==1) pips*=10;
  else if(Digits==2) pips*=100;
//---
  return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  if(AutoTrade == true)
      CheckForSignal();
     
    if(TotalOpenOrders() > 4)
      {
      lotSize = lotArray[3];
      } 
      else
      {
      lotSize = lotArray[0];
      }
     
  //if(TotalOpenOrders() >= count_lotSize)
  //  {
  //  lotSize = lotArray[0];
  //  }
  }
//+------------------------------------------------------------------+
//| Check for Signal - Signal für automatischen Handel              |
//+------------------------------------------------------------------+
void CheckForSignal()
{
  if(TotalOpenOrders() < 9)
      PlaceOrder(OP_SELL);
}
//+------------------------------------------------------------------+
//| PlaceOrder-Function                                              |
//+------------------------------------------------------------------+
void PlaceOrder(int dir)
  {
      if(dir==OP_BUY)
        {
        int ticket=OrderSend(Symbol(),dir,lotArray[count_lotSize],Ask,30,Ask-(SL*pips),Ask+(TP*pips),MyComment,0,0,clrGreen);
        count_lotSize++;
        }
      if(dir==OP_SELL)
        {
        int ticket=OrderSend(Symbol(),dir,lotArray[count_lotSize],Bid,30,Bid+(SL*pips),Bid-(TP*pips),MyComment,0,0,clrRed);
        count_lotSize++;
        }
}
//+------------------------------------------------------------------+
//| Total of ALL orders place by this expert.                        |
//+------------------------------------------------------------------+
int TotalOpenOrders()
  {
  int total=0;
  if(OrdersTotal()>0)for(int i=OrdersTotal()-1; i>=0; i--)
    {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
        if(OrderSymbol() == Symbol())
            total++;
        } 
      else Print(__FUNCTION__," Failed to select order ",i," ",GetLastError());
    }
  return (total);
  }
//+------------------------------------------------------------------+


next user 05.03.18 22:13

Ich schreib dir morgen früh was dazu.

Würde gern etwas genauer auf deinen Code eingehen und jetzt fehlt aber die Zeit.
Also bis morgen, sofern niemand anderes antwortet ;)

next user 06.03.18 11:21

Zitat:

Zitat von dundale (Beitrag 40465)
Im Test macht er 4 Trades auf und schließt sie wieder. Aber er soll eigentlich 8 Trades eröffnen.

Sehe jetzt auf den ersten Blick nicht, warum er bei dir nur 4 eröffnet. Da wären Ausgaben an entsprechenden Stellen hilfreich.
Habs mal getestet und bei mir eröffnet er 8.

Noch zum Code:
Code:

if(Digits==3 || Digits==5 || Digits==1)
  pips*=10;
else if(Digits==2)
  pips*=100;

vereinfachen wir das mal...
Code:

if(Digits == 2)
  pips *= 100;
else
  pips *= 10;

=================================================

Code:

if(AutoTrade == true)
  CheckForSignal();

if(TotalOpenOrders() > 4)
  lotSize = lotArray[3];
else
  lotSize = lotArray[0];

  • True braucht man nicht auszuschreiben, einfach if(AutoTrade)
  • Es wäre sinnvoller, ERST die LotSize bei evtl. manuell erstellten Orders anzupassen, und DANN erst eine neue Order zu eröffnen.
  • Müsste der untere Teil nicht so aussehen:
    Code:

    if(TotalOpenOrders() > 4)
      lotSize = lotArray[3];
    else
      lotSize = lotArray[count_lotSize-1];

    So wie du es jetzt hast, müssten die ersten 4 Orders bei dir die ERSTE LotSize haben.
    Die -1 am Ende für den richtigen Index (ohne: bei Order 4 -> Index 4 -> Array Out of Range...)
  • Ich hoffe, dein Code im OnTick() ist nur zum testen. So ein ungefiltertes, direktes setzen einer Order bei jedem Tick ist nicht so toll.

=================================================

Code:

void CheckForSignal()
{
  if(TotalOpenOrders() < 9)
      PlaceOrder(OP_SELL);
}

Da du es bei jedem einzelnen Tick ausführst, "überlappen" sich die Orders extrem.
Auch das kann eine Fehlerquelle sein. Wenn der Kurs jetzt um einen Pip nach unten geht, platzierst du eine Order.
Der Kurs geht einen Pip nach oben -> du platzierst eine Order. Was passiert, wenn der Kurs jetzt um einen Pip wieder nach unten geht ???
Wenn man dann noch beachtet, das du nur Sell-Orders erstellst...

=================================================

Code:

void PlaceOrder(int dir)
{
  if(dir==OP_BUY)
  {
      int ticket=OrderSend(Symbol(),dir,lotArray[count_lotSize],Ask,30,Ask-(SL*pips),Ask+(TP*pips),MyComment,0,0,clrGreen);
      count_lotSize++;
  }
 
  if(dir==OP_SELL)
  {
      int ticket=OrderSend(Symbol(),dir,lotArray[count_lotSize],Bid,30,Bid+(SL*pips),Bid-(TP*pips),MyComment,0,0,clrRed);
      count_lotSize++;
  }
}

Zum einen erstellst du hier zwei mal die gleiche Variable (beim Kompilieren müsste er dir "'ticket' - variable already defined" sagen).
Zum anderen ist "ticket" hier sinnlos, da du nichts weiter damit anfängst.

=================================================

Code:

int TotalOpenOrders()
{
  int total=0;
 
  if(OrdersTotal()>0)
  {
      for(int i=OrdersTotal()-1; i>=0; i--)
      {
        if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
            if(OrderSymbol() == Symbol())
              total++;
        } 
        else
            Print(__FUNCTION__," Failed to select order ",i," ",GetLastError());
      }
  }
 
  return (total);
}

Die Funktion ist ja doch anders, als ich vermutet hatte. Da hast du mich aber nicht (wirklich) darauf hingeweisen...
Um nicht so viele Funktionsaufrufe zu haben, könnte man es noch etwas verändern, z.B.:
Code:

// Globale Variablen (im Code global!)
int  totalOrders = 0;
int  sameSymbolOrders = 0;

// Bei Ordereröffnung...
void PlaceOrder(int dir)
{
  int ticket = 0;

  if(dir == OP_BUY)
      ticket = OrderSend(Symbol(),dir,lotArray[count_lotSize],Ask,30,Ask-(SL*pips),Ask+(TP*pips),MyComment,0,0,clrGreen);
  else if(dir == OP_SELL)
      ticket = OrderSend(Symbol(),dir,lotArray[count_lotSize],Bid,30,Bid+(SL*pips),Bid-(TP*pips),MyComment,0,0,clrRed);
     
  if(ticket != -1)
  {
      count_lotSize++;
      sameSymbolOrders++;
      totalOrders++;
  }
}

// In OnTick()...
void OnTick()
{
  if(OrdersTotal() != totalOrders)
      CheckAllOrders();

  if(sameSymbolOrders > 4)
      lotSize = lotArray[3];
  else
      lotSize = lotArray[count_lotSize-1];
     
  if(AutoTrade)
      CheckForSignal();
}

// CheckAllOrders()... (TotalOpenOrders())
void CheckAllOrders()
{
  totalOrders = OrdersTotal();
  int count = 0;
 
  for(int i=totalOrders-1; i>=0; i--)
  {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
        if(OrderSymbol() == Symbol())
            count++;
      } 
      else
        Print(__FUNCTION__," Failed to select order ",i," ",GetLastError());
  }
 
  if(sameSymbolOrders != count)
      sameSymbolOrders = count;
     
  // Wenn manuell erstellte Orders auch zu "count_lotSize" zählen sollen
  // count_lotSize++;
}

So wird die Funktion nur aufgerufen, wenn manuell eine Order erstellt wurde (oder eine gelöscht wurde), und nicht bei jedem Tick erneut.
Außerdem habe ich paar Kleinigkeiten im Code angepasst ("ticket" abgefangen, Code verkleinert, ect...).


Alle Zeitangaben in WEZ +2. Es ist jetzt 22:16 Uhr.

Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.6.1
Powered by vBCMS® 2.7.0 ©2002 - 2024 vbdesigns.de
Copyright ©2009 - 2023 by Expert-Advisor.com - Das Metatrader Forum