Thema: CCalc klasse
Einzelnen Beitrag anzeigen
  #1 (permalink)  
Alt 16.02.22
Aleksi Aleksi ist offline
Neues Mitglied
 
Registriert seit: May 2020
Ort: Duisburg
Beiträge: 28
Aleksi befindet sich auf einem aufstrebenden Ast
Lightbulb CCalc klasse

Immer wieder muss man Preise runden damit es nicht zu Fehlern wie "Invalid Price" oder "Invalid Vloume" kommt. An dieser Stelle hilft die CCalc Klasse

Sie beinhaltet neben den runden der Preise und Volumen auch eine Moneymanagement - Komponente, bei dieser (GetLot) wird das Volumen anhand des SL als double fertig ausgegeben.

Auch kann der aktuelle Start des Tages, der Woche,des Monat oder Jahr abgefragt werden.

Code:
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCalc
  {
private:

   double            roundLots(string symbol,double& lots);

protected:

   double            Getlot(string symbol,double sl,ENUM_ORDER_TYPE PosType,double riskaspercent);
   double            roundUp(string symbol, double price);
   double            roundDn(string symbol, double price);

   datetime          GetDayStart();
   datetime          GetWeekStart();
   datetime          GetMonthStart();
   datetime          GetYearStart();
public:





  };
//+------------------------------------------------------------------+
//| Matrix Zeitraum Tag                                              |
//+------------------------------------------------------------------+
datetime CCalc::GetDayStart()
  {
   datetime MatrixDay;
   string StartDay="00:00:00";
   return MatrixDay=StringToTime(StartDay);
  }
//+------------------------------------------------------------------+
//| Matrix Zeitraum Woche                                            |
//+------------------------------------------------------------------+
datetime CCalc::GetWeekStart()
  {
   MqlDateTime int2;
   TimeToStruct(TimeTradeServer(),int2);
   int dayofWeekServer=int2.day_of_week;
   string StartDay="00:00:00";
   datetime Day=StringToTime(StartDay);

   if(dayofWeekServer==1)
     {
      Day=StringToTime(StartDay);
     }
   else
      if(dayofWeekServer==2)
        {
         Day=StringToTime(StartDay)-86400;
        }
      else
         if(dayofWeekServer==3)
           {
            Day=StringToTime(StartDay)-172800;
           }
         else
            if(dayofWeekServer==4)
              {
               Day=StringToTime(StartDay)-259200;
              }
            else
               if(dayofWeekServer==5)
                 {
                  Day=StringToTime(StartDay)-345600;
                 }
               else
                  if(dayofWeekServer==6)
                    {
                     Day=StringToTime(StartDay)-432000;
                    }
                  else
                     if(dayofWeekServer==0)
                       {
                        Day=StringToTime(StartDay)-518400;
                       }
   return Day;
  }
//+------------------------------------------------------------------+
//| Matrix Zeitraum Monat                                            |
//+------------------------------------------------------------------+
datetime CCalc::GetMonthStart()
  {
   MqlDateTime stm;
   TimeToStruct(TimeTradeServer(),stm);
   stm.day=1;
   stm.hour=0;
   stm.min=0;
   stm.sec=0;
   return(StructToTime(stm));
  }
//+------------------------------------------------------------------+
//| Matrix Zeitraum Jahr                                             |
//+------------------------------------------------------------------+
datetime CCalc::GetYearStart()
  {
   MqlDateTime stm;
   TimeToStruct(TimeTradeServer(),stm);
   stm.day=1;
   stm.mon=1;
   stm.hour=0;
   stm.min=0;
   stm.sec=0;
   return(StructToTime(stm));
  }
//+------------------------------------------------------------------+
//| Ermittlung des Handelsvolumen / OK                               |
//+------------------------------------------------------------------+
double CCalc::Getlot(string symbol,double sl,ENUM_ORDER_TYPE PosType,double riskaspercent)
  {
   double res=0;
   double lot=0;
   double Capitalbase = AccountInfoDouble(ACCOUNT_EQUITY);

   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   if(PosType==ORDER_TYPE_BUY)
     {
      //Umrechnung SL in Pip
      double kurs=SymbolInfoDouble(symbol,SYMBOL_ASK);
      int SLinPoint=(int)NormalizeDouble((kurs-sl)/point,0);

      //Berechnung der Lot
      double risk = MathMin(riskaspercent,100.0)/100;
      lot=Capitalbase*risk*kurs/SLinPoint;
      // Print("risk: ",risk," Cap: ",Capitalbase,"SLinPoint: ",SLinPoint,"Lot: ",lot);
     }

   if(PosType==ORDER_TYPE_SELL)
     {
      //Umrechnung SL in Pip
      double kurs=SymbolInfoDouble(symbol,SYMBOL_BID);
      int SLinPoint=(int)NormalizeDouble((sl-kurs)/point,0);

      //Berechnung der Lot
      double risk = MathMin(riskaspercent,100.0)/100;
      lot=Capitalbase*risk*kurs/SLinPoint;
      //Print("risk: ",risk," Cap: ",Capitalbase,"SLinPoint: ",SLinPoint,"Lot: ",lot);
     }
   res=roundLots(symbol,lot);
//Print("Res: ",res);
   return res;
  }

//+------------------------------------------------------------------+
//| Aufunden des Preises /OK                                         |
//+------------------------------------------------------------------+
double CCalc::roundUp(string symbol, double price)
  {
   int Dig=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
   double Points=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_POINT),Dig);
   double ticksize =
      NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE),Dig);
   price = NormalizeDouble(price,Dig);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,Dig);
   if(rest != 0)
     {
      for(double i = Points; i <= ticksize; i += Points)
        {
         price = NormalizeDouble(price + Points,Dig);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,Dig);
         if(rest == 0)
            break;
        }
     }
   return price;
  }
//+------------------------------------------------------------------+
//| Abunden des Preises /OK                                          |
//+------------------------------------------------------------------+
double CCalc::roundDn(string symbol,double price)
  {
   int Dig=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
   double Points=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_POINT),Dig);
   double ticksize =NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE),Dig);
   price = NormalizeDouble(price,Dig);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,Dig);
   if(rest != 0)
     {
      for(double i = Points; i <= ticksize; i += Points)
        {
         price = NormalizeDouble(price - Points,Dig);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,Dig);
         if(rest == 0)
            break;
        }
     }
   return price;
  }
//+------------------------------------------------------------------+
//| Runden des zuvor klakulierten Handelsvolumen /OK                 |
//+------------------------------------------------------------------+
double CCalc::roundLots(string symbol,double& lots)
  {
   double startLots = lots;
   double lotstep = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP),2);
   lots = NormalizeDouble(lots,2);

   double rest = lots - NormalizeDouble(lots/lotstep,0) * lotstep;
   rest = NormalizeDouble(rest,2);
   if(rest != 0)
     {
      for(double i = 0.01; i <= lotstep; i += 0.01)
        {
         lots = NormalizeDouble(lots + 0.01,2);
         rest = lots - NormalizeDouble(lots/lotstep,0) * lotstep;
         rest = NormalizeDouble(rest,2);
         if(rest == 0)
            break;
        }
     }

   if(lots - startLots > startLots - (lots - lotstep))
     {
      lots -= lotstep;
     }
   lots = MathMin(lots,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX));
   lots = MathMax(lots,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN));
   return lots;
  }
//+------------------------------------------------------------------+
Man kann natürlich auch die funktionen als Public deklarieren... ich habe diese nur Protected weil diese nur in bestimmten Punkten meiner Klassenhirachie verfügbar sein sollen.

Geändert von Aleksi (16.02.22 um 21:08 Uhr)