//+------------------------------------------------------------------+ //| SignalPB.mqh | //+------------------------------------------------------------------+ #property copyright "AnimateDread" #property version "1.0" #property description "Pin Bar Signal" #include "..\Expert\ExpertSignalCustom.mqh" // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signal of candle pattern 'Pin Bar' | //| Type=SignalAdvanced | //| Name=Pin Bar Pattern | //| ShortName=PB | //| Class=CSignalPB | //| Page= | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| CSignalPB class. | //| Purpose: Class of trading signal Pin Bar Pattern | //| It is derived from the CExpertSignalCustom class. | //+------------------------------------------------------------------+ class CSignalPB : public CExpertSignalCustom { protected: //--- Pattern weights int m_pattern_0; // Weight for pattern 0, weak int m_pattern_1; // Weight for pattern 1, moderate int m_pattern_2; // Weight for pattern 2, strong public: CSignalPB(); ~CSignalPB(); //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0 = value; } void Pattern_1(int value) { m_pattern_1 = value; } void Pattern_2(int value) { m_pattern_2 = value; } virtual void ApplyPatternWeight(int patternNumber, int weight); //--- Methods to generate signals to enter the market int CalculateConditions(bool isLong); virtual int LongCondition(void); virtual int ShortCondition(void); protected: }; //+------------------------------------------------------------------+ //| Constructor. | //+------------------------------------------------------------------+ CSignalPB::CSignalPB() : m_pattern_0(10), m_pattern_1(20), m_pattern_2(40) { m_id = "PB"; m_pattern_count = 3; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalPB::~CSignalPB(void) { } //+------------------------------------------------------------------+ //| Common function to calculate conditions | //+------------------------------------------------------------------+ int CSignalPB::CalculateConditions(bool isLong) { int idx = StartIndex(); // Current candle index, usually 0 int prevIdx = idx + 1; // Previous candle index, usually 1 int prevPrevIdx = prevIdx + 1; // Candle before the previous one, usually 2 int result = 0; int conditionCount = 0; //--- Preparing the data double bodySize = fabs(Close(idx) - Open(idx)); double wholeRange = High(idx) - Low(idx); double wickSize = fmax(High(idx) - fmin(Open(idx), Close(idx)), fmax(Open(idx), Close(idx)) - Low(idx)); // Check if bodySize is zero to prevent division by zero double wickBodyRatio = (bodySize != 0) ? wickSize / bodySize : 0; //--- Checking the Pin Bar pattern // Condition 1: The open and close prices of the Pin Bar should fall within the range of the bars on either side if((Open(idx) >= Low(prevIdx) && Open(idx) <= High(prevIdx) && Close(idx) >= Low(prevIdx) && Close(idx) <= High(prevIdx)) && (Open(idx) >= Low(prevPrevIdx) && Open(idx) <= High(prevPrevIdx) && Close(idx) >= Low(prevPrevIdx) && Close(idx) <= High(prevPrevIdx))) { conditionCount++; } // Condition 2: The open and close prices of the Pin Bar should be close together if(bodySize <= wholeRange * 0.2) { conditionCount++; } // Condition 3: The open and close prices of the Pin Bar should be towards the end of the bar if(isLong) { if((Close(idx) >= Open(idx) && Close(idx) >= High(idx) - (wholeRange * 0.2)) || (Open(idx) >= Close(idx) && Open(idx) >= High(idx) - (wholeRange * 0.2))) { conditionCount++; } } else { if((Close(idx) <= Open(idx) && Close(idx) <= Low(idx) + (wholeRange * 0.2)) || (Open(idx) <= Close(idx) && Open(idx) <= Low(idx) + (wholeRange * 0.2))) { conditionCount++; } } // Condition 4: Wick-to-body ratio check if(wickBodyRatio >= 2) { conditionCount++; } // If all conditions are met, assign Pattern_0 if(conditionCount == 4) { result = m_pattern_0; m_active_pattern = "Pattern_0"; } return result; } //+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalPB::LongCondition(void) { int result = CalculateConditions(true); if(result != 0) { m_active_direction = "Buy"; } return result; } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalPB::ShortCondition(void) { int result = CalculateConditions(false); if(result != 0) { m_active_direction = "Sell"; } return result; } //+------------------------------------------------------------------+ //| Set the specified pattern's weight to the specified value | //+------------------------------------------------------------------+ void CSignalPB::ApplyPatternWeight(int patternNumber, int weight) { switch(patternNumber) { default: break; case 0: Pattern_0(weight); break; case 1: Pattern_1(weight); break; case 2: Pattern_2(weight); break; } } //+------------------------------------------------------------------+