forked from dng/NN_in_Trading
//+------------------------------------------------------------------+
| |
//| MyTreeNode.mqh |
| |
//| Copyright 2022, DNG |
| |
//| https://www.mql5.com/ru/users/dng |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2022, DNG"
| |
#property link "https://www.mql5.com/ru/users/dng"
| |
#property version "1.00"
| |
//---
| |
#include <Arrays\ArrayObj.mqh>
| |
//---
| |
class CMyTreeNode : public CArrayObj
| |
{
| |
protected:
| |
CMyTreeNode *m_cParent;
| |
ulong m_iIndex;
| |
float m_dSupport;
| |
| |
public:
| |
CMyTreeNode();
| |
~CMyTreeNode();
| |
//--- methods of access to protected data
| |
CMyTreeNode* Parent(void) const { return(m_cParent); }
| |
void Parent(CMyTreeNode *node) { m_cParent = node; }
| |
void IncreaseSupport(float support) { m_dSupport += support; }
| |
float GetSupport(void) { return m_dSupport; }
| |
void SetSupport(float support) { m_dSupport = support; }
| |
ulong ID(void) { return m_iIndex; }
| |
void ID(ulong ID) { m_iIndex = ID; }
| |
float GetConfidence(void);
| |
float GetConfidence(const ulong ID);
| |
//---
| |
CMyTreeNode *GetNext(const ulong ID);
| |
matrix NodesGetConfidence(void);
| |
CMyTreeNode *AddNode(const ulong ID, float weight = 0);
| |
bool DeleteNode(const ulong ID);
| |
//---
| |
uint GetDepth(void);
| |
//---
| |
bool Mining(vectorf &data, matrixf &paths, const ulong ID, float min_conf);
| |
//--- methods for working with files
| |
virtual bool Save(const int file_handle);
| |
virtual bool Load(const int file_handle);
| |
//--- method of creating an element of array
| |
virtual bool CreateElement(const int index);
| |
};
| |
//+------------------------------------------------------------------+
| |
//| m d Su pp or t implementation |
| |
//+------------------------------------------------------------------+
| |
CMyTreeNode::CMyTreeNode() : m_dSupport(0)
| |
{
| |
Clear();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Destructor |
| |
//+------------------------------------------------------------------+
| |
CMyTreeNode::~CMyTreeNode()
| |
{
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
float CMyTreeNode::GetConfidence(void)
| |
{
| |
CMyTreeNode *parent = Parent();
| |
if(!parent)
| |
return 1;
| |
//---
| |
float result = m_dSupport / parent.GetSupport();
| |
return result;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
float CMyTreeNode::GetConfidence(const ulong ID)
| |
{
| |
CMyTreeNode *temp = GetNext(ID);
| |
if(!temp)
| |
return 0;
| |
//---
| |
return temp.GetConfidence();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Getting the element by ID |
| |
//+------------------------------------------------------------------+
| |
CMyTreeNode *CMyTreeNode::GetNext(const ulong ID)
| |
{
| |
if(m_data_total <= 0)
| |
return NULL;
| |
//---
| |
CMyTreeNode *result = NULL;
| |
for(int i = 0; i < m_data_total; i++)
| |
{
| |
CMyTreeNode *temp = m_data[i];
| |
if(!temp)
| |
continue;
| |
if(temp.ID() != ID)
| |
continue;
| |
result = temp;
| |
break;
| |
}
| |
//---
| |
return result;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CMyTreeNode::DeleteNode(const ulong ID)
| |
{
| |
for(int i = 0; i < m_data_total; i++)
| |
{
| |
CMyTreeNode *temp = m_data[i];
| |
if(!temp)
| |
{
| |
if(!Delete(i))
| |
continue;
| |
return DeleteNode(ID);
| |
}
| |
if(temp.ID() != ID)
| |
continue;
| |
return Delete(i);
| |
}
| |
//---
| |
return false;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Adding a node |
| |
//+------------------------------------------------------------------+
| |
CMyTreeNode *CMyTreeNode::AddNode(const ulong ID, float support)
| |
{
| |
CMyTreeNode *node = new CMyTreeNode();
| |
if(!node)
| |
return node;
| |
node.ID(ID);
| |
if(!Add(node))
| |
{
| |
delete node;
| |
return node;
| |
}
| |
node.Parent(GetPointer(this));
| |
//---
| |
if(support > 0)
| |
node.SetSupport(support);
| |
return node;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
uint CMyTreeNode::GetDepth(void)
| |
{
| |
CMyTreeNode *parent = Parent();
| |
if(!parent)
| |
return 0;
| |
return parent.GetDepth() + 1;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CMyTreeNode::Mining(vectorf &supports, matrixf &paths, const ulong ID, float min_conf)
| |
{
| |
if(ID == m_iIndex)
| |
if(GetConfidence() < min_conf)
| |
return true;
| |
//---
| |
float support = m_dSupport;
| |
for(int i = 0; i < m_data_total; i++)
| |
{
| |
CMyTreeNode *temp = m_data[i];
| |
if(!temp)
| |
{
| |
if(Delete(i))
| |
i--;
| |
continue;
| |
}
| |
if(!temp.Mining(supports, paths, (ID == m_iIndex ? ULONG_MAX : ID), min_conf))
| |
return false;
| |
support -= temp.GetSupport();
| |
if(temp.ID() == ID)
| |
if(Delete(i))
| |
i--;
| |
}
| |
//---
| |
if(ID == m_iIndex || ID == ULONG_MAX)
| |
if(support > 0 && !!m_cParent)
| |
{
| |
CMyTreeNode *parent = m_cParent;
| |
ulong row = paths.Rows();
| |
if(!paths.Resize(row + 1, paths.Cols()))
| |
return false;
| |
if(!paths.Row(vectorf::Zeros(paths.Cols()), row))
| |
return false;
| |
supports[m_iIndex] += support;
| |
while(!!parent)
| |
{
| |
if(parent.ID() != ULONG_MAX)
| |
{
| |
supports[parent.ID()] += support;
| |
paths[row, parent.ID()] = support;
| |
}
| |
parent = parent.Parent();
| |
}
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CMyTreeNode::CreateElement(const int index)
| |
{
| |
if(index >= m_data_max)
| |
if(!Resize(index + 1))
| |
return false;
| |
m_data[index] = new CMyTreeNode();
| |
if(!m_data[index])
| |
return false;
| |
m_data_total = fmax(index, m_data_total);
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CMyTreeNode::Save(const int file_handle)
| |
{
| |
if(!CArrayObj::Save(file_handle))
| |
return false;
| |
if(FileWriteLong(file_handle, m_iIndex) < sizeof(m_iIndex))
| |
return false;
| |
if(FileWriteDouble(file_handle, m_dSupport) < sizeof(m_dSupport))
| |
return false;
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CMyTreeNode::Load(const int file_handle)
| |
{
| |
if(!CArrayObj::Load(file_handle))
| |
return false;
| |
m_iIndex = FileReadLong(file_handle);
| |
m_dSupport = (float)FileReadDouble(file_handle);
| |
CMyTreeNode *point = GetPointer(this);
| |
//---
| |
for(int i = 0; i < m_data_total; i++)
| |
{
| |
CMyTreeNode *temp = m_data[i];
| |
if(!temp)
| |
{
| |
if(Delete(i))
| |
i--;
| |
continue;
| |
}
| |
temp.Parent(point);
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
|