766 lines
24 KiB
Plaintext
766 lines
24 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| library_functions.mqh |
|
|
//| Copyright 2023, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
|
|
|
|
|
|
#include <Trade/Trade.mqh>
|
|
|
|
|
|
|
|
int findMondayFromLastPeriodWeeks(int _period);
|
|
|
|
// FRACTALS RELATED FUNCTIONS
|
|
bool isLowFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame); // checks if the given index candle is, a low fractal of the left, right periods
|
|
bool isHighFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame); // checks if the given index candle is, a high fractal of the left, right periods
|
|
|
|
// TIME FRAME RELATED FUNCTIONS
|
|
string getChartTimeFrameInString() ; // gets the chart time frame in string format
|
|
string timeFrameToString(ENUM_TIMEFRAMES _timeFrame);
|
|
|
|
// SESSIONS RELATED FUNCTIONS
|
|
bool sessionIsNy(); // checks if the session is ny
|
|
bool sessionIsLondon(); // checks if the session is london
|
|
bool sessionIsTokyo();
|
|
|
|
|
|
|
|
// TRADE RELATED FUNCTIONS
|
|
bool closePartialFromAllPositions(double partialAmount) ; // closes partial of all open positions the partial is partialAmount (parameter)
|
|
bool closePartialFromSpecificPosition(ulong posTicket, double partialToClose) ; // closes a partial from the given position ticket
|
|
bool stopLossIsValidBuys(double stopLoss, double _maxPipsRiskAmount);
|
|
bool stopLossIsValidSells(double stopLoss,double _maxPipsRiskAmount);
|
|
double positionProfitInPips(ulong posTicket); // returns the position profit in pips
|
|
double positionStopLoss(ulong posTicket);
|
|
void positionTrailStopLoss(ulong posTicket, double newStopLoss, double takeProfit);
|
|
|
|
|
|
|
|
// CANDLE ANATOMY RELATED FUNCTIONS
|
|
bool buyBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody); // checks if the buy breaker candle is big enough
|
|
bool sellBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody); // checks if the sell breaker candle is big enough
|
|
bool bearishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection); // this function assumes that the previous candle is bearish
|
|
bool bullishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection); // this function assumes that the previous candle is bullish
|
|
double retestWickFormedOnTheFirstHalfOfCandle(ENUM_TIMEFRAMES _mainTimeFrame, ENUM_TIMEFRAMES _secondaryTimeFrame);
|
|
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index);
|
|
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index);
|
|
bool candleClosedDoji(ENUM_TIMEFRAMES _timeFrame, int _index);
|
|
bool candleBodyIsValid(ENUM_TIMEFRAMES _timeFrame, int _index); // this function is used for enhancing the detection of supports/resistances
|
|
|
|
|
|
// SUPPORT AND RESISTANCE RELATED FUNCTIONS
|
|
bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index=0); // _index = 0 is the default state which is a specific case of the general function with _index = i
|
|
bool resistancePatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index=0);// _index = 0 is the default state which is a specific case of the general function with _index = i
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* WARNING FOR THE NEXT FUNCTION*/
|
|
/* IF A FRIDAY WAS NOT ON THE BROKER, THE FUNCTION WILL NOT COUNT THE WEEK. MAKE SURE BEFORE APPLYING IT TO SEE VISUALLY THAT IT WAS LAUNCHED RIGHT */
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int findMondayFromLastPeriodWeeks(int _period) { // _period = 1 means the previous week. _period = 2 means 2 weeks ago. and so on ...
|
|
|
|
int startCountFromIndex = 0 ;
|
|
datetime localTime = TimeLocal();
|
|
MqlDateTime dateTimeStructure ;
|
|
TimeToStruct(localTime,dateTimeStructure);
|
|
int dayOfTheWeek = dateTimeStructure.day_of_week;
|
|
int hourOfTheDay = dateTimeStructure.hour;
|
|
|
|
if(dayOfTheWeek == 5) { // means if we called the function on friday , start counting from the candle of index 25, because our goal is to reach the pervious week friday, so we know we are in the previous week
|
|
startCountFromIndex = 25 ;
|
|
}
|
|
if(dayOfTheWeek == 6 || dayOfTheWeek == 7) {
|
|
Alert("Its saturday/sunday start next week !");
|
|
}
|
|
|
|
MqlDateTime shiftedBarTimeStruct ;
|
|
int weeksPassed = 0 ; // count of how many weeks we passed. it starts with 0 since we start at week 0. and will end in _period
|
|
int lockCounter = 0;
|
|
int i = startCountFromIndex ; // i represents the distance from the moment we started. by the end of the function it will point to the first monday of the desired week that we want
|
|
while(weeksPassed < _period) {
|
|
datetime shiftedBarTime=iTime(_Symbol,PERIOD_CURRENT,i); // take the date of the current candle
|
|
TimeToStruct(shiftedBarTime,shiftedBarTimeStruct); // change the date to a struct
|
|
|
|
if(shiftedBarTimeStruct.day_of_week == 5 && lockCounter == 0) { // if we reached friday, add the weeksPassed by 1 and lock the block for the next friday
|
|
weeksPassed++; // each time we reach a friday this means we are in a previous week. (we are counting the weeks starting from the current moment and going back in time)
|
|
lockCounter++;
|
|
|
|
} else if(shiftedBarTimeStruct.day_of_week == 5 && lockCounter > 0) { // stay locked until we pass the current friday
|
|
lockCounter++ ;
|
|
} else if(shiftedBarTimeStruct.day_of_week == 4) { // if reached thursday , then release the lock
|
|
lockCounter = 0;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
Print("weeks passed value is: "+ weeksPassed);
|
|
return i-2 ;
|
|
|
|
}
|
|
|
|
|
|
// ************************ FRACTALS FUNCTIONS ************************
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool isLowFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame) { // checks if the given index candle is, a low fractal of the left, right periods
|
|
|
|
for(int i = index+1 ; i < (index + leftPeriod + 1) ; i++) {
|
|
if(!(iLow(Symbol(),timeFrame,index) <= iLow(Symbol(),timeFrame,i))) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
if(index > rightPeriod) { // this means we have enough candles to the right
|
|
|
|
for(int j = index-1 ; (j > index - rightPeriod - 1) ; j--) {
|
|
if(!(iLow(Symbol(),timeFrame,index) <= iLow(Symbol(),timeFrame,j))) {
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
return false ;
|
|
}
|
|
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool isHighFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame) { // checks if the given index candle is, a high fractal of the left, right periods
|
|
|
|
for(int i = index+1 ; i < (index + leftPeriod + 1) ; i++) {
|
|
if(!(iHigh(Symbol(),timeFrame,index) >= iHigh(Symbol(),timeFrame,i))) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(index > rightPeriod) { // this means we have enough candles to the right
|
|
|
|
for(int j = index-1 ; (j > index - rightPeriod - 1) ; j--) {
|
|
if(!(iHigh(Symbol(),timeFrame,index) >= iHigh(Symbol(),timeFrame,j))) {
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ************************ TIME FRAMES FUNCTIONS ************************
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string getChartTimeFrameInString() {
|
|
|
|
ENUM_TIMEFRAMES period = Period();
|
|
|
|
switch(period) {
|
|
|
|
case PERIOD_M1:
|
|
return "PERIOD_M1" ;
|
|
break;
|
|
|
|
case PERIOD_M2:
|
|
return "PERIOD_M2" ;
|
|
break;
|
|
|
|
case PERIOD_M3:
|
|
return "PERIOD_M3" ;
|
|
break;
|
|
|
|
case PERIOD_M4:
|
|
return "PERIOD_M4" ;
|
|
break;
|
|
|
|
case PERIOD_M5:
|
|
return "PERIOD_M5" ;
|
|
break;
|
|
|
|
case PERIOD_M6:
|
|
return "PERIOD_M6" ;
|
|
break;
|
|
case PERIOD_M10:
|
|
return "PERIOD_M10" ;
|
|
break;
|
|
|
|
case PERIOD_M12:
|
|
return "PERIOD_M12" ;
|
|
break;
|
|
|
|
case PERIOD_M15:
|
|
return "PERIOD_M15" ;
|
|
break;
|
|
|
|
case PERIOD_M20:
|
|
return "PERIOD_M20" ;
|
|
break;
|
|
|
|
case PERIOD_M30:
|
|
return "PERIOD_M30" ;
|
|
break;
|
|
case PERIOD_H1:
|
|
return "PERIOD_H1" ;
|
|
break;
|
|
|
|
case PERIOD_H2:
|
|
return "PERIOD_H2" ;
|
|
break;
|
|
|
|
case PERIOD_H3:
|
|
return "PERIOD_H3" ;
|
|
break;
|
|
|
|
case PERIOD_H4:
|
|
return "PERIOD_H4" ;
|
|
break;
|
|
|
|
case PERIOD_H6:
|
|
return "PERIOD_H6" ;
|
|
break;
|
|
|
|
case PERIOD_H8:
|
|
return "PERIOD_H8" ;
|
|
break;
|
|
case PERIOD_H12:
|
|
return "PERIOD_H12" ;
|
|
break;
|
|
|
|
case PERIOD_D1:
|
|
return "PERIOD_D1" ;
|
|
break;
|
|
case PERIOD_W1:
|
|
return "PERIOD_W1" ;
|
|
break;
|
|
|
|
case PERIOD_MN1:
|
|
return "PERIOD_MN1" ;
|
|
break;
|
|
|
|
}
|
|
|
|
return "" ;
|
|
}
|
|
|
|
|
|
string timeFrameToString(ENUM_TIMEFRAMES _timeFrame){
|
|
switch(_timeFrame) {
|
|
|
|
case PERIOD_M1:
|
|
return "PERIOD_M1" ;
|
|
break;
|
|
|
|
case PERIOD_M2:
|
|
return "PERIOD_M2" ;
|
|
break;
|
|
|
|
case PERIOD_M3:
|
|
return "PERIOD_M3" ;
|
|
break;
|
|
|
|
case PERIOD_M4:
|
|
return "PERIOD_M4" ;
|
|
break;
|
|
|
|
case PERIOD_M5:
|
|
return "PERIOD_M5" ;
|
|
break;
|
|
|
|
case PERIOD_M6:
|
|
return "PERIOD_M6" ;
|
|
break;
|
|
case PERIOD_M10:
|
|
return "PERIOD_M10" ;
|
|
break;
|
|
|
|
case PERIOD_M12:
|
|
return "PERIOD_M12" ;
|
|
break;
|
|
|
|
case PERIOD_M15:
|
|
return "PERIOD_M15" ;
|
|
break;
|
|
|
|
case PERIOD_M20:
|
|
return "PERIOD_M20" ;
|
|
break;
|
|
|
|
case PERIOD_M30:
|
|
return "PERIOD_M30" ;
|
|
break;
|
|
case PERIOD_H1:
|
|
return "PERIOD_H1" ;
|
|
break;
|
|
|
|
case PERIOD_H2:
|
|
return "PERIOD_H2" ;
|
|
break;
|
|
|
|
case PERIOD_H3:
|
|
return "PERIOD_H3" ;
|
|
break;
|
|
|
|
case PERIOD_H4:
|
|
return "PERIOD_H4" ;
|
|
break;
|
|
|
|
case PERIOD_H6:
|
|
return "PERIOD_H6" ;
|
|
break;
|
|
|
|
case PERIOD_H8:
|
|
return "PERIOD_H8" ;
|
|
break;
|
|
case PERIOD_H12:
|
|
return "PERIOD_H12" ;
|
|
break;
|
|
|
|
case PERIOD_D1:
|
|
return "PERIOD_D1" ;
|
|
break;
|
|
case PERIOD_W1:
|
|
return "PERIOD_W1" ;
|
|
break;
|
|
|
|
case PERIOD_MN1:
|
|
return "PERIOD_MN1" ;
|
|
break;
|
|
|
|
}
|
|
|
|
return "" ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ************************ SESSIONS FUNCTIONS ************************
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool sessionIsNy() {
|
|
MqlDateTime mqldt ;
|
|
datetime currTime = TimeCurrent(mqldt);
|
|
|
|
if(mqldt.hour >= 12 && mqldt.hour <= 20) {
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool sessionIsLondon() {
|
|
MqlDateTime mqldt ;
|
|
datetime currTime = TimeCurrent(mqldt);
|
|
|
|
if(mqldt.hour >= 8 && mqldt.hour <= 12) {
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
bool sessionIsTokyo(){
|
|
MqlDateTime mqldt ;
|
|
datetime currTime = TimeCurrent(mqldt);
|
|
|
|
if(mqldt.hour >= 4 && mqldt.hour <= 8) {
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|
|
|
|
// ************************ TRADE FUNCTIONS ************************
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool closePartialFromAllPositions(double partialAmount) {
|
|
CTrade trade ;
|
|
for(uint i=0 ; i< PositionsTotal() ; i++) {
|
|
|
|
ulong positionTicket = PositionGetTicket(i);
|
|
if(PositionSelectByTicket(positionTicket)) {
|
|
|
|
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
|
double lotsToClose = positionVolume * partialAmount ;
|
|
if(trade.PositionClosePartial(positionTicket,NormalizeDouble(lotsToClose,2))) {
|
|
Print("Closed partials succesffully");
|
|
return true ;
|
|
} else {
|
|
Print("Failed to close partials, Error: " + GetLastError());
|
|
return false ;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
return false ;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool closePartialFromSpecificPosition(ulong posTicket, double partialToClose) {
|
|
|
|
CTrade trade ;
|
|
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
|
double lotsToClose = positionVolume * partialToClose ;
|
|
if(trade.PositionClosePartial(posTicket,NormalizeDouble(lotsToClose,2))) {
|
|
|
|
return true ;
|
|
|
|
} else {
|
|
return false ;
|
|
}
|
|
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool stopLossIsValidBuys(double stopLoss, double _maxPipsRiskAmount) {
|
|
|
|
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLoss < _maxPipsRiskAmount) {
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
double positionProfitInPips(ulong posTicket) {
|
|
|
|
double currentProfitInPips = -1 ;
|
|
if(PositionSelectByTicket(posTicket)) {
|
|
|
|
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT) ;
|
|
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
|
|
|
|
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
|
currentProfitInPips = currentPrice - positionOpenPrice ;
|
|
}
|
|
|
|
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
|
|
|
currentProfitInPips = positionOpenPrice - currentPrice ;
|
|
}
|
|
} else {
|
|
|
|
Comment("Error from positionProfitInPips() function: Failed to select position, Error " + GetLastError());
|
|
}
|
|
|
|
|
|
|
|
return currentProfitInPips ;
|
|
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
double positionStopLoss(ulong posTicket) {
|
|
|
|
double posStopLoss = -1 ;
|
|
if(PositionSelectByTicket(posTicket)) {
|
|
posStopLoss = PositionGetDouble(POSITION_SL) ;
|
|
|
|
} else {
|
|
Comment("Error from positionStopLoss() function: Failed to select position, Error " + GetLastError());
|
|
}
|
|
|
|
return posStopLoss;
|
|
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool stopLossIsValidSells(double stopLoss,double _maxPipsRiskAmount) {
|
|
if(stopLoss - SymbolInfoDouble(_Symbol, SYMBOL_BID) < _maxPipsRiskAmount) {
|
|
return true ;
|
|
}
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void positionTrailStopLoss(ulong posTicket, double newStopLoss, double takeProfit) {
|
|
|
|
CTrade trade ;
|
|
trade.PositionModify(posTicket,newStopLoss,takeProfit);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// ************************ CANDLE ANATOMY FUNCTIONS ************************
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool buyBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody) {
|
|
|
|
if((iClose(_Symbol,_timeFrame,1) - iOpen(_Symbol,_timeFrame,1)) >= _sizeOfBreakerCandleBody) {
|
|
return true ;
|
|
} else {
|
|
datetime currTime = TimeCurrent();
|
|
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
|
Comment(timeInStr + " Bullish Breaker candle body is too small to take a trade !");
|
|
return false ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool sellBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody) {
|
|
if((iOpen(_Symbol,_timeFrame,1) - iClose(_Symbol,_timeFrame,1)) >= _sizeOfBreakerCandleBody) {
|
|
return true ;
|
|
} else {
|
|
datetime currTime = TimeCurrent();
|
|
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
|
Comment(timeInStr + " Bearish Breaker candle body is too small to take a trade !");
|
|
return false ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool bearishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection) { // this function assumes that the previous candle is bearish
|
|
|
|
double upperWickLength = iHigh(_Symbol,_timeFrame,index) - iOpen(_Symbol,_timeFrame,index) ;
|
|
double totalCandleLength = iHigh(_Symbol,_timeFrame,index) - iClose(_Symbol,_timeFrame,index);
|
|
if((upperWickLength / totalCandleLength) >= wickRatioRejection) { // this means the candle is weak
|
|
Comment("Bearish Candle Is Weak");
|
|
return true ;
|
|
} else {
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool bullishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection) { // this function assumes that the previous candle is bullish
|
|
double lowerWickLength = iOpen(_Symbol,_timeFrame,index) - iLow(_Symbol,_timeFrame,index) ;
|
|
double totalCandleLength = iClose(_Symbol,_timeFrame,index) - iLow(_Symbol,_timeFrame,index) ;
|
|
|
|
if((lowerWickLength/totalCandleLength) >= wickRatioRejection) { // this means the candle is weak
|
|
Comment("Bullish Candle is weak");
|
|
return true ;
|
|
} else {
|
|
return false ;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
|
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
|
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
|
|
|
|
|
if(candleClose >candleOpen) { // the candle closed bullish
|
|
|
|
return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index) {
|
|
|
|
|
|
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
|
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
|
|
|
|
|
if(candleClose < candleOpen) { // the candle closed bullish
|
|
|
|
return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool candleClosedDoji(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
|
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
|
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
|
|
|
if(candleClose == candleOpen) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool candleBodyIsValid(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
|
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
|
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
|
double candleHigh = iHigh(_Symbol,_timeFrame,_index);
|
|
double candleLow = iLow(_Symbol,_timeFrame,_index);
|
|
double topWickSize ;
|
|
double bottomWickSize ;
|
|
double candleBodySize ;
|
|
|
|
if(candleClosedBearish(_timeFrame,_index)) {
|
|
topWickSize = candleHigh - candleOpen ;
|
|
bottomWickSize = candleClose - candleLow ;
|
|
candleBodySize = candleOpen - candleClose ;
|
|
|
|
} else if(candleClosedBullish(_timeFrame,_index)) {
|
|
topWickSize = candleHigh - candleClose ;
|
|
bottomWickSize = candleOpen - candleLow ;
|
|
candleBodySize = candleClose - candleOpen ;
|
|
} else if(candleClosedDoji(_timeFrame,_index)) {
|
|
|
|
return false ;
|
|
}
|
|
|
|
|
|
if((topWickSize >= (15*candleBodySize)) || (bottomWickSize >= (15* candleBodySize))) { // 8 is fixed number ,
|
|
//which means that if i find a candle's wick that is 15 times bigger than the body then i dont want to consider it when detecting a support or resistance, this is for the cases that the candle looks almost like a doji but not an actual doji
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
/*double retestWickFormedOnTheFirstHalfOfCandle(ENUM_TIMEFRAMES _mainTimeFrame, ENUM_TIMEFRAMES _secondaryTimeFrame){
|
|
|
|
if(candleClosedBullish(_mainTimeFrame,1)){ // previous candle closed bullish, this means checking a wick on a bullish candle on the main timeframe
|
|
if(candleClosedBearish(_secondaryTimeFrame)){
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if(candleClosedBearish(_mainTimeFrame)){ // previous candle closed bullish, this means checking a wick on a bearish candle on the main timeframe
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
|
|
// ************************ SUPPORT AND RESISTANCE RELATED FUNCTIONS ************************
|
|
|
|
|
|
/*bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame){ // this is a spicific case of the next function, the _index parameter here is 0
|
|
if((candleClosedBearish(_timeFrame,2) && candleClosedBullish(_timeFrame,1) && candleBodyIsValid(_timeFrame,1)&& candleBodyIsValid(_timeFrame,2))
|
|
|| (candleClosedBearish(_timeFrame,3) && candleClosedDoji(_timeFrame,2) && candleClosedBullish(_timeFrame,1))
|
|
|| candleClosedBearish(_timeFrame,3) && candleBodyIsValid(_timeFrame,3) && !candleBodyIsValid(_timeFrame,2) && candleClosedBullish(_timeFrame,1) && candleBodyIsValid(_timeFrame,1)) {
|
|
return true ;
|
|
|
|
}
|
|
return false ;
|
|
}*/
|
|
|
|
|
|
bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index = 0){ // this is the same previous function but with geniric index to detect the support on . its used for detecing old supports (that are not currently happeneing)
|
|
|
|
|
|
if((candleClosedBearish(_timeFrame,_index+2) && candleClosedBullish(_timeFrame,_index+1) && candleBodyIsValid(_timeFrame,_index+1)&& candleBodyIsValid(_timeFrame,_index+2))
|
|
|| (candleClosedBearish(_timeFrame,_index+3) && candleClosedDoji(_timeFrame,_index+2) && candleClosedBullish(_timeFrame,_index+1))
|
|
|| candleClosedBearish(_timeFrame,_index+3) && candleBodyIsValid(_timeFrame,_index+3) && !candleBodyIsValid(_timeFrame,_index + 2) && candleClosedBullish(_timeFrame,_index+1)
|
|
&& candleBodyIsValid(_timeFrame,_index+1) ){
|
|
return true ;
|
|
|
|
}
|
|
return false ;
|
|
|
|
}
|
|
bool resistancePatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index = 0){ // this is a spicific case of the next function
|
|
|
|
if((candleClosedBullish(_timeFrame,_index+2) && candleClosedBearish(_timeFrame,_index+1) && candleBodyIsValid(_timeFrame,_index+2) && candleBodyIsValid(_timeFrame,_index+1))
|
|
|| (candleClosedBullish(_timeFrame,3) && candleClosedDoji(_timeFrame,2) && candleClosedBearish(_timeFrame,1) )){
|
|
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|