Problem with EA code syntax

 

Hello! I am having an problems with my code  in lines 222, is anyone able to help me understand?

The error is: '{' - unbalanced parentheses TradingProve.mq5 222 37



//+------------------------------------------------------------------+
//|                                                  WyckoffEA.mq5   |
//|                                     Copyright 2024, Your Name    |
//|                                      https://www.yourwebsite.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Your Name"
#property link "https://www.yourwebsite.com"
#property version "1.00"
#property strict

// Include necessary libraries
#include <Arrays\ArrayObj.mqh>
#include <Trade\Trade.mqh>

#define BENCHMARK_SYMBOL "US500Cash"

// Declare global variables
CTrade trade;                       // Object for performing trading operations
input int LookbackPeriod = 100;     // Period for Wyckoff analysis
input double RiskPercent = 1.0;     // Risk percentage per trade
input int VolumeMAPeriod = 20;      // Volume moving average period
input int PriceMAShortPeriod = 20;  // Short price moving average period
input int PriceMALongPeriod = 50;   // Long price moving average period
input double SignificantMoveThreshold = 0.001;  // Threshold for significant moves

// Timeframes to analyze
ENUM_TIMEFRAMES g_analyzedTimeframes[] = {PERIOD_CURRENT, PERIOD_H4, PERIOD_D1};

// Enumerations
enum ENUM_WYCKOFF_PHASE {
  PHASE_ACCUMULATION,
  PHASE_MARKUP,
  PHASE_DISTRIBUTION,
  PHASE_MARKDOWN,
  PHASE_UNKNOWN
};

enum ENUM_WYCKOFF_EVENT {
  EVENT_NONE,
  EVENT_SPRING,
  EVENT_UPTHRUST,
  EVENT_SIGN_OF_STRENGTH,
  EVENT_SIGN_OF_WEAKNESS,
  EVENT_LAST_POINT_OF_SUPPORT,
  EVENT_LAST_POINT_OF_SUPPLY,
  EVENT_TESTING_SUPPORT,
  EVENT_TESTING_RESISTANCE
};

enum ENUM_MARKET_STRUCTURE {
  STRUCTURE_BULLISH,
  STRUCTURE_BEARISH,
  STRUCTURE_SIDEWAYS,
  STRUCTURE_UNKNOWN
};

// Structures
struct SWyckoffAnalysis {
  ENUM_WYCKOFF_PHASE phase;
  ENUM_WYCKOFF_EVENT currentEvent;
  double effortVsResult;
  double relativeStrength;
  double supplyDemandImbalance;
  string relativeStrengthInterpretation;
  double relativeStrengthRSI;
  bool rsDivergence;
  string marketCharacter;
};

struct SMarketData {
  datetime time[];
  double open[];
  double high[];
  double low[];
  double close[];
  long volume[];
  double volumeMA[];
  double priceMAShort[];
  double priceMALong[];
  double vwap[];
};


class CDataManager {
 private:
  SMarketData m_data;
  int m_dataPoints;
  int m_volumeMAPeriod;
  int m_priceMAShortPeriod;
  int m_priceMALongPeriod;
  int m_vwapPeriod;

  int m_handleVolume;
  int m_handlePriceMAShort;
  int m_handlePriceMALong;

 public:
  CDataManager(int dataPoints, int volumeMAPeriod, int priceMAShortPeriod,
               int priceMALongPeriod, int vwapPeriod)
      : m_dataPoints(dataPoints),
        m_volumeMAPeriod(volumeMAPeriod),
        m_priceMAShortPeriod(priceMAShortPeriod),
        m_priceMALongPeriod(priceMALongPeriod),
        m_vwapPeriod(vwapPeriod)
  {
    InitializeIndicators();
  }
  
  ~CDataManager() 
  {
    ReleaseIndicators();
  }


  bool UpdateData() {
    if (!GetMarketData() || !CalculateIndicators()) return false;
    return true;
  }

