記事"MQL5 クックブック: 連想配列またはクイック データアクセスのための辞書の実装"についてのディスカッション - ページ 3

 
外国為替金のテクニカル分析取引所、グループ番号は375124107、グループ検証77に、ご協力ありがとうございました!
 

StrategyGUIDはulong型の識別子で、StrategyはCObjectを継承したクラスに基づいて作成されたストラテジーである。

したがって、CDictionary StrategyBook(アクティブなストラテジーのブック)を含む必要な変数を宣言し、必要なストラテジーStrategy01、Strategy02を作成し、EAのOnInit()関数で、一意のGUIDの割り当てを含む様々なパラメーターを開始する。OnInit()の一番最後に、ストラテジーをStrategyBookに保存することにしました。

StrategyBook.AddObject(Strategy01.strGUID,Strategy01);

StrategyBook.AddObject(Strategy02.strGUID,Strategy02); 

そして、両方の行で "StrategyXX - parameter conversion not allowed "というエラーが出ました。

私のC#での経験に基づけば、すべてが正しく行われています。しかし、MQL5ではこのエラーが出ます。

何が関係しているのでしょうか?

 
Сергей Лебедев:

StrategyGUIDはulong型の識別子で、StrategyはCObjectを継承したクラスに基づいて作成されたストラテジーである。

したがって、CDictionary StrategyBook(アクティブなストラテジーのブック)を含む必要な変数を宣言し、必要なストラテジーStrategy01、Strategy02を作成し、EAのOnInit()関数で、一意のGUIDの割り当てを含む様々なパラメーターを開始する。OnInit()の一番最後に、ストラテジーをStrategyBookに保存することにしました。

StrategyBook.AddObject(Strategy01.strGUID,Strategy01);

StrategyBook.AddObject(Strategy02.strGUID,Strategy02); 

そして、両方の行で "StrategyXX - parameter conversion not allowed "というエラーが出ました。

私のC#での経験に基づけば、すべてが正しく行われています。しかし、MQL5ではこのエラーが出ます。

何が関係しているのでしょうか?

いくつかの理由が考えられます。最も考えられるのは、型の非互換性か、ポインターの扱い方が間違っていることです。また、テンプレート・メソッドの特殊性も排除できません(テンプレート・メソッドにも独自のニュアンスがあります)。

一般的には、既製の取引エンジンを使用する方が良いでしょう。https://www.mql5.com/ja/articles/2166、多くの時間と神経を節約できます。

Универсальный торговый эксперт: Торговые режимы стратегий (Часть 1)
Универсальный торговый эксперт: Торговые режимы стратегий (Часть 1)
  • 2016.01.07
  • Vasiliy Sokolov
  • www.mql5.com
Каждый экспертописатель, независимо от уровня своей подготовки, ежедневно сталкивается с одними и теми же торговыми задачами и алгоритмическими проблемами, которые так или иначе приходится решать для организации надежного торгового процесса. Данная статья описывает возможности торгового движка CStrategy, способного взять на себя решение этих задач и предоставить пользователю удобные механизмы для описания своей торговой идеи.
 

ああ、結局そうすることにしたんだ。

 

ご苦労様です。しかし、どのコード例も動作させることができないようです。

Dictionary dict; CDictionary dict でなければならないようです

簡単な動作例はどうでしょうか?

削除済み  

新しいMT4(Build 1080、2017年5月12日)に関して、コンパイル中にこれらのエラーが発生し、実行できません:

'm_array' - オブジェクトを含む構造体は使用できません Dictionary.mqh 303 25

cannot cast 'DoubleValue' to 'ULongValue' Dictionary.mqh 252 14

 

こんにちは、

以前他の方がおっしゃったように、コンパイル可能な例はありません。

ロシア語のコメントのファイルだけです。

 
こんにちは、バシリー、

参考になる記事をありがとうございます。MQL5ビルド2063でdictionary.mqhをダウンロードしてコンパイルすると、以下のエラーが発生します:

'GetKey' - 関数がすでに定義されており、型が異なります。
'Compress' -関数は すでに定義されており、型が異なります。

なぜこのようになるのでしょうか?

よろしくお願いします。
ゲリック
 

ヴァシリイのライブラリーをうまく使わせてもらっている。本当に助かっている!

私もコンパイラのエラーがいくつかあったのを覚えていて、それを修正することができました。ただ、どのエラーで、何をしたのかはよくわかりません。

また、私はMQL5のコードの書式に非常に悩まされていて、いつもすべてをモダンなC++の書式(適切なインデント、不要な括弧の回避、コメントの乱雑さの排除など)に直しているので、コードの本当の変更点が何であったかを言うことはできません。覚えているのは、変更が小さかったということだけだ。

