2026-01-05 16:50:37 -03:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| UnitTests.mq5 |
|
|
|
|
|
//| Douglas Rechia |
|
|
|
|
|
//| https://www.mql5.com |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#property copyright "Douglas Rechia"
|
|
|
|
|
#property link "https://www.mql5.com"
|
|
|
|
|
#property version "2.00"
|
|
|
|
|
|
2026-02-03 10:27:54 -03:00
|
|
|
#include "../knitpkg/include/douglasrechia/bar/BarMqlRates.mqh"
|
|
|
|
|
#include "../knitpkg/include/douglasrechia/bar/BarWatcher.mqh"
|
|
|
|
|
#include "../knitpkg/include/douglasrechia/bar/TimeSeriesArray.mqh"
|
2026-01-05 16:50:37 -03:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestBarRefresh()
|
|
|
|
|
{
|
|
|
|
|
BarMqlRates bar(_Symbol, PERIOD_CURRENT);
|
|
|
|
|
if(!bar.Refresh(5))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
MqlRates m_rates[];
|
|
|
|
|
ArraySetAsSeries(m_rates, true);
|
|
|
|
|
|
|
|
|
|
if(CopyRates(_Symbol, PERIOD_CURRENT, 0, 10, m_rates) <= 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return bar.Close(1) == m_rates[1].close &&
|
|
|
|
|
bar.Close(2) == m_rates[2].close &&
|
|
|
|
|
bar.Close(3) == m_rates[3].close &&
|
|
|
|
|
bar.Close(4) == m_rates[4].close &&
|
|
|
|
|
bar.Size() == 5;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestNewBar()
|
|
|
|
|
{
|
|
|
|
|
BarWatcher watcher(_Symbol, PERIOD_M1);
|
|
|
|
|
watcher.Update();
|
|
|
|
|
|
|
|
|
|
bool ok;
|
|
|
|
|
ok = watcher.IsFirstTick() && !watcher.IsNewBar();
|
|
|
|
|
|
|
|
|
|
datetime now=TimeLocal();
|
|
|
|
|
int nowint = (int)now;
|
|
|
|
|
int wait=((int)(nowint/60)+1)*60-nowint+2;
|
|
|
|
|
|
|
|
|
|
PrintFormat("Waiting for a new bar - %d seconds...", wait);
|
|
|
|
|
Sleep(wait*1000);
|
|
|
|
|
|
|
|
|
|
watcher.Update();
|
|
|
|
|
ok = !watcher.IsFirstTick() && watcher.IsNewBar();
|
|
|
|
|
if(!ok)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("Watcher failed. Check if market is open, this test could fail if %s don't get updated from the server", _Symbol);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watcher.Update();
|
|
|
|
|
ok = !watcher.IsFirstTick() && !watcher.IsNewBar();
|
|
|
|
|
|
|
|
|
|
if(!ok)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("Watcher failed. Check if market is open, this test could fail if %s don't get updated from the server", _Symbol);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestBarSeries()
|
|
|
|
|
{
|
|
|
|
|
BarMqlRates bar(_Symbol, PERIOD_CURRENT);
|
|
|
|
|
if(!bar.Refresh(5))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
bar.TimeSeries().ValueAtShift(0) == bar.Time(0) &&
|
|
|
|
|
bar.TimeSeries().ValueAtShift(1) == bar.Time(1) &&
|
|
|
|
|
bar.TimeSeries().ValueAtShift(2) == bar.Time(2) &&
|
|
|
|
|
bar.TimeSeries().ValueAtShift(3) == bar.Time(3) &&
|
|
|
|
|
bar.TimeSeries().ValueAtShift(4) == bar.Time(4) &&
|
|
|
|
|
bar.OpenSeries().ValueAtShift(0) == bar.Open(0) &&
|
|
|
|
|
bar.OpenSeries().ValueAtShift(1) == bar.Open(1) &&
|
|
|
|
|
bar.OpenSeries().ValueAtShift(2) == bar.Open(2) &&
|
|
|
|
|
bar.OpenSeries().ValueAtShift(3) == bar.Open(3) &&
|
|
|
|
|
bar.OpenSeries().ValueAtShift(4) == bar.Open(4) &&
|
|
|
|
|
bar.HighSeries().ValueAtShift(0) == bar.High(0) &&
|
|
|
|
|
bar.HighSeries().ValueAtShift(1) == bar.High(1) &&
|
|
|
|
|
bar.HighSeries().ValueAtShift(2) == bar.High(2) &&
|
|
|
|
|
bar.HighSeries().ValueAtShift(3) == bar.High(3) &&
|
|
|
|
|
bar.HighSeries().ValueAtShift(4) == bar.High(4) &&
|
|
|
|
|
bar.LowSeries().ValueAtShift(0) == bar.Low(0) &&
|
|
|
|
|
bar.LowSeries().ValueAtShift(1) == bar.Low(1) &&
|
|
|
|
|
bar.LowSeries().ValueAtShift(2) == bar.Low(2) &&
|
|
|
|
|
bar.LowSeries().ValueAtShift(3) == bar.Low(3) &&
|
|
|
|
|
bar.LowSeries().ValueAtShift(4) == bar.Low(4) &&
|
|
|
|
|
bar.CloseSeries().ValueAtShift(0) == bar.Close(0) &&
|
|
|
|
|
bar.CloseSeries().ValueAtShift(1) == bar.Close(1) &&
|
|
|
|
|
bar.CloseSeries().ValueAtShift(2) == bar.Close(2) &&
|
|
|
|
|
bar.CloseSeries().ValueAtShift(3) == bar.Close(3) &&
|
|
|
|
|
bar.CloseSeries().ValueAtShift(4) == bar.Close(4) &&
|
|
|
|
|
bar.VolumeSeries().ValueAtShift(0) == bar.Volume(0) &&
|
|
|
|
|
bar.VolumeSeries().ValueAtShift(1) == bar.Volume(1) &&
|
|
|
|
|
bar.VolumeSeries().ValueAtShift(2) == bar.Volume(2) &&
|
|
|
|
|
bar.VolumeSeries().ValueAtShift(3) == bar.Volume(3) &&
|
|
|
|
|
bar.VolumeSeries().ValueAtShift(4) == bar.Volume(4) &&
|
|
|
|
|
bar.TickVolumeSeries().ValueAtShift(0) == bar.TickVolume(0) &&
|
|
|
|
|
bar.TickVolumeSeries().ValueAtShift(1) == bar.TickVolume(1) &&
|
|
|
|
|
bar.TickVolumeSeries().ValueAtShift(2) == bar.TickVolume(2) &&
|
|
|
|
|
bar.TickVolumeSeries().ValueAtShift(3) == bar.TickVolume(3) &&
|
|
|
|
|
bar.TickVolumeSeries().ValueAtShift(4) == bar.TickVolume(4) &&
|
|
|
|
|
bar.OpenSeries().Size() == bar.Size();
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayInt(const int &arrayInt[])
|
|
|
|
|
{
|
|
|
|
|
TimeSeriesArray<int> arrayIntS(arrayInt, -1, -1, true);
|
|
|
|
|
|
|
|
|
|
return arrayIntS.Size() == ArraySize(arrayInt) &&
|
|
|
|
|
arrayIntS.ValueAtShift(0) == arrayInt[0] &&
|
|
|
|
|
arrayIntS.ValueAtShift(1) == arrayInt[1] &&
|
|
|
|
|
arrayIntS.ValueAtShift(2) == arrayInt[2] &&
|
|
|
|
|
arrayIntS.ValueAtShift(3) == arrayInt[3];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayInt1()
|
|
|
|
|
{
|
|
|
|
|
int arrayInt[] = {0, 2, 4, 6, 8};
|
|
|
|
|
|
|
|
|
|
return TestArrayInt(arrayInt);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayDouble(const double &arrayD[])
|
|
|
|
|
{
|
|
|
|
|
TimeSeriesArray<double> arrayDS(arrayD, -1, -1, true);
|
|
|
|
|
|
|
|
|
|
return arrayDS.Size() == ArraySize(arrayD) &&
|
|
|
|
|
arrayDS.ValueAtShift(0) == arrayD[0] &&
|
|
|
|
|
arrayDS.ValueAtShift(1) == arrayD[1] &&
|
|
|
|
|
arrayDS.ValueAtShift(2) == arrayD[2];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayDouble1()
|
|
|
|
|
{
|
|
|
|
|
double arrayD[] = {1.2, 3.4, 6.4, 3.6};
|
|
|
|
|
|
|
|
|
|
return TestArrayDouble(arrayD);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayDouble2()
|
|
|
|
|
{
|
|
|
|
|
double arrayD[] = {1.2, 3.4, 6.4, 3.6};
|
|
|
|
|
|
|
|
|
|
TimeSeriesArray<double> arrayDS(arrayD, -1, -1, false);
|
|
|
|
|
|
|
|
|
|
return arrayDS.Size() == ArraySize(arrayD) &&
|
|
|
|
|
arrayDS.ValueAtShift(3) == arrayD[0] &&
|
|
|
|
|
arrayDS.ValueAtShift(2) == arrayD[1] &&
|
|
|
|
|
arrayDS.ValueAtShift(1) == arrayD[2] &&
|
|
|
|
|
arrayDS.ValueAtShift(0) == arrayD[3];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayDouble3()
|
|
|
|
|
{
|
|
|
|
|
double arrayD[] = {1.2, 3.4, 6.4, 3.6, 5, 6, 8, 4};
|
|
|
|
|
|
|
|
|
|
TimeSeriesArray<double> arrayDS(arrayD, 2, 4, false);
|
|
|
|
|
|
|
|
|
|
return arrayDS.Size() == 3 &&
|
|
|
|
|
arrayDS.ValueAtShift(2) == arrayD[2] &&
|
|
|
|
|
arrayDS.ValueAtShift(1) == arrayD[3] &&
|
|
|
|
|
arrayDS.ValueAtShift(0) == arrayD[4];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool TestArrayDouble4()
|
|
|
|
|
{
|
|
|
|
|
double arrayD[] = {1.2, 3.4, 6.4, 3.6, 5, 6, 8, 4};
|
|
|
|
|
|
|
|
|
|
TimeSeriesArray<double> arrayDS(arrayD, 2, 4, true);
|
|
|
|
|
|
|
|
|
|
return arrayDS.Size() == 3 &&
|
|
|
|
|
arrayDS.ValueAtShift(2) == arrayD[4] &&
|
|
|
|
|
arrayDS.ValueAtShift(1) == arrayD[3] &&
|
|
|
|
|
arrayDS.ValueAtShift(0) == arrayD[2];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| DoTests |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void DoTests(int &tests_performed,int &tests_passed)
|
|
|
|
|
{
|
|
|
|
|
string test_name="";
|
|
|
|
|
|
|
|
|
|
//--- TestBarRefresh
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestBarRefresh";
|
|
|
|
|
if(TestBarRefresh())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestBarSeries
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestBarSeries";
|
|
|
|
|
if(TestBarSeries())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestArrayInt1
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestArrayInt1";
|
|
|
|
|
if(TestArrayInt1())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestArrayDouble1
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestArrayDouble1";
|
|
|
|
|
if(TestArrayDouble1())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestArrayDouble2
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestArrayDouble2";
|
|
|
|
|
if(TestArrayDouble2())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestArrayDouble3
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestArrayDouble3";
|
|
|
|
|
if(TestArrayDouble3())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestArrayDouble4
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestArrayDouble4";
|
|
|
|
|
if(TestArrayDouble4())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
//--- TestNewBar
|
|
|
|
|
tests_performed++;
|
|
|
|
|
test_name="TestNewBar";
|
|
|
|
|
if(TestNewBar())
|
|
|
|
|
{
|
|
|
|
|
tests_passed++;
|
|
|
|
|
PrintFormat("%s pass",test_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
PrintFormat("%s failed",test_name);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| UnitTests() |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void UnitTests(const string package_name)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("Unit tests for Package %s\n",package_name);
|
|
|
|
|
//--- initial values
|
|
|
|
|
int tests_performed=0;
|
|
|
|
|
int tests_passed=0;
|
|
|
|
|
//--- test distributions
|
|
|
|
|
DoTests(tests_performed,tests_passed);
|
|
|
|
|
//--- print statistics
|
|
|
|
|
PrintFormat("\n%d of %d passed",tests_passed,tests_performed);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Script program start function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void OnStart()
|
|
|
|
|
{
|
|
|
|
|
UnitTests("BarMqlRates");
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|