last backup ...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,877 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class
|
||||
// -------------------------------------------------
|
||||
// Name: XCXOM1Signaller ...
|
||||
// Description: XOM1EA Signaller Class ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property description "SaherElm XOM1EA Signaller Class"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include "../../Helpers/x-saherelm.xom1.helper.mq5"
|
||||
#include "../Classes/xom1ea.x-poi.drawer.class.mq5"
|
||||
#include "../Libraries/xom1ea.lib.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// All Available Signaller Configurations
|
||||
// which allow to Decide Based on Zones ...
|
||||
struct XOM1SignallerConfig
|
||||
{
|
||||
//
|
||||
// Props ...
|
||||
bool processAllTicks; // Do Process All Ticks ...
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XOM1SignallerConfig()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
/**
|
||||
* Cleanup ...
|
||||
*/
|
||||
void Clean()
|
||||
{
|
||||
ZeroMemory(this);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Implementation ...
|
||||
|
||||
//
|
||||
// Base Signaller Class ...
|
||||
// Provides Zone Detection Mechanism ...
|
||||
class XCXOM1SignallerBase
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Props ...
|
||||
string name; // Name ...
|
||||
string symbol; // Symbol ...
|
||||
XOM1Zone zones[]; // Detected Zones ...
|
||||
XOM1Inputs inputs; // Indicator Inputs ...
|
||||
ENUM_TIMEFRAMES period; // Period ...
|
||||
XCXOM1POIDrawer drawer; // POI Drawer ...
|
||||
XOM1SignallerConfig config; // Configuration ...
|
||||
TCanAnalyse canAnalyseEventListener; // CanAnalyse Event Listener ...
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XCXOM1SignallerBase(
|
||||
string _name, // Name ...
|
||||
string _symbol, // Symbol ...
|
||||
ENUM_TIMEFRAMES _period, // Period ...
|
||||
XOM1Inputs &_inputs, // Indicator Inputs ...
|
||||
XOM1SignallerConfig &_config // Config ...
|
||||
)
|
||||
{
|
||||
//
|
||||
// Validate ...
|
||||
bool isValid =
|
||||
IsSpecifiedValid(_name) &&
|
||||
IsSpecifiedValid(_symbol) &&
|
||||
IsSpecifiedValid(_period) &&
|
||||
_inputs.IsValid();
|
||||
if (!isValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Make Helper Class Instance ...
|
||||
mHelper = new XCXOM1Helper();
|
||||
bool isInited = mHelper.Init(
|
||||
_symbol,
|
||||
_period,
|
||||
_inputs //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
//
|
||||
delete mHelper;
|
||||
ZeroMemory(mHelper);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Props ...
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
period = _period;
|
||||
inputs = _inputs;
|
||||
config = _config;
|
||||
|
||||
//
|
||||
// Set Dfault Values ...
|
||||
mProcessedTicksCount = 0;
|
||||
mLastCheckedBarTime = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XCXOM1SignallerBase()
|
||||
{
|
||||
//
|
||||
inputs.Clean();
|
||||
|
||||
//
|
||||
SpecifiedClean(zones);
|
||||
|
||||
//
|
||||
delete mHelper;
|
||||
ZeroMemory(mHelper);
|
||||
}
|
||||
|
||||
//
|
||||
// Signal Event Handlers ...
|
||||
|
||||
//
|
||||
void AddOnSignalEventHandler(TOnSignal handler)
|
||||
{
|
||||
//
|
||||
if (handler == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
Add(
|
||||
handler,
|
||||
mOnSignalEventHandlers //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
void NotifyOnSignalEvent(XSignal &signal)
|
||||
{
|
||||
//
|
||||
int count = ArraySize(mOnSignalEventHandlers);
|
||||
bool has = IsValidSize(count) && signal.IsValid();
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Calling Event Handlers ...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
mOnSignalEventHandlers[i](signal);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Actions ...
|
||||
|
||||
/**
|
||||
* Handle Ticks Process ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
virtual void ProcessTick(int barIndex = 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Guards Based on MarketConditions ...
|
||||
*
|
||||
* @param guards: XGuard[]
|
||||
* @param barIndex: int
|
||||
*
|
||||
* @return ( int )
|
||||
*/
|
||||
int CheckForGuard(
|
||||
XGuard &guards[],
|
||||
int barIndex = 0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
SpecifiedClean(guards);
|
||||
|
||||
//
|
||||
result = ArraySize(guards);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Virtuals ...
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
XCXOM1Helper *mHelper; // Indicator Helper ...
|
||||
|
||||
//
|
||||
int mProcessedTicksCount; // Prcoessed Ticks Count ...
|
||||
datetime mLastCheckedBarTime; // Last Checked Bar Time ...
|
||||
|
||||
/**
|
||||
* Check Permissions for Analysing Market ...
|
||||
*
|
||||
* @param _symbol: Symbol ...
|
||||
* @param _period: Period ...
|
||||
* @param time: Specified Date Time ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool CanAnalyse(
|
||||
string _symbol,
|
||||
ENUM_TIMEFRAMES _period,
|
||||
datetime time //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
if (canAnalyseEventListener != NULL)
|
||||
{
|
||||
//
|
||||
result = canAnalyseEventListener(
|
||||
_symbol,
|
||||
_period,
|
||||
time //
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle New Bar's Process ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
void ProcessNewBar(int barIndex = 0)
|
||||
{
|
||||
//
|
||||
// Normalize Bar Index ...
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to Update Zone's Lifetime ...
|
||||
int count = ArraySize(zones);
|
||||
bool has = count > 0;
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Loop through Zones ...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//
|
||||
// Update Lifetime by Bar Index ...
|
||||
// zones[i].UpdateByBarIndex(barIndex);
|
||||
|
||||
//
|
||||
// drawer.DrawZone(
|
||||
// zones[i],
|
||||
// true, // Draw Price ...
|
||||
// true, // Draw Middle ...
|
||||
// true // Draw From ...
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check XOMZones Validations ...
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Exists Zones ...
|
||||
* Detect a Zone for trigger ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
void ProcessZones(int barIndex = 0)
|
||||
{
|
||||
//
|
||||
// Check Zones Exists ...
|
||||
int count = ArraySize(zones);
|
||||
bool has = IsValidSize(count);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop Through Zones ...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts iZone to Signal and Notify Signal ...
|
||||
*
|
||||
* @param iZone: XOM1Zone
|
||||
*/
|
||||
void PrepareSignal(XOM1Zone &zone)
|
||||
{
|
||||
//
|
||||
// Validate Zone ...
|
||||
if (!zone.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Create Signal ...
|
||||
XSignal signal;
|
||||
|
||||
//
|
||||
signal.time = zone.to;
|
||||
signal.provider = name;
|
||||
signal.symbol = zone.symbol;
|
||||
signal.period = zone.period;
|
||||
signal.mode = X_ORDER_MODE_MARKET;
|
||||
signal.conditions = "XConditions";
|
||||
signal.comment = ToXString(zone.reason);
|
||||
signal.type = zone.IsBullish()
|
||||
? POSITION_TYPE_BUY
|
||||
: POSITION_TYPE_SELL;
|
||||
|
||||
//
|
||||
// Get Entry ...
|
||||
signal.entry = GetXEntry(zone.symbol, zone.dir);
|
||||
|
||||
//
|
||||
// Calculate SL ...
|
||||
double providedSL = zone.IsBullish()
|
||||
? zone.lower
|
||||
: zone.upper;
|
||||
signal.sl = providedSL;
|
||||
|
||||
//
|
||||
// Calculate Risk ...
|
||||
double risk = MathAbs(signal.entry - signal.sl);
|
||||
|
||||
//
|
||||
// Calculate Reward ...
|
||||
double r2r = 2;
|
||||
double reward = risk * r2r;
|
||||
|
||||
//
|
||||
// Calculate TP ...
|
||||
double providedTP = zone.IsBullish()
|
||||
? signal.entry + reward
|
||||
: signal.entry - reward;
|
||||
signal.tp = providedTP;
|
||||
|
||||
//
|
||||
// Calculate Targets ...
|
||||
// TODO: Handle this ...
|
||||
|
||||
//
|
||||
// Set Min Volume ...
|
||||
signal.volume = 0.01;
|
||||
|
||||
//
|
||||
NotifyOnSignalEvent(signal);
|
||||
}
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
TOnSignal mOnSignalEventHandlers[]; // Signal Recieved Event Handlers ...
|
||||
};
|
||||
|
||||
//
|
||||
class XCXOM1FIMASignaller : public XCXOM1SignallerBase
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XCXOM1FIMASignaller(
|
||||
string _name, // Name ...
|
||||
string _symbol, // Symbol ...
|
||||
ENUM_TIMEFRAMES _period, // Period ...
|
||||
XOM1Inputs &_inputs, // Indicator Inputs ...
|
||||
XOM1SignallerConfig &_config // Config ...
|
||||
) : XCXOM1SignallerBase(_name,
|
||||
_symbol,
|
||||
_period,
|
||||
_inputs,
|
||||
_config //
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XCXOM1FIMASignaller()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Overrides ...
|
||||
|
||||
/**
|
||||
* Handle Ticks Process ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
virtual void ProcessTick(int barIndex = 0)
|
||||
{
|
||||
//
|
||||
// Normalize Bar Index ...
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Define Requirements ...
|
||||
XOHCL iBar;
|
||||
bool has = false;
|
||||
bool isNewBar = false;
|
||||
|
||||
//
|
||||
// Get Current Bar Time ...
|
||||
datetime cBarTime = GetBarTime(
|
||||
symbol,
|
||||
period,
|
||||
barIndex //
|
||||
);
|
||||
|
||||
//
|
||||
// Validate Bar Time ...
|
||||
has = IsSpecifiedValid(cBarTime);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Process Permissions ...
|
||||
has = CanAnalyse(symbol, period, cBarTime);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if new Bar, Reset Processed Ticks Count ...
|
||||
isNewBar = cBarTime > mLastCheckedBarTime;
|
||||
if (isNewBar)
|
||||
{
|
||||
//
|
||||
mProcessedTicksCount = 0;
|
||||
ProcessNewBar(barIndex);
|
||||
}
|
||||
|
||||
//
|
||||
// Check Allow Process ...
|
||||
// Process All Ticks ...
|
||||
// Process New Bars ...
|
||||
has = config.processAllTicks ||
|
||||
(!config.processAllTicks && isNewBar);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Last Works ...
|
||||
mProcessedTicksCount++;
|
||||
mLastCheckedBarTime = cBarTime;
|
||||
|
||||
//
|
||||
// Initialize iBar ...
|
||||
has = iBar.Init(
|
||||
symbol,
|
||||
period,
|
||||
barIndex //
|
||||
);
|
||||
if (!has)
|
||||
{
|
||||
//
|
||||
iBar.Clean();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Update Indicator Helper ...
|
||||
mHelper.Update(barIndex);
|
||||
|
||||
//
|
||||
// Process Exists Zone ...
|
||||
ProcessZones(barIndex);
|
||||
|
||||
//
|
||||
// Do All Processing Mechanism ...
|
||||
|
||||
//
|
||||
// Reading Conditions from Helper ...
|
||||
XOM1Conditions iConditions;
|
||||
has = mHelper.GetConditions(
|
||||
iConditions,
|
||||
barIndex //
|
||||
);
|
||||
if (!has)
|
||||
{
|
||||
//
|
||||
iBar.Clean();
|
||||
iConditions.Clean();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int zIdx = 0;
|
||||
int cIdx = zIdx + 1;
|
||||
int pIdx = cIdx + 1;
|
||||
int p2Idx = pIdx + 1;
|
||||
|
||||
//
|
||||
// Check Zones Flags ...
|
||||
bool checkPVZones = false;
|
||||
bool checkMAZones = true;
|
||||
|
||||
//
|
||||
// Check PV Zones ...
|
||||
if (checkPVZones)
|
||||
{
|
||||
//
|
||||
// Check New Peak or Vale Happens ...
|
||||
|
||||
//
|
||||
// New Vale Over Last ...
|
||||
bool isValeReason = iConditions.valeBuffer[cIdx] > iConditions.valeBuffer[pIdx];
|
||||
|
||||
//
|
||||
// New Peak Under Last ...
|
||||
bool isPeakReason = iConditions.peakBuffer[cIdx] < iConditions.peakBuffer[pIdx];
|
||||
|
||||
//
|
||||
has = isValeReason || isPeakReason;
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Prepare Reason ...
|
||||
ENUM_XOM1_ZONE_REASON iReason = isValeReason
|
||||
? X_OM1_ZONE_REASON_VALE
|
||||
: X_OM1_ZONE_REASON_PEAK;
|
||||
|
||||
//
|
||||
// Extract Upper / Lower Values ...
|
||||
double iUpper = iConditions.peakBuffer[pIdx];
|
||||
double iLower = iConditions.valeBuffer[pIdx];
|
||||
|
||||
//
|
||||
// Calculate Mid Range ...
|
||||
double iMiddle = iLower + ((iUpper - iLower) / 2);
|
||||
if (iMiddle > 0)
|
||||
{
|
||||
iMiddle = NormalizePrice(iMiddle, symbol);
|
||||
}
|
||||
|
||||
//
|
||||
// Detect Reason Price ...
|
||||
double iPrice =
|
||||
isValeReason
|
||||
? iConditions.valeBuffer[cIdx]
|
||||
: iConditions.peakBuffer[cIdx];
|
||||
if (iPrice > 0)
|
||||
{
|
||||
iPrice = NormalizePrice(iPrice, symbol);
|
||||
}
|
||||
|
||||
//
|
||||
// Detect Reason Direction ...
|
||||
ENUM_X_DIRECTION iDir = iPrice > iMiddle
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
|
||||
//
|
||||
// Try to Initialize Zone ...
|
||||
XOM1Zone iZone;
|
||||
has = iZone.Init(
|
||||
symbol,
|
||||
period,
|
||||
name, // Signaller Name ...
|
||||
iUpper,
|
||||
iLower,
|
||||
iPrice,
|
||||
iDir,
|
||||
iReason,
|
||||
iConditions.bars[pIdx].time, // From ...
|
||||
iConditions.bars[zIdx].time // To
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Add New Detected Zone to Zones ...
|
||||
AddRef(
|
||||
iZone,
|
||||
zones //
|
||||
);
|
||||
|
||||
//
|
||||
// Prepare Signal ...
|
||||
PrepareSignal(iZone);
|
||||
}
|
||||
|
||||
//
|
||||
iZone.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check MA Zones ...
|
||||
if (checkMAZones)
|
||||
{
|
||||
//
|
||||
// Crossed Over ...
|
||||
bool isFastCrossedOverSlow = iConditions.maFastBuffer[cIdx] > iConditions.maSlowBuffer[cIdx] &&
|
||||
!(iConditions.maFastBuffer[pIdx] >= iConditions.maSlowBuffer[pIdx]);
|
||||
|
||||
//
|
||||
// Crossed Under ...
|
||||
bool isFastCrossedUnderSlow = iConditions.maFastBuffer[cIdx] < iConditions.maSlowBuffer[cIdx] &&
|
||||
!(iConditions.maFastBuffer[pIdx] <= iConditions.maSlowBuffer[pIdx]);
|
||||
|
||||
//
|
||||
double iFast = iConditions.maFastBuffer[cIdx];
|
||||
double iSlow = iConditions.maSlowBuffer[cIdx];
|
||||
double iFibUpper = iConditions.fiboUpperBuffer[cIdx];
|
||||
double iFibLower = iConditions.fiboLowerBuffer[cIdx];
|
||||
|
||||
//
|
||||
double iValues[] = {
|
||||
iFast,
|
||||
iSlow,
|
||||
iFibUpper,
|
||||
iFibLower //
|
||||
};
|
||||
|
||||
//
|
||||
// Extract Upper / Lower Values ...
|
||||
double iUpper = GetMax(iValues);
|
||||
double iLower = GetMin(iValues);
|
||||
|
||||
//
|
||||
double iZoneUpper = MathMax(iFibUpper, iFibLower);
|
||||
double iZoneLower = MathMin(iFibUpper, iFibLower);
|
||||
|
||||
//
|
||||
has = isFastCrossedOverSlow || isFastCrossedUnderSlow;
|
||||
|
||||
//
|
||||
// Validate Cross Between Zone ...
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Validate MA Place ...
|
||||
has = iFast >= iZoneLower &&
|
||||
iFast <= iZoneUpper &&
|
||||
iSlow >= iZoneLower &&
|
||||
iSlow <= iZoneUpper;
|
||||
|
||||
//
|
||||
// Validate PSar ...
|
||||
bool isSarBullish = iConditions.sarStateBuffer[cIdx] > 0;
|
||||
bool isSarBearish = iConditions.sarStateBuffer[cIdx] < 0;
|
||||
has =
|
||||
has &&
|
||||
(isFastCrossedOverSlow
|
||||
? isSarBullish
|
||||
: isSarBearish //
|
||||
);
|
||||
|
||||
//
|
||||
// Validate Fibo Zone ...
|
||||
for (int idx = cIdx; idx < cIdx + 2; idx++)
|
||||
{
|
||||
//
|
||||
// Check Fibo Upper ...
|
||||
has = has &&
|
||||
iConditions.fiboUpperBuffer[idx] == iConditions.fiboUpperBuffer[idx + 1];
|
||||
if (!has)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Fibo Lower ...
|
||||
has = has &&
|
||||
iConditions.fiboLowerBuffer[idx] == iConditions.fiboLowerBuffer[idx + 1];
|
||||
if (!has)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Moving Forward if Validated ...
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Prepare Reason ...
|
||||
ENUM_XOM1_ZONE_REASON iReason = isFastCrossedOverSlow
|
||||
? X_OM1_ZONE_REASON_FCOS
|
||||
: X_OM1_ZONE_REASON_FCUS;
|
||||
|
||||
//
|
||||
// Calculate Mid Range ...
|
||||
double iMiddle = iLower + ((iUpper - iLower) / 2);
|
||||
if (iMiddle > 0)
|
||||
{
|
||||
iMiddle = NormalizePrice(iMiddle, symbol);
|
||||
}
|
||||
|
||||
//
|
||||
// Detect Reason Price ...
|
||||
double iPrice = iConditions.maFastBuffer[cIdx];
|
||||
if (iPrice > 0)
|
||||
{
|
||||
iPrice = NormalizePrice(iPrice, symbol);
|
||||
}
|
||||
|
||||
//
|
||||
// Detect Reason Direction ...
|
||||
ENUM_X_DIRECTION iDir = isFastCrossedOverSlow
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
|
||||
//
|
||||
// Try to Initialize Zone ...
|
||||
XOM1Zone iZone;
|
||||
has = iZone.Init(
|
||||
symbol,
|
||||
period,
|
||||
name, // Signaller Name ...
|
||||
iZoneUpper,
|
||||
iZoneLower,
|
||||
iPrice,
|
||||
iDir,
|
||||
iReason,
|
||||
iConditions.bars[pIdx].time, // From ...
|
||||
iConditions.bars[zIdx].time // To
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
// Add New Detected Zone to Zones ...
|
||||
AddRef(
|
||||
iZone,
|
||||
zones //
|
||||
);
|
||||
|
||||
//
|
||||
// Prepare Signal ...
|
||||
PrepareSignal(iZone);
|
||||
}
|
||||
|
||||
//
|
||||
iZone.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
Clean(iValues);
|
||||
}
|
||||
|
||||
//
|
||||
// Clean Resources ...
|
||||
iBar.Clean();
|
||||
iConditions.Clean();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
class XCXIMAC5020Signaller : public XCXOM1SignallerBase
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XCXIMAC5020Signaller(
|
||||
string _name, // Name ...
|
||||
string _symbol, // Symbol ...
|
||||
ENUM_TIMEFRAMES _period, // Period ...
|
||||
XOM1Inputs &_inputs, // Indicator Inputs ...
|
||||
XOM1SignallerConfig &_config // Config ...
|
||||
) : XCXOM1SignallerBase(_name,
|
||||
_symbol,
|
||||
_period,
|
||||
_inputs,
|
||||
_config //
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XCXIMAC5020Signaller()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Overrides ...
|
||||
|
||||
/**
|
||||
* Handle Ticks Process ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
virtual void ProcessTick(int barIndex = 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Extensions ...
|
||||
|
||||
//
|
||||
@@ -0,0 +1,219 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class
|
||||
// -------------------------------------------------
|
||||
// Name: XCXOM1POIDrawer ...
|
||||
// Description: XOM1EA POI Drawer Class ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property description "SaherElm XOM1EA POI Drawer Class"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
||||
#include "../Libraries/xom1ea.lib.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// Implementation ...
|
||||
class XCXOM1POIDrawer : public XCBase
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XCXOM1POIDrawer()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XCXOM1POIDrawer()
|
||||
{
|
||||
mObjects.Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Actions ...
|
||||
|
||||
/**
|
||||
* Draw Specified Zone ...
|
||||
*
|
||||
* @param zone: XOM1Zone
|
||||
* @param drawPrice: bool
|
||||
* @param drawMiddle: bool
|
||||
*/
|
||||
void DrawZone(
|
||||
XOM1Zone &zone,
|
||||
bool drawPrice = false,
|
||||
bool drawMiddle = false,
|
||||
bool drawFrom = false //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool has = false;
|
||||
|
||||
//
|
||||
// Validate ...
|
||||
has = zone.IsValid();
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Converts to Box ...
|
||||
XBoxZone box;
|
||||
has = zone.ToBox(box);
|
||||
if (!has)
|
||||
{
|
||||
//
|
||||
box.Clean();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Draw Box ...
|
||||
XCBoxObject *object;
|
||||
has = mDrawer.DrawBox(
|
||||
box,
|
||||
object,
|
||||
true // Ignore At ...
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
mObjects.Add(object);
|
||||
}
|
||||
|
||||
//
|
||||
// Draw Price ...
|
||||
if (drawPrice)
|
||||
{
|
||||
//
|
||||
CChartObjectTrend *mLineObj;
|
||||
string mLineName = "pl_" + ToMD5(zone.GetTag());
|
||||
mLineObj = new CChartObjectTrend();
|
||||
has = mLineObj.Create(
|
||||
mDrawer.ChartIdentification(),
|
||||
mLineName,
|
||||
mDrawer.SubWindowIdentification(),
|
||||
zone.from,
|
||||
zone.price,
|
||||
zone.to,
|
||||
zone.price //
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
mDrawer.ApplyTrendLineStyle(
|
||||
mLineObj,
|
||||
zone.dir //
|
||||
);
|
||||
|
||||
//
|
||||
mObjects.Add(mLineObj);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Draw Middle ...
|
||||
if (drawMiddle)
|
||||
{
|
||||
//
|
||||
CChartObjectTrend *mLineObj;
|
||||
double mlPrice = zone.lower + ((zone.upper - zone.lower) / 2);
|
||||
string mLineName = "ml_" + ToMD5(zone.GetTag());
|
||||
mLineObj = new CChartObjectTrend();
|
||||
has = mLineObj.Create(
|
||||
mDrawer.ChartIdentification(),
|
||||
mLineName,
|
||||
mDrawer.SubWindowIdentification(),
|
||||
zone.from,
|
||||
mlPrice,
|
||||
zone.to,
|
||||
mlPrice //
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
mDrawer.ApplyTrendLineStyle(
|
||||
mLineObj,
|
||||
zone.dir //
|
||||
);
|
||||
|
||||
//
|
||||
mObjects.Add(mLineObj);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Draw From ...
|
||||
if (drawFrom)
|
||||
{
|
||||
//
|
||||
CChartObjectVLine *mLineObj;
|
||||
string mLineName = "mfl_" + ToMD5(zone.GetTag());
|
||||
mLineObj = new CChartObjectVLine();
|
||||
has = mLineObj.Create(
|
||||
mDrawer.ChartIdentification(),
|
||||
mLineName,
|
||||
mDrawer.SubWindowIdentification(),
|
||||
zone.from //
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
mDrawer.ApplyLineStyle(
|
||||
mLineObj,
|
||||
zone.dir //
|
||||
);
|
||||
|
||||
//
|
||||
mObjects.Add(mLineObj);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Clean Resources ...
|
||||
box.Clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Drawn Objects ...
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
mObjects.Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Props ...
|
||||
CArrayObj mObjects; // Drawn Objects ...
|
||||
XCPOIDrawer mDrawer; // Base POI Drawer ...
|
||||
};
|
||||
|
||||
//
|
||||
@@ -0,0 +1,429 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Indicator
|
||||
// -------------------------------------------------
|
||||
// Name: XOM1EA Lib
|
||||
// Description: Library for XOM1EA ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property description "SaherElm Library for XOM1EA Signaller"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include "../../Libraries/x-saherelm.common.lib.mq5"
|
||||
#include "../../Libraries/x-saherelm.x-poi.lib.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// Zone Creation Reason ...
|
||||
enum ENUM_XOM1_ZONE_REASON
|
||||
{
|
||||
X_OM1_ZONE_REASON_NONE, // NONE
|
||||
X_OM1_ZONE_REASON_PEAK, // PEAK
|
||||
X_OM1_ZONE_REASON_VALE, // VALE
|
||||
X_OM1_ZONE_REASON_FCOS, // FCOS
|
||||
X_OM1_ZONE_REASON_FCUS, // FCUS
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a Zone Creation Reason ...
|
||||
*
|
||||
* @param value: ENUM_XOM1_ZONE_REASON
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsXValid(ENUM_XOM1_ZONE_REASON value)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = value != X_OM1_ZONE_REASON_NONE;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Zone Reason to String ...
|
||||
*
|
||||
* @param value: ENUM_XOM1_ZONE_REASON
|
||||
*
|
||||
* @return ( string )
|
||||
*/
|
||||
string ToXString(ENUM_XOM1_ZONE_REASON value)
|
||||
{
|
||||
return EnumToString(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Zone Reason to String ...
|
||||
*
|
||||
* @param value: ENUM_XOM1_ZONE_REASON
|
||||
*
|
||||
* @return ( string )
|
||||
*/
|
||||
ENUM_XOM1_ZONE_REASON FromXString(string value)
|
||||
{
|
||||
//
|
||||
ENUM_XOM1_ZONE_REASON result = X_OM1_ZONE_REASON_NONE;
|
||||
|
||||
//
|
||||
if (!IsSpecifiedValid(value))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
if (value == ToXString(X_OM1_ZONE_REASON_NONE))
|
||||
{
|
||||
result = X_OM1_ZONE_REASON_NONE;
|
||||
}
|
||||
else if (value == ToXString(X_OM1_ZONE_REASON_PEAK))
|
||||
{
|
||||
result = X_OM1_ZONE_REASON_PEAK;
|
||||
}
|
||||
else if (value == ToXString(X_OM1_ZONE_REASON_VALE))
|
||||
{
|
||||
result = X_OM1_ZONE_REASON_VALE;
|
||||
}
|
||||
else if (value == ToXString(X_OM1_ZONE_REASON_FCOS))
|
||||
{
|
||||
result = X_OM1_ZONE_REASON_FCOS;
|
||||
}
|
||||
else if (value == ToXString(X_OM1_ZONE_REASON_FCUS))
|
||||
{
|
||||
result = X_OM1_ZONE_REASON_FCUS;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// this is a Zone Which
|
||||
// we start Looking for
|
||||
// Signal Detecting ...
|
||||
struct XOM1Zone
|
||||
{
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
string symbol; // Symbol
|
||||
ENUM_TIMEFRAMES period; // Period
|
||||
string signaller; // Signaller Identifier
|
||||
datetime from; // Detection Time
|
||||
datetime to; // Lifetime
|
||||
ENUM_X_DIRECTION dir; // Direction
|
||||
ENUM_XOM1_ZONE_REASON reason; // Creation Reason
|
||||
double upper; // Upper Level
|
||||
double lower; // Lower Level
|
||||
double price; // Reason Price
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XOM1Zone()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
/**
|
||||
* Initialize ...
|
||||
*
|
||||
* @param _symbol: Symbol
|
||||
* @param _period: Period
|
||||
* @param _signaller: Signaller Identifier
|
||||
* @param _upper: Upper Value (PEAK)
|
||||
* @param _lower: Lower Value (VALE)
|
||||
* @param _price: Price (Changed Peak or Vale)
|
||||
* @param _dir: Direction
|
||||
* @param _reason: Creation Reason
|
||||
* @param _from: Detection Time
|
||||
* @param _to: Lifetime Time
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool Init(
|
||||
string _symbol,
|
||||
ENUM_TIMEFRAMES _period,
|
||||
string _signaller,
|
||||
double _upper,
|
||||
double _lower,
|
||||
double _price,
|
||||
ENUM_X_DIRECTION _dir,
|
||||
ENUM_XOM1_ZONE_REASON _reason,
|
||||
datetime _from,
|
||||
datetime _to = NULL //
|
||||
)
|
||||
{
|
||||
//
|
||||
to = _from;
|
||||
dir = _dir;
|
||||
from = _from;
|
||||
upper = _upper;
|
||||
lower = _lower;
|
||||
price = _price;
|
||||
symbol = _symbol;
|
||||
period = _period;
|
||||
reason = _reason;
|
||||
signaller = _signaller;
|
||||
|
||||
//
|
||||
if (IsSpecifiedValid(_to))
|
||||
{
|
||||
to = _to;
|
||||
}
|
||||
|
||||
//
|
||||
bool result = IsValid();
|
||||
if (!result)
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Lifetime by Data ...
|
||||
*
|
||||
* @param _to: datetime
|
||||
*/
|
||||
void UpdateByDate(datetime _to)
|
||||
{
|
||||
//
|
||||
// Validate ...
|
||||
bool isValid = IsValid() &&
|
||||
IsSpecifiedValid(_to) &&
|
||||
_to > to;
|
||||
if (!isValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
to = _to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Lifetime by BarIndex ...
|
||||
*
|
||||
* @param barIndex: int
|
||||
*/
|
||||
void UpdateByBarIndex(int barIndex)
|
||||
{
|
||||
//
|
||||
// Normalize ...
|
||||
if (barIndex <= 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
if (!IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
datetime _to = GetBarTime(
|
||||
symbol,
|
||||
period,
|
||||
barIndex //
|
||||
);
|
||||
if (!IsSpecifiedValid(_to))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
UpdateByDate(_to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean ...
|
||||
*/
|
||||
void Clean()
|
||||
{
|
||||
ZeroMemory(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsValid()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
IsSpecifiedValid(symbol) &&
|
||||
IsSpecifiedValid(period) &&
|
||||
IsSpecifiedValid(signaller) &&
|
||||
IsSpecifiedValid(from) &&
|
||||
IsSpecifiedValid(to) &&
|
||||
to >= from &&
|
||||
HasDirection(dir) &&
|
||||
IsXValid(reason) &&
|
||||
upper > 0 &&
|
||||
lower > 0 &&
|
||||
price > 0 &&
|
||||
upper > lower &&
|
||||
price <= upper &&
|
||||
price >= lower
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Lifetime Age ...
|
||||
*
|
||||
* @return ( int )
|
||||
*/
|
||||
int GetBarLife()
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
if (!IsValid())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int fromIDX = GetBarIndex(
|
||||
symbol,
|
||||
period,
|
||||
from //
|
||||
);
|
||||
int toIDX = GetBarIndex(
|
||||
symbol,
|
||||
period,
|
||||
to //
|
||||
);
|
||||
bool isValid = IsValidIndex(fromIDX) && IsValidIndex(toIDX);
|
||||
if (!isValid)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = MathAbs(fromIDX - toIDX);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Zone is Bullish ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsBullish()
|
||||
{
|
||||
return IsValid() && IsSpecifiedBullish(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Zone is Bearish ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsBearish()
|
||||
{
|
||||
return IsValid() && IsSpecifiedBearish(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to Box ...
|
||||
*
|
||||
* @param box: Dest
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool ToBox(XBoxZone &box)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
box.Clean();
|
||||
result = IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
box.to = to;
|
||||
box.dir = dir;
|
||||
box.from = from;
|
||||
box.upper = upper;
|
||||
box.lower = lower;
|
||||
box.symbol = symbol;
|
||||
box.period = period;
|
||||
box.type = signaller;
|
||||
|
||||
//
|
||||
result = box.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
box.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique Identifier ...
|
||||
*
|
||||
* @return ( string )
|
||||
*/
|
||||
string GetTag()
|
||||
{
|
||||
//
|
||||
string result = NULL;
|
||||
|
||||
//
|
||||
result = "XOM1Zone_" +
|
||||
symbol + "_" +
|
||||
ToXString(period) + "_" +
|
||||
signaller + "_" +
|
||||
ToXString(dir) + "_" +
|
||||
ToXString(reason) + "_" +
|
||||
ToXString(TimeToSeconds(from));
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
Reference in New Issue
Block a user