Help Needed: Invalid Stops

 

#property copyright "2024, eitan gauchman, you steal this, you go to court"
#include <Trade\Trade.mqh>
CTrade trade;

// Define global variables
datetime lastTradeTime = 0;      // Variable to store the last trade time to prevent duplicate trades
input double StopLossFactor = 1.5;
input double RiskPercentage = 5; // Risk percentage of the capital for each trade
input int ExpirationSeconds = 20; // Expiration time for binary options in seconds
input int CandleMultiplier = 3;  // Multiplier for detecting a large candle
input int LookbackPeriod = 15;   // Lookback period in seconds to find the largest candle
input int SearchDuration = 20;   // Duration to search for a big candle after event release in seconds

double tickSize; // Variable to store tick size
double lotSize;  // Variable to store lot size

// Define a structure to store event information
struct Event 
{
    string currencyPair;       // Currency pair for the event
    datetime releaseTime;      // Release time of the event
    bool isUSDCategory;        // Flag indicating if the event is a USD category event
    double largestMovement;    // Largest price movement found before the event
};

Event events[];  // Array to store all events

// Function to add an event to the events array
void AddEvent(string currencyPair, datetime releaseTime, bool isUSDCategory) 
{
    Event newEvent;
    newEvent.currencyPair = currencyPair;
    newEvent.releaseTime = releaseTime;
    newEvent.isUSDCategory = isUSDCategory;
    newEvent.largestMovement = 0; // Initialize with zero
    ArrayResize(events, ArraySize(events) + 1);  // Resize the array to accommodate the new event
    events[ArraySize(events) - 1] = newEvent;   // Add the new event to the array
    
    // Log event addition
    Print("Event added: ", currencyPair, " at ", TimeToString(releaseTime));
}

double FindLargestMovement(string symbol, datetime eventTime) 
{
    double largestMovement = 0;
    ulong lookbackStart = (ulong)(eventTime - LookbackPeriod) * 1000; // Convert to milliseconds
    ulong lookbackEnd = (ulong)eventTime * 1000; // Convert to milliseconds

    MqlTick ticks[];
    int copied = CopyTicksRange(symbol, ticks, COPY_TICKS_ALL, lookbackStart, lookbackEnd);

    if (copied <= 0)
    {
        Print("Failed to copy ticks for ", symbol, " within the lookback period.");
        return 0;
    }

    Print("Copied ", copied, " ticks for ", symbol, " within the lookback period.");

    for (int i = 1; i < copied; i++) 
    {
        double previousPrice = ticks[i - 1].ask; // Use the 'ask' price
        double currentPrice = ticks[i].ask; // Use the 'ask' price

        // Calculate movement as the absolute difference between consecutive prices
        double movement = MathAbs(currentPrice - previousPrice);
        if (movement > largestMovement)
            largestMovement = movement;
    }
    largestMovement = NormalizeDouble(largestMovement, 5);
    Print("Largest movement found for ", symbol, ": ", largestMovement);

    return largestMovement;
}

// Function to detect a large candle
bool IsLargeCandle(string symbol, double largestMovement) 
{
    MqlTick tick;
    double prevPrice = 0;
  
    // Search for a large candle in the search duration
    datetime searchEnd = TimeCurrent() + SearchDuration;
    while (TimeCurrent() < searchEnd) 
    {
        if (SymbolInfoTick(symbol, tick)) 
        {
            double currentPrice = tick.ask;
            if (prevPrice != 0) 
            {
                double currentMovement = MathAbs(currentPrice - prevPrice);
                if (currentMovement >= CandleMultiplier * largestMovement) 
                {
                    Print("Large candle detected for ", symbol, " at price ", currentPrice);
                    return true;  // Return true if a large candle is found
                }
            }
            prevPrice = currentPrice;
        }
        Sleep(400); // Sleep for 0.4 seconds before checking again
    }
  
    return false;  // Return false if no large candle is found
}
// Function to execute a trade without specifying stop loss and take profit
// Example function to execute a trade with dynamic stop loss
// Example adjustment to lot size calculation


