Hi all. I really need some help with fixing some errors in the below mql5 code.
I'm working on creating an Expert Advisor that trades the breakout of Contracting Ending Diagonals, using Elliott Wave & Fibonacci rules.
It was started by ChatGPT, but despite going back and forth multiple times, ChatGPT was unable to correct all errors.
To add context, if Contracting Ending Diagonals form, they can occur during Wave 5 & Wave C of Elliott Wave Cycles.
This thread therefore assumes familiarity with Elliott Wave principles.
The really cool thing about having this project successful is that when the EA takes a trade we can immediately understand that the breakout has been from either Wave 5 or Wave C, trading Wave A or Wave 1 respectively, which then helps in identifying and trading Waves 3 & 5 !
As Elliott Waves are fractal in nature, when considering a timeframe to focus on, my preference would be the 1 hour timeframe.
Alternatively, the EA could simply apply to the 'Current' TF.
In terms of Stop Loss placement, it should ideally be at the end of Wave 5 or Wave C of the contracting triangle.
A profit target could simply be a 3:1 R:R.
If anyone can help complete the code successfully, we want to make it freely available for all to use.
OK, so the code so far is:
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("Contracting Ending Diagonal EA Initialized.");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("Contracting Ending Diagonal EA Deinitialized.");
}
//+------------------------------------------------------------------+
//| Expert tick function (main loop) |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if the pattern is detected and valid
if (IsContractingEndingDiagonal())
{
// If the pattern is valid, analyze and trade
ManageTrade();
}
}
//+------------------------------------------------------------------+
//| Function to detect contracting ending diagonal |
//+------------------------------------------------------------------+
bool IsContractingEndingDiagonal()
{
// Ensure a 5-wave structure is present
if (CountWaves() != 5)
{
Print("Not a valid 5-wave structure.");
return false; // Not a valid 5-wave structure
}
// Check if the waves are contracting
if (!IsContracting())
{
Print("Waves are not contracting.");
return false; // Waves are not contracting
}
// Check if Wave 2 and Wave 4 are corrective
if (!WaveConfirmation())
{
Print("Wave 2 and/or Wave 4 is not corrective.");
return false; // Wave confirmation failed
}
// Check if the pattern aligns with Fibonacci retracement levels
if (!CheckFibonacciLevels())
{
Print("Fibonacci validation failed.");
return false; // Fibonacci validation failed
}
// Check the strength of the pattern
if (PatternStrength() < 0.75) // Example threshold for strong pattern
{
Print("Pattern strength is too weak.");
return false; // Pattern is too weak to trade
}
return true; // Valid contracting ending diagonal pattern detected
}
//+------------------------------------------------------------------+
//| Function to count the number of waves in the pattern |
//+------------------------------------------------------------------+
int CountWaves()
{
int waveCount = 0;
int bars = Bars;
// Loop through and count the number of peaks (waves)
for (int i = 1; i < bars - 1; i++)
{
// Check if a peak is detected (local max)
if (High[i] > High[i - 1] && High[i] > High[i + 1])
{
waveCount++;
}
// Check if a trough is detected (local min)
if (Low[i] < Low[i - 1] && Low[i] < Low[i + 1])
{
waveCount++;
}
}
return waveCount; // Return the number of waves detected
}
//+------------------------------------------------------------------+
//| Function to check if the waves are contracting |
//+------------------------------------------------------------------+
bool IsContracting()
{
double waveSizes[4]; // Stores the length of each wave (example)
// Loop through each wave to calculate its size
for (int i = 1; i < ArraySize(waveSizes); i++)
{
waveSizes[i] = High[i] - Low[i]; // Calculate wave size (distance between peak and trough)
if (i > 0 && waveSizes[i] > waveSizes[i - 1]) // Check for contracting pattern
{
return false; // Waves are not contracting
}
}
return true; // All waves are contracting
}
//+------------------------------------------------------------------+
//| Function to check Wave 2 and Wave 4 confirmation (corrective) |
//+------------------------------------------------------------------+
bool WaveConfirmation()
{
// Check if Wave 2 and Wave 4 are corrective in nature (Zigzag or Flat)
// In this case, we'll check that Wave 2 and Wave 4 are within a reasonable Fibonacci retracement level
double wave1High = High[1]; // High of Wave 1
double wave1Low = Low[1]; // Low of Wave 1
double wave2High = High[2]; // High of Wave 2
double wave2Low = Low[2]; // Low of Wave 2
double wave4High = High[4]; // High of Wave 4
double wave4Low = Low[4]; // Low of Wave 4
// Check if Wave 2 is a valid corrective wave (should retrace between 50% to 78.6% of Wave 1)
double wave2Retrace = (wave2Low - wave1High) / (wave1High - wave1Low);
if (wave2Retrace < 0.5 || wave2Retrace > 0.786)
{
return false; // Wave 2 is not within a corrective range
}
// Check if Wave 4 is a valid corrective wave (should retrace between 50% to 78.6% of Wave 3)
double wave3High = High[3]; // High of Wave 3
double wave3Low = Low[3]; // Low of Wave 3
double wave4Retrace = (wave4Low - wave3High) / (wave3High - wave3Low);
if (wave4Retrace < 0.5 || wave4Retrace > 0.786)
{
return false; // Wave 4 is not within a corrective range
}
return true; // Waves 2 and 4 are both corrective
}
//+------------------------------------------------------------------+
//| Function to check Fibonacci levels for wave validation |
//+------------------------------------------------------------------+
bool CheckFibonacciLevels()
{
double fibLevels[] = {0.236, 0.382, 0.618, 0.786}; // Fibonacci retracement levels
double wave1High = High[1]; // High of Wave 1
double wave1Low = Low[1]; // Low of Wave 1
double fibLevel;
// Check Fibonacci levels relative to Wave 1 (adjust logic to work for other waves as needed)
for (int i = 0; i < ArraySize(fibLevels); i++)
{
fibLevel = wave1Low + (wave1High - wave1Low) * fibLevels[i];
// Check if price touches the Fibonacci level (simplified version)
if (Ask >= fibLevel - 5 * Point && Ask <= fibLevel + 5 * Point)
{
return true; // Fibonacci level validated
}
}
return false; // No valid Fibonacci level found
}
//+------------------------------------------------------------------+
//| Function to evaluate pattern strength |
//+------------------------------------------------------------------+
double PatternStrength()
{
double strength = 0.0;
int waveCount = CountWaves();
if (waveCount == 5)
{
strength += 0.5; // Basic pattern count check (5 waves expected)
}
if (IsContracting())
{
strength += 0.3; // Contracting waves add strength to the pattern
}
if (CheckFibonacciLevels())
{
strength += 0.2; // Fibonacci alignment adds strength
}
return strength; // Return pattern strength (from 0 to 1)
}
//+------------------------------------------------------------------+
//| Function to manage trades based on detected pattern |
//+------------------------------------------------------------------+
void ManageTrade()
{
double entryPrice = Ask;
double stopLoss = 0;
double takeProfit = 0;
double lotSize = CalculateLotSize(); // Dynamic lot size based on risk
// Calculate stop-loss and take-profit based on the wave sizes
double waveSize = High[1] - Low[1]; // Simplified wave size (adjust as needed)
// Stop loss below the last trough and take-profit at a Fibonacci extension
stopLoss = Low[1] - (waveSize * 0.618);
takeProfit = High[1] + (waveSize * 1.618);
// Create the order request
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = lotSize;
request.type = ORDER_TYPE_BUY;
request.price = entryPrice;
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 10;
// Send the order
if (OrderSend(request, result))
{
Print("Buy order placed successfully with ticket: ", result.order);
}
else
{
Print("Error opening buy order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Function to calculate dynamic lot size based on risk and account |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double riskPercentage = 0.02; // 2% of account balance risk per trade
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double lotSize = (accountBalance * riskPercentage) / 1000; // Adjust position size based on risk
return NormalizeDouble(lotSize, 2);
}
//+------------------------------------------------------------------+
Changes and Fixes so far:
I'm working on creating an Expert Advisor that trades the breakout of Contracting Ending Diagonals, using Elliott Wave & Fibonacci rules.
It was started by ChatGPT, but despite going back and forth multiple times, ChatGPT was unable to correct all errors.
To add context, if Contracting Ending Diagonals form, they can occur during Wave 5 & Wave C of Elliott Wave Cycles.
This thread therefore assumes familiarity with Elliott Wave principles.
The really cool thing about having this project successful is that when the EA takes a trade we can immediately understand that the breakout has been from either Wave 5 or Wave C, trading Wave A or Wave 1 respectively, which then helps in identifying and trading Waves 3 & 5 !
As Elliott Waves are fractal in nature, when considering a timeframe to focus on, my preference would be the 1 hour timeframe.
Alternatively, the EA could simply apply to the 'Current' TF.
In terms of Stop Loss placement, it should ideally be at the end of Wave 5 or Wave C of the contracting triangle.
A profit target could simply be a 3:1 R:R.
If anyone can help complete the code successfully, we want to make it freely available for all to use.
OK, so the code so far is:
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("Contracting Ending Diagonal EA Initialized.");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("Contracting Ending Diagonal EA Deinitialized.");
}
//+------------------------------------------------------------------+
//| Expert tick function (main loop) |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if the pattern is detected and valid
if (IsContractingEndingDiagonal())
{
// If the pattern is valid, analyze and trade
ManageTrade();
}
}
//+------------------------------------------------------------------+
//| Function to detect contracting ending diagonal |
//+------------------------------------------------------------------+
bool IsContractingEndingDiagonal()
{
// Ensure a 5-wave structure is present
if (CountWaves() != 5)
{
Print("Not a valid 5-wave structure.");
return false; // Not a valid 5-wave structure
}
// Check if the waves are contracting
if (!IsContracting())
{
Print("Waves are not contracting.");
return false; // Waves are not contracting
}
// Check if Wave 2 and Wave 4 are corrective
if (!WaveConfirmation())
{
Print("Wave 2 and/or Wave 4 is not corrective.");
return false; // Wave confirmation failed
}
// Check if the pattern aligns with Fibonacci retracement levels
if (!CheckFibonacciLevels())
{
Print("Fibonacci validation failed.");
return false; // Fibonacci validation failed
}
// Check the strength of the pattern
if (PatternStrength() < 0.75) // Example threshold for strong pattern
{
Print("Pattern strength is too weak.");
return false; // Pattern is too weak to trade
}
return true; // Valid contracting ending diagonal pattern detected
}
//+------------------------------------------------------------------+
//| Function to count the number of waves in the pattern |
//+------------------------------------------------------------------+
int CountWaves()
{
int waveCount = 0;
int bars = Bars;
// Loop through and count the number of peaks (waves)
for (int i = 1; i < bars - 1; i++)
{
// Check if a peak is detected (local max)
if (High[i] > High[i - 1] && High[i] > High[i + 1])
{
waveCount++;
}
// Check if a trough is detected (local min)
if (Low[i] < Low[i - 1] && Low[i] < Low[i + 1])
{
waveCount++;
}
}
return waveCount; // Return the number of waves detected
}
//+------------------------------------------------------------------+
//| Function to check if the waves are contracting |
//+------------------------------------------------------------------+
bool IsContracting()
{
double waveSizes[4]; // Stores the length of each wave (example)
// Loop through each wave to calculate its size
for (int i = 1; i < ArraySize(waveSizes); i++)
{
waveSizes[i] = High[i] - Low[i]; // Calculate wave size (distance between peak and trough)
if (i > 0 && waveSizes[i] > waveSizes[i - 1]) // Check for contracting pattern
{
return false; // Waves are not contracting
}
}
return true; // All waves are contracting
}
//+------------------------------------------------------------------+
//| Function to check Wave 2 and Wave 4 confirmation (corrective) |
//+------------------------------------------------------------------+
bool WaveConfirmation()
{
// Check if Wave 2 and Wave 4 are corrective in nature (Zigzag or Flat)
// In this case, we'll check that Wave 2 and Wave 4 are within a reasonable Fibonacci retracement level
double wave1High = High[1]; // High of Wave 1
double wave1Low = Low[1]; // Low of Wave 1
double wave2High = High[2]; // High of Wave 2
double wave2Low = Low[2]; // Low of Wave 2
double wave4High = High[4]; // High of Wave 4
double wave4Low = Low[4]; // Low of Wave 4
// Check if Wave 2 is a valid corrective wave (should retrace between 50% to 78.6% of Wave 1)
double wave2Retrace = (wave2Low - wave1High) / (wave1High - wave1Low);
if (wave2Retrace < 0.5 || wave2Retrace > 0.786)
{
return false; // Wave 2 is not within a corrective range
}
// Check if Wave 4 is a valid corrective wave (should retrace between 50% to 78.6% of Wave 3)
double wave3High = High[3]; // High of Wave 3
double wave3Low = Low[3]; // Low of Wave 3
double wave4Retrace = (wave4Low - wave3High) / (wave3High - wave3Low);
if (wave4Retrace < 0.5 || wave4Retrace > 0.786)
{
return false; // Wave 4 is not within a corrective range
}
return true; // Waves 2 and 4 are both corrective
}
//+------------------------------------------------------------------+
//| Function to check Fibonacci levels for wave validation |
//+------------------------------------------------------------------+
bool CheckFibonacciLevels()
{
double fibLevels[] = {0.236, 0.382, 0.618, 0.786}; // Fibonacci retracement levels
double wave1High = High[1]; // High of Wave 1
double wave1Low = Low[1]; // Low of Wave 1
double fibLevel;
// Check Fibonacci levels relative to Wave 1 (adjust logic to work for other waves as needed)
for (int i = 0; i < ArraySize(fibLevels); i++)
{
fibLevel = wave1Low + (wave1High - wave1Low) * fibLevels[i];
// Check if price touches the Fibonacci level (simplified version)
if (Ask >= fibLevel - 5 * Point && Ask <= fibLevel + 5 * Point)
{
return true; // Fibonacci level validated
}
}
return false; // No valid Fibonacci level found
}
//+------------------------------------------------------------------+
//| Function to evaluate pattern strength |
//+------------------------------------------------------------------+
double PatternStrength()
{
double strength = 0.0;
int waveCount = CountWaves();
if (waveCount == 5)
{
strength += 0.5; // Basic pattern count check (5 waves expected)
}
if (IsContracting())
{
strength += 0.3; // Contracting waves add strength to the pattern
}
if (CheckFibonacciLevels())
{
strength += 0.2; // Fibonacci alignment adds strength
}
return strength; // Return pattern strength (from 0 to 1)
}
//+------------------------------------------------------------------+
//| Function to manage trades based on detected pattern |
//+------------------------------------------------------------------+
void ManageTrade()
{
double entryPrice = Ask;
double stopLoss = 0;
double takeProfit = 0;
double lotSize = CalculateLotSize(); // Dynamic lot size based on risk
// Calculate stop-loss and take-profit based on the wave sizes
double waveSize = High[1] - Low[1]; // Simplified wave size (adjust as needed)
// Stop loss below the last trough and take-profit at a Fibonacci extension
stopLoss = Low[1] - (waveSize * 0.618);
takeProfit = High[1] + (waveSize * 1.618);
// Create the order request
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = lotSize;
request.type = ORDER_TYPE_BUY;
request.price = entryPrice;
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 10;
// Send the order
if (OrderSend(request, result))
{
Print("Buy order placed successfully with ticket: ", result.order);
}
else
{
Print("Error opening buy order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Function to calculate dynamic lot size based on risk and account |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double riskPercentage = 0.02; // 2% of account balance risk per trade
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double lotSize = (accountBalance * riskPercentage) / 1000; // Adjust position size based on risk
return NormalizeDouble(lotSize, 2);
}
//+------------------------------------------------------------------+
Changes and Fixes so far:
- Array Access: Fixed issues related to accessing High[] and Low[] correctly (e.g., High[1], Low[1]).
- Trade Management: Corrected the usage of MqlTradeRequest and ensured proper execution of buy orders.
- Error Handling: Included proper error handling for placing orders and logging error messages.
- Account Information: Correct use of AccountInfoDouble(ACCOUNT_BALANCE) for fetching the account balance.