Gespräche über die PLO in der Lounge - Seite 4

 
Dennis Kirichenko:

Gutes Argument. Es wäre schön, wenn die Argumente durch Code untermauert würden, statt nur bla, bla, bla.

Rückendeckung.

Hier ist meine CMyObject-Klasse:

#include <Object.mqh>

// Перечисление, в котором должны указываться все объекты, которые могут быть пронаследованны от моего объекта
enum EMyObjectTypes
{
   MOT_BASE_OBJECT                              =  0001,          // Просто CObject - фактически, никогда не должен использоваться.
   MOT_STRUCT_WRAPPER                           =  0002,          // Неинициализированный CStructWrapper
   MOT_PRICE_POINT                              =  0003,          // Класс CPricePoint   
   MOT_PRICEIDX_POINT                           =  0004,          // Класс CPriceIdxPoint  
   MOT_WPRICEIDX_POINT                          =  0005,          // Класс CWPriceIdxPoint  
   MOT_WAVE_TRIANGLE_DATA                       =  0006,          // Класс CWaveTriangleData
   MOT_WAVE_TRIANGLE                            =  0007,          // Класс CWaveTriangle
   MOT_TRADERESULT_I                            =  0008,          // Класс CTradeResultI
   MOT_TRADERESULT                              =  0009,          // Класс CTradeResult

   // Тут еще куча типов объектов - для каждого класса, свой ID
           
   MOT_UNKNOWN                                  = -0001           // Неинициализированный объект.
};

/*

Класс СMyObject - потомок от СObject, несет функциональность именования.

*/

class CMyObject: public CObject
{
protected:
   EMyObjectTypes m_motType;
   int            m_iUDCreationValue;  // Значение, определяемое пользователем при создании объекта. Предназначено для идентификации отдельных экземпляров объекта.  
   
   
   void SetMyObjectType(EMyObjectTypes motType) { m_motType = motType; };  

   // Функции вывода на печать параметров. 
   void _PrintStringParameter(string strParameterName,string strParameterValue) { Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + strParameterValue + "; String."); };
   void _PrintDoubleParameter(string strParameterName,double dParameterValue,int iDigits = 8) { Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + DoubleToString(dParameterValue,iDigits) + "; Double"); };
   void _PrintIntegerParameter(string strParameterName,long lParameterValue) {  Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + IntegerToString(lParameterValue) + "; Integer"); };
   void _PrintBoolParameter(string strParameterName,bool bParameterValue) { if(bParameterValue) Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = True; Bool"); else Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = False; Bool"); };
   
public:
   CMyObject(int iUDCreationValue = WRONG_VALUE) { m_iUDCreationValue = iUDCreationValue;  m_motType = MOT_UNKNOWN;  };
   
   EMyObjectTypes GetType() const { return(m_motType);    };
   bool CheckType(EMyObjectTypes motType) { return(m_motType == motType); }; 
   
   int GetUDCreationValue() { return(m_iUDCreationValue); };
   void SetUDCreationValue(int iValue) { m_iUDCreationValue = iValue; };
};

#ifdef  ASSERTION_CODE_ON

CMyObject* _PerformObjectConvertWithCheck(CMyObject* pmoObject,EMyObjectTypes motType)
{
   ASSERT_MYPOINTER(pmoObject);                    // проверим указатель
   ASSERT(pmoObject.CheckType(motType) == true);   // проверим внутренний ID типа объекта
   
   return(pmoObject);
};

#define  CONVERT_OBJECT_WITH_CHECK(objFrom,typeTo,checkType) ((typeTo*)_PerformObjectConvertWithCheck(objFrom,checkType))

#else // ASSERTION_CODE_ON

#define  CONVERT_OBJECT_WITH_CHECK(objFrom,typeTo,checkType) ((typeTo*)objFrom)

#endif // ASSERTION_CODE_ON

