Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools
Zurück   Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools > Metatrader 5 > Programmierung MQL5

Programmierung MQL5 Hier gehts rund ums Programmieren in MQL5.

Login
Benutzername:
Kennwort:


Statistik
Themen: 4982
Beiträge: 43280
Benutzer: 7.229
Aktive Benutzer: 70
Links: 84
Wir begrüßen unseren neuesten Benutzer: JinjianYu
Mit 2.475 Benutzern waren die meisten Benutzer gleichzeitig online (16.01.20 um 22:38).
Neue Benutzer:
vor einer Woche
- JinjianYu
vor einer Woche
- ben007
vor einer Woche
- sirius 888
vor einer Woche
- BessieGove
vor 2 Wochen
- RoKo

Onlineuser
'Wer ist online' anzeigen Benutzer: 0
Gäste: 353
Gesamt: 353
Team: 0
Team:  
Benutzer:  
Freunde anzeigen

Empfehlungen

Antwort
 
Themen-Optionen Thema durchsuchen Ansicht
  #1 (permalink)  
Alt 04.04.24
Neues Mitglied
 
Registriert seit: Feb 2024
Beiträge: 8
murkel befindet sich auf einem aufstrebenden Ast
Standard Array-Wert trotz fortlaufender Bars "behalten"

Es ist der Klassiker - Außenstab und seine Range vom Hoch zum Tief.

Ich wollte und habe den Code selber geschrieben und mein Vorhaben nahezu komplett gelöst. Nun ist aber doch noch ein kleines, aber entscheidendes Problem aufgetaucht:

Wenn die Range vom Außenstab verlassen wird, soll der EA dies mit einem Print ausweisen und ab da an auch wieder Trades erlauben. Ich habe hierzu einen Array erstellt und fülle diesen Array mit Kursinformationen vom aktuellen Chart an.

Mit open der aktuellen Bar[0] wird der Außenstab Bar[2] ausgewiesen (Bar[1] entsprechend als Innenstab). Das klappt soweit alles.

Nun soll der EA wie oben erwähnt bei verlassen der Range vom Außenstab dies mitteilen und den Handel wieder erlauben. Das funktioniert ebenfalls, aber nur, wenn die Range mit der Bar[0], die den Außenstab deklariert hat, geschieht. Erfolgt der Range-Ausbruch ein oder mehrere Kerzen später, passiert nichts.

Ich vermute, dass der Fehler darin liegt, dass ich zwar die Bar[2] auslese und die Werte eine Variablen zuordne, doch beim öffnen der nächsten Bar passen die werte nicht mehr. Anders ausgedrückt: die Werte werden nur verwendet, solange es keine neue Bar gibt.

Kann man die Werte aus dem Array irgendwie fixieren, dass sie dauerhaft bleiben - zumindest bis sie getriggert werden?

Hier der Code dazu (der Code dient lediglich zu Lernzwecken und stellt keine Strategie dar):

--> es geht vermutlich hauptsächlich um die Bereiche
calcSetup()
calcOutsideBarRange()

Code:
//+------------------------------------------------------------------+
//|                                            lern- und test-EA.mq5 |
//|                                         Copyright 2024, Anfänger |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Anfänger"
#property version   "1.10"

#include       <Trade/Trade.mqh>

enum ENUM_LOT  {LOT_FIX,LOT_AMOUNT,LOT_PERCENT};
enum ENUM_SL   {SL_FIX,SL_CANDLE};

input group    "SIGNAL"
input string   TimeRangeStart          = "11:02";
input string   TimeRangeEnd            = "11:12";

input group    "RISIKO"
input ENUM_LOT Lotcalculation          = LOT_AMOUNT;
input double   RiskInLots              = 0.2;
input double   RiskInAmount            = 10.00;
input double   RiskInPercent           = 0.25;

input group    "HANDEL"
input ENUM_SL  SlVariable              = SL_CANDLE;
input uint     SlInitial               = 1500;
input uint     TpInitial               = 3000;

