ラウンジでPLOについて語る - ページ 4

 
Dennis Kirichenko:

良い 点です。ただボソボソと言うのではなく、コードで裏付けされた主張があると良いのですが。

裏打ちする。

以下は、私のCMyObjectクラスです。

#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

最後に CONVERT_OBJECT_WITH_CHECK マクロも定義されており、DEBUG 版ではオブジェクト型に基づくポインタ変換 チェックを追加で行います。

 
George Merts:

裏打ちする。

以下は、私のCMyObjectクラスです。

最後にCONVERT_OBJECT_WITH_CHECKマクロも定義されており、DEBUG版では、オブジェクトタイプに基づくポインタ変換 チェックを追加で実行します。


美しいですね。もちろん、好みの問題です。しかし、MQLの構文からすると、このように書くことになります。

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:

美しいですね。もちろん、好みの問題です。しかし、MQLの構文からすると、私ならこのように書きます。

はい、その通りです。

しかし、これは私の老人的な「プログラミングスタイル」です(最近のスレッドを持つVolchanskyさん、こんにちは)。

私はすべての列挙 - Eで始まる、そして「こぶ」表記 - 名前を持っています。そして、列挙における型そのものは、列挙型の省略形(4文字以内)で始まる。

従って、列挙は EMyObjectType であるため、全ての値は MOT_ で始まる。

 
Комбинатор:

バカじゃねーの?)) F#の悪口はひとつも言っていない。馬鹿なコメントを投稿する前に、言われたことを読んで理解することを学びましょう。

OOPとFPを比較するならば、純粋なFP言語、つまりHaskelと比較する方が賢明です。F#はもうそこそこ、pythonやRは全然です。そういうことなんです。そうでなければ、C++もFP言語ということになりかねません。

お前は文盲の荒らしだ。ちなみに、リストアップされた言語はすべて、何らかの形で機能するものです。その分野を学んできてください。アンドレイが どのようなフレームでFP言語の一つを実践しているのかを理解するための質問でしたので、非常に一般的なリストになっています。

 
George Merts:

どういうことですか?

齋藤さんによると、「ベースオブジェクト」には何が入るべきなのでしょうか?

個人的には、すべてのプロジェクトで、ほとんどすべてのオブジェクトをCMyObject: public CObjectから継承し、(私のオブジェクトでは、クラス名とインスタンスIDという2つのフィールドが追加されています)、繰り返し、CObject::Compare() 機能を非常に必要としていることがわかりました。リストのポインタも何度か役に立ちました。

CObjectの 目的は一つ、型制御を行うことです。そして、それを揺るぎなく管理する。Next()、Prev()などのメソッドは、非常に特殊なコレクションのためのものです。CObjectには属さない。SaveとLoadのメソッドも同様です。Comparerも入っていない方がいいのですが、インターフェイスがない分、これしかないですね。

Type()メソッドについては、通常の数値を返すので、厳密な型付けはできない。ご自身のコードの例でご確認ください。型を列挙して返す新しい GetType() メソッドを定義します。本当に他に方法がないんです、自分でやってますから。そのため、標準のCObjectを付加する必要があり、不正解です。

 

CObject::Compare() の続きを見てみましょう。

私はそのようなオブジェクトCFactoryBalanceResultSeriesを持っています - それはExpert Advisorのファクトリーオブジェクトを参照してバランスの結果を持つシリーズです。実際には、取引したExpert Advisorを参考にした履歴上のバランスカーブです。

そこで、この非常にバランスの良いシリーズを比較するスクリプトを用意しました。

2つのシリーズしかない以上、比較は容易です。しかし、それが何十個もあるとなると......目で見て比較することはできず、もっと正式な比較が必要です。

そして、このプロセスを自動化するために、まさにこれらのシリーズをソートする関数を書かなければなりませんでした。また、CFactoryBalanceResultSeriesクラスは、比較機能を持つCObjectの後継であるため、ここで役に立ちました。この関数をオーバーライドすると、シリーズをソートすることができるようになります。

私の場合、この関数はこんな感じです。

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);
};

つまり、ソートの種類に応じて、一般的なソート機能で使用される比較関数を選択するのである。

例えば、残高シリーズを最大値からの最後のドローダウンの一部でソートしたい場合、以下の関数が使用されます。

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:

CObject::Compare()の続きを書いてみます。

最近から

CDouble & CDoubleVector
CDouble & CDoubleVector
  • 投票: 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:



イマイチ可愛くないんですよね。

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));

関数へのポインタを使えば いいんだよ。

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:

はい、その通りです。

しかし、それは私の老人的な「プログラミングスタイル」です(最近のスレッドを持つWolchanskyさん、こんにちは)。

私はすべての列挙 - Eで始まる、そして「こぶ」表記 - 名前を持っています。そして、列挙における型そのものは、列挙型の省略形(4文字以内)で始まる。

EMyObjectType列挙は、すべての値がMOT_で始まるので、それに対応する。


はい、同じように列挙しています。

ZS: 今、パソコンに向かったところです。案の定、このスレッドはすぐにゴミ箱に落ちました(笑)。仮想関数の 話は、また後日仕上げようと思っています。このフォーラムをBlah Blah Blahと呼ぶべきでしょう)。

 

みんなの様々な興味を読んで...私は今、仮想 グリッドを設定し管理 するためのクラスを再設計しているところです、必要なんです。