last backup ...
This commit is contained in:
@@ -0,0 +1,742 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 Class
|
||||
// -------------------------------------------------
|
||||
// Name: XCBaseSignaller ...
|
||||
// Description: Base Signaller Class ...
|
||||
//
|
||||
// - Create an Instance based on this ...
|
||||
// - Attach Required Helpers for Indicator Usages ...
|
||||
// - Override Virtual Methdos:
|
||||
// - [] ProcessTick: Processing All Ticks
|
||||
// - [] ProcessNewBar: Processing All New Bars
|
||||
// - [] CheckForGuard: Check For Guards
|
||||
// - [] NormalizeSignal: Normalizing Prepared Signal ...
|
||||
// - [] CheckAdditionslSignallerValidations: Additional Class Validations
|
||||
//
|
||||
// - Dont Forget to Call OnSignal Event in Process Methods when
|
||||
// a signal Appears ...
|
||||
//
|
||||
// - also Whenever you want you can call PrepareSignal Action to
|
||||
// provide a Signal based on Current Market State ...
|
||||
//
|
||||
// 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 Base Signaller Class"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
#include "../Classes/x-saherelm.base.class.mq5"
|
||||
#include "../Classes/x-saherelm.x-market.pattern.class.mq5"
|
||||
#include "../Libraries/x-saherelm.x-trade.lib.mq5"
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
// Implementations ...
|
||||
class XCBaseSignaller : public XCBase
|
||||
{
|
||||
//
|
||||
// Public ...
|
||||
public:
|
||||
//
|
||||
// Props ...
|
||||
string name; // Name ...
|
||||
string symbol; // Symbol ...
|
||||
ENUM_TIMEFRAMES period; // Period ...
|
||||
|
||||
//
|
||||
bool ignoreTargets; // Ignore Signal Targets ...
|
||||
double slAdditionDistance; // SL Addition Distance ...
|
||||
double maxAllowedRiskDistance; // Max Allowed Risk In Points ...
|
||||
|
||||
//
|
||||
// Restrictions ...
|
||||
datetime restUntil; // Resting Time ...
|
||||
int restingSignals; // Resting Signals ...
|
||||
datetime lastSignalAt; // Holding Last Signal's Time ...
|
||||
int restingDelay; // Resting Bars After Last Signal ...
|
||||
int loosingTrades; // Loosing Trades ...
|
||||
|
||||
//
|
||||
TCanAnalyse canAnalyseEventListener;
|
||||
|
||||
//
|
||||
XCMarketPatternDetector *patternDetector;
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
XCBaseSignaller(
|
||||
string _name, // Name ...
|
||||
string _symbol, // Symbol ...
|
||||
ENUM_TIMEFRAMES _period, // Period ...
|
||||
bool _processAllTicks = false, // Process All Ticks ...
|
||||
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
|
||||
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
|
||||
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
|
||||
)
|
||||
{
|
||||
//
|
||||
// Assign Properties ...
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
period = _period;
|
||||
|
||||
//
|
||||
ignoreTargets = false;
|
||||
slAdditionDistance = 0;
|
||||
maxAllowedRiskDistance = 0;
|
||||
|
||||
//
|
||||
processAllTicks = _processAllTicks;
|
||||
defaultSignalR2R = _defaultSignalR2R;
|
||||
defaultSignalVolume = _defaultSignalVolume;
|
||||
defaultSignalRiskInPoint = _defaultSignalRiskInPoint;
|
||||
|
||||
//
|
||||
// Normalize ...
|
||||
defaultSignalR2R = NormalizeDouble(defaultSignalR2R, 1, 10);
|
||||
defaultSignalVolume = NormalizeDouble(defaultSignalVolume, 0.01);
|
||||
defaultSignalVolume = NormalizeVolume(defaultSignalVolume, symbol, 2);
|
||||
defaultSignalRiskInPoint = NormalizeDouble(defaultSignalRiskInPoint, 10);
|
||||
|
||||
//
|
||||
// Set Dfault Values ...
|
||||
mProcessedTicksCount = 0;
|
||||
mLastCheckedBarTime = NULL;
|
||||
|
||||
//
|
||||
patternDetector = new XCMarketPatternDetector();
|
||||
}
|
||||
|
||||
//
|
||||
// Deconstructor ...
|
||||
~XCBaseSignaller()
|
||||
{
|
||||
//
|
||||
// Cleanup Event Listeners ...
|
||||
SpecifiedClean(onSignalEventListeners);
|
||||
|
||||
//
|
||||
delete patternDetector;
|
||||
ZeroMemory(patternDetector);
|
||||
}
|
||||
|
||||
//
|
||||
// Event Listeners ...
|
||||
|
||||
/**
|
||||
* Add On Signal Event Listener ...
|
||||
*
|
||||
* @param listener: TOnSignal instance ...
|
||||
*/
|
||||
void AddOnSignalEventHandler(TOnSignal listener)
|
||||
{
|
||||
//
|
||||
// Validate ...
|
||||
if (listener == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
Add(
|
||||
listener,
|
||||
onSignalEventListeners //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Actions ...
|
||||
|
||||
/**
|
||||
* Check Signaller Validation ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsValid()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
IsSpecifiedValid(name) &&
|
||||
IsSpecifiedValid(symbol) &&
|
||||
IsSpecifiedValid(period) &&
|
||||
//
|
||||
patternDetector != NULL &&
|
||||
//
|
||||
CheckAdditionslSignallerValidations()
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling On Tick Event ...
|
||||
*
|
||||
* @param barIndex: int, Specified Bar Index ...
|
||||
*/
|
||||
void OnTick(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 Rest Until ...
|
||||
has = !IsXValid(restUntil) || (IsXValid(restUntil) && cBarTime > restUntil);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Process Permissions ...
|
||||
has = CanAnalyseMarket(cBarTime);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if new Bar, Reset Processed Ticks Count ...
|
||||
isNewBar = cBarTime > mLastCheckedBarTime;
|
||||
if (isNewBar)
|
||||
{
|
||||
//
|
||||
mProcessedTicksCount = 0;
|
||||
ProcessNewBar(barIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Allow Process ...
|
||||
// Process All Ticks ...
|
||||
// Process New Bars ...
|
||||
has = processAllTicks ||
|
||||
(!processAllTicks && isNewBar);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Last Works ...
|
||||
mProcessedTicksCount++;
|
||||
mLastCheckedBarTime = cBarTime;
|
||||
|
||||
//
|
||||
ProcessTick(barIndex);
|
||||
}
|
||||
|
||||
//
|
||||
// Virtuals ...
|
||||
|
||||
/**
|
||||
* Processing Tick ...
|
||||
*
|
||||
* @param barIndex: int, Specified Bar Index ...
|
||||
*/
|
||||
virtual void ProcessTick(int barIndex = 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing New Bar ...
|
||||
*
|
||||
* @param barIndex: int, Specified Bar Index ...
|
||||
*/
|
||||
virtual void ProcessNewBar(int barIndex = 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Guards Based on MarketConditions ...
|
||||
*
|
||||
* @param guards: XGuard, reference collection to holds result ...
|
||||
* @param positions: XPosition, reference collection to provides positions ...
|
||||
* @param barIndex: int
|
||||
*
|
||||
* @return ( int )
|
||||
*/
|
||||
int virtual CheckForGuard(
|
||||
XGuard &guards[],
|
||||
XPosition &positions[],
|
||||
int barIndex = 0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
SpecifiedClean(guards);
|
||||
|
||||
//
|
||||
result = ArraySize(guards);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Additional Validations on Childs Instances ...
|
||||
*
|
||||
* @return ( bool virtual )
|
||||
*/
|
||||
bool virtual CheckAdditionslSignallerValidations()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizing Signal by Signaller Custom Props ...
|
||||
*
|
||||
* @param signal: XSignal ...
|
||||
*/
|
||||
void virtual NormalizeSignal(XSignal &signal)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Restrictions Update For Losing Trades ...
|
||||
*/
|
||||
void LoseTrade()
|
||||
{
|
||||
//
|
||||
restingSignals++;
|
||||
loosingTrades++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Restrictions For Winning Trades ...
|
||||
*/
|
||||
void WinTrade()
|
||||
{
|
||||
//
|
||||
if (loosingTrades > 0)
|
||||
{
|
||||
loosingTrades--;
|
||||
}
|
||||
|
||||
//
|
||||
if (restingSignals > 0)
|
||||
{
|
||||
restingSignals--;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Protected ...
|
||||
protected:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
bool processAllTicks; // Specified Processing All Ticks or not ...
|
||||
|
||||
//
|
||||
int mProcessedTicksCount; // Prcoessed Ticks Count ...
|
||||
datetime mLastCheckedBarTime; // Last Checked Bar Time ...
|
||||
|
||||
//
|
||||
double defaultSignalR2R; // Default Signal Risk To Reward Ratio ...
|
||||
double defaultSignalVolume; // Default Signal Volume ...
|
||||
double defaultSignalRiskInPoint; // Default Signal Risk In Point ...
|
||||
|
||||
//
|
||||
// Event Notifiers ...
|
||||
|
||||
/**
|
||||
* Notify OnSignal Event Listeners ...
|
||||
*
|
||||
* @param signal: XSignal, Specified Signal to Notify ...
|
||||
*/
|
||||
void NotifySignalEventListeners(XSignal &signal)
|
||||
{
|
||||
//
|
||||
int count = ArraySize(onSignalEventListeners);
|
||||
|
||||
//
|
||||
// Validate ...
|
||||
if (!IsValidSize(count) || !signal.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Restrictions ...
|
||||
if (HasRestrictions())
|
||||
{
|
||||
//
|
||||
bool ignore = HandleRestrictions(signal);
|
||||
if (ignore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do Notify ...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
onSignalEventListeners[i](signal);
|
||||
}
|
||||
|
||||
//
|
||||
lastSignalAt = signal.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling Can Analyse Event Listeners ...
|
||||
* Check Can Analayse Market or not ...
|
||||
*
|
||||
* @param time: datetime, Specified Time for Checking ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool CanAnalyseMarket(datetime time = NULL)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
// Normalize ...
|
||||
time = NormalizeTime(time);
|
||||
|
||||
//
|
||||
// Validation ...
|
||||
result = IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = canAnalyseEventListener == NULL;
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calling Can Analyse Event Listener ...
|
||||
result = canAnalyseEventListener(
|
||||
symbol,
|
||||
period,
|
||||
time //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preparing Default Signal ...
|
||||
*
|
||||
* @param signal: XSignal, holding result Signal ...
|
||||
* @param forDir: ENUM_X_DIRECTION
|
||||
* @param targets: XTarget Array, Provides Signal Targets (Price) ...
|
||||
* @param r2r: double, Provides Signal (r2r), if not Provided uses Default R2R ...
|
||||
* @param slPrice: double, Provides Signal SL Price, if not Provided uses riskInPoint ...
|
||||
* @param riskInPoint: double, Provides Signal Risk Amount which Multiplied to Points, if not Provided uses DefaultRiskInPoint ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool PrepareSignal(
|
||||
XSignal &signal,
|
||||
ENUM_X_DIRECTION forDir,
|
||||
XTarget &targets[], //
|
||||
double r2r = 0,
|
||||
double slPrice = 0,
|
||||
double riskInPoint = 0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
// Prepare ...
|
||||
signal.Clean();
|
||||
|
||||
//
|
||||
// Normalize ...
|
||||
|
||||
//
|
||||
// Validate ...
|
||||
result = IsValid() &&
|
||||
HasDirection(forDir);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isBullish = IsSpecifiedBullish(forDir);
|
||||
|
||||
//
|
||||
double point = GetPoints(symbol);
|
||||
double spread = GetSpread(symbol);
|
||||
double volume = defaultSignalVolume;
|
||||
double entry = GetEntry(symbol, forDir);
|
||||
|
||||
//
|
||||
riskInPoint = riskInPoint > 0 && slPrice <= 0
|
||||
? riskInPoint
|
||||
: defaultSignalRiskInPoint;
|
||||
double risk = (riskInPoint * point);
|
||||
risk = slPrice > 0
|
||||
? MathAbs(entry - slPrice)
|
||||
: risk;
|
||||
|
||||
//
|
||||
r2r = r2r > 0
|
||||
? r2r
|
||||
: defaultSignalR2R;
|
||||
double reward = (risk * r2r) + spread;
|
||||
|
||||
//
|
||||
double tp =
|
||||
isBullish
|
||||
? entry + reward
|
||||
: entry - reward;
|
||||
|
||||
//
|
||||
double sl =
|
||||
isBullish
|
||||
? entry - risk
|
||||
: entry + risk;
|
||||
|
||||
//
|
||||
// Filling Values ...
|
||||
signal.tp = tp;
|
||||
signal.sl = sl;
|
||||
signal.entry = entry;
|
||||
signal.provider = name;
|
||||
signal.symbol = symbol;
|
||||
signal.period = period;
|
||||
signal.volume = volume;
|
||||
signal.time = TimeCurrent();
|
||||
signal.type =
|
||||
isBullish
|
||||
? POSITION_TYPE_BUY
|
||||
: POSITION_TYPE_SELL;
|
||||
signal.mode = X_ORDER_MODE_MARKET;
|
||||
|
||||
//
|
||||
// Apply Targets ...
|
||||
if (HasChild(targets))
|
||||
{
|
||||
//
|
||||
ApplyTargetsOnSignal(
|
||||
forDir,
|
||||
targets,
|
||||
signal //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Validate Signal ...
|
||||
result = signal.IsValid();
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
NormalizeSignal(signal);
|
||||
result = signal.IsValid();
|
||||
}
|
||||
|
||||
//
|
||||
if (!result)
|
||||
{
|
||||
signal.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Signaller Has Restrictions or not ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool HasRestrictions()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
// Rest Delay ...
|
||||
restingDelay > 0 ||
|
||||
//
|
||||
// Resting Signals ...
|
||||
restingSignals > 0 ||
|
||||
//
|
||||
// Rest Until ...
|
||||
IsXValid(restUntil)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Restrictions On Signal ...
|
||||
*
|
||||
* @param signal: XSignal, reference to Provided Sginal ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool HandleRestrictions(XSignal &signal)
|
||||
{
|
||||
//
|
||||
// Ignore Signal Execution ...
|
||||
bool result = true;
|
||||
|
||||
//
|
||||
// Check Restrictions Exists ...
|
||||
if (!HasRestrictions())
|
||||
{
|
||||
//
|
||||
// Disable Signal Ignoring and Allow Notify Signal ...
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
datetime cTime = TimeCurrent();
|
||||
|
||||
//
|
||||
// Resting Signals ...
|
||||
if (restingSignals > 0)
|
||||
{
|
||||
//
|
||||
restingSignals--;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Rest Until ...
|
||||
if (IsXValid(restUntil))
|
||||
{
|
||||
//
|
||||
if (cTime > restUntil)
|
||||
{
|
||||
//
|
||||
restUntil = NULL;
|
||||
|
||||
//
|
||||
// Disable Signal Ignoring and Allow Notify Signal ...
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Ignore Signal ...
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Resting Delay ...
|
||||
if (restingDelay > 0 &&
|
||||
IsXValid(lastSignalAt))
|
||||
{
|
||||
//
|
||||
int lastSignalIDX = GetBarIndex(
|
||||
signal.symbol,
|
||||
signal.period,
|
||||
lastSignalAt //
|
||||
);
|
||||
if (IsValidIndex(lastSignalIDX))
|
||||
{
|
||||
//
|
||||
if (lastSignalIDX > restingDelay)
|
||||
{
|
||||
//
|
||||
restingDelay = 0;
|
||||
//
|
||||
// Disable Signal Ignoring and Allow Notify Signal ...
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Ignore Signal ...
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset All Restrictions ...
|
||||
*/
|
||||
void ResetRestrictions()
|
||||
{
|
||||
//
|
||||
restingDelay = 0;
|
||||
restUntil = NULL;
|
||||
restingSignals = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
// Event Listeners ...
|
||||
TOnSignal onSignalEventListeners[];
|
||||
};
|
||||
|
||||
//
|
||||
Reference in New Issue
Block a user