input group    "DIVERS"
input uint     SymbolBuffer            = 100;
input ulong    Magic                   = 202403271656;

CTrade         trade;
ulong          buyTicket;
ulong          sellTicket;
double         high1;
double         low1;
static double  outsideBarHigh;
static double  outsideBarLow;
bool           outsideBar;
bool           outsideBarRange;
bool           noSignal;
bool           longSignal;
bool           shortSignal;
datetime       timeRangeStart;
datetime       timeRangeEnd;
datetime       timeSignal;


int OnInit(){
   static bool isInit = false;
   if(!isInit){
      isInit = true;
      Print(__FUNCTION__," > EA (re)start");
   }
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){
   
}

void OnTick(){
   //---TimeRange
   if(timeRangeStart != StringToTime(TimeRangeStart)){
      calcTimes();
   }
   
   //---Signal
   if(TimeCurrent() >= timeRangeStart && TimeCurrent() < timeRangeEnd){
      timeSignal = iTime(_Symbol,PERIOD_CURRENT,0);
      static datetime timestapSignal;
      if(timestapSignal != timeSignal){
         timestapSignal = timeSignal;
         calcSetup();
      }
   }
   
   //---Range Outsidebar
   if(outsideBar == true){
      calcOutsideBarRange();
   }
   
   //---Order
   if(longSignal == true){
      executeBuy();
   }
   longSignal = false;
   
   if(shortSignal == true){
      executeSell();
   }
   shortSignal = false;
   
   //---Close Order
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(OrderSelect(buyTicket) && bid <= OrderGetDouble(ORDER_SL)){
      closeOrder();
   }
   if(OrderSelect(sellTicket) && bid >= OrderGetDouble(ORDER_SL)){
      closeOrder();
   }
}

void calcTimes(){
   timeRangeStart = StringToTime(TimeRangeStart);
   timeRangeEnd   = StringToTime(TimeRangeEnd);
}

void calcSetup(){
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   // Array erstellen
   MqlRates priceInformation[];
   
   // Abwärts sortieren
   ArraySetAsSeries(priceInformation,true);
   
   // Preisdaten in das Array kopieren
   int Data = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),priceInformation);
     
   // Outsidebar[2] prüfen
   if(priceInformation[2].high >= priceInformation[1].high && priceInformation[2].low <= priceInformation[1].low){
      outsideBar = true;
      outsideBarHigh = priceInformation[2].high;
      outsideBarLow  = priceInformation[2].low;
      Print(priceInformation[2].time," no signal - outsideBar (H ",outsideBarHigh,"; L ",outsideBarLow,")");
      Print(priceInformation[1].time," no signal - insideBar");
   }else outsideBar = false;
      
   //---Candle 1
   double open1       = iOpen(_Symbol,PERIOD_CURRENT,1);
          high1       = iHigh(_Symbol,PERIOD_CURRENT,1);
          low1        = iLow(_Symbol,PERIOD_CURRENT,1);
   double close1      = iClose(_Symbol,PERIOD_CURRENT,1);
   
   //---Candle 2
   double open2       = iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2       = iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2        = iLow(_Symbol,PERIOD_CURRENT,2);
   double close2      = iClose(_Symbol,PERIOD_CURRENT,2);
   
   //---No Signal
   bool higherLowerBar = (high1 > high2 && low1 < low2);
   bool doji          = (open1 == close1);
   
   if(higherLowerBar == true){
      noSignal = true;
         if(outsideBar == true){
            Print(priceInformation[1].time," no signal (H/L-Bar) - inside an outsideBar ");
         }else Print(priceInformation[1].time," no signal - higherLowerBar ");
      return;
   }
   if(doji == true){
      noSignal = true;
         if(outsideBar == true){
            Print(priceInformation[1].time," no signal (doji) - inside an outsideBar ");
         }else Print(priceInformation[1].time," no signal - doji ");
      return;
   }
   
   //---Long Signal
   bool lowerLow      = (low1 < low2 && high1 <= high2);
   
   if(lowerLow == true){
      if(outsideBarRange == true){
         Print(priceInformation[1].time," no long signal - inside an outsideBarRange ");
      }else if(outsideBarRange == false){
         longSignal = true;
         Print(priceInformation[1].time," !!! LONG SIGNAL");
      }
   }
   
   //---Short Signal
   bool higherHigh    = (high1 > high2 && low1 >= low2);
   
   if(higherHigh == true){
      if(outsideBarRange == true){
         Print(priceInformation[1].time," no short signal - inside an outsideBarRange ");
      }else if(outsideBarRange == false){
         shortSignal = true;
         Print(priceInformation[1].time," !!! SHORT SIGNAL");
      }
   }
}

