Files
MQL4Data/Bkp/Used/14020425/21-00/Libraries/x-saherelm.xma.mc.signal.lib.mq4
T
2024-01-25 04:05:58 +03:30

491 lines
11 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL4 XMA Signal Global Library
// ---------------------------------------------------
// saherelm useful tools and definitions ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Includes library ...
#include "../Libraries/x-saherelm.lib.mq4"
//
// Includes Indicator library ...
#include "../Libraries/x-saherelm.indicator.lib.mq4"
//
// Includes Models library ...
#include "../Libraries/x-saherelm.models.lib.mq4"
//
// START Global Requirement Functions ...
//
//
// XMA Based Signal Conditions ...
struct XMAMCLongSignalConditions {
//
datetime mcFastCrossUnderSlowTime;
double crossUnderMCFast;
double crossUnderMCSlow;
//
datetime mcFastCrossOverSlowTime;
double crossOverMCFast;
double crossOverMCSlow;
//
datetime mcFastBiggerThanCrossUnderSlowTime;
};
//
static XMAMCLongSignalConditions xmaMCLongConds;
//
// END Global Requirement Functions ...
//
//
// START Functions ...
//
//
// Check and Fill CC Signal Conditions ...
void CheckXMAMCLongSignalConditions(
const int bar_index,
const int marketLen,
//
double stp,
double mxm,
//
int scFMult,
int scSMult,
//
int mcFMult,
int mcSMult
) {
//
XCycleState mcs[];
int positionsMarketLen = bar_index + marketLen;
//
// Retrieve Bar Time ...
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
// Resize Arrays ...
ArrayResize(
mcs,
marketLen
);
//
int index = 0;
for (int i = bar_index; i < positionsMarketLen; i++) {
//
XCycleState mc = GetXMAMC(
i,
marketLen,
mcFMult,
mcSMult
);
mcs[index] = mc;
//
index++;
}
//
bool isMCFastCrossUnderSlow =
mcs[0].fast < mcs[0].slow
&& !(mcs[1].fast <= mcs[1].slow)
;
bool isMCFastCrossOverSlow =
mcs[0].fast > mcs[0].slow
&& !(mcs[1].fast >= mcs[1].slow)
;
//
if (
isMCFastCrossUnderSlow
&& xmaMCLongConds.mcFastCrossUnderSlowTime == 0
) {
//
xmaMCLongConds.crossUnderMCFast = mcs[0].fast;
xmaMCLongConds.crossUnderMCSlow = mcs[0].slow;
xmaMCLongConds.mcFastCrossUnderSlowTime = barTime;
return;
}
//
if (
isMCFastCrossUnderSlow
&& xmaMCLongConds.mcFastCrossUnderSlowTime > 0
) {
//
ClearXMAMCLongSignalConditions();
//
xmaMCLongConds.crossUnderMCFast = mcs[0].fast;
xmaMCLongConds.crossUnderMCSlow = mcs[0].slow;
xmaMCLongConds.mcFastCrossUnderSlowTime = barTime;
return;
}
//
if (
isMCFastCrossOverSlow
&& xmaMCLongConds.mcFastCrossUnderSlowTime > 0
&& xmaMCLongConds.mcFastCrossOverSlowTime == 0
) {
//
xmaMCLongConds.crossOverMCFast = mcs[0].fast;
xmaMCLongConds.crossOverMCSlow = mcs[0].slow;
xmaMCLongConds.mcFastCrossOverSlowTime = barTime;
return;
}
//
if (
xmaMCLongConds.mcFastCrossUnderSlowTime > 0
&& xmaMCLongConds.mcFastCrossOverSlowTime > 0
&& mcs[0].fast > xmaMCLongConds.crossUnderMCSlow
&& xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime == 0
) {
//
xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime = barTime;
return;
}
}
//
// Convert XMA Long Signal Conditions to XSignal ...
XSignalRequest GenerateXMAMCLongSignal(
const int bar_index, // Bar Index ...
const int marketLen, // MarketLength for TP and SL ...
const double r2r, // Risk to Reward ratio ...
const double shpDetectMult,
const double smoother = 50
) {
//
XSignalRequest result = {};
//
result.hasSignal = false;
result.type = X_SIGNAL_NONE;
result.provider = X_UNKNOWN_PROVIDER;
//
if (
!ValidateXMAMCLongConditions(
marketLen,
shpDetectMult,
smoother
)
) {
return result;
}
//
// Price Calculations ...
//
RefreshRates();
//
double entryPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_ASK
);
//
double exitPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_BID
);
//
double priceGap = MathAbs(entryPrice - exitPrice);
//
double ll =
GetMarketLowestLow(
bar_index,
3
);
//
double openPrice = iOpen(
_Symbol,
_Period,
bar_index
);
//
double closePrice = iClose(
_Symbol,
_Period,
bar_index
);
//
double risk = MathMin(openPrice, closePrice) - ll;
double reward = risk * r2r;
//
double sl = 0;
double tp = entryPrice + reward;
//
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
result.signal.tp = tp;
result.signal.sl = sl;
result.signal.symbol = _Symbol;
result.signal.type = X_SIGNAL_LONG;
result.signal.id = totalSignals + 1;
result.signal.entry = entryPrice;
result.signal.provider = X_XMA_PROVIDER;
result.signal.time = barTime;
//
result.hasSignal = true;
result.type = X_SIGNAL_LONG;
result.provider = X_XMA_PROVIDER;
//
return result;
}
//
// Validate XMA Signal Conditions ...
bool ValidateXMAMCLongConditions(
const int marketLen,
const double shpDetectMult,
const double smoother = 50
) {
//
bool isConditionsFilled =
xmaMCLongConds.crossOverMCSlow > 0
&& xmaMCLongConds.crossOverMCFast > 0
&& xmaMCLongConds.crossUnderMCFast > 0
&& xmaMCLongConds.crossUnderMCSlow > 0
&& xmaMCLongConds.mcFastCrossOverSlowTime != 0
&& xmaMCLongConds.mcFastCrossUnderSlowTime != 0
&& xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime != 0
;
//
bool isBLFilled = false;
if (isConditionsFilled) {
//
int crossUnderBarIndex = iBarShift(
_Symbol,
_Period,
xmaMCLongConds.mcFastCrossUnderSlowTime
);
//
int crossOverAndBiggerBarIndex = iBarShift(
_Symbol,
_Period,
xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime
);
//
int cycleMarketLen = MathMin(
MathAbs(crossUnderBarIndex - crossOverAndBiggerBarIndex),
marketLen * 2
);
double hh = GetMarketHighestHigh(
crossOverAndBiggerBarIndex,
cycleMarketLen
);
double ll = GetMarketLowestLow(
crossOverAndBiggerBarIndex,
cycleMarketLen
);
//
double high = iHigh(
_Symbol,
_Period,
crossOverAndBiggerBarIndex
);
double pcHigh = iHigh(
_Symbol,
_Period,
crossOverAndBiggerBarIndex + 1
);
//
double diff = (hh - ll);
double shpValue = shpDetectMult * _Point;
//
bool isPriceRegular =
//
true
//
&&
(
diff < shpValue
|| diff < shpValue - (smoother * _Point)
)
&&
!(
high == hh
|| pcHigh == hh
|| MathAbs(hh - high) < (smoother * _Point)
|| MathAbs(hh - pcHigh) < (smoother * _Point)
)
;
//
// LogMessage("Price Regular: " + isPriceRegular);
//
isBLFilled =
isPriceRegular
&& xmaMCLongConds.mcFastCrossUnderSlowTime < xmaMCLongConds.mcFastCrossOverSlowTime
&& xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime >= xmaMCLongConds.mcFastCrossUnderSlowTime
;
}
//
bool result =
isBLFilled
&& isConditionsFilled
;
//
// Since maybe Conditions Filled but
// Slope is Negative, for Handling Next Signals and
// Prevent from infinity loop, here we Clear Signal Conditions ...
if (
!result
&& isConditionsFilled
) {
ClearXMAMCLongSignalConditions();
}
//
return result;
}
//
// Clear Long Signal Conditions for New One ...
void ClearXMAMCLongSignalConditions() {
//
xmaMCLongConds.mcFastCrossUnderSlowTime = 0;
xmaMCLongConds.crossUnderMCFast = 0;
xmaMCLongConds.crossUnderMCSlow = 0;
//
xmaMCLongConds.mcFastCrossOverSlowTime = 0;
xmaMCLongConds.crossOverMCFast = 0;
xmaMCLongConds.crossOverMCSlow = 0;
//
xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime = 0;
}
//
// Check XMA State for Long Signals ...
bool IsReadyForXMAMCLongSignals(
const XSignal &signal,
const XState &states[],
const int marketLen
) {
//
bool result = false;
//
int countRangedCandles = 0;
bool isMarketRanging = false;
for (int i = 1; i < marketLen; i++) {
//
double high = iHigh(
_Symbol,
_Period,
i
);
//
double low = iLow(
_Symbol,
_Period,
i
);
//
bool isRanging =
//
high > states[i].mc.fast
&& high > states[i].mc.slow
//
&& low < states[i].mc.fast
&& low < states[i].mc.slow
;
if (isRanging) {
countRangedCandles++;
}
}
//
XStateInfo info = ParseXMAStates(states);
double mmSlope = GetSlope(
1,
states[1].marketMiddleage,
2,
states[0].marketMiddleage
);
double mmSlope1 = GetSlope(
1,
states[2].marketMiddleage,
2,
states[1].marketMiddleage
);
double mmSlopeDiff = mmSlope - mmSlope1;
//
isMarketRanging = countRangedCandles > 0;
//
result =
//
true
//
&& mmSlope > 0
&& mmSlope1 > 0
&& mmSlopeDiff > 0
&& !isMarketRanging
&& states[0].marketMiddleage < info.mmMax
;
// if (result) {
// LogMessage("mmSlope: " + mmSlope + ", mmSlope1: " + mmSlope1 + ", Diff: " + mmSlopeDiff);
// }
//
return result;
}
//
// END Functions ...
//