barhelper/tests/UnitTests.mq5
2026-02-12 10:12:42 -03:00

190 lines
6.9 KiB
MQL5

//+------------------------------------------------------------------+
//| UnitTests.mq5 |
//| Unit Tests for Package barhelper |
//| Organization: douglasrechia |
//+------------------------------------------------------------------+
#property copyright "Douglas Rechia"
#property link "https://knitpkg.dev"
#property description ""
#property description "Version: 1.0.0"
#property description ""
#property description "Description: Unit tests for package barhelper"
#property description "Organization: douglasrechia"
#property description "Author: Douglas Rechia"
#property description "License: MIT"
#property description ""
#property description "Powered by KnitPkg for MetaTrader"
#property description "https://knitpkg.dev"
// Include the headers under test
#include "../knitpkg/include/douglasrechia/barhelper/Cross.mqh"
//+------------------------------------------------------------------+
//| Tests CrossUp when series1 crosses up series2 |
//+------------------------------------------------------------------+
bool TestBasicScenario1()
{
double array2[] = {0.99, 0.98, 1.00, 1.00, 1.03, 1.04, 1.02};
double array1[] = {1.00, 1.01, 1.01, 1.01, 1.02, 1.01, 1.03};
bool expected[] = {false, false, false, false, false, false, true};
douglasrechia::TimeSeriesArray<double> series1(array1, -1, -1, false);
douglasrechia::TimeSeriesArray<double> series2(array2, -1, -1, false);
for(int i=5;i>=0;i--)
{
// expected index is in the inverse order because TimeSeries index 0 is the latest element
if(douglasrechia::CrossUp(series1, series2, i) != expected[ArraySize(expected)-i-1])
{
Print(StringFormat("Fail at shift %d", i));
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
//| Tests CrossUp when series2 crosses up series1 |
//+------------------------------------------------------------------+
bool TestBasicScenario2()
{
double array1[] = {1.00, 1.01, 1.01, 1.01, 1.02, 1.01, 1.03};
double array2[] = {0.99, 0.98, 1.00, 1.00, 1.03, 1.04, 1.02};
bool expected[] = {false, false, false, false, true, false, false};
douglasrechia::TimeSeriesArray<double> series1(array1, -1, -1, false);
douglasrechia::TimeSeriesArray<double> series2(array2, -1, -1, false);
for(int i=5;i>=0;i--)
{
// expected index is in the inverse order because TimeSeries index 0 is the latest element
if(douglasrechia::CrossUp(series2, series1, i) != expected[ArraySize(expected)-i-1])
{
Print(StringFormat("Fail at shift %d", i));
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
//| Tests CrossUp returns false when shift is out of bounds |
//+------------------------------------------------------------------+
bool TestShiftOutOfBounds()
{
double array1[] = {1.00, 1.01, 1.01, 1.01, 1.02, 1.01, 1.03};
double array2[] = {1.00, 1.03, 1.04, 1.02};
douglasrechia::TimeSeriesArray<double> series1(array1, -1, -1, false);
douglasrechia::TimeSeriesArray<double> series2(array2, -1, -1, false);
for(int i=3;i<10;i++)
if(douglasrechia::CrossUp(series2, series1, i) != false)
{
Print(StringFormat("Fail at shift %d", i));
return false;
}
for(int i=-1;i>-5;i--)
if(douglasrechia::CrossUp(series2, series1, i) != false)
{
Print(StringFormat("Fail at shift %d", i));
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Tests Cross detects crossings in either direction |
//+------------------------------------------------------------------+
bool TestCross()
{
double array1[] = {1.00, 1.01, 1.01, 1.01, 1.02, 1.01, 1.03};
double array2[] = {0.99, 0.98, 1.00, 1.00, 1.03, 1.04, 1.02};
bool expected[] = {false, false, false, false, true, false, true};
douglasrechia::TimeSeriesArray<double> series1(array1, -1, -1, false);
douglasrechia::TimeSeriesArray<double> series2(array2, -1, -1, false);
for(int i=5;i>=0;i--)
{
// expected index is in the inverse order because TimeSeries index 0 is the latest element
if(douglasrechia::Cross(series2, series1, i) != expected[ArraySize(expected)-i-1])
{
Print(StringFormat("Fail at shift %d", i));
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
//| DoTests |
//+------------------------------------------------------------------+
void DoTests(int &testsPerformed,int &testsPassed)
{
string testName="";
//--- TestBasicScenario1
testsPerformed++;
testName="TestBasicScenario1";
if(TestBasicScenario1())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//---
testsPerformed++;
testName="TestBasicScenario2";
if(TestBasicScenario2())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//---
testsPerformed++;
testName="TestShiftOutOfBounds";
if(TestShiftOutOfBounds())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//---
testsPerformed++;
testName="TestCross";
if(TestCross())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
}
//+------------------------------------------------------------------+
//| UnitTests() |
//+------------------------------------------------------------------+
void UnitTests(const string packageName)
{
PrintFormat("Unit tests for Package %s\n",packageName);
//--- initial values
int testsPerformed=0;
int testsPassed=0;
//--- test distributions
DoTests(testsPerformed,testsPassed);
//--- print statistics
PrintFormat("\n%d of %d passed",testsPassed,testsPerformed);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
UnitTests("barhelper");
}
//+------------------------------------------------------------------+