Discussing the article: "Advanced Order Execution Algorithms in MQL5: TWAP, VWAP, and Iceberg Orders"
Great article!
Which pairs do you recommend for this Algo?
Which time frames? M5, M30 etc.
Which session?
Thanks and kind regards
Testing your algo.
IN file, ExecutionAlgorithm.mqh, added this line request.type_filling = ORDER_FILLING_IOC; in placing order to fix order placing issue.
Back tested it at M5, it opened only 1 trade for 2 months period, no partial order opened.
Tested it at H1, it never applied the SL, or TP and all trades closed in loss.
also while compiling it generates warnings
suggest how tyo test the algo,
Time frame. and any other recommendations.
also while compiling it generates warnings
i changed the code line
m_volumeProfile[intervalIndex] += rates[i].tick_volu
to
It fixed the warnings
Now need you guidence regarding my other queries, as
Time frame
And also
why all trades during backtest result in Loss
how to test this great work from you..
Great Article
Testing your algo.
IN file, ExecutionAlgorithm.mqh, added this line request.type_filling = ORDER_FILLING_IOC; in placing order to fix order placing issue.
Back tested it at M5, it opened only 1 trade for 2 months period, no partial order opened.
Tested it at H1, it never applied the SL, or TP and all trades closed in loss.
also while compiling it generates warnings
suggest how tyo test the algo,
Time frame. and any other recommendations.
The warnings aren't the problem but could get fixed quickly. But yes it would be great if the author could show step-by-step which settings and inputs he used for the backtest.
I agree with Dominic as the warnings are just warnings. I_Virgo's results are probably because he used the wrong time frame and currency pair. From the Back Test report, of nearly 2000 bars, it must have been either M1 or M5 as the time frame with an unknown pair.
It would be nice if MQ added the time frame and currency pair or pairs and also separated the pair results in more details to the Back Test report so we could more closely replicate author's back test results as well as determining its applicability over the forex pairs.. Also, it would be extremely helpful if the EA could post text to the chart while it is running.
I also think it is a great article and plan to study it thoroughly in anticipation of adapting his techniques to other EAs
CapeCoddah
//+------------------------------------------------------------------+ //| Base class for all execution algorithms | //+------------------------------------------------------------------+ class CExecutionAlgorithm { protected: string m_symbol; // Trading symbol double m_totalVolume; // Total volume to execute double m_executedVolume; // Volume already executed double m_remainingVolume; // Volume remaining to execute datetime m_startTime; // Start time of execution datetime m_endTime; // End time of execution int m_slippage; // Allowed slippage in points bool m_isActive; // Is algorithm currently active // Statistics double m_avgExecutionPrice; // Average execution price int m_totalOrders; // Total number of orders placed int m_filledOrders; // Number of filled orders public: // Constructor CExecutionAlgorithm(string symbol, double volume, datetime startTime, datetime endTime, int slippage); // Destructor virtual ~CExecutionAlgorithm(); // Virtual methods to be implemented by derived classes virtual bool Initialize(); virtual bool Execute() = 0; virtual bool Update() = 0; virtual bool Terminate() = 0; // Common methods bool IsActive() { return m_isActive; } double GetExecutedVolume() { return m_executedVolume; } double GetRemainingVolume() { return m_remainingVolume; } double GetAverageExecutionPrice() { return m_avgExecutionPrice; } // Helper methods bool PlaceOrder(ENUM_ORDER_TYPE orderType, double volume, double price = 0.0); bool ModifyOrder(ulong ticket, double price, double sl, double tp); bool CancelOrder(ulong ticket); void UpdateAverageExecutionPrice(double price, double volume); // Helper method to get appropriate filling mode ENUM_ORDER_TYPE_FILLING GetFillingMode(); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CExecutionAlgorithm::CExecutionAlgorithm(string symbol, double volume, datetime startTime, datetime endTime, int slippage) { m_symbol = symbol; m_totalVolume = volume; m_executedVolume = 0.0; m_remainingVolume = volume; m_startTime = startTime; m_endTime = endTime; m_slippage = slippage; m_isActive = false; m_avgExecutionPrice = 0.0; m_totalOrders = 0; m_filledOrders = 0; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CExecutionAlgorithm::~CExecutionAlgorithm() { // Clean up resources if needed } //+------------------------------------------------------------------+ //| Initialize the algorithm | //+------------------------------------------------------------------+ bool CExecutionAlgorithm::Initialize() { // Validate inputs if(m_symbol == "" || m_totalVolume <= 0.0) { Print("Invalid inputs for execution algorithm"); return false; } // Check if the symbol exists if(!SymbolSelect(m_symbol, true)) { Print("Symbol not found: ", m_symbol); return false; } // Reset statistics m_executedVolume = 0.0; m_remainingVolume = m_totalVolume; m_avgExecutionPrice = 0.0; m_totalOrders = 0; m_filledOrders = 0; return true; } //+------------------------------------------------------------------+ //| Get appropriate filling mode for the symbol | //+------------------------------------------------------------------+ ENUM_ORDER_TYPE_FILLING CExecutionAlgorithm::GetFillingMode() { // Get symbol filling modes int filling_modes = (int)SymbolInfoInteger(m_symbol, SYMBOL_FILLING_MODE); // Check available filling modes in order of preference if((filling_modes & SYMBOL_FILLING_FOK) == SYMBOL_FILLING_FOK) return ORDER_FILLING_FOK; else if((filling_modes & SYMBOL_FILLING_IOC) == SYMBOL_FILLING_IOC) return ORDER_FILLING_IOC; else return ORDER_FILLING_RETURN; } //+------------------------------------------------------------------+ //| Place an order | //+------------------------------------------------------------------+ bool CExecutionAlgorithm::PlaceOrder(ENUM_ORDER_TYPE orderType, double volume, double price = 0.0) { // Validate inputs if(volume <= 0.0) { Print("Invalid order volume"); return false; } // Prepare the request MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.symbol = m_symbol; request.volume = volume; request.type = orderType; request.deviation = m_slippage; request.magic = 123456; // Magic number for identification // Set appropriate action and price based on order type if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_SELL) { // Market order request.action = TRADE_ACTION_DEAL; request.type_filling = GetFillingMode(); if(orderType == ORDER_TYPE_BUY) request.price = SymbolInfoDouble(m_symbol, SYMBOL_ASK); else request.price = SymbolInfoDouble(m_symbol, SYMBOL_BID); } else { // Pending order request.action = TRADE_ACTION_PENDING; if(price <= 0.0) { Print("Price must be specified for pending orders"); return false; } request.price = price; } // Send the order if(!OrderSend(request, result)) { Print("OrderSend error: ", GetLastError()); return false; } // Check the result if(result.retcode != TRADE_RETCODE_DONE) { Print("OrderSend failed with code: ", result.retcode, " - ", result.comment); return false; } // Update statistics m_totalOrders++; // For market orders, update execution statistics immediately if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_SELL) { m_filledOrders++; UpdateAverageExecutionPrice(request.price, volume); m_executedVolume += volume; m_remainingVolume -= volume; } Print("Order placed successfully. Ticket: ", result.order, " Volume: ", volume, " Price: ", request.price); return true; } //+------------------------------------------------------------------+ //| Modify an existing order | //+------------------------------------------------------------------+ bool CExecutionAlgorithm::ModifyOrder(ulong ticket, double price, double sl, double tp) { // Prepare the request MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_MODIFY; request.order = ticket; request.price = price; request.sl = sl; request.tp = tp; // Send the modification request if(!OrderSend(request, result)) { Print("OrderModify error: ", GetLastError()); return false; } // Check the result if(result.retcode != TRADE_RETCODE_DONE) { Print("OrderModify failed with code: ", result.retcode, " - ", result.comment); return false; } Print("Order modified successfully. Ticket: ", ticket); return true; } //+------------------------------------------------------------------+ //| Cancel an existing order | //+------------------------------------------------------------------+ bool CExecutionAlgorithm::CancelOrder(ulong ticket) { // Prepare the request MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_REMOVE; request.order = ticket; // Send the cancellation request if(!OrderSend(request, result)) { Print("OrderCancel error: ", GetLastError()); return false; } // Check the result if(result.retcode != TRADE_RETCODE_DONE) { Print("OrderCancel failed with code: ", result.retcode, " - ", result.comment); return false; } Print("Order cancelled successfully. Ticket: ", ticket); return true; } //+------------------------------------------------------------------+ //| Update the average execution price | //+------------------------------------------------------------------+ void CExecutionAlgorithm::UpdateAverageExecutionPrice(double price, double volume) { // Calculate the new average execution price if(m_executedVolume > 0.0) { // Weighted average of old and new prices m_avgExecutionPrice = (m_avgExecutionPrice * m_executedVolume + price * volume) / (m_executedVolume + volume); } else { // First execution m_avgExecutionPrice = price; } } //+------------------------------------------------------------------+

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Check out the new article: Advanced Order Execution Algorithms in MQL5: TWAP, VWAP, and Iceberg Orders.
An MQL5 framework that brings institutional-grade execution algorithms (TWAP, VWAP, Iceberg) to retail traders through a unified execution manager and performance analyzer for smoother, more precise order slicing and analytics.
“Sure,” you might shrug, “but I’m not moving institutional sums.” Here’s the kicker: you don’t have to. Whether you’re deploying a half-lot or a handful of mini-lots, volatility can still twist your execution. These tools help you:
Fly Under the Radar: Iceberg Orders, in particular, cloak your true order size, keeping prying algos guessing.
Today’s democratized landscape means the same execution tech that once demanded multi-million-dollar budgets can now run on your personal trading station. By dropping polished MQL5 code for TWAP, VWAP, and Iceberg strategies into your platform, you’ll arm yourself with institutional firepower—without ever leaving the retail domain.
Get ready to flip the script on your execution process. The game is changing, and with these algorithms in your toolkit, you’ll be playing to win.
Author: N Soumik