// Main function that runs on every tick
void OnTick() 
{
    datetime currentTime = TimeCurrent();  // Get the current server time
    MqlTick tick;
    MqlTick prevTick;

    // Loop through all events
    for (int i = 0; i < ArraySize(events); i++) 
    {
        Event currentEvent = events[i];

        // Check if the current time is within the relevant window for the event
        if (currentEvent.releaseTime - 5 <= currentTime && 
            currentTime <= currentEvent.releaseTime + SearchDuration) 
        {
            // Check if the event has not already triggered a trade recently
            if (currentEvent.releaseTime > lastTradeTime) 
            {
                // Calculate the largest movement if it hasn't been calculated yet
                if (currentEvent.largestMovement == 0) 
                {
                    currentEvent.largestMovement = FindLargestMovement(currentEvent.currencyPair, currentEvent.releaseTime);
                    Print("Largest movement found for ", currentEvent.currencyPair, ": ", currentEvent.largestMovement);
                }

                // Check if a large candle is detected
                if (IsLargeCandle(currentEvent.currencyPair, currentEvent.largestMovement)) 
                {
                    // Determine direction based on tick to tick price difference
                    if (SymbolInfoTick(currentEvent.currencyPair, tick)) 
                    {
                        bool isLong = (tick.ask > prevTick.ask);
                        prevTick = tick; // Update prevTick for the next comparison
                        Print("Preparing to execute trade for ", currentEvent.currencyPair, ". Long: ", isLong ? "true" : "false");
                        ExecuteTrade(currentEvent.currencyPair, isLong,currentEvent.largestMovement);  // Execute trade if conditions are met
                    }
                }
            }
        }
    }
}


// Initialization function
int OnInit()
{
  // Add events manually
  AddEvent("EURUSD", D'2024.06.28 15:30', true);
  AddEvent("EURUSD", D'2024.06.25 17:00', true);
  AddEvent("EURUSD", D'2024.06.21 16:45', true);
  AddEvent("EURUSD", D'2024.04.18 15:30', true);
  AddEvent("EURUSD", D'2024.06.17 15:30', true);
  AddEvent("EURUSD", D'2024.05.03 15:30', true);
  AddEvent("EURUSD", D'2024.05.03 15:30', true);
  AddEvent("EURUSD", D'2024.05.01 21:00', true);
  AddEvent("EURUSD", D'2024.04.12 17:00', true);
  AddEvent("EURUSD", D'2024.04.11 15:30', true);
  AddEvent("EURUSD", D'2024.04.10 15:30', true);
  AddEvent("EURUSD", D'2024.04.05 15:30', true);
  AddEvent("EURUSD", D'2024.04.04 15:30', true);
  AddEvent("EURUSD", D'2024.04.03 17:00', true);
  AddEvent("EURUSD", D'2024.04.03 15:15', true);
  AddEvent("EURUSD", D'2024.04.02 17:00', true);
  AddEvent("EURUSD", D'2024.03.29 15:30', true);
  AddEvent("EURUSD", D'2024.03.28 16:00', true);
  AddEvent("EURUSD", D'2024.03.28 14:30', true);
  AddEvent("EURUSD", D'2024.03.26 16:00', true);
  AddEvent("EURUSD", D'2024.03.20 20:00', true);
  AddEvent("EURUSD", D'2024.03.12 14:30', true);
  AddEvent("EURUSD", D'2024.03.08 15:30', true);
  AddEvent("EURUSD", D'2024.03.06 15:15', true);
  AddEvent("EURUSD", D'2024.03.05 17:00', true);
  AddEvent("EURUSD", D'2024.02.29 15:30', true);
  AddEvent("EURUSD", D'2024.02.28 15:30', true);
  AddEvent("EURUSD", D'2024.02.27 17:00', true);
  AddEvent("EURUSD", D'2024.02.27 15:30', true);
  AddEvent("EURUSD", D'2024.02.13 15:30', true);
  AddEvent("EURUSD", D'2024.02.05 17:00', true);
  AddEvent("EURUSD", D'2024.02.02 15:30', true);
  AddEvent("EURUSD", D'2024.01.31 21:00', true);
...
  AddEvent("EURUSD", D'2023.05.03 21:00', true);
  return INIT_SUCCEEDED;
}

