194 lignes
Pas d'EOL
5,8 Kio
MQL5
194 lignes
Pas d'EOL
5,8 Kio
MQL5
//what we simply do right here is
|
|
// read candlestick momentum by
|
|
// #1 comparing upper vs lower wick
|
|
// #2 closure beyond prev candle
|
|
|
|
|
|
//--REQUIREMENTS
|
|
extern MqlRates rates[];
|
|
#include <Generic/Queue.mqh>
|
|
|
|
//Cqueue<int>candlesticksCollection;
|
|
|
|
class CCandlestick{
|
|
protected:
|
|
enum closure {CLOSEDBELOW=-1, CLOSEDNONE=0, CLOSEDABOVE=1};
|
|
CQueue<closure> candleClosureCollection;
|
|
enum relativeMomentum {MOMENTUMDOWN=-1,MOMENTUMEQUAL=0, MOMENTUMUP=1};
|
|
CQueue<relativeMomentum> candleRelMomentumCollection;//array of rel momentum (up vs down)
|
|
int m_latestCandleBias;
|
|
void coreLogic();
|
|
|
|
|
|
|
|
public:
|
|
//methods of accessing the protected
|
|
int getLatestCandleBias(){return m_latestCandleBias;};
|
|
bool getCandleCollection(int &dstArray[], bool modeClosure=false);
|
|
//array of closure DSA
|
|
//array of relative momentum DSA
|
|
|
|
//updating the data
|
|
bool wasWhat(int candleIndex, int &bias); //returning the bias of the specific candle
|
|
bool wasWhat(int startIndex, int count,/*&dsa, */bool asSeries=true); //try to fill the array with history data
|
|
void update(void); //run this inside OnTick()
|
|
double getUpperSize(int candleIndex=1);
|
|
double getLowerSize(int candleIndex=1);
|
|
bool isBull(int candleIndex=1);
|
|
bool isBear(int candleIndex=1);
|
|
bool isOpposingCandle(int &flag, const int index=1); //checks whether
|
|
bool isEngulfing(int &flag, const int index);
|
|
bool isInsideBar(int &flag, const int index);
|
|
|
|
|
|
|
|
};
|
|
|
|
void CCandlestick::coreLogic(void){
|
|
|
|
}
|
|
|
|
bool CCandlestick::isBull(int candleIndex=1){
|
|
return rates[candleIndex].close>rates[candleIndex].open;
|
|
}
|
|
|
|
bool CCandlestick::isBear(int candleIndex=1){
|
|
return rates[candleIndex].close<rates[candleIndex].open;
|
|
}
|
|
|
|
double CCandlestick::getUpperSize(int candleIndex=1){
|
|
double upperSize = MathAbs(rates[candleIndex].high-MathMax(rates[candleIndex].close,rates[candleIndex].open));
|
|
return upperSize;
|
|
}
|
|
|
|
double CCandlestick::getLowerSize(int candleIndex=1){
|
|
double lowerSize = MathAbs(rates[1].high-MathMax(rates[1].close,rates[1].open));
|
|
return lowerSize;
|
|
}
|
|
|
|
bool CCandlestick::wasWhat(int candleIndex,int &bias){
|
|
//validating the index
|
|
if(candleIndex>ArraySize(rates)){
|
|
Print("ATTENTION: candleIndex requested is far from reach, wait while fetching some data");
|
|
|
|
}
|
|
|
|
else //if the Index is reachable
|
|
double lowerSize = MathAbs(rates[candleIndex].low-MathMin(rates[candleIndex].close,rates[candleIndex].open));
|
|
double upperSize = MathAbs(rates[candleIndex].high-MathMax(rates[candleIndex].close,rates[candleIndex].open));
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
void CCandlestick::update(void){
|
|
|
|
//fill the array
|
|
//run the core logic here
|
|
double lowerSize = MathAbs(rates[1].low-MathMin(rates[1].close,rates[1].open));
|
|
double upperSize = MathAbs(rates[1].high-MathMax(rates[1].close,rates[1].open));
|
|
|
|
//Momentum check
|
|
if(lowerSize>upperSize){
|
|
if(!candleRelMomentumCollection.Enqueue(MOMENTUMUP)){
|
|
Print("Failed to register a candles parameter, retrying..");
|
|
candleRelMomentumCollection.Enqueue(MOMENTUMUP);
|
|
}
|
|
}
|
|
else if(lowerSize<upperSize){
|
|
if(!candleRelMomentumCollection.Enqueue(MOMENTUMDOWN)){
|
|
Print("Failed to register a candles parameter, retrying..");
|
|
candleRelMomentumCollection.Enqueue(MOMENTUMDOWN);
|
|
}
|
|
}
|
|
else candleRelMomentumCollection.Enqueue(MOMENTUMEQUAL);
|
|
|
|
|
|
|
|
//run the core closure logic
|
|
bool closedBeyond = rates[1].close>rates[2].high || rates[1].close<rates[2].low;
|
|
bool isCRT = !closedBeyond && (rates[1].high>rates[2].high || rates[1].low<rates[2].low);
|
|
|
|
//bias by candle closure
|
|
if(closedBeyond && CCandlestick::isBull()){
|
|
candleClosureCollection.Enqueue(CLOSEDABOVE);
|
|
//log success/failure
|
|
}
|
|
else if(closedBeyond && CCandlestick::isBear()){
|
|
candleClosureCollection.Enqueue(CLOSEDBELOW);
|
|
// Log
|
|
}
|
|
else candleClosureCollection.Enqueue(CLOSEDNONE);
|
|
|
|
|
|
}
|
|
|
|
//bool CCandlestick::getCandleCollection(int &dstArray[], bool modeClosure=false){
|
|
// if(!modeClosure){ //default to rel momentum
|
|
// if(candleRelMomentumCollection.CopyTo(dstArray)>0){return true;}
|
|
// else {//failed to copy
|
|
// //log failure to copy
|
|
// return false;
|
|
// }
|
|
// }
|
|
//
|
|
// else{ //chose to copy closure
|
|
// if(candleClosureCollection.CopyTo(dstArray)>0){return true;}
|
|
// else {//failed to copy
|
|
// //log failure to copy
|
|
// return false;
|
|
// }
|
|
// }
|
|
//}
|
|
bool CCandlestick::isOpposingCandle(int &flag, const int index=1){
|
|
if(rates[index].close>rates[index].open //bull
|
|
&& rates[index+1].close<rates[index+1].open){ //pred by bear
|
|
flag=1;
|
|
return true;
|
|
}
|
|
|
|
if(rates[index].close<rates[index].open //bear
|
|
&& rates[index+1].close>rates[index+1].open){ //pred by bull
|
|
flag=-1;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CCandlestick::isEngulfing(int &flag,const int index=1){
|
|
if(rates[index].high>rates[index+1].high
|
|
&& rates[index].low<rates[index+1].low){ //taking both prev candle extremes
|
|
if(CCandlestick::isBull(index)){ // assigning flag to bullish engulfing
|
|
flag=1;
|
|
return true;
|
|
}
|
|
else if(CCandlestick::isBear(index)){ //bearish engulfing
|
|
flag=-1;
|
|
return true;
|
|
}
|
|
|
|
}
|
|
//else
|
|
return false;
|
|
}
|
|
//
|
|
|
|
bool CCandlestick::isInsideBar(int &flag,const int index){
|
|
if(rates[index].high<rates[index+1].high
|
|
&& rates[index].low>rates[index+1].low){ //not breaking any of prev candle' extremes
|
|
if(CCandlestick::isBull(index)){ // assigning flag to bullish engulfing
|
|
flag=1;
|
|
return true;
|
|
}
|
|
else if(CCandlestick::isBear(index)){ //bearish engulfing
|
|
flag=-1;
|
|
return true;
|
|
}
|
|
|
|
}
|
|
//else
|
|
|
|
|
|
return false;
|
|
} |