適切な書式のライブラリを使いたい場合は、ここにある:

(タブを使用しているので、書式が崩れているように見えますが、MetaEditorでは崩れていません!)

//+------------------------------------------------------------------+
//|CDictionary.mqh
//|著作権 2015, Vasiliy Sokolov.|
//|http://mql5.commql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link          "http://www.mql5.com"

#include  <Object.mqh>
#include  <Arrays\List.mqh>

#define  FOREACH_DICT(dict) for (CObject* node = (dict).GetFirstNode(); node != NULL; node = (dict).GetNextNode())

class KeyValuePair : public CObject
{
        private:
                string                          m_string_key;
                double                          m_double_key;
                ulong                           m_ulong_key;
                ulong                           m_hash;
                bool                            m_free_mode;
        public:
                CObject*                        object;
                KeyValuePair*           next_kvp;
                KeyValuePair*           prev_kvp;
                template <typename T>
                void                            KeyValuePair(T key, ulong hash, CObject *obj);
                                                        ~KeyValuePair();
                template <typename T>
                bool                            EqualKey(T key);
                template <typename T>
                void                            GetKey(T& gkey);
                ulong                           GetHash()                                       { return m_hash; }
                void                            FreeMode(bool free_mode)        { m_free_mode = free_mode; }
                bool                            FreeMode(void)                          { return m_free_mode; }
};

template <typename T>
void KeyValuePair::KeyValuePair(T key, ulong hash, CObject *obj)
{
        m_hash = hash;
        string name = typename(key);
        if (name == "string")
                m_string_key = (string)key;
        else if
                (name == "double" || name == "float")
        
        m_double_key = (double)key;
        else
                m_ulong_key=(ulong)key;
        
        object = obj;
        m_free_mode = true;
}

template <typename T>
void KeyValuePair::GetKey(T& gkey)
{
        string name = typename(gkey);
        if (name  ==  "string")
                gkey = (T)m_string_key;
        else if (name == "double" || name == "float")
                gkey = (T)m_double_key;
        else
                gkey = (T)m_ulong_key;
}

KeyValuePair::~KeyValuePair()
{
        if (m_free_mode)
                delete object;
}

template <typename T>
bool KeyValuePair::EqualKey(T key)
{
        string name=typename(key);
        if (name == "string")
                return m_string_key  ==  (string)key;
        if (name == "double" || name == "float")
                return m_double_key  ==  (double)key;
        else
                return m_ulong_key  ==  (ulong)key;
}

class CDictionary : public CObject
{
        private:
                int                                     m_array_size;
                int                                     m_total;
                bool                            m_free_mode;
                bool                            m_auto_free;
                int                                     m_index;
                ulong                           m_hash;
                CList*                          m_array[];
                union casting_struct
                {
                        double d_value;
                        ulong  l_value;
                } casting;
                
                KeyValuePair*           m_first_kvp;
                KeyValuePair*           m_current_kvp;
                KeyValuePair*           m_last_kvp;
        
                ulong                           Adler32(string line);
                int                                     GetIndexByHash(ulong hash);
                template <typename T>
                ulong                           GetHashByKey(T key);
                void                            Resize();
                int                                     FindNextSimpleNumber(int number);
                int                                     FindNextLevel();
                void                            Init(int capacity);
        
        public:
                                                        CDictionary();
                                                        CDictionary(int capacity);
                                                        ~CDictionary();
                void                            Compress(void);

                int Total(void)         { return m_total; }

                template <typename T>
                CObject*                        GetObjectByKey(T key);
                template <typename T>
                bool                            AddObject(T key, CObject *value);
                template <typename T>
                bool                            DeleteObjectByKey(T key);
                template <typename T>
                bool                            ContainsKey(T key);
                template <typename T>
                void                            GetCurrentKey(T &key);
                bool                            DeleteCurrentNode(void);
                bool                            FreeMode(void)                                          { return(m_free_mode); }
                void                            FreeMode(bool free_mode);
                void                            AutoFreeMemory(bool autoFree)           { m_auto_free = autoFree; }
                void                            Clear();
        
                CObject*                        GetNextNode(void);
                CObject*                        GetPrevNode(void);
                CObject*                        GetCurrentNode(void);
                CObject*                        GetFirstNode(void);
                CObject*                        GetLastNode(void);
};

CDictionary::CDictionary()
{
        Init(3);
        m_free_mode = true;
        m_auto_free = true;
}

CDictionary::CDictionary(int capacity)
{
        if (capacity < 3)
                Init(3);
        else
                Init(capacity);

        m_free_mode = true;
        m_auto_free = true;
}

