| //+------------------------------------------------------------------+
|
| //| AsocRules.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 "MyTreeNode.mqh"
|
| //---
|
| class CAssocRules : public CObject
|
| {
|
| protected:
|
| CMyTreeNode m_cRoot;
|
| CMyTreeNode m_cBuyRules;
|
| CMyTreeNode m_cSellRules;
|
| vectorf m_vMin;
|
| vectorf m_vStep;
|
| int m_iSections;
|
| matrixf m_mPositions;
|
| matrixf m_BuyPositions;
|
| matrixf m_SellPositions;
|
| //---
|
| bool NewPath(CMyTreeNode *root, matrixf &path);
|
| CMyTreeNode *CheckPath(CMyTreeNode *root, vectorf &path);
|
| //---
|
| bool PrepaerData(matrixf &data, matrixf &bin_data, vectorf &buy, vectorf &sell, const int sections = 10, const float min_sup = 0.03f);
|
| matrixf CreatePath(vectorf &bin_data, matrixf &positions);
|
| matrixf CreatePositions(vectorf &support, const float min_sup = 0.03f);
|
| bool GrowsTree(CMyTreeNode *root, matrixf &bin_data, matrixf &positions);
|
| float Probability(CMyTreeNode *root, vectorf &data, matrixf &positions);
|
|
|
| public:
|
| CAssocRules();
|
| ~CAssocRules();
|
| //---
|
| bool CreateRules(matrixf &data, vectorf &buy, vectorf &sell, int sections = 10, float min_freq = 0.03f, float min_prob = 0.3f);
|
| bool Probability(vectorf &data, float &buy, float &sell);
|
| //--- methods for working with files
|
| virtual bool Save(const int file_handle);
|
| virtual bool Load(const int file_handle);
|
| virtual bool Save(const string file_name);
|
| virtual bool Load(const string file_name);
|
| };
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | C As so cR ul es implementation. |
|
| //+------------------------------------------------------------------+
|
| CAssocRules::CAssocRules() : m_iSections(10)
|
| {
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CAssocRules::~CAssocRules()
|
| {
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | N ew Pa th implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::NewPath(CMyTreeNode *root, matrixf &path)
|
| {
|
| ulong total = path.Cols();
|
| if(total <= 0)
|
| return false;
|
| CMyTreeNode *parent = root;
|
| root.IncreaseSupport(path[1, 0]);
|
| for(ulong i = 0; i < total; i++)
|
| {
|
| CMyTreeNode *temp = parent.GetNext((ulong)path[0, i]);
|
| if(!temp)
|
| {
|
| temp = parent.AddNode((int)path[0, i], 0);
|
| if(!temp)
|
| return false;
|
| }
|
| temp.IncreaseSupport(path[1, i]);
|
| parent = temp;
|
| }
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | C re at eR ul es implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::CreateRules(matrixf &data, vectorf &buy, vectorf &sell, int sections = 10, float min_sup = 0.03f, float min_conf = 0.3f)
|
| {
|
| if(data.Rows() <= 0 || data.Cols() <= 0 || sections <= 0 ||
|
| data.Rows() != buy.Size() || data.Rows() != sell.Size())
|
| return false;
|
| //---
|
| matrixf binary_data;
|
| if(!PrepaerData(data, binary_data, buy, sell, sections))
|
| return false;
|
| //---
|
| double k = 1.0 / (double)(binary_data.Rows());
|
| if(!GrowsTree(GetPointer(m_cRoot), binary_data * k, m_mPositions))
|
| return false;
|
| //--- create buy rules
|
| vectorf supports = vectorf::Zeros(binary_data.Cols());
|
| binary_data = matrixf::Zeros(0, binary_data.Cols());
|
| if(!m_cRoot.Mining(supports, binary_data, m_cBuyRules.ID(), min_conf))
|
| return false;
|
| supports[m_cBuyRules.ID()] = 0;
|
| m_BuyPositions = CreatePositions(supports, min_sup);
|
| if(m_BuyPositions.Rows() > 0)
|
| if(!GrowsTree(GetPointer(m_cBuyRules), binary_data, m_BuyPositions))
|
| return false;
|
| //--- create sell rules
|
| supports = vectorf::Zeros(binary_data.Cols());
|
| binary_data = matrixf::Zeros(0, binary_data.Cols());
|
| if(!m_cRoot.Mining(supports, binary_data, m_cSellRules.ID(), min_conf))
|
| return false;
|
| supports[m_cSellRules.ID()] = 0;
|
| m_SellPositions = CreatePositions(supports, min_sup);
|
| if(m_SellPositions.Rows() > 0)
|
| if(!GrowsTree(GetPointer(m_cSellRules), binary_data, m_SellPositions))
|
| return false;
|
| //---
|
| m_cRoot.Clear();
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | P re pa er Da ta implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::PrepaerData(matrixf & data, matrixf & bin_data, vectorf & buy, vectorf & sell, const int sections = 10, const float min_sup = 0.03f)
|
| {
|
| //---
|
| m_iSections = sections;
|
| m_vMin = data.Min(0);
|
| vectorf max = data.Max(0);
|
| vectorf delt = max - m_vMin;
|
| m_vStep = delt / sections + 1e-8;
|
| m_cBuyRules.ID(data.Cols() * m_iSections);
|
| m_cSellRules.ID(m_cBuyRules.ID() + 1);
|
| bin_data = matrixf::Zeros(data.Rows(), m_cSellRules.ID() + 1);
|
| for(ulong r = 0; r < data.Rows(); r++)
|
| {
|
| vectorf pos = (data.Row(r) - m_vMin) / m_vStep;
|
| if(!pos.Clip(0, m_iSections - 1))
|
| return false;
|
| for(ulong c = 0; c < pos.Size(); c++)
|
| bin_data[r, c * sections + (int)pos[c]] = 1;
|
| }
|
| if(!bin_data.Col(buy, m_cBuyRules.ID()) ||
|
| !bin_data.Col(sell, m_cSellRules.ID()))
|
| return false;
|
| vectorf supp = bin_data.Sum(0) / bin_data.Rows();
|
| m_mPositions = CreatePositions(supp, min_sup);
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | P ro ba bi li ty implementation. |
|
| //+------------------------------------------------------------------+
|
| float CAssocRules::Probability(CMyTreeNode * root, vectorf & data, matrixf & positions)
|
| {
|
| if(m_cRoot.Total() <= 0)
|
| return 0;
|
| if(data.Size() != m_vMin.Size())
|
| return 0;
|
| vectorf pos = (data - m_vMin) / m_vStep;
|
| if(!pos.Clip(0, m_iSections - 1))
|
| return 0;
|
| vectorf bin_data = vectorf::Zeros(data.Size() * m_iSections);
|
| for(ulong c = 0; c < pos.Size(); c++)
|
| bin_data[c * m_iSections + (int)pos[c]] = 1;
|
| matrixf path = CreatePath(bin_data, positions);
|
| CMyTreeNode *temp = CheckPath(root, path.Row(0));
|
| if(!temp)
|
| return 0;
|
| if(temp.Total() > 0)
|
| return 0;
|
| //---
|
| return temp.GetConfidence();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | C re at eP at h implementation. |
|
| //+------------------------------------------------------------------+
|
| matrixf CAssocRules::CreatePath(vectorf & bin_data, matrixf & positions)
|
| {
|
| ulong size = bin_data.Size();
|
| //---
|
| ulong total = positions.Rows();
|
| int vect_pos = 0;
|
| matrixf path = matrixf::Zeros(2, total);
|
| for(ulong c = 0; c < total; c++)
|
| {
|
| ulong pos = (ulong)positions[c, 0];
|
| if(pos >= size)
|
| continue;
|
| if(bin_data[pos] == 0)
|
| continue;
|
| path[0, vect_pos] = (float)pos;
|
| path[1, vect_pos] = bin_data[pos];
|
| vect_pos++;
|
| }
|
| if(!path.Resize(2, vect_pos))
|
| return matrixf::Zeros(0, 0);
|
| //---
|
| return path;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CMyTreeNode *CAssocRules::CheckPath(CMyTreeNode * root, vectorf & path)
|
| {
|
| ulong total = path.Size();
|
| CMyTreeNode *node = root;
|
| for(ulong i = 0; i < total; i++)
|
| {
|
| node = node.GetNext((ulong)path[i]);
|
| if(!node)
|
| break;
|
| }
|
| //---
|
| return node;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | C re at eP os it io ns implementation. |
|
| //+------------------------------------------------------------------+
|
| matrixf CAssocRules::CreatePositions(vectorf &support, const float min_sup = 0.03f)
|
| {
|
| matrixf result = matrixf::Ones(support.Size(), 2);
|
| result = result.CumSum(0) - 1;
|
| if(!result.Col(support, 1))
|
| return matrixf::Zeros(0, 0);
|
| bool change = false;
|
| do
|
| {
|
| change = false;
|
| ulong total = result.Rows() - 1;
|
| for(ulong i = 0; i < total; i++)
|
| {
|
| if(result[i, 1] >= result[i + 1, 1])
|
| continue;
|
| if(result.SwapRows(i, i + 1))
|
| change = true;
|
| }
|
| }
|
| while(change);
|
| int i = 0;
|
| while(result[i, 1] >= min_sup)
|
| i++;
|
| if(!result.Resize(i, 2))
|
| return matrixf::Zeros(0, 0);
|
| //---
|
| return result;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | G ro ws Tr ee implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::GrowsTree(CMyTreeNode * root, matrixf & bin_data, matrixf &positions)
|
| {
|
| ulong rows = bin_data.Rows();
|
| for(ulong r = 0; r < rows; r++)
|
| {
|
| matrixf path = CreatePath(bin_data.Row(r), positions);
|
| ulong size = path.Cols();
|
| if(size <= 0)
|
| continue;
|
| if(!NewPath(root, path))
|
| return false;
|
| }
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | P ro ba bi li ty implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::Probability(vectorf &data, float &buy, float &sell)
|
| {
|
| buy = Probability(GetPointer(m_cBuyRules), data, m_BuyPositions);
|
| sell = Probability(GetPointer(m_cSellRules), data, m_BuyPositions);
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | S av e implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::Save(const string file_name)
|
| {
|
| if(file_name == NULL)
|
| return false;
|
| //---
|
| int handle = FileOpen(file_name, FILE_WRITE | FILE_BIN);
|
| bool result = Save(handle);
|
| FileClose(handle);
|
| return result;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | L oa d implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::Load(const string file_name)
|
| {
|
| if(file_name == NULL)
|
| return false;
|
| //---
|
| int handle = FileOpen(file_name, FILE_READ | FILE_BIN);
|
| bool result = Load(handle);
|
| FileClose(handle);
|
| return result;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | S av e implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::Save(const int file_handle)
|
| {
|
| if(!m_cBuyRules.Save(file_handle) ||
|
| !m_cSellRules.Save(file_handle))
|
| return false;
|
| //---
|
| ulong rows = m_BuyPositions.Rows();
|
| ulong cols = m_BuyPositions.Cols();
|
| if(FileWriteLong(file_handle, rows) < sizeof(rows) ||
|
| FileWriteLong(file_handle, cols) < sizeof(cols))
|
| return false;
|
| for(ulong r = 0; r < rows; r++)
|
| for(ulong c = 0; c < cols; c++)
|
| if(FileWriteDouble(file_handle, m_BuyPositions[r, c]) < sizeof(m_BuyPositions[r, c]))
|
| return false;
|
| //---
|
| rows = m_SellPositions.Rows();
|
| cols = m_SellPositions.Cols();
|
| if(FileWriteLong(file_handle, rows) < sizeof(rows) ||
|
| FileWriteLong(file_handle, cols) < sizeof(cols))
|
| return false;
|
| for(ulong r = 0; r < rows; r++)
|
| for(ulong c = 0; c < cols; c++)
|
| if(FileWriteDouble(file_handle, m_SellPositions[r, c]) < sizeof(m_SellPositions[r, c]))
|
| return false;
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //| | L oa d implementation. |
|
| //+------------------------------------------------------------------+
|
| bool CAssocRules::Load(const int file_handle)
|
| {
|
| if(!m_cBuyRules.Load(file_handle) ||
|
| !m_cSellRules.Load(file_handle))
|
| return false;
|
| //---
|
| ulong rows = FileReadLong(file_handle);
|
| ulong cols = FileReadLong(file_handle);
|
| if(!m_BuyPositions.Resize(rows, cols))
|
| return false;
|
| for(ulong r = 0; r < rows; r++)
|
| for(ulong c = 0; c < cols; c++)
|
| m_BuyPositions[r, c] = (float)FileReadDouble(file_handle);
|
| //---
|
| rows = FileReadLong(file_handle);
|
| cols = FileReadLong(file_handle);
|
| if(!m_SellPositions.Resize(rows, cols))
|
| return false;
|
| for(ulong r = 0; r < rows; r++)
|
| for(ulong c = 0; c < cols; c++)
|
| m_SellPositions[r, c] = (float)FileReadDouble(file_handle);
|
| //---
|
| return true;
|
| }
|
| //+------------------------------------------------------------------+
|
|
|