  SMarketData GetData() { return m_data; }
  
 private:
  bool InitializeIndicators() {
    m_handleVolume = iVolumes(_Symbol, PERIOD_CURRENT, VOLUME_TICK);
    m_handlePriceMAShort = iMA(_Symbol, PERIOD_CURRENT, m_priceMAShortPeriod, 0, MODE_SMA, PRICE_CLOSE);
    m_handlePriceMALong = iMA(_Symbol, PERIOD_CURRENT, m_priceMALongPeriod, 0, MODE_SMA, PRICE_CLOSE);

    return (m_handleVolume != INVALID_HANDLE &&
            m_handlePriceMAShort != INVALID_HANDLE &&
            m_handlePriceMALong != INVALID_HANDLE);
  }
  
   void ReleaseIndicators() {
    IndicatorRelease(m_handleVolume);
    IndicatorRelease(m_handlePriceMAShort);
    IndicatorRelease(m_handlePriceMALong);
  }

  bool GetMarketData() {
    ArraySetAsSeries(m_data.time, true);
    ArraySetAsSeries(m_data.open, true);
    ArraySetAsSeries(m_data.high, true);
    ArraySetAsSeries(m_data.low, true);
    ArraySetAsSeries(m_data.close, true);
    ArraySetAsSeries(m_data.volume, true);

    if (CopyTime(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.time) != m_dataPoints ||
        CopyOpen(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.open) != m_dataPoints ||
        CopyHigh(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.high) != m_dataPoints ||
        CopyLow(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.low) != m_dataPoints ||
        CopyClose(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.close) != m_dataPoints ||
        CopyTickVolume(_Symbol, PERIOD_CURRENT, 0, m_dataPoints, m_data.volume) != m_dataPoints)
      return false;

    return true;
  }

  bool CalculateIndicators() {
    ArraySetAsSeries(m_data.volumeMA, true);
    ArraySetAsSeries(m_data.priceMAShort, true);
    ArraySetAsSeries(m_data.priceMALong, true);
    ArraySetAsSeries(m_data.vwap, true);

    if (CopyBuffer(m_handleVolume, 0, 0, m_dataPoints, m_data.volumeMA) != m_dataPoints ||
        CopyBuffer(m_handlePriceMAShort, 0, 0, m_dataPoints, m_data.priceMAShort) != m_dataPoints ||
        CopyBuffer(m_handlePriceMALong, 0, 0, m_dataPoints, m_data.priceMALong) != m_dataPoints)
      return false;

double volumeBuffer[];
    ArraySetAsSeries(volumeBuffer, true);
    if(CopyBuffer(m_handleVolume, 0, 0, m_dataPoints, volumeBuffer) != m_dataPoints)
        return false;

    ArrayResize(m_data.volumeMA, m_dataPoints);
    for(int i = 0; i < m_dataPoints; i++) {
        double sum = 0;
        int count = 0;
        for(int j = 0; j < m_volumeMAPeriod && i+j < m_dataPoints; j++) {
            sum += volumeBuffer[i+j];
            count++;
        }
        m_data.volumeMA[i] = sum / count;
    }
    // Calculate VWAP
    double cumulativeTPV = 0;
    double cumulativeVolume = 0;

    for (int i = m_dataPoints - 1; i >= 0; i--) {
      double typicalPrice = (m_data.high[i] + m_data.low[i] + m_data.close[i]) / 3;
      cumulativeTPV += typicalPrice * m_data.volume[i];
      cumulativeVolume += m_data.volume[i];
      m_data.vwap[i] = cumulativeTPV / cumulativeVolume;
    }

    return true;
  }
};

class CDataManager;
class CSupportResistanceAnalyzer;

class CDataManager;
class CSupportResistanceAnalyzer;