Am Ende ist auch das Makro CONVERT_OBJECT_WITH_CHECK definiert, das für die DEBUG-Version eine zusätzliche Zeigerumwandlungsprüfung auf der Grundlage des Objekttyps durchführt

 
George Merts:

Sicherung der Daten.

Hier ist meine CMyObject-Klasse:

Am Ende ist auch das Makro CONVERT_OBJECT_WITH_CHECK definiert, das in der DEBUG-Version eine zusätzliche Prüfung der Zeigerumwandlung auf der Grundlage des Objekttyps durchführt


Es ist wunderschön. Das ist natürlich eine Frage des Geschmacks. Aber basierend auf der MQL-Syntax würde ich es so schreiben:

enum ENUM_OBJECT_TYPES
{
   OBJECT_TYPES_BASE_OBJECT                              =  0001,          // Просто CObject - фактически, никогда не должен использоваться.
   OBJECT_TYPES_STRUCT_WRAPPER                           =  0002,          // Неинициализированный CStructWrapper
   OBJECT_TYPES_PRICE_POINT                              =  0003,          // Класс CPricePoint   
   OBJECT_TYPES_PRICEIDX_POINT                           =  0004,          // Класс CPriceIdxPoint  
   OBJECT_TYPES_WPRICEIDX_POINT                          =  0005,          // Класс CWPriceIdxPoint  
   OBJECT_TYPES_WAVE_TRIANGLE_DATA                       =  0006,          // Класс CWaveTriangleData
   OBJECT_TYPES_WAVE_TRIANGLE                            =  0007,          // Класс CWaveTriangle
   OBJECT_TYPES_TRADERESULT_I                            =  0008,          // Класс CTradeResultI
   OBJECT_TYPES_TRADERESULT                              =  0009,          // Класс CTradeResult

   // Тут еще куча типов объектов - для каждого класса, свой ID
           
   OBJECT_TYPES_UNKNOWN                                  = -0001           // Неинициализированный объект.
};
 
Dennis Kirichenko:

Es ist wunderschön. Das ist natürlich eine Frage des Geschmacks. Aber basierend auf der MQL-Syntax würde ich es so schreiben:

Ja, das ist richtig.

Aber das ist mein seniler "Programmierstil" (hallo, Volchansky mit seinem jüngsten Thread).

Ich habe alle Aufzählungen - beginnen Sie mit E, und dann mit "Buckel" Notation - Name. Und die Typen selbst in der Aufzählung beginnen mit einer Abkürzung (bis zu vier Buchstaben) des Aufzählungstyps.

Da es sich bei der Aufzählung um EMyObjectType handelt, beginnen alle Werte mit MOT_

 
Комбинатор:

Sind Sie ein Idiot? )) Ich habe kein einziges schlechtes Wort über F# gesagt. Lernen Sie, zu lesen und zu verstehen, was man Ihnen sagt, bevor Sie Ihre dummen Kommentare abgeben.

Wenn man OOP mit FP vergleicht, ist es sinnvoller, es mit einer reinen FP-Sprache zu vergleichen, z.B. Haskel. F# ist bereits sehr gut, während Python und R überhaupt nicht gut sind. Das ist es, was ich meine. Andernfalls könnten wir an einen Punkt kommen, an dem C++ auch eine FP-Sprache ist.

Sie sind ein ungebildeter Troll. Alle aufgeführten Sprachen sind auf die eine oder andere Weise funktional. Lernen Sie das Fachgebiet kennen. Die Frage wurde gestellt, um zu verstehen, in welchem BezugsrahmenAndrei wahrscheinlich eine der RP-Sprachen praktiziert, daher war die Auflistung sehr allgemein.

 
George Merts:

Was soll das denn heißen?

Was sollte Ihrer Meinung nach im "Basisobjekt" enthalten sein?