CDictionary::~CDictionary()
{
        Clear();
}

void CDictionary::FreeMode(bool free_mode)
{
        if (free_mode == m_free_mode)
                return;

        m_free_mode = free_mode;

        for (int i=0; i < ArraySize(m_array); i++)
        {
                CList *list = m_array[i];
                if (CheckPointer(list) == POINTER_INVALID)
                        continue;

                for (KeyValuePair* kvp = list.GetFirstNode(); kvp != NULL; kvp = list.GetNextNode())
                        kvp.FreeMode(m_free_mode);
        }
}

void CDictionary::Init(int capacity)
{
        m_array_size = ArrayResize(m_array,capacity);
        m_index = 0;
        m_hash  = 0;
        m_total = 0;
}

int CDictionary::FindNextLevel()
{
        double value=4;
        for (int i=2; i <= 31; i++)
        {
                value = MathPow(2.0,(double)i);
                if (value > m_total)
                        return (int)value;
        }
        
        return (int)value;
}

ulong CDictionary::Adler32(string line)
  {
        ulong s1 = 1;
        ulong s2 = 0;
        uint buflength = StringLen(line);
        uchar char_array[];
        ArrayResize(char_array, buflength, 0);
        StringToCharArray(line, char_array, 0, -1, CP_ACP);
        for (uint n=0; n < buflength; n++)
        {
                s1 = (s1 + char_array[n]) % 65521;
                s2 = (s2 + s1) % 65521;
        }
        return ((s2  <<  16) + s1);
}

template <typename T>
ulong CDictionary::GetHashByKey(T key)
{
        ulong ukey = 0;
        string name = typename(key);
        if (name == "string")
                return Adler32((string)key);
        if (name == "double" || name == "float")
        {
                casting.d_value = (double)key;
                ukey = casting.l_value;
        }
        else
                ukey = (ulong)key;
        return ukey;
}

template <typename T>
void CDictionary::GetCurrentKey(T &key)
{
        m_current_kvp.GetKey(key);
}

int CDictionary::GetIndexByHash(ulong key)
{
        return (int)(key % m_array_size);
}

void CDictionary::Clear(void)
{
        int size = ArraySize(m_array);
        for (int i=0; i < size; i++)
        {
                if (CheckPointer(m_array[i]) != POINTER_INVALID)
                {
                        m_array[i].FreeMode(true);
                        delete m_array[i];
                }
        }
        ArrayFree(m_array);
        if (m_auto_free)
                Init(3);
        else
                Init(size);
                
        m_first_kvp = m_last_kvp = m_current_kvp = NULL;
  }

void CDictionary::Resize(void)
  {
        int level = FindNextLevel();
        int n = level;
        CList* temp_array[];
        ArrayCopy(temp_array, m_array);
        ArrayFree(m_array);
        m_array_size = ArrayResize(m_array,n);
        int total = ArraySize(temp_array);
        KeyValuePair* kv = NULL;
        
        for (int i=0; i < total; i++)
        {
                if (temp_array[i] == NULL)
                        continue;

                CList* list = temp_array[i];
                int count = list.Total();
                list.FreeMode(false);
                kv = list.GetFirstNode();

                while (kv != NULL)
                {
                        int index = GetIndexByHash(kv.GetHash());
                        if (CheckPointer(m_array[index]) == POINTER_INVALID)
                        {
                                m_array[index] = new CList();
                                m_array[index].FreeMode(true);  // KeyValuePair を使用する。
                        }
                        list.DetachCurrent();
                        m_array[index].Add(kv);
                        kv = list.GetCurrentNode();
                }
                delete list;
        }
        int size = ArraySize(temp_array);
        ArrayFree(temp_array);
}

void CDictionary::Compress(void)
{
        if (!m_auto_free)
                return;
        
        double koeff = m_array_size / (double)(m_total+1);
        if (koeff < 2.0 || m_total <= 4)
                return;

        Resize();
}

template <typename T>
CObject* CDictionary::GetObjectByKey(T key)
{
        if (!ContainsKey(key))
                return NULL;
        CObject *obj = m_current_kvp.object;
        return obj;
}

template <typename T>
bool CDictionary::ContainsKey(T key)
{
        m_hash = GetHashByKey(key);
        m_index = GetIndexByHash(m_hash);
        
        if (CheckPointer(m_array[m_index]) == POINTER_INVALID)
                return false;
        
        CList* list = m_array[m_index];
        
        KeyValuePair* current_kvp = list.GetCurrentNode();
        
        if (current_kvp  ==  NULL)
                return false;
        
        if (current_kvp.EqualKey(key))
        {
                m_current_kvp = current_kvp;
                return true;
        }
        
        current_kvp = list.GetFirstNode();
        while (true)
        {
                if (current_kvp.EqualKey(key))
                {
                        m_current_kvp = current_kvp;
                        return true;
                }
                current_kvp = list.GetNextNode();
                if (current_kvp == NULL)
                        return false;
        }
        return false;
  }