class CMarketCharacterAnalyzer {
private:
    CDataManager* m_dataManager;
    CSupportResistanceAnalyzer* m_srAnalyzer;
    int m_lookbackPeriod;
    double m_significantMoveThreshold;

public:
    CMarketCharacterAnalyzer(CDataManager* dataManager,
                             CSupportResistanceAnalyzer* srAnalyzer,
                             int lookbackPeriod,
                             double significantMoveThreshold)
        : m_dataManager(dataManager),
          m_srAnalyzer(srAnalyzer),
          m_lookbackPeriod(lookbackPeriod),
          m_significantMoveThreshold(significantMoveThreshold)          

    string AnalyzeMarketCharacter() {
       SMarketData* data = m_dataManager.GetData();
       CArrayObj* levels = m_srAnalyzer.GetLevels();
       string character = "";

    // Analyze price reaction to key levels
    for (int i = 0; i < levels.Total(); i++) {
      CSupportResistanceAnalyzer::Level* level = levels.At(i);
      if (IsPriceNearLevel(data.close[0], level.price)) {
        string reaction = AnalyzePriceReaction(data, level);
        character += StringFormat("Reaction to %s at %.5f: %s\n",
                                  level.isSupport ? "support" : "resistance",
                                  level.price, reaction);
                                  
        return character;
      }
    }
    
    
    
private:
  bool IsPriceNearLevel(double price, double level) {
    return MathAbs(price - level) / level < 0.001;  // Within 0.1% of the level
  }

  string AnalyzePriceReaction(SMarketData* data,
                              const CSupportResistanceAnalyzer::Level* level) {
    int bounces = 0, breakouts = 0;    
    
    for (int i = 0; i < m_lookbackPeriod; i++) {
      if (level.isSupport) {
        if (data.low[i] <= level.price && data.close[i] > level.price)
          bounces++;
        else if (data.close[i] < level.price &&
                 data.low[i] <
                     level.price - m_significantMoveThreshold * Point())
          breakouts++;
      } else  // resistance
      {
        if (data.high[i] >= level.price && data.close[i] < level.price)
          bounces++;
        else if (data.close[i] > level.price &&
                 data.high[i] >
                     level.price + m_significantMoveThreshold * Point())
          breakouts++;
      }
    }

    if (bounces > breakouts)
      return "Level respected";
    else if (breakouts > bounces)
      return "Tendency to break the level";
    else
      return "Mixed behavior";
  }
  
  string AnalyzeOverallBehavior(SMarketData* data) {
    int upMoves = 0, downMoves = 0;
    double avgUpMove = 0, avgDownMove = 0;

    for (int i = 1; i < m_lookbackPeriod; i++) {
      double move = data.close[i] - data.close[i - 1];
      if (move > 0) {
        upMoves++;
        avgUpMove += move;
      } else if (move < 0) {
        downMoves++;
        avgDownMove += MathAbs(move);
      }
    }
    
     avgUpMove /= (upMoves > 0) ? upMoves : 1;
    avgDownMove /= (downMoves > 0) ? downMoves : 1;

    string behavior = "";

    if (upMoves > downMoves * 1.5)
      behavior += "Strongly bullish market. ";
    else if (downMoves > upMoves * 1.5)
      behavior += "Strongly bearish market. ";
      
      
class CAdvancedRelativeStrength {
      
 private:
  string m_symbol;
  string m_benchmarkSymbol;
  ENUM_TIMEFRAMES m_timeframes[];
  int m_rsiPeriod;
  int m_lookbackPeriod;

 public:
  CAdvancedRelativeStrength(string symbol, string benchmarkSymbol,
                            ENUM_TIMEFRAMES& timeframes[], int rsiPeriod,
                            int lookbackPeriod)
      : m_symbol(symbol),
        m_benchmarkSymbol(benchmarkSymbol),
        m_rsiPeriod(rsiPeriod),
        m_lookbackPeriod(lookbackPeriod) {
    ArrayCopy(m_timeframes, timeframes);
  }
  
  
void CalculateRelativeStrength(SWyckoffAnalysis& analysis) {
    double relativeStrength[];
    double relativeStrengthRSI[];
    ArrayResize(relativeStrength, ArraySize(m_timeframes));
    ArrayResize(relativeStrengthRSI, ArraySize(m_timeframes));

    for (int i = 0; i < ArraySize(m_timeframes); i++) {
      relativeStrength[i] =
          CalculateRelativeStrengthForTimeframe(m_timeframes[i]);
      relativeStrengthRSI[i] = CalculateRelativeStrengthRSI(m_timeframes[i]);
    }
    analysis.rsDivergence = CalculateDivergence();
    analysis.relativeStrength =
        relativeStrength[0];  // Using the current timeframe
    analysis.relativeStrengthRSI =
        relativeStrengthRSI[0];  // Using the current timeframe

    if (analysis.phase == PHASE_UNKNOWN)
      analysis.phase =
          DetermineWyckoffPhase(relativeStrength[0], relativeStrengthRSI[0]);
  }
  
 private:
  double CalculateRelativeStrengthForTimeframe(ENUM_TIMEFRAMES timeframe) {
    double symbolReturn = CalculateReturn(m_symbol, timeframe);
    double benchmarkReturn = CalculateReturn(m_benchmarkSymbol, timeframe);

    if (benchmarkReturn != 0)
      return symbolReturn / benchmarkReturn;
    else
      return 1.0;  // Neutral if benchmark return is zero
  }
  
  double CalculateReturn(string symbol, ENUM_TIMEFRAMES timeframe) {
    double prices[];
    ArraySetAsSeries(prices, true);

    if (CopyClose(symbol, timeframe, 0, m_lookbackPeriod, prices) !=
        m_lookbackPeriod) {
      Print("Error copying price data for ", symbol);
      return 0;
    }

    if (m_lookbackPeriod < 2 || prices[m_lookbackPeriod - 1] == 0) return 0;

    return (prices[0] - prices[m_lookbackPeriod - 1]) /
           prices[m_lookbackPeriod - 1];
  }
  
  
  double CalculateRelativeStrengthRSI(ENUM_TIMEFRAMES timeframe) {
    double symbolRSI = CalculateRSI(m_symbol, timeframe);
    double benchmarkRSI = CalculateRSI(m_benchmarkSymbol, timeframe);

    return symbolRSI - benchmarkRSI;
  }
  
    double CalculateRSI(string symbol, ENUM_TIMEFRAMES timeframe) {
    double rsi[];
    ArraySetAsSeries(rsi, true);

    int rsiHandle = iRSI(symbol, timeframe, m_rsiPeriod, PRICE_CLOSE);
    if (rsiHandle == INVALID_HANDLE) {
      Print("Error creating RSI indicator for ", symbol);
      return 0;
    }

    if (CopyBuffer(rsiHandle, 0, 0, 1, rsi) != 1) {
      Print("Error copying RSI data for ", symbol);
      IndicatorRelease(rsiHandle);
      return 0;
    }

    IndicatorRelease(rsiHandle);
    return rsi[0];
  }

  bool CalculateDivergence() {
    double prices[];
    double relativeStrength[];
    ArraySetAsSeries(prices, true);
    ArraySetAsSeries(relativeStrength, true);

    if (CopyClose(m_symbol, m_timeframes[0], 0, m_lookbackPeriod, prices) !=
        m_lookbackPeriod) {
      Print("Error copying price data for divergence calculation");
      return false;
    }

    ArrayResize(relativeStrength, m_lookbackPeriod);
    for (int i = 0; i < m_lookbackPeriod; i++) {
      relativeStrength[i] =
          CalculateRelativeStrengthForTimeframe(m_timeframes[0]);
    }

    bool priceUptrend = prices[0] > prices[m_lookbackPeriod - 1];
    bool rsUptrend =
        relativeStrength[0] > relativeStrength[m_lookbackPeriod - 1];

    return (priceUptrend && !rsUptrend) || (!priceUptrend && rsUptrend);
  }

  ENUM_WYCKOFF_PHASE DetermineWyckoffPhase(double relativeStrength,
                                           double relativeStrengthRSI) {
    if (relativeStrength > 1.1 && relativeStrengthRSI > 10)
      return PHASE_MARKUP;
    else if (relativeStrength < 0.9 && relativeStrengthRSI < -10)
      return PHASE_MARKDOWN;
    else if (relativeStrength > 1.0 && relativeStrength <= 1.1 &&
             relativeStrengthRSI > 0)
      return PHASE_ACCUMULATION;
    else if (relativeStrength < 1.0 && relativeStrength >= 0.9 &&
             relativeStrengthRSI < 0)
      return PHASE_DISTRIBUTION;
    else
      return PHASE_UNKNOWN;
  }
  };
  
class CWyckoffAnalyzer {

 private:
  CMultiTimeframeDataManager* m_dataManager;
  SWyckoffAnalysis m_analyses[];
  ENUM_TIMEFRAMES m_timeframes[];
  int m_lookbackPeriod;
  string m_benchmarkSymbol;
  int m_relativeStrengthPeriod;
  CAdvancedRelativeStrength* m_advancedRS;
  CSupportResistanceAnalyzer* m_srAnalyzers[];
  CMarketCharacterAnalyzer* m_marketCharacterAnalyzers[];
  
   public:
  CWyckoffAnalyzer(CMultiTimeframeDataManager* dataManager,
                   ENUM_TIMEFRAMES& timeframes[], int lookbackPeriod,
                   string benchmarkSymbol, int relativeStrengthPeriod,
                   double significantMoveThreshold)
      : m_dataManager(dataManager),
        m_lookbackPeriod(lookbackPeriod),
        m_benchmarkSymbol(benchmarkSymbol),
        m_relativeStrengthPeriod(relativeStrengthPeriod) {
    ArrayCopy(m_timeframes, timeframes);
    ArrayResize(m_analyses, ArraySize(timeframes));
    ArrayResize(m_srAnalyzers, ArraySize(timeframes));
    ArrayResize(m_marketCharacterAnalyzers, ArraySize(timeframes));

    m_advancedRS = new CAdvancedRelativeStrength(
        _Symbol, benchmarkSymbol, timeframes, 14, relativeStrengthPeriod);

    for (int i = 0; i < ArraySize(timeframes); i++) {
      m_srAnalyzers[i] = new CSupportResistanceAnalyzer(
          dataManager.GetData(timeframes[i]), lookbackPeriod);
      m_marketCharacterAnalyzers[i] = new CMarketCharacterAnalyzer(
          dataManager.GetData(timeframes[i]), m_srAnalyzers[i], lookbackPeriod,
          significantMoveThreshold);
    }
  }
  
   ~CWyckoffAnalyzer() {
    delete m_advancedRS;
    for (int i = 0; i < ArraySize(m_srAnalyzers); i++) {
      delete m_srAnalyzers[i];
      delete m_marketCharacterAnalyzers[i];
    }
  }

  void Analyze() {
    for (int i = 0; i < ArraySize(m_timeframes); i++) {
      SMarketData* data = m_dataManager.GetData(m_timeframes[i]);
      if (data != NULL) {
        AnalyzeTimeframe(data, m_analyses[i], i);
      }
    }
  }
  
  SWyckoffAnalysis* GetAnalysis(ENUM_TIMEFRAMES timeframe) {
    for (int i = 0; i < ArraySize(m_timeframes); i++) {
      if (m_timeframes[i] == timeframe) return &m_analyses[i];
    }
    return NULL;
  }
The Craziest & Most Affordable Hosting Deal Ever!
The Craziest & Most Affordable Hosting Deal Ever!
  • monsterhost.com
Powerful & Fast WP sites
 
Danny01_:

Hello! I am having an problems with my code  in lines 222, is anyone able to help me understand?

The error is: '{' - unbalanced parentheses TradingProve.mq5 222 37



Manca o ce n'è qualcuna di troppo, una o più parentesi, ricontrolla il codice. 
 
Danny01_:

Hello! I am having an problems with my code  in lines 222, is anyone able to help me understand?

The error is: '{' - unbalanced parentheses TradingProve.mq5 222 37



class CMarketCharacterAnalyzer {
private:
    CDataManager* m_dataManager;
    CSupportResistanceAnalyzer* m_srAnalyzer;
    int m_lookbackPeriod;
    double m_significantMoveThreshold;

public:
    CMarketCharacterAnalyzer(CDataManager* dataManager,
                             CSupportResistanceAnalyzer* srAnalyzer,
                             int lookbackPeriod,
                             double significantMoveThreshold)
        : m_dataManager(dataManager),
          m_srAnalyzer(srAnalyzer),
          m_lookbackPeriod(lookbackPeriod),
          m_significantMoveThreshold(significantMoveThreshold)          
    { }

    string AnalyzeMarketCharacter() {
       SMarketData* data = m_dataManager->GetData();
       CArrayObj* levels = m_srAnalyzer->GetLevels();
       string character = "";

       // Analyze price reaction to key levels
       for (int i = 0; i < levels->Total(); i++) {
          CSupportResistanceAnalyzer::Level* level = levels->At(i);
          if (IsPriceNearLevel(data->close[0], level->price)) {
              string reaction = AnalyzePriceReaction(data, level);
              character += StringFormat("Reaction to %s at %.5f: %s\n",
                                        level->isSupport ? "support" : "resistance",
                                        level->price, reaction);
          }
       }

       // Additional analysis (if any)

       return character;
    }
    
private:
  bool IsPriceNearLevel(double price, double level) {
    return MathAbs(price - level) / level < 0.001;  // Within 0.1% of the level
  }

  string AnalyzePriceReaction(SMarketData* data,
                              const CSupportResistanceAnalyzer::Level* level) {
    int bounces = 0, breakouts = 0;    
    
    for (int i = 0; i < m_lookbackPeriod; i++) {
      if (level->isSupport) {
        if (data->low[i] <= level->price && data->close[i] > level->price)
          bounces++;
        else if (data->close[i] < level->price &&
                 data->low[i] <
                     level->price - m_significantMoveThreshold * Point())
          breakouts++;
      } else {  // resistance
        if (data->high[i] >= level->price && data->close[i] < level->price)
          bounces++;
        else if (data->close[i] > level->price &&
                 data->high[i] >
                     level->price + m_significantMoveThreshold * Point())
          breakouts++;
      }
    }

    if (bounces > breakouts)
      return "Level respected";
    else if (breakouts > bounces)
      return "Tendency to break the level";
    else
      return "Mixed behavior";
  }
  
  string AnalyzeOverallBehavior(SMarketData* data) {
    int upMoves = 0, downMoves = 0;
    double avgUpMove = 0, avgDownMove = 0;

    for (int i = 1; i < m_lookbackPeriod; i++) {
      double move = data->close[i] - data->close[i - 1];
      if (move > 0) {
        upMoves++;
        avgUpMove += move;
      } else if (move < 0) {
        downMoves++;
        avgDownMove += MathAbs(move);
      }
    }
    
    avgUpMove /= (upMoves > 0) ? upMoves : 1;
    avgDownMove /= (downMoves > 0) ? downMoves : 1;

    string behavior = "";

    if (upMoves > downMoves * 1.5)
      behavior += "Strongly bullish market. ";
    else if (downMoves > upMoves * 1.5)
      behavior += "Strongly bearish market. ";
    
    // Complete the analysis
    return behavior;
  }
};

it should be correct