Files
MQL4Data/Bkp/UnUsed/Libs/x-saherelm.signal.lib.mq4
T
2024-01-25 04:05:58 +03:30

1468 lines
33 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL4 Signal Draw 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 Logger library ...
#include "../Libraries/x-saherelm.log.lib.mq4"
//
// Includes Models library ...
#include "../Libraries/x-saherelm.models.lib.mq4"
//
// Includes Drawing library ...
#include "../Libraries/x-saherelm.draw.lib.mq4"
//
// Start Signal Functions ...
//
//
// Generate a Unique ID for Signal ...
string GenerateSignalTAG(
const XSignal &signal,
const string tag = "",
const string longSignalLabel = "",
const string shortSignalLabel = ""
) {
//
// Generate Propper Label for Signal ...
string label = signal.type == X_LONG ? longSignalLabel : signal.type == X_SHORT ? shortSignalLabel : "UN_KNOWN";
//
// Generate Unique String Identifier for Signal ...
string result = tag +
"_[ID:" + IntegerToString(signal.id) + "]" +
"_[" + label + "]" +
"_[" + signal.symbol + "]" +
"_[Time:" + TimeToStr(signal.time) + "]" +
"_[TP:" + DoubleToString(signal.tp) + "]" +
"_[SL:" + DoubleToString(signal.sl) + "]";
//
return result;
}
//
// Logging a Signal ...
void LogSignal(
const XSignal &signal,
const string tag = "",
const string longSignalLabel = "",
const string shortSignalLabel = ""
) {
//
// Generate Message ...
string signalMessage = GenerateSignalTAG(
signal,
tag,
longSignalLabel,
shortSignalLabel
);
//
LogMessage(signalMessage);
}
//
// Retrieve Price Action Candlestick Type ...
double GetPCandleType(const int bar_index) {
//
double result = iCustom(
_Symbol,
_Period,
pcrtIndicatorName,
0,
bar_index
);
//
return result;
}
//
// Retrieve OSC Snapshot State ...
XOSCState GetOSCState(const int bar_index) {
//
// Temp Result ...
XOSCState result = {};
//
// Start Extract Data from Oscillator ...
//
//
// Fast OSC ...
double fastOSC = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
0, // Fast OSC Buffer Index ...
bar_index
);
result.fastOSC = fastOSC;
//
// Prev FastOSC ...
double fastOSCPrev = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
0, // Fast OSC Buffer Index ...
bar_index + 1
);
result.fastOSCPrev = fastOSCPrev;
//
// Slow OSC ...
double slowOSC = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
1, // Slow OSC Buffer Index ...
bar_index
);
result.slowOSC = slowOSC;
//
// Prev Slow OSC ...
double slowOSCPrev = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
1, // Slow OSC Buffer Index ...
bar_index + 1
);
result.slowOSCPrev = slowOSCPrev;
//
// Power OSC ...
double powerOSC = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
2, // Power OSC Buffer Index ...
bar_index
);
result.powerOSC = powerOSC;
//
double powerOSCPrev = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
2, // Power OSC Buffer Index ...
bar_index + 1
);
result.powerOSCPrev = powerOSCPrev;
//
// Var OSC ...
double varOSC = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
3, // Var OSC Buffer Index ...
bar_index
);
result.varOSC = varOSC;
//
double varOSCPrev = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
3, // Var OSC Buffer Index ...
bar_index + 1
);
result.varOSCPrev = varOSCPrev;
//
// Tan FS OSC ...
double tanFSOSC = iCustom(
_Symbol,
_Period,
oscIndicatorName,
fastOSCLength,
fastOSCMultiplier,
slowOSCLength,
slowOSCMultiplier,
4, // Tan F/S OSC Buffer Index ...
bar_index
);
result.tanFSOSC = tanFSOSC;
//
// End Extract Data from Oscillator ...
//
//
return result;
}
//
// Retrieve Ma Snapshot State ...
XMaState GetMaState(
const int bar_index,
int fastMaPeriod = 20,
ENUM_MA_METHOD fastMaMethod = MODE_EMA,
ENUM_APPLIED_PRICE fastMaAppliedPrice = PRICE_CLOSE,
int slowMaPeriod = 50,
ENUM_MA_METHOD slowMaMethod = MODE_EMA,
ENUM_APPLIED_PRICE slowMaAppliedPrice = PRICE_CLOSE
) {
//
XMaState result = {};
//
double fastMa = iCustom(
_Symbol,
_Period,
maIndicatorName,
fastMaPeriod,
fastMaMethod,
fastMaAppliedPrice,
slowMaPeriod,
slowMaMethod,
slowMaAppliedPrice,
0,
bar_index
);
result.fastMa = fastMa;
//
double fastMaPrev = iCustom(
_Symbol,
_Period,
maIndicatorName,
fastMaPeriod,
fastMaMethod,
fastMaAppliedPrice,
slowMaPeriod,
slowMaMethod,
slowMaAppliedPrice,
0,
bar_index + 1
);
result.fastMaPrev = fastMaPrev;
//
double slowMa = iCustom(
_Symbol,
_Period,
maIndicatorName,
fastMaPeriod,
fastMaMethod,
fastMaAppliedPrice,
slowMaPeriod,
slowMaMethod,
slowMaAppliedPrice,
1,
bar_index
);
result.slowMa = slowMa;
//
double slowMaPrev = iCustom(
_Symbol,
_Period,
maIndicatorName,
fastMaPeriod,
fastMaMethod,
fastMaAppliedPrice,
slowMaPeriod,
slowMaMethod,
slowMaAppliedPrice,
1,
bar_index + 1
);
result.slowMaPrev = slowMaPrev;
//
Print(fastMa, slowMa, fastMaPrev, slowMaPrev);
//
return result;
}
//
// Retrieve MACD info ...
XMACDState GetMACDState() {
//
XMACDState result = {};
//
// TODO: Complete this later ...
//
return result;
}
//
// Check OSC Has Signal ...
// default Method ...
XSignalInfo OSCHasSignal(
const XOSCState &oscState,
const double &minimumSignalPower,
const double &minimumVarPower
) {
//
// Genrate Temp Result ...
XSignalInfo result = {};
//
bool isCrossedOver = oscState.fastOSC > oscState.slowOSC && !(oscState.fastOSCPrev > oscState.slowOSCPrev);
bool hasLongSignal = isCrossedOver && oscState.powerOSC >= minimumSignalPower;
result.hasLongSignal = hasLongSignal;
//
bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev);
bool hasShortSignal = isCrossedUnder && oscState.powerOSC >= minimumSignalPower;
result.hasShortSignal = hasShortSignal;
//
bool hasSignal = hasLongSignal || hasShortSignal;
result.hasSignal = hasSignal;
//
return result;
}
//
// Check OSC Has Signal ...
// Method 1 ...
XSignalInfo OSCHasSignal_1(
const XOSCState &oscState,
const double &minimumSignalPower,
const double &minimumVarPower
) {
//
static bool canSignalLong = true;
static bool canSignalShort = true;
//
// Genrate Temp Result ...
XSignalInfo result = {};
//return result;
//
// bool hasLongSignal = false;
bool isCrossedOver = oscState.fastOSC > oscState.slowOSC &&
!(oscState.fastOSCPrev > oscState.slowOSCPrev);
bool hasLongSignal = isCrossedOver &&
oscState.powerOSC >= minimumSignalPower &&
oscState.varOSC >= minimumVarPower;
result.hasLongSignal = hasLongSignal;
// if (hasLongSignal) {
// canSignalLong = false;
// }
//
// bool hasShortSignal = false;
bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev);
bool hasShortSignal = isCrossedUnder &&
oscState.powerOSC >= minimumSignalPower &&
oscState.varOSC >= minimumVarPower;
result.hasShortSignal = hasShortSignal;
// if (hasShortSignal) {
// canSignalShort = false;
// }
//
bool hasSignal = hasLongSignal || hasShortSignal;
result.hasSignal = hasSignal;
//
// Fix can Signal Long ...
//if (oscState.fastOSC >= 0 && !canSignalLong) {
// canSignalLong = true;
//}
//
// Fix can Signal Short ...
//if (oscState.fastOSC <= 1 && !canSignalShort) {
// canSignalShort = true;
//}
//
return result;
}
//
// Check OSC Has Signal ...
// Method 2 ...
XSignalInfo OSCHasSignal_2(
const XOSCState &oscState,
const int &bar_index
) {
//
static bool canSignalLong = true;
static bool canSignalShort = true;
//
// Genrate Temp Result ...
XSignalInfo result = {};
//return result;
//
// bool hasLongSignal = false;
bool isCrossedOver = oscState.fastOSC > oscState.slowOSC &&
!(oscState.fastOSCPrev > oscState.slowOSCPrev);
//
// Get Prev Price Action Candle Type ...
int pCandleType = (int) GetPCandleType(bar_index + 1);
bool hasLongSignal = isCrossedOver
&& oscState.slowOSC > 0.5
&& oscState.varOSC > 0;
// && oscState.powerOSC >= 0.006
// && oscState.powerOSC - oscState.powerOSCPrev > 0
// && oscState.tanFSOSC >= 0.06
// && (
// pCandleType == X_CT_HAMMER ||
// pCandleType == X_CT_BULLISH_BELT ||
// pCandleType == X_CT_MORNING_STAR ||
// pCandleType == X_CT_BULLISH_KICKER ||
// pCandleType == X_CT_BULLISH_HARAMI ||
// pCandleType == X_CT_INVERTED_HAMMER ||
// pCandleType == X_CT_BULLISH_ENGULFING ||
// pCandleType == 0
// )
result.hasLongSignal = hasLongSignal;
if (hasLongSignal) {
//
// Print("Tan: " + oscState.tanFSOSC);
}
// if (hasLongSignal) {
// canSignalLong = false;
// }
//
// bool hasShortSignal = false;
bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev);
bool hasShortSignal = false;
result.hasShortSignal = hasShortSignal;
// if (hasShortSignal) {
// canSignalShort = false;
// }
//
bool hasSignal = hasLongSignal || hasShortSignal;
result.hasSignal = hasSignal;
//
// Fix can Signal Long ...
//if (oscState.fastOSC >= 0 && !canSignalLong) {
// canSignalLong = true;
//}
//
// Fix can Signal Short ...
//if (oscState.fastOSC <= 1 && !canSignalShort) {
// canSignalShort = true;
//}
//
return result;
}
//
// Check Ma Has Signal ...
XSignalInfo MaHasSignal(
const XMaState &maState,
const int &bar_index
) {
//
XSignalInfo result = {};
result.hasSignal = false;
//
// Long ...
bool isFastCrossOverSlow = maState.fastMa > maState.slowMa
&& !(maState.fastMaPrev > maState.slowMaPrev);
bool hasLongSignal = isFastCrossOverSlow;
result.hasLongSignal = hasLongSignal;
//
// Short ...
bool isFastCrossUnderSlow = maState.fastMa < maState.slowMa
&& !(maState.fastMaPrev < maState.slowMaPrev);
bool hasShortSignal = isFastCrossUnderSlow;
result.hasShortSignal = hasShortSignal;
//
bool hasSignal = hasLongSignal || hasShortSignal;
result.hasSignal = hasSignal;
//
return result;
}
//
// Reading Swing SL ...
XSLInfo GetSwngSL(const int &bar_index) {
//
// Temp result ...
XSLInfo result = {};
//
// Start Reading SL ...
//
//
// Long SL ...
double longSL = iCustom(
_Symbol,
_Period,
slIndicatorName,
slLoopback, // SL IND Inputs ...
slThrshold, // SL IND Inputs ...
0, // Long SL Buffer Index ...
bar_index
);
longSL = NormalizeDouble(longSL, _Digits);
result.longSL = longSL;
//
// Short SL ...
double shortSL = iCustom(
_Symbol,
_Period,
slIndicatorName,
slLoopback, // SL IND Inputs ...
slThrshold, // SL IND Inputs ...
1, // Short SL Buffer Index ...
bar_index
);
shortSL = NormalizeDouble(shortSL, _Digits);
result.shortSL = shortSL;
//
// End Reading SL ...
//
//
return result;
}
//
// Reading TP based on SwingSL ...
XTPInfo GetTP(const int &bar_index) {
//
// Temp result ...
XTPInfo result = {};
//
// Start Reading TP ...
//
//
// Long TP ...
double longTP = iCustom(
_Symbol,
_Period,
tpIndicatorName,
slLoopback, // TP IND Inputs ...
slThrshold, // SL IND Inputs ...
riskToRewardRatio, // TP IND Inputs ...
0, // Long TP Buffer Index ...
bar_index
);
longTP = NormalizeDouble(longTP, _Digits);
result.longTP = longTP;
//
// Short TP ...
double shortTP = iCustom(
_Symbol,
_Period,
tpIndicatorName,
slLoopback, // TP IND Inputs ...
slThrshold, // SL IND Inputs ...
riskToRewardRatio, // TP IND Inputs ...
1, // Short TP Buffer Index ...
bar_index
);
shortTP = NormalizeDouble(shortTP, _Digits);
result.shortTP = shortTP;
//
// End Reading TP ...
//
//
return result;
}
//
// Calculate Signal ...
// Default Method ...
XSignalRequest CalculateOSCSignal(
const int bar_index,
const double minimumSignalPower = 0.03,
const double minimumVarPower = 0.01
) {
//
XSignalRequest result = {};
result.hasSignal = false;
result.type = X_NONE;
//
// Reading Oscillator State ...
XOSCState oscState = GetOSCState(bar_index);
//
// Generate Signals From OSC ...
XSignalInfo signalInfo = OSCHasSignal(
oscState,
minimumSignalPower,
minimumVarPower
);
//
result.hasSignal = signalInfo.hasSignal;
if (!signalInfo.hasSignal) {
return result;
}
//
// increase signal count ...
signalCount++;
//
// increase long/short signal count ...
if (signalInfo.hasLongSignal) {
longSignalCount++;
} else if (signalInfo.hasShortSignal) {
shortSignalCount++;
}
//
// Retrieve Open Price ...
double openPrice = iOpen(_Symbol, _Period, bar_index);
openPrice = NormalizeDouble(openPrice, _Digits);
//
// Signal Entry Price ...
double signalEntryPrice = signalInfo.hasLongSignal ? Ask : Bid;
signalEntryPrice = NormalizeDouble(signalEntryPrice, _Digits);
//
// Signal Time ...
datetime signalTime = iTime(_Symbol, _Period, bar_index);
//
// Signal Type ...
X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT;
result.type = signalType;
//
// Reading SL ...
XSLInfo slInfo = GetSwngSL(bar_index);
//
// Reading TP ...
XTPInfo tpInfo = GetTP(bar_index);
//
// Generate Signal SL ...
double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL;
//
// Generate Signal TP ...
double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP;
//
// Generate XSignal Instance based on received Data ...
XSignal signal = {};
signal.id = signalCount;
signal.sl = signalSL;
signal.tp = signalTP;
signal.time = signalTime;
signal.type = signalType;
signal.symbol = _Symbol;
// signal.openPrice = openPrice;
// signal.entryPrice = signalEntryPrice;
//
result.signal = signal;
//
return result;
}
//
// Calculate Signal ...
// Method 1 ...
XSignalRequest CalculateSignal_1(
const int bar_index,
const double minimumSignalPower = 0.03,
const double minimumVarPower = 0.01
) {
//
XSignalRequest result = {};
result.hasSignal = false;
result.type = X_NONE;
//
// Reading Oscillator State ...
XOSCState oscState = GetOSCState(bar_index);
//
// Retrieve Price Action Theory based Candlestick Type ...
int pCandleType = (int) GetPCandleType(bar_index);
//
// Generate Signals From OSC ...
XSignalInfo signalInfo = OSCHasSignal_1(
oscState,
minimumSignalPower,
minimumVarPower
);
//
result.hasSignal = signalInfo.hasSignal;
if (!signalInfo.hasSignal) {
return result;
}
//
// Get Price Action Candlestick Verification on Long Signals ...
if (signalInfo.hasLongSignal) {
//
// Check current Candle Type based on Price Action Theory ...
if (pCandleType == X_P_CT_BEARISH) {
//
result.hasSignal = false;
return result;
} else if (pCandleType == X_P_CT_NEUTRAL) {
//
// Here we must loop through back bar indexes until find a
// candle which no NEUTRAL ...
int barCounter = bar_index + 1;
int prevUnNeutralPCandleType = -1;
while(
barCounter <= Bars &&
prevUnNeutralPCandleType == -1
) {
//
int cPCType = (int) GetPCandleType(barCounter);
if (cPCType != X_P_CT_NEUTRAL) {
prevUnNeutralPCandleType = cPCType;
} else {
barCounter++;
}
}
//
result.hasSignal = false;
if (prevUnNeutralPCandleType != X_P_CT_BULLISH) {
return result;
}
//
result.hasSignal = true;
}
}
//
// Get Price Action Candlestick Verification on Short Signals ...
if (signalInfo.hasShortSignal) {
//
// Check current Candle Type based on Price Action Theory ...
if (pCandleType == X_P_CT_BULLISH) {
//
result.hasSignal = false;
return result;
} else if (pCandleType == X_P_CT_NEUTRAL) {
//
// Here we must loop through back bar indexes until find a
// candle which no NEUTRAL ...
int barCounter = bar_index + 1;
int prevUnNeutralPCandleType = -1;
while(
barCounter <= Bars &&
prevUnNeutralPCandleType == -1
) {
//
int cPCType = (int) GetPCandleType(barCounter);
if (cPCType != X_P_CT_NEUTRAL) {
prevUnNeutralPCandleType = cPCType;
} else {
barCounter++;
}
}
//
result.hasSignal = false;
if (prevUnNeutralPCandleType != X_P_CT_BEARISH) {
return result;
}
//
result.hasSignal = true;
}
}
//
// increase signal count ...
signalCount++;
//
// increase long/short signal count ...
if (signalInfo.hasLongSignal) {
longSignalCount++;
} else if (signalInfo.hasShortSignal) {
shortSignalCount++;
}
//
// Retrieve Open Price ...
double openPrice = iOpen(_Symbol, _Period, bar_index);
openPrice = NormalizeDouble(openPrice, _Digits);
//
// Signal Entry Price ...
RefreshRates();
double signalEntryPrice = signalInfo.hasLongSignal ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
// signalInfo.hasLongSignal ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
signalEntryPrice = NormalizeDouble(signalEntryPrice, _Digits);
//
// Signal Time ...
datetime signalTime = iTime(_Symbol, _Period, bar_index);
//
// Signal Type ...
X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT;
result.type = signalType;
//
// Reading SL ...
XSLInfo slInfo = GetSwngSL(bar_index);
//
// Reading TP ...
XTPInfo tpInfo = GetTP(bar_index);
//
// Generate Signal SL ...
double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL;
//
// Generate Signal TP ...
double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : slInfo.longSL; // tpInfo.shortTP;
//
// Generate XSignal Instance based on received Data ...
XSignal signal = {};
signal.id = signalCount;
signal.sl = signalSL;
signal.tp = signalTP;
signal.time = signalTime;
signal.type = signalType;
signal.symbol = _Symbol;
// signal.openPrice = openPrice;
// signal.entryPrice = signalEntryPrice;
//
result.signal = signal;
//
return result;
}
//
// Calculate Signal ...
// Method 2 ...
XSignalRequest CalculateSignal_2(const int bar_index) {
//
XSignalRequest result = {};
result.hasSignal = false;
result.type = X_NONE;
//
// Reading Oscillator State ...
XOSCState oscState = GetOSCState(bar_index);
//
// Generate Signals From OSC ...
XSignalInfo signalInfo = OSCHasSignal_2(
oscState,
bar_index
);
//
result.hasSignal = signalInfo.hasSignal;
if (!signalInfo.hasSignal) {
return result;
}
//
// increase signal count ...
signalCount++;
//
// increase long/short signal count ...
if (signalInfo.hasLongSignal) {
longSignalCount++;
} else if (signalInfo.hasShortSignal) {
shortSignalCount++;
}
//
// Signal Time ...
datetime signalTime = iTime(_Symbol, _Period, bar_index);
//
// Signal Type ...
X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT;
result.type = signalType;
//
// Reading SL ...
XSLInfo slInfo = GetSwngSL(bar_index);
//
// Reading TP ...
XTPInfo tpInfo = GetTP(bar_index);
//
// Generate Signal SL ...
double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL;
//
// Generate Signal TP ...
double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP;
//
// Generate XSignal Instance based on received Data ...
XSignal signal = {};
signal.id = signalCount;
signal.sl = signalSL;
signal.tp = signalTP;
signal.time = signalTime;
signal.type = signalType;
signal.symbol = _Symbol;
//
result.signal = signal;
//
return result;
}
//
// Calculate Signal ...
// Using Ma ...
XSignalRequest CalculateMaSignal(const int bar_index) {
//
XSignalRequest result = {};
result.hasSignal = false;
result.type = X_NONE;
//
// Reading Moving Average State ...
XMaState maState = GetMaState(bar_index);
//
// Generate Signals From OSC ...
XSignalInfo signalInfo = MaHasSignal(
maState,
bar_index
);
Print("Ma HasSignal: ", signalInfo.hasSignal);
//
result.hasSignal = signalInfo.hasSignal;
if (!signalInfo.hasSignal) {
return result;
}
//
// increase signal count ...
signalCount++;
//
// increase long/short signal count ...
if (signalInfo.hasLongSignal) {
longSignalCount++;
} else if (signalInfo.hasShortSignal) {
shortSignalCount++;
}
//
// Signal Time ...
datetime signalTime = iTime(_Symbol, _Period, bar_index);
//
// Signal Type ...
X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT;
result.type = signalType;
//
// Reading SL ...
XSLInfo slInfo = GetSwngSL(bar_index);
//
// Reading TP ...
XTPInfo tpInfo = GetTP(bar_index);
//
// Generate Signal SL ...
double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL;
//
// Generate Signal TP ...
double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP;
//
// Generate XSignal Instance based on received Data ...
XSignal signal = {};
signal.id = signalCount;
signal.sl = signalSL;
signal.tp = signalTP;
signal.time = signalTime;
signal.type = signalType;
signal.symbol = _Symbol;
//
result.signal = signal;
//
return result;
}
//
// Count Open Positions ...
int CountOpenPositions() {
//
int result = 0;
//
// Loop through Orders ...
for (int i = 0; i < OrdersTotal(); i++) {
//
// Select indexed Order ...
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
//
// Check Order ...
if (OrderSymbol() == _Symbol) {
result++;
}
}
}
//
// Return Result ...
return result;
}
//
// Handle Trading On Signals ...
void TradeOnSignal(
const XSignal &signal,
double tradeVolume = 0.1,
string signalTag = "X-Signal",
string longSignalLabel = "X-Long",
color longSignalColor = clrLime,
string shortSignalLabel = "X-Short",
color shortSignalColor = clrRed
) {
//
// Start Genearting required data ...
//
//
// START implementing Money Management ...
//
if (tradeCount == 0) {
//
initialBalance = AccountBalance();
//
string msg = StringConcatenate("Initial Account Balance: ", initialBalance);
LogMessage(msg);
}
//
// Retrieve current Account balance
double currentBalance = AccountBalance();
if (currentBalance < initialBalance / 2) {
//
string msg = StringConcatenate("Account Balance less than minimum allowed, trading off ...");
LogMessage(msg);
//
return;
}
//
// END implementing Money Management ...
//
//
// Detect Trade is Long or Short ...
bool isLongSignal = signal.type == X_LONG;
//
// Generate Trade Comment ...
string tradeComment = GenerateSignalTAG(
signal,
signalTag,
longSignalLabel,
shortSignalLabel
);
//
// Detect Trade Operation ...
int tradeOperation = isLongSignal ? OP_BUY : OP_SELL;
//
// Detect Trade Color ...
color tradeColor = isLongSignal ? longSignalColor : shortSignalColor;
//
// End Genearting required data ...
//
//
double price = 0;
double closePrice = 0;
double priceGap = 0;
double tp = 0;
double sl = 0;
//
RefreshRates();
//
// Calculating Open, SL, TP for Positions ...
if (isLongSignal) {
//
// Long Positions ...
//
// Prices ...
price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
closePrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
//
priceGap = closePrice - price;
//
// SL ...
if (signal.sl > 0) {
sl = signal.sl + priceGap;
}
//
// TP ...
if (signal.tp > 0) {
tp = signal.tp - priceGap;
}
} else {
//
// Short Positions ...
//
// Prices ...
price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
closePrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
//
// SL ...
if (signal.sl > 0) {
sl = signal.sl - priceGap;
}
//
// TP ...
if (signal.tp > 0) {
tp = signal.tp + priceGap;
}
}
//
// Ignore last TP and SL Calculation and Use Default ...
// sl = signal.sl;
// tp = signal.tp;
//
// Normalize Prices ...
price = NormalizeDouble(price, _Digits);
sl = NormalizeDouble(sl, _Digits);
tp = NormalizeDouble(tp, _Digits);
//
// Define Trade Variables ...
double slGap = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
//
// Price Check ...
if (price == 0) {
return;
}
//
// Prevent Open Trading when price doesn't fill slGap ...'
if (signal.sl > 0 && signal.sl < slGap) {
return;
}
//
// Prevent Open Trading when price doesn't fill slGap ...'
if (signal.tp > 0 && signal.tp < slGap) {
return;
}
//
// Fix Signal SL and Price Same issue ...
if (price == sl || MathAbs(price - sl) <= slGap) {
//
// string msg = StringConcatenate("id: ", signal.id , ", Price: ", price, ", sl: ", sl);
// LogMessage(msg);
//
return;
}
//
// Placing Order ...
int orderTicket = OrderSend(
signal.symbol,
tradeOperation,
tradeVolume,
price,
3,
sl,
tp,
tradeComment,
(int)signal.id,
0,
tradeColor
);
//
if (orderTicket >= 0) {
tradeCount++;
}
}
//
// Draw Signal Shapes on Chart ...
bool DrawSignalShape(
const XSignal &signal,
long chartID = 0,
int subWindowID = 0,
const double positionThresholdFactor = 10,
string signalTag = "X-Signal",
string longSignalLabel = "X-Long",
color longSignalColor = clrAqua,
string shortSignalLabel = "X-Short",
color shortSignalColor = clrFuchsia
) {
//
// Generate isLongSignal Var ...
bool isLongSignal = signal.type == X_LONG;
//
// Signal Bar Index ...
int bar_index = iBarShift(
_Symbol,
_Period,
signal.time
);
//
// START Draw Signal Arrow ...
//
//
// Arrow Shape Name ...
string arrowName = StringConcatenate(signalTag, "_Arrow_", signal.id);
//
// Arrow Price ...
double arrowPrice = 0;
if (isLongSignal) {
//
arrowPrice = iLow(
_Symbol,
_Period,
bar_index
);
//
arrowPrice = arrowPrice - (positionThresholdFactor * _Point);
} else {
//
arrowPrice = iHigh(
_Symbol,
_Period,
bar_index
);
//
arrowPrice = arrowPrice + (positionThresholdFactor * _Point);
}
//
// Arrow Code ...
uchar arrowCode = isLongSignal ? SYMBOL_ARROWUP : SYMBOL_ARROWDOWN;
//
// Arrow Anchor Point ...
ENUM_ARROW_ANCHOR arrowAnchorPoint = isLongSignal ? ANCHOR_BOTTOM : ANCHOR_TOP;
//
// Arrow Color ...
color arrowColor = isLongSignal ? longSignalColor : shortSignalColor;
//
// Draw Signal Arrow Shape ...
bool result = DrawArrow(
chartID,
arrowName,
subWindowID,
signal.time,
arrowPrice,
arrowCode,
arrowAnchorPoint,
arrowColor,
STYLE_SOLID,
3,
false,
false,
false,
0
);
//
// END Draw Signal Arrow ...
//
//
// START Draw Signal SL/TP ...
//
string slLineName = StringConcatenate(signalTag, "_SL_", signal.id);
string tpLineName = StringConcatenate(signalTag, "_TP_", signal.id);
//
color slColor = isLongSignal ? shortSignalColor : longSignalColor;
//
datetime time1 = iTime(
_Symbol,
_Period,
bar_index + 1
);
//
// Draw Signal SL ...
result = DrawTrendLine(
chartID,
slLineName,
subWindowID,
time1,
signal.sl,
signal.time,
signal.sl,
slColor,
STYLE_SOLID,
2
);
//
// Draw Signal TP ...
result = DrawTrendLine(
chartID,
tpLineName,
subWindowID,
time1,
signal.tp,
signal.time,
signal.tp,
arrowColor,
STYLE_SOLID,
2
);
//
// END Draw Signal SL/TP ...
//
//
// Start Draw Signal Label ...
//
//
string labelName = StringConcatenate(signalTag, "_Label_", signal.id);
//
double labelPrice = isLongSignal ? arrowPrice - (positionThresholdFactor * _Point) : arrowPrice + (positionThresholdFactor * _Point);
//
string labelText = isLongSignal ? longSignalLabel : shortSignalLabel;
//
result = DrawText(
chartID,
labelName,
subWindowID,
signal.time,
labelPrice,
labelText,
"Arial",
10,
arrowColor,
0,
ANCHOR_CENTER
);
//
// End Draw Signal Label ...
//
//
return result;
}
//
// End Signal Functions ...
//