template <typename T>
bool CDictionary::AddObject(T key, CObject *value)
{
        if (ContainsKey(key))
                return false;
        
        if (m_total == m_array_size)
        {
                Resize();
                ContainsKey(key);
        }
        
        if (CheckPointer(m_array[m_index]) == POINTER_INVALID)
        {
                m_array[m_index] = new CList();
                m_array[m_index].FreeMode(true);
        }
        
        KeyValuePair *kv = new KeyValuePair(key,m_hash,value);
        kv.FreeMode(m_free_mode);
        
        if (m_array[m_index].Add(kv) != -1)
                m_total++;
        
        if (CheckPointer(m_current_kvp) == POINTER_INVALID)
        {
                m_first_kvp = kv;
                m_current_kvp = kv;
                m_last_kvp = kv;
        }
        else
        {
                while (m_current_kvp.next_kvp != NULL)
                        m_current_kvp = m_current_kvp.next_kvp;
                        
                m_current_kvp.next_kvp = kv;
                kv.prev_kvp = m_current_kvp;
                m_current_kvp = kv;
                m_last_kvp = kv;
        }
        return true;
}


CObject* CDictionary::GetCurrentNode(void)
{
        if (m_current_kvp == NULL)
                return NULL;

        return m_current_kvp.object;
}

CObject* CDictionary:: GetPrevNode(void)
{
        if (m_current_kvp == NULL)
                return NULL;

        if (m_current_kvp.prev_kvp == NULL)
                return NULL;

        KeyValuePair *kvp = m_current_kvp.prev_kvp;
        m_current_kvp = kvp;

        return kvp.object;
}

CObject* CDictionary::GetNextNode(void)
{
        if (m_current_kvp == NULL)
                return NULL;
        
        if (m_current_kvp.next_kvp == NULL)
                return NULL;
        
        m_current_kvp = m_current_kvp.next_kvp;

        return m_current_kvp.object;
}

CObject* CDictionary::GetFirstNode(void)
{
        if (m_first_kvp == NULL)
                return NULL;

        m_current_kvp = m_first_kvp;
        return m_first_kvp.object;
}

CObject *CDictionary::GetLastNode(void)
{
        if (m_last_kvp == NULL)
                return NULL;

        m_current_kvp = m_last_kvp;
        return m_last_kvp.object;
}

bool CDictionary::DeleteCurrentNode(void)
{
        if (m_current_kvp == NULL)
                return false;

        KeyValuePair* p_kvp = m_current_kvp.prev_kvp;
        KeyValuePair* n_kvp = m_current_kvp.next_kvp;

        if (CheckPointer(p_kvp) != POINTER_INVALID)
                p_kvp.next_kvp = n_kvp;

        if (CheckPointer(n_kvp) != POINTER_INVALID)
                n_kvp.prev_kvp = p_kvp;

        m_array[m_index].FreeMode(m_free_mode);
        bool res = m_array[m_index].DeleteCurrent();

        if (res)
        {
                m_total--;
                Compress();
        }
        return res;
}

template <typename T>
bool CDictionary::DeleteObjectByKey(T key)
{
        if (!ContainsKey(key))
                return false;
        return DeleteCurrentNode();
}

 

要素を削除して最後の要素に移動しようとしたときにバグを見つけたようだ:

class CWord : CObject
{
        string m_Word;

        public:
                CWord(string word) : m_Word(word) {}
                ~CWord() {}
                
                string GetWord() { return m_Word; }
};
CDictionary* testDict = new CDictionary(10);

testDict.AddObject(0, (CObject*)new CWord("A"));
testDict.AddObject(100, (CObject*)new CWord("A"));
testDict.AddObject(200, (CObject*)new CWord("B"));
testDict.AddObject(300, (CObject*)new CWord("C"));

CWord* lastWord = (CWord*)testDict.GetLastNode();
Print(lastWord.GetWord());

CWord* firstWord = (CWord*)testDict.GetFirstNode();
Print(firstWord.GetWord());

testDict.DeleteCurrentNode();

lastWord = testDict.GetLastNode(); // CDictionary::GetLastNode(void) -> return m_last_kvp.object; -> m_last_kvp は無効なポインタです!
Print(lastWord.GetWord());

CDictionary.mqhでエラーが出る:

'Dictionary.mqh'の無効なポインタ アクセス (463,9)

どなたかこれを確認できますか?修正方法があれば教えてください。