// Deinitialization function
void OnDeinit(const int reason)
{
  // Cleanup if needed (not required in this example)
}
/*
//2024.07.17 23:37:55.212       2024.06.12 21:00:14   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:14   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Large candle detected for EURUSD at price 1.08308
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Preparing to execute trade for EURUSD. Long: true
2024.07.17 23:37:55.212 2024.06.12 21:00:16   current account state: Balance: 10000.00, Credit: 0.00, Commission: 0.00, Accumulated: 0.00, Assets: 0.00, Liabilities: 0.00, Equity 10000.00, Margin: 0.00, FreeMargin: 10000.00
2024.07.17 23:37:55.212 2024.06.12 21:00:16   calculated account state: Assets: 0.00, Liabilities: 0.00, Equity 10000.00, Margin: 161662000.00, FreeMargin: -161652000.00
2024.07.17 23:37:55.212 2024.06.12 21:00:16   not enough money [instant buy 500 EURUSD at 1.08308]
2024.07.17 23:37:55.212 2024.06.12 21:00:16   failed instant buy 500 EURUSD at 1.08308 [No money]
2024.07.17 23:37:55.212 2024.06.12 21:00:16   CTrade::OrderSend: instant buy 500.00 EURUSD at 1.08308 [not enough money]
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Trade executed for EURUSD. Long: true
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Copied 17 ticks for EURUSD within the lookback period.
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:16   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Large candle detected for EURUSD at price 1.0826
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Preparing to execute trade for EURUSD. Long: true
2024.07.17 23:37:55.212 2024.06.12 21:00:18   requote 1.08239 / 1.08246 (instant buy 500 EURUSD at 1.08260)
2024.07.17 23:37:55.212 2024.06.12 21:00:18   requote 1.08239 / 1.08246 (instant buy 500 EURUSD at 1.08260)
2024.07.17 23:37:55.212 2024.06.12 21:00:18   CTrade::OrderSend: instant buy 500.00 EURUSD at 1.08260 [requote (1.08239/1.08246)]
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Trade executed for EURUSD. Long: true
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Copied 17 ticks for EURUSD within the lookback period.
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:18   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.212 2024.06.12 21:00:37   Large candle detected for EURUSD at price 1.08242
2024.07.17 23:37:55.212 2024.06.12 21:00:37   Preparing to execute trade for EURUSD. Long: true
2024.07.17 23:37:55.212 2024.06.12 21:00:37   current account state: Balance: 10000.00, Credit: 0.00, Commission: 0.00, Accumulated: 0.00, Assets: 0.00, Liabilities: 0.00, Equity 10000.00, Margin: 0.00, FreeMargin: 10000.00
2024.07.17 23:37:55.212 2024.06.12 21:00:37   calculated account state: Assets: 0.00, Liabilities: 0.00, Equity 10000.00, Margin: 161563000.00, FreeMargin: -161553000.00
2024.07.17 23:37:55.212 2024.06.12 21:00:37   not enough money [instant buy 500 EURUSD at 1.08242]
2024.07.17 23:37:55.212 2024.06.12 21:00:37   failed instant buy 500 EURUSD at 1.08242 [No money]
2024.07.17 23:37:55.212 2024.06.12 21:00:37   CTrade::OrderSend: instant buy 500.00 EURUSD at 1.08242 [not enough money]
2024.07.17 23:37:55.212 2024.06.12 21:00:37   Trade executed for EURUSD. Long: true
2024.07.17 23:37:55.261 2024.06.13 15:29:55   Copied 15 ticks for EURUSD within the lookback period.
2024.07.17 23:37:55.261 2024.06.13 15:29:55   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.261 2024.06.13 15:29:55   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.261 2024.06.13 15:30:02   Large candle detected for EURUSD at price 1.08011
2024.07.17 23:37:55.261 2024.06.13 15:30:02   Preparing to execute trade for EURUSD. Long: true
2024.07.17 23:37:55.261 2024.06.13 15:30:02   requote 1.08021 / 1.08028 (instant buy 500 EURUSD at 1.08011)
2024.07.17 23:37:55.261 2024.06.13 15:30:02   requote 1.08021 / 1.08028 (instant buy 500 EURUSD at 1.08011)
2024.07.17 23:37:55.261 2024.06.13 15:30:02   CTrade::OrderSend: instant buy 500.00 EURUSD at 1.08011 [requote (1.08021/1.08028)]
2024.07.17 23:37:55.261 2024.06.13 15:30:02   Trade executed for EURUSD. Long: true
2024.07.17 23:37:55.261 2024.06.13 15:30:03   Copied 22 ticks for EURUSD within the lookback period.
2024.07.17 23:37:55.261 2024.06.13 15:30:03   Largest movement found for EURUSD: 0.00013
2024.07.17 23:37:55.261 2024.06.13 15:30:03   Largest movement found for EURUSD: 0.00013
I have no idea whats up with the margin, its a demo account that has been loaded with 10000, and haven't placed any trade, if I change the amount in the backtest the wild margin number adjustes at well (if I 10x he too)
*/
// The issue you're encountering with the margin calculation and the "not enough money" error seems to be related to the way you're calculating the lot size and the margin required for the trade. The margin calculation might be incorrect, leading to an unrealistic margin requirement.
// 
// Let's break down the potential issues and provide a solution:
// 
// 1. **Lot Size Calculation**: The lot size should be calculated based on the account balance and the risk percentage. However, it should also consider the leverage and the minimum lot size allowed by the broker.
// 
// 2. **Margin Calculation**: The margin required for a trade depends on the leverage and the lot size. The margin calculation should be done using the correct formula.
// 
// 3. **Trade Execution**: Ensure that the trade execution is done with the correct parameters and that the margin requirement is checked properly before placing the trade.
// 
// Here's an updated version of the `ExecuteTrade` function with these considerations:
// 

