190 lines
6.9 KiB
MQL5
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");
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|