Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2017.09.26 09:55
Cross-platform version of Expert Advisor// MQL4&5-code #ifdef __MQL5__ bool RefreshRates( void ) { return(true); } double MarketInfo( const string Symb, const ENUM_SYMBOL_INFO_DOUBLE Property ) { return(SymbolInfoDouble(Symb, Property)); } int MarketInfo( const string Symb, const ENUM_SYMBOL_INFO_INTEGER Property ) { return((int)SymbolInfoInteger(Symb, Property)); } bool IsTesting(void) { return(MQLInfoInteger(MQL_TESTER) || MQLInfoInteger(MQL_OPTIMIZATION)); } bool IsTradeContextBusy( void ) { return(false); } bool IsTradeAllowed(void) { return(MQLInfoInteger(MQL_TRADE_ALLOWED)); } bool IsExpertEnabled(void) { return(AccountInfoInteger(ACCOUNT_TRADE_EXPERT)); } int ObjectFind( const string Name ) { return(ObjectFind(0, Name)); } int ObjectsTotal( void ) { return(ObjectsTotal(0)); } bool ObjectDelete( const string Name ) { return(ObjectDelete(0, Name)); } string ObjectName( const int Pos ) { return(ObjectName(0, Pos)); } double AccountFreeMarginCheck(const string Symb,const int Cmd,const double dVolume) { double Margin; return(OrderCalcMargin((ENUM_ORDER_TYPE)Cmd, Symb, dVolume, SymbolInfoDouble(Symb, (Cmd == ORDER_TYPE_BUY) ? SYMBOL_ASK : SYMBOL_BID), Margin) ? AccountInfoDouble(ACCOUNT_MARGIN_FREE) - Margin : -1); } #define False false #define True true #define Digits _Digits #define Point _Point #define MODE_BID SYMBOL_BID #define MODE_ASK SYMBOL_ASK #define MODE_POINT SYMBOL_POINT #define MODE_DIGITS SYMBOL_TRADE_STOPS_LEVEL #define MODE_STOPLEVEL SYMBOL_TRADE_STOPS_LEVEL #define MODE_SPREAD SYMBOL_SPREAD #define StrToTime StringToTime #define StrToInteger StringToInteger #define TimeToStr TimeToString #define DoubleToStr DoubleToString #define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID) #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) #define MT4_TICKET_TYPE // Обязываем OrderSend и OrderTicket возвращать значение такого же типа, как в MT4 - int. #include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006 // Нужно для графиков в отчетах // #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280 #define REPORT_TESTER // В тестере будут автоматически записываться отчеты #include <Report.mqh> // https://www.mql5.com/ru/code/18801 #endif // __MQL5__ #include "Quantum 103.mq4" // https://www.mql5.com/ru/code/19133
Result of backtest on real ticks on MT5
Standard MT5 report
Custom report (MT4 style)
Attached MT4-style report MT5-backtest, because the standard report is read with difficulty - see both in the attach.
You can clearly see the impact on the result of MT5-backtest of this adviser slippage and commission.
I'm trying to implement a strategy (which obviously works fine in MT4) but I've hit a brick wall.
The EA begins a new sequence of trades whenever a new signal is generated, so each traded pair will usually have multiple sequences running.
Every trade has an SL & TP, and the EA needs to track what happened (SL or TP) to the most recent trade in each sequence by checking the order history.
Unfortunately, this does not seem to be possible based on the library notes (below) and various attempts to make the system work:
// In MT4 OrderSelect in SELECT_BY_TICKET mode selects a ticket regardless of MODE_TRADES / MODE_HISTORY,
// since "Ticket number is a unique order ID".
// In MT5, the ticket number is NOT unique,
// so OrderSelect in SELECT_BY_TICKET mode has the following selection priorities for matching tickets:
// MODE_TRADES: existing position> existing order> transaction> canceled order
// MODE_HISTORY: transaction> canceled order> existing position> existing order
From experimentation, I have confirmed that the ticket number always changes after an SL/TP event, and that the only common info is the magic number - not even the order comment is retained.
In testing, placing an initial order with an SL, TP, magic number and trade comment returns ticket #2 and displays all of the expected information.
However, when the SL or TP is hit, ticket #2 vanishes and cannot be retrieved using either SELECT_BY_POS or SELECT_BY_TICKET.
Instead, (assuming no other trading activity) there will now be ticket #3, which has no order comment set.
With no consistency regarding ticket number, and no order comment to reference, there seems no simple way to identify the last order in a given sequence :(
Hopefully @fxsaber can find a solution or suggest a workaround :)
Unfortunately, I did not understand the problem.
Sorry for the late reply :(
The issue is that 'MODE_HISTORY' trade information is basically unusable because:
1) when a trade closes, the ticket number changes ...you can easily test this by opening a buy / sell trade with a TP and SL - if the trade opens as ticket #2, that trade will become ticket #3 in the history pool after the SL or TP triggers
2) the magic number is lost
3) the ticket comment is lost
So, if the EA code needs to check whether a trade closed with a profit or loss, it's impossible because there's no information available to identify the trade.
I'm hoping that you can tweak things to retain the magic number and make the trade comment behave like MT4 - maybe you can find a way to retain the ticket number too.
Sorry for the late reply :(
The issue is that 'MODE_HISTORY' trade information is basically unusable because:
1) when a trade closes, the ticket number changes ...you can easily test this by opening a buy / sell trade with a TP and SL - if the trade opens as ticket #2, that trade will become ticket #3 in the history pool after the SL or TP triggers
2) the magic number is lost
3) the ticket comment is lost
So, if the EA code needs to check whether a trade closed with a profit or loss, it's impossible because there's no information available to identify the trade.
I'm hoping that you can tweak things to retain the magic number and make the trade comment behave like MT4 - maybe you can find a way to retain the ticket number too.
Example
#include <MT4Orders.mqh> #define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID) #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) #define PRINT(A) Print(#A + " = " + (string)(A)) void OnInit() { long Ticket; PRINT((Ticket = OrderSend(_Symbol, OP_BUY, 1, Ask, 0, Bid - 100 * _Point, Bid + 100 * _Point, "Hello World!", 12345))); if (OrderSelect(Ticket, SELECT_BY_TICKET)) PRINT(OrderClose(OrderTicket(), 0.3, OrderClosePrice(), 0)); } void OnDeinit( const int ) { const int Total = OrdersHistoryTotal(); for (int i = 1; i < Total; i++) if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { OrderPrint(); PRINT(OrderTicket()); PRINT(OrderMagicNumber()); PRINT(OrderComment()); PRINT(OrderTicketOpen()); } }
Result
2018.03.25 00:00:00 instant buy 1.00 EURUSD at 1.23527 sl: 1.23414 tp: 1.23614 (1.23514 / 1.23527) 2018.03.25 00:00:00 deal #2 buy 1.00 EURUSD at 1.23527 done (based on order #2) 2018.03.25 00:00:00 deal performed [#2 buy 1.00 EURUSD at 1.23527] 2018.03.25 00:00:00 order performed buy 1.00 at 1.23527 [#2 buy 1.00 EURUSD at 1.23527] 2018.03.25 00:00:00 (Ticket=OrderSend(_Symbol,OP_BUY,1,Ask,0,Bid-100*_Point,Bid+100*_Point,Hello World!,12345)) = 2 2018.03.25 00:00:00 instant sell 0.30 EURUSD at 1.23514, close #2 (1.23514 / 1.23527) 2018.03.25 00:00:00 deal #3 sell 0.30 EURUSD at 1.23514 done (based on order #3) 2018.03.25 00:00:00 deal performed [#3 sell 0.30 EURUSD at 1.23514] 2018.03.25 00:00:00 order performed sell 0.30 at 1.23514 [#3 sell 0.30 EURUSD at 1.23514] 2018.03.25 00:00:00 OrderClose(OrderTicket(),0.3,OrderClosePrice(),0) = true 2018.03.26 01:04:40 take profit triggered #2 buy 0.70 EURUSD 1.23527 sl: 1.23414 tp: 1.23614 [#4 sell 0.70 EURUSD at 1.23614] 2018.03.26 01:04:40 deal #4 sell 0.70 EURUSD at 1.23614 done (based on order #4) 2018.03.26 01:04:40 deal performed [#4 sell 0.70 EURUSD at 1.23614] 2018.03.26 01:04:40 order performed sell 0.70 at 1.23614 [#4 sell 0.70 EURUSD at 1.23614] final balance 10000046.11 EUR 2018.03.26 23:59:59 #3 2018.03.25 00:00:00 buy 0.30 EURUSD 1.23527 1.23414 1.23614 2018.03.25 00:00:00 1.23514 0.00 0.00 -3.16 Hello World! 12345 2018.03.26 23:59:59 OrderTicket() = 3 2018.03.26 23:59:59 OrderMagicNumber() = 12345 2018.03.26 23:59:59 OrderComment() = Hello World! 2018.03.26 23:59:59 OrderTicketOpen() = 2 2018.03.26 23:59:59 #4 2018.03.25 00:00:00 buy 0.70 EURUSD 1.23527 0.00000 1.23614 2018.03.26 01:04:40 1.23614 0.00 0.00 49.27 tp 1.23614 12345 2018.03.26 23:59:59 OrderTicket() = 4 2018.03.26 23:59:59 OrderMagicNumber() = 12345 2018.03.26 23:59:59 OrderComment() = tp 1.23614 2018.03.26 23:59:59 OrderTicketOpen() = 2
Forum on trading, automated trading systems and testing trading strategies
Carl Schreiber, 2015.11.21 13:46
the broker are free to change the comment. E.g. some replace the comment by [tp] or [sl] if the order has been closed by profit target or stop loss!!
- www.mql5.com
Forum on trading, automated trading systems and testing trading strategies
fxsaber, 2017.04.20 06:20
The latest version is always here.Updated.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2018.12.05 19:43
// Demonstration of how to manually send trade orders to the Visualizer. #include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006 #define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID) #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) bool IsModify() { static long PrevTime = 0; const long NewTime = FileGetInteger(__FILE__, FILE_MODIFY_DATE); const bool Res = (PrevTime != NewTime); if (Res) PrevTime = NewTime; return(Res); } bool CreateFile() { uchar Bytes[]; return(FileSave(__FILE__, Bytes) && IsModify()); } string GetCommand() { uchar Bytes[]; FileLoad(__FILE__, Bytes); return(CharArrayToString(Bytes)); } bool OrdersScan( const int Type ) { for (int i = ::OrdersTotal() - 1; i >= 0; i--) if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type)) return(true); return(false); } bool SendCommand( const string Command, const double Lot = 1, const int Offset = 100 ) { bool Res = false; if (Command == "open buy") Res = (OrderSend(_Symbol, OP_BUY, Lot, Ask, 0, 0, 0) > 0); else if (Command == "open sell") Res = (OrderSend(_Symbol, OP_SELL, Lot, Bid, 0, 0, 0) > 0); else if (Command == "open buylimit") Res = (OrderSend(_Symbol, OP_BUYLIMIT, Lot, Ask - Offset * _Point, 0, 0, 0) > 0); else if (Command == "open selllimit") Res = (OrderSend(_Symbol, OP_SELLLIMIT, Lot, Bid + Offset * _Point, 0, 0, 0) > 0); else if (Command == "close buy") Res = OrdersScan(OP_BUY) && OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); else if (Command == "close sell") Res = OrdersScan(OP_SELL) && OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); else if (Command == "close buylimit") Res = OrdersScan(OP_BUYLIMIT) && OrderDelete(OrderTicket()); else if (Command == "close selllimit") Res = OrdersScan(OP_SELLLIMIT) && OrderDelete(OrderTicket()); return(Res); } bool TesterManual() { static const bool IsVisual = MQLInfoInteger(MQL_VISUAL_MODE) && CreateFile(); return(IsVisual && IsModify() && SendCommand(GetCommand())); } void OnTick() { TesterManual(); }

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
MT4Orders:
Author: fxsaber