void calcOutsideBarRange(){
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(bid <= outsideBarHigh && bid >= outsideBarLow){
      outsideBarRange = true;
   }else if(bid > outsideBarHigh || bid < outsideBarLow){
      outsideBarRange = false;
      outsideBar =false;
      Print("  left OutsideBarRange");
   }
}

void executeBuy(){
   double ask   = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid   = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double spread = roundUp(ask - bid);
   double sl = 0;
   
   double entry = roundUp(high1 + spread + SymbolBuffer * _Point);
   if(SlVariable == SL_FIX){
          sl    = entry - SlInitial * _Point;
   }else  sl    = roundUp(low1 - SymbolBuffer * _Point);
   double tp    = roundUp(entry + TpInitial * _Point);
   Print("  Long: entry ",entry," (spread ",spread,"), sl ",sl,", tp ",tp);
   
   double lots  = calclots(entry - sl);
   double price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(price < entry){  
      if(trade.BuyStop(lots,entry,_Symbol,sl,tp,0,0)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            buyTicket = trade.ResultOrder();
            Print("  --> Buy-Stop-Order #",buyTicket," was sent");
         }
      }
   }
   if(price >= entry){
      if(trade.Buy(lots,_Symbol,entry,sl,tp)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            buyTicket = trade.ResultOrder();
            Print("  --> Buy-Market-Order #",buyTicket," was sent");
         }
      }
   }
}

void executeSell(){
   double ask   = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid   = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double spread = roundUp(ask - bid);
   double sl = 0;
   
   double entry = roundDn(low1 - SymbolBuffer * _Point);
   if(SlVariable == SL_FIX){
          sl    = entry + SlInitial * _Point;
   }else  sl    = roundDn(high1 + spread + SymbolBuffer * _Point);
   double tp    = roundDn(entry - TpInitial * _Point);
   Print("  Short: entry ",entry,", sl ",sl," (spread ",spread,"), tp ",tp);
   
   double lots  = calclots(sl - entry);
   double price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(price > entry){  
      if(trade.SellStop(lots,entry,_Symbol,sl,tp,0,0)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            sellTicket = trade.ResultOrder();
            Print("  --> Sell-Stop-Order #",sellTicket," was sent");
         }
      }
   }
   if(price <= entry){
      if(trade.Sell(lots,_Symbol,entry,sl,tp)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            sellTicket = trade.ResultOrder();
            Print("  --> Sell-Market-Order #",sellTicket," was sent");
         }
      }
   }
}

void closeOrder(){
   for(int i = OrdersTotal()-1; i >= 0; i--){
      buyTicket = OrderGetTicket(i);
      if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue;
      if(OrderSelect(buyTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){
         if(trade.OrderDelete(buyTicket)){
            Print("  -x-> Buy-Stop-Order #",buyTicket," gelöscht da SL erreicht");
         }
      }
   }
   for(int i = OrdersTotal()-1; i >= 0; i--){
      sellTicket = OrderGetTicket(i);
      if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue;
      if(OrderSelect(sellTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP){
         if(trade.OrderDelete(sellTicket)){
            Print("  -x-> Sell-Stop-Order #",sellTicket," gelöscht da SL erreicht");
         }
      }
   }
}

double roundUp(double price){
   double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits);
   price = NormalizeDouble(price,_Digits);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,_Digits);
   if(rest != 0){
      for (double i = _Point; i <= ticksize; i += _Point){
         price = NormalizeDouble(price + _Point,_Digits);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,_Digits);
         if(rest == 0) break;
      }
   }
   return price;
}