Ich persönlich habe fast ALLE Objekte in allen meinen Projekten - geerbt von CMyObject: public CObject, (in meinem Objekt sind zwei weitere Felder hinzugefügt - Klassenname und Instanz-ID), und immer wieder festgestellt, dass ich CObject::Compare() Funktionalität sehr viel brauchen. Ein paar Mal waren Listenhinweise auch sehr nützlich.

CObject hat ein Ziel - die Typkontrolle. Und es gelingt ihm nur zögerlich. Methoden wie Next(), Prev() usw. sind für sehr spezielle Sammlungen gedacht. Sie gehören nicht zu CObject. Das Gleiche gilt für die Methoden Speichern und Laden. Es wäre auch schön, wenn Comparer nicht dabei wäre, aber dies ist die einzige Lösung ohne Schnittstellen.

Die Methode Type() bietet keine strenge Typisierung, da sie die übliche Zahl zurückgibt. Sie können am Beispiel Ihres eigenen Codes sehen. Sie definieren eine neue Methode GetType(), die den Typ als Aufzählung zurückgibt. Es gibt wirklich keinen anderen Weg, ich mache es selbst. Deshalb muss das Standard-CObject angehängt werden, und das ist falsch.

 

Lassen Sie uns mit CObject::Compare() fortfahren.

Ich habe ein solches Objekt CFactoryBalanceResultSeries - es handelt sich um eine Serie mit Bilanzergebnissen mit Bezug auf das Factory-Objekt des Expert Advisors. Eigentlich handelt es sich um eine Gleichgewichtskurve in der Historie mit Bezug auf den Expert Advisor, der sie gehandelt hat.

Ich habe also ein Skript, in dem ich diese sehr ausgewogenen Serien vergleiche.

Solange es nur zwei Serien gibt, ist es einfach, sie zu vergleichen. Aber wenn es Dutzende von ihnen gibt, kann man nicht nach Augenmaß vergleichen, sondern braucht einen formaleren Vergleich.

Und nur um diesen Prozess zu automatisieren, musste ich eine Funktion schreiben, die genau diese Serien sortiert. Und hier war es nützlich, denn die Klasse CFactoryBalanceResultSeries ist ein Erbe von CObject mit seiner Vergleichsfunktion. Wenn wir diese Funktion außer Kraft setzen, haben wir eine fertige Möglichkeit, Serien zu sortieren.

So sieht diese Funktion in meinem Fall aus:

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

      case FSM_BY_LAST_PRCDATA_A:      return(_CompareByLastPrcdataWith(pfdsAnother,true));
      case FSM_BY_LAST_PRCDATA_D:      return(_CompareByLastPrcdataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYDATA_A:      return(_CompareByLastMnydataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYDATA_D:      return(_CompareByLastMnydataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYLOTDATA_A:   return(_CompareByLastMnylotdataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYLOTDATA_D:   return(_CompareByLastMnylotdataWith(pfdsAnother,false));
      
      case FSM_BY_PRCYEARRECOVERY_A:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,true));
      case FSM_BY_PRCYEARRECOVERY_D:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYYEARRECOVERY_A:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYYEARRECOVERY_D:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYLOTYEARRECOVERY_A:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYLOTYEARRECOVERY_D:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,false));
      
      case FSM_BY_PRCVAR_A:            return(_CompareByPrcVarWith(pfdsAnother,true));
      case FSM_BY_PRCVAR_D:            return(_CompareByPrcVarWith(pfdsAnother,false));
      case FSM_BY_MNYVAR_A:            return(_CompareByMnyVarWith(pfdsAnother,true));
      case FSM_BY_MNYVAR_D:            return(_CompareByMnyVarWith(pfdsAnother,false));
      case FSM_BY_MNYLOTVAR_A:         return(_CompareByMnylotVarWith(pfdsAnother,true));
      case FSM_BY_MNYLOTVAR_D:         return(_CompareByMnylotVarWith(pfdsAnother,false));
      
      case FSM_BY_PRC_GRAILRATIO_A:    return(_CompareByPrcGrailratioWith(pfdsAnother,true));
      case FSM_BY_PRC_GRAILRATIO_D:    return(_CompareByPrcGrailratioWith(pfdsAnother,false));

      case FSM_BY_MAGIC_A:             return(_CompareByMagicWith(pfdsAnother,true));
      case FSM_BY_MAIGC_D:             return(_CompareByMagicWith(pfdsAnother,false));
      default:
         break;
      };
         
   return(NULL);
};

