1064 lines
22 KiB
Plaintext
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 ...
|
|
//
|