double roundDn(double price){
   double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits);
   price = NormalizeDouble(price,_Digits);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,_Digits);
   if(rest != 0){
      for (double i = _Point; i <= ticksize; i += _Point){
         price = NormalizeDouble(price - _Point,_Digits);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,_Digits);
         if(rest == 0) break;
      }
   }
   return price;
}

double calclots(double slPoints){ // slPoints = Strecke (entry - sl; sl - entry)
   double lots = 0;
   double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   double tickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   double lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;

   if(Lotcalculation == LOT_FIX){
      lots = NormalizeDouble(RiskInLots,_Digits);
      Print("  Fixe Lotsize: ",lots," lots");
   }
   if(Lotcalculation == LOT_AMOUNT){
      lots = NormalizeDouble(MathFloor(RiskInAmount / moneyPerLotstep) * lotstep,_Digits);
      Print("  Lotsize berechnet über Betrag: ",lots," lots");
   }
   if(Lotcalculation == LOT_PERCENT){  // ACCOUNT_EQUITY = inkl. offene Positionen; ACCOUNT_BALANCE = ohne offene Positionen
      double riskPerTrade = AccountInfoDouble(ACCOUNT_EQUITY) * RiskInPercent / 100;
      lots = NormalizeDouble(MathFloor(riskPerTrade / moneyPerLotstep) * lotstep,_Digits);
      Print("  Lotsize prozentual berechnet: ",lots," lots");
   }
   lots = MathMin(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX));
   lots = MathMax(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN));
   return lots;
}
Vorab schon mal vielen Dank für die Tipps und Hinweise. :-)
Mit Zitat antworten
  #2 (permalink)  
Alt 05.04.24
Neues Mitglied
 
Registriert seit: Feb 2024
Beiträge: 8
murkel befindet sich auf einem aufstrebenden Ast
Standard

Evtl. wird mein Problem anhand von folgendem Beispiel deutlicher:



In obigem Bild (Grafik) wird mit open Kerze C die Kerze A als outsidebar deklariert. Da noch innerhalb der Kerze C der Kurs das High der outsidebar verlässt, wird dies im Journal um 11:02:28 Uhr auch korrekt wiedergegeben:



Mit open der Kerze 3 wird Kerze 1 als outsidebar deklariert. Hier verlässt der Kurs die Range der outsidebar erst mit Kerze 5 (11:08 Uhr) - und im Journal wird nichts ausgewiesen:



Das Ziel war, dass auch in diesem Beispiel irgendwann innerhalb der Minutenkerze um 11:08 Uhr die Meldung "left OutsideBarRange" kommt. Was aber nicht passiert.

... sorry, merke eben, dass ich nicht fähig bin, Bilder direkt zwischen den Text zu integrieren - obwohl ich [IMG] vor der URL und [/IMG] danach geschrieben habe ...
Angehängte Grafiken
Dateityp: png Chart.png (6,2 KB, 2x aufgerufen)
Dateityp: png Journal1.png (5,6 KB, 1x aufgerufen)
Dateityp: png Journal2.png (16,1 KB, 1x aufgerufen)
Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are aus
Pingbacks are aus
Refbacks are aus




Alle Zeitangaben in WEZ +2. Es ist jetzt 00:47 Uhr.





Suchmaschine - Reisen - Wavesnode - Facebook Forum - Spam Firewall
-----------------------------------------------------------------------------------------------------------------------------
Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Powered by vBCMS® 2.7.0 ©2002 - 2024 vbdesigns.de
SEO by vBSEO 3.6.1
Copyright ©2009 - 2023 by Expert-Advisor.com - Das Metatrader Forum
MetaTrader bzw. MetaTrader 4 und MetaTrader 5 sind eingetragene Marken der MetaQuotes Software Corp.
-----------------------------------------------------------------------------------------------------------------------------