void ExecuteTrade(string symbol, bool isLong, double largestMovement)
{
    double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
    double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
    long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE);
    double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
    double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);

    // Calculate the risk amount in account currency
    double riskAmount = accountBalance * RiskPercentage / 100;

    // Calculate the lot size based on the risk amount and the largest movement
    double stopLossPips = StopLossFactor * largestMovement / SymbolInfoDouble(symbol, SYMBOL_POINT);
    lotSize = riskAmount / (stopLossPips * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE));

    // Adjust lot size to the nearest valid step and ensure it's not below the minimum lot size
    lotSize = MathMax(minLot, MathFloor(lotSize / lotStep) * lotStep);
    lotSize = NormalizeDouble(lotSize, 2); // Normalize to 2 decimal places

    if (lotSize < minLot)
    {
        Print("Lot size too small for ", symbol);
        return;
    }

    double price = isLong ? SymbolInfoDouble(symbol,SYMBOL_ASK) : SymbolInfoDouble(symbol,SYMBOL_BID);
    double slippage = 10; // Set slippage to 10 points (adjust as needed)

    // Calculate stop loss based on largest movement found
    double stopLoss = isLong ? price - StopLossFactor * largestMovement : price + StopLossFactor * largestMovement;

    // Calculate the margin required for the trade
    double marginRequired = (price * lotSize) / leverage;

    if (marginRequired > freeMargin)
    {
        Print("Not enough free margin to execute trade for ", symbol);
        return;
    }

    // Place order with calculated stop loss
    if (isLong)
    {
        trade.Buy(lotSize, symbol, price, slippage,stopLoss, "Trade executed by EA");
      
    }
    else
    {
        trade.Sell(lotSize, symbol, price, slippage,2.0, "Trade executed by EA");
        
    }

    Print("Trade executed for ", symbol, ". Long: ", isLong ? "true" : "false");
}


this is the error im getting ( I copied a part its repeating itself:
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Large candle detected for EURUSD at price 1.0838700000000001
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:11   failed instant buy 83.33 EURUSD at 1.08387 sl: 10.00000 tp: 1.08381 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:11   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08387 sl: 10.00000 tp: 1.08381 [invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Trade executed for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Large candle detected for EURUSD at price 1.08407
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:11   failed instant buy 83.33 EURUSD at 1.08407 sl: 10.00000 tp: 1.08401 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:11   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08407 sl: 10.00000 tp: 1.08401 [invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:11   Trade executed for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:12   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:12   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:12   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Large candle detected for EURUSD at price 1.08392
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:13   failed instant buy 83.33 EURUSD at 1.08392 sl: 10.00000 tp: 1.08386 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:13   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08392 sl: 10.00000 tp: 1.08386 [invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Trade executed for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:13   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:14   Large candle detected for EURUSD at price 1.08406
2024.07.18 00:06:55.613 2024.01.30 17:00:14   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:14   failed instant buy 83.33 EURUSD at 1.08406 sl: 10.00000 tp: 1.08400 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:14   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08406 sl: 10.00000 tp: 1.08400 [invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:14   Trade executed for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:15   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:15   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:15   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Large candle detected for EURUSD at price 1.08394
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:17   failed instant buy 83.33 EURUSD at 1.08394 sl: 10.00000 tp: 1.08388 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:17   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08394 sl: 10.00000 tp: 1.08388 [invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Trade executed for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Copied 179 ticks for EURUSD within the lookback period.
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:17   Largest movement found for EURUSD: 0.00004
2024.07.18 00:06:55.613 2024.01.30 17:00:21   Large candle detected for EURUSD at price 1.08416
2024.07.18 00:06:55.613 2024.01.30 17:00:21   Preparing to execute trade for EURUSD. Long: true
2024.07.18 00:06:55.613 2024.01.30 17:00:21   failed instant buy 83.33 EURUSD at 1.08416 sl: 10.00000 tp: 1.08410 [Invalid stops]
2024.07.18 00:06:55.613 2024.01.30 17:00:21   CTrade::OrderSend: instant buy 83.33 EURUSD at 1.08416 sl: 10.00000 tp: 1.08410 [invalid stops]


does anybody know how to fix this?
thank you. 🙏

 
 // Place order with calculated stop loss
    if (isLong)
    {
        trade.Buy(lotSize, symbol, price, slippage,stopLoss, "Trade executed by EA");
      
    }
    else
    {
        trade.Sell(lotSize, symbol, price, slippage,2.0, "Trade executed by EA");
        
    }


Here you're making a mistake with the params, there is no slippage parameter. This "slippage" is where the stopLoss parameter should be. That's why you're seeing SL = 10.0 which is wrong (slippage is 10). 


it should be:

trade.Sell(lotSize, symbol, price, stopLoss, takeProfit, "");

trade.Buy(lotSize, symbol, price, stopLoss, takeProfit, "");