Das heißt, je nach Art der Sortierung wählen wir die erforderliche Vergleichsfunktion, die in der allgemeinen Sortierfunktion verwendet wird.

Wenn wir z.B. die Saldenreihe nach dem Anteil der letzten Inanspruchnahme am Maximum sortieren wollen, werden die folgenden Funktionen verwendet:

int CFactoryBalanceResultSeries::_CompareDblData(double dDataFirst,double dDataSecond,bool bAccending) const
{
   if(dDataFirst > dDataSecond)
      {
      if(bAccending)
         return(1);
      else   
         return(-1);
      };
   
   if(dDataFirst < dDataSecond)
      {
      if(bAccending)
         return(-1);
      else   
         return(1);
      };
      
   return(NULL);         
};

int CFactoryBalanceResultSeries::_CompareByPartOfMaxDDWith(CFactoryBalanceResultSeries* pfdsAnother,bool bAccending) const
{
   if(Total()==0 || pfdsAnother.Total() == 0 || m_pepfFactory.GetControlParams().m_dMaxPriceDrawdown == 0)
      return(NULL);
   
   double dLocalPart = GetCurPriceDD() / m_pepfFactory.GetControlParams().m_dMaxPriceDrawdown;
   double dRemotePart = pfdsAnother.GetCurPriceDD() / pfdsAnother.GetFactory().GetControlParams().m_dMaxPriceDrawdown;
      
   return(_CompareDblData(dLocalPart,dRemotePart,bAccending));   
};
 
George Merts:

Ich werde mit CObject::Compare() fortfahren.

Aus der jüngsten

CDouble & CDoubleVector
CDouble & CDoubleVector
  • Stimmen: 4
  • 2018.01.09
  • nicholishen
  • www.mql5.com
A library for common rounding methods used in MQL development, primitive wrapper class for type (double), and vector for CDouble objects. MQL5 and MQL4 compatible! CDouble The CDouble class wraps a value of the primitive type double in an object. Additionally, this class provides several methods and static methods for rounding doubles and...
 
George Merts:



Das ist nicht sehr hübsch, finde ich.

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

Sie könnten einen Zeiger auf eine Funktion verwenden.

typedef int (*TCompare1)(int,bool); 
// ---
int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(TCompare1(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(TCompare1(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(TCompare1(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(TCompare1(pfdsAnother,false));

.....
      }
}
 
George Merts:

Ja, das ist richtig.

Aber das ist mein seniler "Programmierstil" (hallo, Wolchansky mit seinem jüngsten Thread).

Ich habe alle Aufzählungen - beginnen Sie mit E, und dann "Buckel" Notation - der Name. Und die Typen selbst in der Aufzählung beginnen mit einer Abkürzung (bis zu vier Buchstaben) des Aufzählungstyps.

Da die EMyObjectType-Aufzählung - alle Werte beginnen mit MOT_ - dementsprechend


Ja, ich habe die gleiche Aufzählung.

ZS: Ich bin jetzt gerade am Computer. Wie zu erwarten war, ist dieser Thread schnell in Müll ausgeartet). Ich werde versuchen, die Geschichte über die virtuellen Funktionen später zu beenden. Wir sollten dieses Forum Blah Blah Blah Blah nennen.)

 

Ich habe die unterschiedlichen Interessen aller gelesen... Ich bin gerade dabei, eine Klasse neu zu gestalten, um ein virtuelles Gitter einzurichten und zu verwalten, ich brauche es.