MQL5: How to Execute Actions on Trade Close?

Introduction to Trade Close Event Handling in MQL5

Understanding the Importance of Trade Close Events

Knowing when a trade closes is crucial for various algorithmic trading tasks. It allows you to:

  • Analyze trade performance in real-time.
  • Implement risk management strategies, such as adjusting position sizes.
  • Trigger follow-up actions based on the trade’s outcome.
  • Maintain comprehensive trade logs for auditing and strategy refinement.

Overview of MQL5 and Its Event-Driven Architecture

MQL5 is an event-driven language. It responds to events like order execution, chart changes, and timer expirations. This makes it efficient for real-time trading applications, a significant improvement over MQL4’s more limited event handling.

Defining ‘Trade Close’ in the MQL5 Context

In MQL5, a ‘trade close’ occurs when a position is fully or partially closed, either manually, by a stop-loss/take-profit order, or by an Expert Advisor (EA). Understanding the precise trigger is important for coding your response.

Methods for Detecting Trade Close Events in MQL5

Using OnTradeTransaction Event Handler

The OnTradeTransaction event handler is the primary method for detecting trade close events. This function is called whenever a trade transaction occurs. By examining the trade and deal parameters within the handler, you can determine if a trade has been closed. Here’s the function signature:

void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result)

Within OnTradeTransaction, you need to check the trans.type to identify transaction types. TRADE_TRANSACTION_DEAL_ADD combined with checking deal.entry for DEAL_ENTRY_OUT signals a trade close.

Polling Trade History: Advantages and Disadvantages

While not recommended for real-time responses, polling trade history (HistorySelect, HistoryDealsTotal, HistoryDealGetTicket, HistoryDealGetDouble) can be useful for post-trade analysis or when an event might have been missed. The disadvantage is the delay and the computational overhead of repeatedly querying the history. Avoid using this for immediate actions after a close.

Combining Event Handling and History Analysis

A robust approach uses OnTradeTransaction for immediate actions and periodic history analysis as a backup to ensure no trade closures are missed, particularly in cases of connection issues or unexpected platform behavior. This is especially important for strategies that rely on precise timing.

Implementing Actions Upon Trade Close: Practical Examples

Example 1: Logging Closed Trade Details

This example demonstrates logging the details of a closed trade to the Experts log.

void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {
   if (trans.type == TRADE_TRANSACTION_DEAL_ADD) {
      if (trans.deal.entry == DEAL_ENTRY_OUT) {
         long ticket = trans.deal.ticket;
         double profit = trans.deal.profit;
         datetime time = trans.time;
         string symbol = trans.symbol;

         Print("Trade Closed: Ticket=", ticket, ", Symbol=", symbol, ", Profit=", profit, ", Time=", TimeToString(time));
      }
   }
}

Example 2: Calculating and Displaying Profit/Loss After Close

This example calculates the cumulative profit/loss after each trade close and displays it as a chart comment.

double totalProfit = 0.0;

void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {
   if (trans.type == TRADE_TRANSACTION_DEAL_ADD) {
      if (trans.deal.entry == DEAL_ENTRY_OUT) {
         totalProfit += trans.deal.profit;
         Comment("Total Profit: ", totalProfit);
      }
   }
}

Example 3: Triggering Notifications on Trade Closure

This example sends a push notification to your mobile device when a trade closes with a profit.

void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {
   if (trans.type == TRADE_TRANSACTION_DEAL_ADD) {
      if (trans.deal.entry == DEAL_ENTRY_OUT && trans.deal.profit > 0) {
         string message = "Trade closed with profit: " + DoubleToString(trans.deal.profit, 2);
         SendNotification(message);
      }
   }
}

Example 4: Initiating a New Trade Based on the Outcome of the Closed Trade

This advanced example places a new trade in the opposite direction if the previous trade closed with a loss. This is a simple example of a grid trading strategy.

void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {
    if (trans.type == TRADE_TRANSACTION_DEAL_ADD) {
        if (trans.deal.entry == DEAL_ENTRY_OUT) {
            if (trans.deal.profit < 0) {
                // Place a new trade in the opposite direction
                MqlTradeRequest newRequest = {};
                newRequest.action = TRADE_ACTION_DEAL;
                newRequest.symbol = trans.symbol;
                newRequest.volume = 0.01; // Example volume
                newRequest.type = (trans.position.type == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
                newRequest.price = SymbolInfoDouble(trans.symbol, (newRequest.type == ORDER_TYPE_BUY) ? SYMBOL_ASK : SYMBOL_BID);
                newRequest.deviation = 10; // Example deviation
                newRequest.magic = 12345; // Example magic number

                MqlTradeResult newResult = {};
                OrderSend(newRequest, newResult);

                if (newResult.retcode != TRADE_RETCODE_DONE) {
                    Print("Error placing new trade: ", EnumToString(newResult.retcode));
                }
            }
        }
    }
}

Important: This is a simplified example. Implement proper risk management and error handling in a real-world application.

Advanced Techniques and Considerations

Handling Multiple Trade Closures Simultaneously

In volatile markets, multiple trades can close in quick succession. Ensure your code is thread-safe and can handle concurrent events without errors or missed data.

Dealing with Partial Trade Closures

The OnTradeTransaction event is triggered for every transaction, including partial closures. Adjust your logic to correctly handle partial closures, potentially tracking remaining position sizes to avoid unintended actions.

Error Handling and Robustness in Trade Close Event Processing

Implement robust error handling to catch exceptions and unexpected situations. Use try-catch blocks to prevent your EA from crashing. Log errors for debugging.

Optimizing Performance for Frequent Trade Closures

Avoid computationally intensive operations within the OnTradeTransaction handler. If necessary, delegate tasks to separate threads or use asynchronous processing to prevent blocking the main trading loop. Minimize unnecessary memory allocations.

Conclusion: Best Practices and Future Directions

Summary of Key Concepts and Techniques

  • Use OnTradeTransaction for real-time trade close detection.
  • Examine the trans.type and trans.deal.entry fields.
  • Implement error handling and logging.
  • Consider asynchronous processing for performance-critical tasks.
  • Periodically cross-validate with history data for robustness.

Recommendations for Effective Trade Close Event Handling

  • Keep the OnTradeTransaction handler concise and efficient.
  • Avoid blocking operations within the handler.
  • Thoroughly test your code with various market conditions and trade scenarios.
  • Monitor your EA’s performance and resource usage.

Future Trends and Potential Enhancements in MQL5 Trade Event Management

Future MQL5 updates may introduce more granular trade event notifications or improved asynchronous processing capabilities, allowing for even more sophisticated trading strategies and efficient event handling. Keep up-to-date with MetaQuotes’ documentation and community forums.


Leave a Reply