Files
xMQL4/Packed/XAUUSD-15M/MQL4/Libraries/x-saherelm.x.signal.lib.mq4
T
2024-01-25 04:03:36 +03:30

1064 lines
22 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL4 X 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 Inputs ...
//
//
input string xStarter = "- X Signal Provider -"; // ---> X Signal Provider <---
//
input bool enableXSignalling = true; // X Signalling Enable
//
input bool enableXLong = true; // X Signalling Enable Long
input bool enableXShort = true; // X Signalling Enable Short
//
input double xShortR2R = 3; // X Short Risk To Reward Ratio
input double xShortLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades
input double xShortMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Short Trade
//
input double xLongR2R = 3; // X Long Risk To Reward Ratio
input double xLongLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades
input double xLongMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Long Trade
//
input double xSharpDetectorFactor = 700; // X Sharp Detection Factor
//
input int xMaximumCandlesPerTrade = 206; // X Maximum Candles which a Trade can open
//
input int xOscillatorLength = 7; // X Oscillator Length
//
input double xPSarStep = 0.02; // X Parabolic Sar Step
input double xPSarMaximum = 0.2; // X Parabolic Sar Maximum
//
input int xRangeMarketLength = 5; // X Range Detector Length
//
input int xSwingLength = 7; // X Signal Swing Length
//
// END Inputs ...
//
//
// START Global Requirement Functions ...
//
//
// X Based Signal Conditions ...
struct XSignalConditions {
datetime startTime;
datetime signalTime;
datetime entryTime;
};
//
struct XMarketState {
double psar;
double fast;
double slow;
double open;
double verifier;
double oscillator;
double oscillatorVerifier;
};
//
static XSignalConditions xLongConds;
static bool xCloseLongTrades = false;
static bool xWaitForLongSignals = true;
//
static XSignalConditions xShortConds;
static bool xCloseShortTrades = false;
static bool xWaitForShortSignals = true;
//
// Count Number of Closed Maximum DrawDown Trades ...
static int xFailedSignals = 0;
//
datetime lastVerifierTouched;
//
// END Global Requirement Functions ...
//
//
// START Functions ...
//
//
// Check and Fill Long and Short Signal Handlers ...
void CheckXSignalHandler(
const int bar_index
) {
//
// Check Market For Enable/Disable Signal Handlers ...
// Checking Market for Long Signals ...
//
if (
!enableXSignalling
|| !(enableXLong || enableXShort)
) {
return;
}
//
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
XOHCL candle = GetCandleModel(bar_index);
XOHCL pCandle = GetCandleModel(bar_index + 1);
XTPOWState tPowState = GetXTPowState(
bar_index + 1,
xSwingLength
);
//
XMarketState state = GetXMarketState(
bar_index + 1
);
//
// Check Verifier Last Touched ...
bool isVerifierTouched = pCandle.high > state.verifier
&& pCandle.low < state.verifier;
//
// Disable Signals if a signal Failed ...
if (xFailedSignals) {
//
// TODO: Complete this ...
}
//
// Enable Or Disable Signalling ...
if (isVerifierTouched) {
//
lastVerifierTouched = barTime;
//
if (xWaitForLongSignals) {
xWaitForLongSignals = false;
}
//
if (xWaitForShortSignals) {
xWaitForShortSignals = false;
}
} else {
//
int lastVerifierTouchedBarIndex = iBarShift(
_Symbol,
_Period,
lastVerifierTouched
);
//
int distance = MathAbs(lastVerifierTouchedBarIndex - bar_index);
//
if (
!xWaitForLongSignals
&& distance > (xSwingLength * 2)
) {
xWaitForLongSignals = true;
}
//
if (
!xWaitForShortSignals
&& (
distance > (xSwingLength * 2)
|| (
tPowState.powerDown > tPowState.powerUp
&& tPowState.powerDown < 49
)
)
) {
xWaitForShortSignals = true;
}
}
//
// Close All Long Open Trades ...
if (
tPowState.powerDown > 55
&& tPowState.powerDown > tPowState.powerUp
) {
// xCloseLongTrades = true;
}
}
//
// Check and Fill Long Signal Conditions ...
void CheckXLongSignalConditions(
const int bar_index
) {
//
if (
!enableXLong
|| !enableXSignalling
|| !xWaitForLongSignals
) {
return;
}
//
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
bool isCrossOver = false;
bool isCrossUnder = false;
//
XMarketState cState = GetXMarketState(1);
XMarketState pState = GetXMarketState(2);
//
isCrossUnder =
cState.fast < cState.slow
&& !(pState.fast < pState.slow)
;
//
isCrossOver =
cState.fast > cState.slow
&& !(pState.fast > pState.slow)
;
//
if (
isCrossUnder
&& xLongConds.startTime == 0
) {
//
xLongConds.startTime = barTime;
return;
}
//
if (
isCrossOver
&& xLongConds.startTime > 0
&& xLongConds.signalTime == 0
) {
//
xLongConds.signalTime = barTime;
xLongConds.entryTime = barTime;
return;
}
}
//
// Check and Fill Short Signal Conditions ...
void CheckXShortSignalConditions(
const int bar_index
) {
//
if (
!enableXShort
|| !enableXSignalling
|| !xWaitForShortSignals
) {
return;
}
//
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
bool isCrossOver = false;
bool isCrossUnder = false;
//
XMarketState cState = GetXMarketState(1);
XMarketState pState = GetXMarketState(2);
//
isCrossUnder =
cState.fast < cState.slow
&& !(pState.fast < pState.slow)
;
//
isCrossOver =
cState.fast > cState.slow
&& !(pState.fast > pState.slow)
;
//
if (
isCrossOver
&& xShortConds.startTime == 0
) {
//
xShortConds.startTime = barTime;
return;
}
//
if (
isCrossUnder
&& xShortConds.startTime > 0
&& xShortConds.signalTime == 0
) {
//
xShortConds.signalTime = barTime;
xShortConds.entryTime = barTime;
return;
}
}
//
// Convert Long Signal Conditions to XSignal ...
XSignalRequest GenerateXSignal(
const ENUM_X_SIGNAL_TYPE type, // Signal Type ...
const string signalTag , // Signal Tag ...
const int bar_index
) {
//
XSignalRequest result = {};
//
result.hasSignal = false;
result.type = X_SIGNAL_NONE;
result.provider = X_UNKNOWN_PROVIDER;
//
if (
!enableXSignalling
|| !(enableXLong || enableXShort)
) {
return result;
}
//
bool requestLong = type == X_SIGNAL_LONG;
//
if (requestLong) {
//
if (
!ValidateXLongConditions()
) {
return result;
}
} else {
//
if (
!ValidateXShortConditions()
) {
return result;
}
}
//
// Price Calculations ...
//
RefreshRates();
//
double askPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_ASK
);
//
double bidPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_BID
);
//
double entryPrice = requestLong ?
askPrice :
bidPrice;
//
double exitPrice = requestLong ?
bidPrice :
askPrice;
//
double priceGap = MathAbs(entryPrice - exitPrice);
//
double ll =
//
GetMarketLowestLow(
bar_index,
xSwingLength
)
;
//
double hh =
//
GetMarketHighestHigh(
bar_index,
xSwingLength
)
;
//
double openPrice = iOpen(
_Symbol,
_Period,
bar_index
);
//
double closePrice = iClose(
_Symbol,
_Period,
bar_index
);
//
double risk = requestLong ?
MathMin(openPrice, closePrice) - ll :
hh - MathMax(openPrice, closePrice)
;
//
double reward =
requestLong ?
risk * xLongR2R :
risk * xShortR2R
;
//
double sl = requestLong ?
0 :
0;
double tp = requestLong ?
entryPrice + reward :
entryPrice - reward
;
//
XRState range = GetXRange(
bar_index,
xRangeMarketLength
);
//
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
result.signal.tp = tp;
result.signal.sl = sl;
result.signal.type = type;
result.signal.time = barTime;
result.signal.tag = signalTag;
result.signal.symbol = _Symbol;
result.signal.entry = entryPrice;
result.signal.id = totalSignals + 1;
result.signal.provider = X_XXX_PROVIDER;
//
result.hasSignal = true;
result.type = type;
result.provider = X_XXX_PROVIDER;
//
return result;
}
//
// Validate Signal Conditions ...
bool ValidateXLongConditions() {
//
if (
!enableXLong
|| !enableXSignalling
) {
return false;
}
//
bool isConditionsFilled =
xLongConds.startTime > 0
&& xLongConds.signalTime > 0
&& xLongConds.entryTime > 0
;
//
bool isBLFilled = false;
if (isConditionsFilled) {
//
int startBarIndex = iBarShift(
_Symbol,
_Period,
xLongConds.startTime
);
//
int signalBarIndex = iBarShift(
_Symbol,
_Period,
xLongConds.signalTime
);
//
int entryBarIndex = iBarShift(
_Symbol,
_Period,
xLongConds.entryTime
);
//
isBLFilled =
//
xLongConds.signalTime > xLongConds.startTime
&& xLongConds.entryTime >= xLongConds.signalTime
// && MathAbs(signalBarIndex - startBarIndex) >= 1
;
}
//
bool result =
isBLFilled
&& isConditionsFilled
&& xWaitForLongSignals
;
//
// 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
) {
ClearXLongSignalConditions();
}
//
return result;
}
//
// Validate Signal Conditions ...
bool ValidateXShortConditions() {
//
if (
!enableXShort
|| !enableXSignalling
) {
return false;
}
//
bool isConditionsFilled =
xShortConds.startTime > 0
&& xShortConds.signalTime > 0
&& xShortConds.entryTime > 0
;
//
bool isBLFilled = false;
if (isConditionsFilled) {
//
int startBarIndex = iBarShift(
_Symbol,
_Period,
xShortConds.startTime
);
//
int signalBarIndex = iBarShift(
_Symbol,
_Period,
xShortConds.signalTime
);
//
int entryBarIndex = iBarShift(
_Symbol,
_Period,
xShortConds.entryTime
);
//
isBLFilled =
//
xShortConds.signalTime > xShortConds.startTime
&& xShortConds.entryTime >= xShortConds.signalTime
;
}
//
bool result =
isBLFilled
&& isConditionsFilled
&& xWaitForShortSignals
;
//
// 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
) {
ClearXShortSignalConditions();
}
//
return result;
}
//
// Clear Long Signal Conditions for New One ...
void ClearXLongSignalConditions() {
//
xLongConds.startTime = 0;
xLongConds.entryTime = 0;
xLongConds.signalTime = 0;
}
//
// Clear Short Signal Conditions for New One ...
void ClearXShortSignalConditions() {
//
xShortConds.startTime = 0;
xShortConds.entryTime = 0;
xShortConds.signalTime = 0;
}
//
// Check State for Long Signals ...
bool IsReadyForXSignals(
const XSignal &signal
) {
//
bool result = false;
//
if (
!enableXSignalling
|| !(enableXLong || enableXShort)
) {
return result;
}
//
int signalBarIndex = iBarShift(
_Symbol,
_Period,
signal.time
);
//
// XOHCL candle = GetCandleModel(0);
XOHCL candle = GetCandleModel(signalBarIndex);
XOHCL pCandle = GetCandleModel(signalBarIndex + 1);
//
// Retrieve Range ...
XRState range = GetXRange(
signalBarIndex,
xRangeMarketLength
);
//
// Retrive XMarket States ...
XMarketState xState0 = GetXMarketState(signalBarIndex);
XMarketState xState1 = GetXMarketState(signalBarIndex + 1);
XMarketState xState2 = GetXMarketState(signalBarIndex + 2);
XMarketState xStateLast = GetXMarketState(signalBarIndex + xSwingLength);
//
// Retrieve Trend Powers ...
XTPOWState xTPow0 = GetXTPowState(
signalBarIndex,
xSwingLength
);
XTPOWState xTPow1 = GetXTPowState(
signalBarIndex + 1,
xSwingLength
);
//
double hh = GetMarketHighestHigh(
signalBarIndex,
xSwingLength
);
double ll = GetMarketLowestLow(
signalBarIndex,
xSwingLength
);
double diffChange = (hh - ll);
bool isBigSharpOccured =
diffChange > (xSharpDetectorFactor * _Point)
;
//
bool isPSarVerified = false;
bool isTPowVerified = false;
bool isStateVerified = false;
bool isPriceVerified = false;
//
// Verify Long Signals ...
if (signal.type == X_SIGNAL_LONG) {
//
// Get Price Verification for Long ...
isPriceVerified =
//
// Starter ...
true
//
&& !isBigSharpOccured
//
&& signal.entry < hh
//
// && signal.entry < range.hh
// && signal.entry > range.mid
// //
// && candle.high > xState0.verifier
// && signal.entry > xState0.verifier
//
// && pCandle.low != ll
&& pCandle.high != hh
;
//
int above20TPowers = 0;
double signalSlope = 0;
int tPowUnverifyConditions = 0;
int tPowUnverifyConditionsIdx = 0;
for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) {
//
XTPOWState iTPowState = GetXTPowState(
i,
xSwingLength
);
//
// Calculate Signal Slope ...
if (i == signalBarIndex) {
//
signalSlope = iTPowState.signal;
} else if (i == signalBarIndex + 1) {
//
signalSlope = GetSlope(
1,
iTPowState.signal,
2,
signalSlope
);
}
//
if (
iTPowState.powerUp > iTPowState.powerDown
&& MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20
) {
above20TPowers++;
}
//
if (tPowUnverifyConditionsIdx < 3) {
//
if (
iTPowState.powerUp < iTPowState.powerDown
|| iTPowState.signal > MathMax(iTPowState.powerUp, iTPowState.powerDown)
) {
tPowUnverifyConditions++;
}
//
tPowUnverifyConditionsIdx++;
}
}
//
isTPowVerified =
above20TPowers > 1
&& tPowUnverifyConditions == 0
;
//
isPSarVerified =
xState0.psar < signal.entry
&& xState0.psar < candle.low;
//
isStateVerified =
//
// Start ...
true
//
// && xState0.open < xState0.slow
;
//
result =
//
// Starter ...
true
//
&& isPSarVerified
//
&& isTPowVerified
//
&& isStateVerified
//
&& isPriceVerified
;
} else
//
// Verify Short Signals ...
if (signal.type == X_SIGNAL_SHORT) {
//
isPSarVerified =
xState0.psar > signal.entry
&& xState0.psar > candle.high
;
//
// Get Price Verification for Short ...
isPriceVerified =
//
// Starter ...
true
//
&& !isBigSharpOccured
//
&& signal.entry > ll
&& pCandle.low != ll
;
//
int above20TPowers = 0;
double signalSlope = 0;
int tPowUnverifyConditions = 0;
int tPowUnverifyConditionsIdx = 0;
for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) {
//
XTPOWState iTPowState = GetXTPowState(
i,
xSwingLength
);
//
// Calculate Signal Slope ...
if (i == signalBarIndex) {
//
signalSlope = iTPowState.signal;
} else if (i == signalBarIndex + 1) {
//
signalSlope = GetSlope(
1,
iTPowState.signal,
2,
signalSlope
);
}
//
if (
iTPowState.powerUp > iTPowState.powerDown
&& MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20
) {
above20TPowers++;
}
//
if (tPowUnverifyConditionsIdx < 3) {
//
if (
iTPowState.powerUp > iTPowState.powerDown
|| iTPowState.signal < MathMax(iTPowState.powerUp, iTPowState.powerDown)
) {
tPowUnverifyConditions++;
}
//
tPowUnverifyConditionsIdx++;
}
}
//
isTPowVerified =
above20TPowers < 1
&& tPowUnverifyConditions == 0
&& MathAbs(xTPow0.powerUp - xTPow0.powerDown) > 50 * _Point
;
//
isStateVerified =
//
// Start ...
true
//
// && (xStateLast.verifier - xState0.verifier) >= 0
//
&& xState0.verifier > signal.entry
//
&& MathAbs(signal.entry - xState0.verifier) < (xSharpDetectorFactor * _Point)
;
//
result =
//
// Starter Condition ...
true
//
&& isPSarVerified
//
&& isTPowVerified
//
&& isStateVerified
//
&& isPriceVerified
;
}
//
return result;
}
//
// END Functions ...
//
//
// START Data Provider ...
//
XMarketState GetXMarketState(
const int bar_index
) {
//
XMarketState result = {};
//
double fast = GetMA(
bar_index,
xSwingLength,
0,
MODE_SMA,
PRICE_CLOSE
);
//
double open = GetMA(
bar_index,
xSwingLength,
0,
MODE_SMA,
PRICE_OPEN
);
//
double slow = GetMA(
bar_index,
xSwingLength * 2,
0,
MODE_SMA,
PRICE_CLOSE
);
//
double oscillator = GetMA(
bar_index,
xSwingLength,
0,
MODE_EMA,
PRICE_CLOSE
);
//
double oscillatorVerifier = GetMA(
bar_index,
xSwingLength,
0,
MODE_EMA,
PRICE_WEIGHTED
);
//
int dailyCount = GetDailyCandleCount();
double verifier = GetMA(
bar_index,
dailyCount,
0,
MODE_EMA,
PRICE_MEDIAN
);
//
double psar = iSAR(
_Symbol,
_Period,
xPSarStep,
xPSarMaximum,
bar_index
);
//
result.psar = psar;
result.fast = fast;
result.open = open;
result.slow = slow;
result.verifier = verifier;
result.oscillator = oscillator;
result.oscillatorVerifier = oscillatorVerifier;
//
return result;
}
//
// END Data Provider ...
//