890 lines
No EOL
50 KiB
MQL5
890 lines
No EOL
50 KiB
MQL5
// #define VIRTUAL_TESTER // Запуск в виртуальном торговом окружении
|
|
// #define VIRTUAL_LIMITS_TP_SLIPPAGE // Лимитники и TP исполняются по первой цене акцепта - положительные проскальзывания
|
|
// #define VIRTUAL_CLOSEALL_BYEND // Закрывает принудительно все ордера в конце тестирования
|
|
// #define VIRTUAL_ONTESTER_FORMULA ::AccountBalance() // Что возвращать в OnTester в режиме VIRTUAL_TESTER
|
|
|
|
#include "Orders.mqh"
|
|
|
|
#define __VIRTUAL__
|
|
|
|
#ifdef __MQL5__
|
|
#ifndef OP_BUY
|
|
#define OP_BUY ORDER_TYPE_BUY
|
|
#endif // OP_BUY
|
|
|
|
#ifndef OP_SELL
|
|
#define OP_SELL ORDER_TYPE_SELL
|
|
#endif // OP_SELL
|
|
|
|
#ifndef OP_BUYLIMIT
|
|
#define OP_BUYLIMIT ORDER_TYPE_BUY_LIMIT
|
|
#endif // OP_BUYLIMIT
|
|
|
|
#ifndef OP_SELLLIMIT
|
|
#define OP_SELLLIMIT ORDER_TYPE_SELL_LIMIT
|
|
#endif // OP_SELLLIMIT
|
|
|
|
#ifndef OP_BUYSTOP
|
|
#define OP_BUYSTOP ORDER_TYPE_BUY_STOP
|
|
#endif // OP_BUYSTOP
|
|
|
|
#ifndef OP_SELLSTOP
|
|
#define OP_SELLSTOP ORDER_TYPE_SELL_STOP
|
|
#endif // OP_SELLSTOP
|
|
#else // __MQL5__
|
|
#ifndef Bid
|
|
#define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
|
|
#endif // Bid
|
|
|
|
#ifndef Ask
|
|
#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
|
|
#endif // Ask
|
|
#endif // __MQL5__
|
|
|
|
class VIRTUAL_DELETE
|
|
{
|
|
public:
|
|
~VIRTUAL_DELETE( void )
|
|
{
|
|
VIRTUAL::DeleteAll();
|
|
}
|
|
};
|
|
|
|
typedef void (*STRATEGY)( void );
|
|
|
|
int VirtualMemory( const int NewValue = 0, const int Value = 0, const bool SetFlag = false )
|
|
{
|
|
static int PrevValue;
|
|
|
|
if (SetFlag)
|
|
PrevValue = Value;
|
|
|
|
return(SetFlag ? NewValue : PrevValue);
|
|
}
|
|
|
|
template <typename T>
|
|
T VirtualMacrosFunc( const T Value )
|
|
{
|
|
VIRTUAL::SelectByHandle(VirtualMemory());
|
|
|
|
return(Value);
|
|
}
|
|
|
|
#define _V(A, B) VirtualMacrosFunc(VIRTUAL::SelectByHandle(VirtualMemory((A), VIRTUAL::GetHandle(), true)) ? (B) : NULL)
|
|
|
|
class VIRTUAL
|
|
{
|
|
private:
|
|
static ORDERS* Orders[];
|
|
static ORDERS* SelectOrders;
|
|
static int CountHandles;
|
|
|
|
static const VIRTUAL_DELETE VirtualDelete;
|
|
|
|
public:
|
|
static int Create( const double dBalance = 0, datetime StartTime = 0, const bool bNetting = false )
|
|
{
|
|
// static int CountHandles = 1; // Нельзя, т.к. будет инициализация после всех глобальных переменных.
|
|
|
|
const int Pos = ::ArrayResize(VIRTUAL::Orders, VIRTUAL::Total() + 1) - 1;
|
|
|
|
if (!StartTime)
|
|
StartTime = ::MQLInfoInteger(MQL_TESTER) ? ::TimeCurrent() : (datetime)::SymbolInfoInteger(_Symbol, SYMBOL_TIME);
|
|
|
|
if ((VIRTUAL::Orders[Pos] = new ORDERS(VIRTUAL::CountHandles, StartTime)) != NULL)
|
|
{
|
|
#ifdef VIRTUAL_TESTER
|
|
MqlTick Tick = {0};
|
|
|
|
::SymbolInfoTick(_Symbol, Tick); // Даже если получить тик не удалось.
|
|
|
|
if (::MQLInfoInteger(MQL_TESTER)) // Без этого на реале можно нарваться на ситуацию, когда виртуальный тик имеет время больше реального.
|
|
{
|
|
Tick.time = ::TimeCurrent(); // Для получения корректного TimeCurrent() в OnInit и ранее.
|
|
Tick.time_msc = (long)Tick.time * 1000;
|
|
}
|
|
|
|
VIRTUAL::Orders[Pos].NewTick(Tick); // Для полноценной работы в виртуале в OnInit и ранее.
|
|
#endif // VIRTUAL_TESTER
|
|
|
|
VIRTUAL::Orders[Pos].Set(dBalance, bNetting);
|
|
|
|
VIRTUAL::CountHandles++;
|
|
}
|
|
|
|
return(VIRTUAL::Orders[Pos] ? VIRTUAL::Orders[Pos].Handle : -1);
|
|
}
|
|
|
|
static bool Delete( void )
|
|
{
|
|
bool Res = (VIRTUAL::SelectOrders != NULL);
|
|
|
|
if (Res)
|
|
{
|
|
const int Size = VIRTUAL::Total();
|
|
|
|
for (int i = 0; i < Size; i++)
|
|
if (Res = (VIRTUAL::Orders[i] == VIRTUAL::SelectOrders))
|
|
{
|
|
for (int j = i; j < Size - 1; j++)
|
|
VIRTUAL::Orders[i] = VIRTUAL::Orders[i + 1];
|
|
|
|
::ArrayResize(VIRTUAL::Orders, Size - 1);
|
|
|
|
delete VIRTUAL::SelectOrders;
|
|
VIRTUAL::SelectOrders = NULL;
|
|
}
|
|
}
|
|
|
|
return(Res);
|
|
}
|
|
|
|
static void DeleteAll( void )
|
|
{
|
|
for (int i = VIRTUAL::Total() - 1; i >= 0; i--)
|
|
delete VIRTUAL::Orders[i];
|
|
|
|
return;
|
|
}
|
|
|
|
static void NewTick( const MqlTick &Tick )
|
|
{
|
|
if (VIRTUAL::SelectOrders)
|
|
VIRTUAL::SelectOrders.NewTick(Tick);
|
|
|
|
return;
|
|
}
|
|
|
|
static void NewTick( const MqlTick &Ticks[], const STRATEGY Strategy = NULL )
|
|
{
|
|
const int Size = ::ArraySize(Ticks);
|
|
|
|
if (Strategy)
|
|
for (int i = 0; (i < Size) && (!::IsStopped()); i++)
|
|
{
|
|
VIRTUAL::NewTick(Ticks[i]);
|
|
|
|
Strategy();
|
|
//Comment(ToString(5));
|
|
}
|
|
else
|
|
for (int i = 0; i < Size; i++)
|
|
VIRTUAL::NewTick(Ticks[i]);
|
|
|
|
return;
|
|
}
|
|
|
|
static void NewTick( void )
|
|
{
|
|
static MqlTick Tick = {0};
|
|
|
|
if (VIRTUAL::SelectOrders && ::SymbolInfoTick(_Symbol, Tick))
|
|
VIRTUAL::NewTick(Tick);
|
|
|
|
return;
|
|
}
|
|
|
|
static int Total( void )
|
|
{
|
|
return(::ArraySize(VIRTUAL::Orders));
|
|
}
|
|
|
|
static int GetHandle( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.Handle : 0);
|
|
}
|
|
|
|
static bool IsNetting( void )
|
|
{
|
|
static const bool RealNetting =
|
|
#ifdef __MQL5__
|
|
!((ENUM_ACCOUNT_MARGIN_MODE)::AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
|
|
#else // __MQL5__
|
|
false
|
|
#endif //__MQL5__
|
|
;
|
|
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.IsNetting() : RealNetting);
|
|
}
|
|
|
|
static string ToString( const int LastHistoryOrders = 0, const bool Pending = true )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.ToString(LastHistoryOrders, Pending) : NULL);
|
|
}
|
|
|
|
static bool SelectByIndex( const int Index = 0 )
|
|
{
|
|
const bool Res = (Index >= 0) && (Index <= VIRTUAL::Total());
|
|
|
|
if (Res)
|
|
VIRTUAL::SelectOrders = Index ? VIRTUAL::Orders[Index - 1] : NULL;
|
|
|
|
return(Res);
|
|
}
|
|
|
|
static bool SelectByHandle( const int Handle = 0 )
|
|
{
|
|
bool Res = (Handle >= 0);
|
|
|
|
if (Res && (Handle != VIRTUAL::GetHandle()))
|
|
{
|
|
if (Handle)
|
|
{
|
|
Res = false;
|
|
|
|
const int Size = VIRTUAL::Total();
|
|
|
|
for (int i = 0; i < Size; i++)
|
|
if (Res = (VIRTUAL::Orders[i].Handle == Handle))
|
|
{
|
|
VIRTUAL::SelectOrders = VIRTUAL::Orders[i];
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
VIRTUAL::SelectOrders = NULL;
|
|
}
|
|
|
|
return(Res);
|
|
}
|
|
|
|
static void Stop( void )
|
|
{
|
|
if (VIRTUAL::SelectOrders)
|
|
VIRTUAL::SelectOrders.Stop();
|
|
|
|
return;
|
|
}
|
|
|
|
static datetime VirtualTimeCurrent( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.TimeCurrent() : ::TimeCurrent());
|
|
}
|
|
|
|
static datetime VirtualTimeCurrent( MqlDateTime &StructTime )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.TimeCurrent(StructTime) : ::TimeCurrent(StructTime));
|
|
}
|
|
|
|
static bool VirtualSymbolInfoTick( const string Symb, MqlTick &Tick )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.SymbolInfoTick(Symb, Tick) : ::SymbolInfoTick(Symb, Tick));
|
|
}
|
|
|
|
static double VirtualSymbolInfoDouble( const string Symb, const ENUM_SYMBOL_INFO_DOUBLE Property )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.SymbolInfoDouble(Symb, Property) : ::SymbolInfoDouble(Symb, Property));
|
|
}
|
|
|
|
static bool VirtualSymbolInfoDouble( const string Symb, const ENUM_SYMBOL_INFO_DOUBLE Property, double &Value )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.SymbolInfoDouble(Symb, Property, Value) : ::SymbolInfoDouble(Symb, Property, Value));
|
|
}
|
|
|
|
static long VirtualSymbolInfoInteger( const string Symb, const ENUM_SYMBOL_INFO_INTEGER Property )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.SymbolInfoInteger(Symb, Property) : ::SymbolInfoInteger(Symb, Property));
|
|
}
|
|
|
|
static long VirtualSymbolInfoInteger( const string Symb, const ENUM_SYMBOL_INFO_INTEGER Property, long &Value )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.SymbolInfoInteger(Symb, Property, Value) : ::SymbolInfoInteger(Symb, Property, Value));
|
|
}
|
|
|
|
static long VirtualAccountInfoInteger( const ENUM_ACCOUNT_INFO_INTEGER Property )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountInfoInteger(Property) : ::AccountInfoInteger(Property));
|
|
}
|
|
|
|
static double VirtualAccountInfoDouble( const ENUM_ACCOUNT_INFO_DOUBLE Property )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountInfoDouble(Property) : ::AccountInfoDouble(Property));
|
|
}
|
|
|
|
static double VirtualAccountBalance( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountBalance() : ::AccountInfoDouble(ACCOUNT_BALANCE));
|
|
}
|
|
|
|
static double VirtualAccountEquity( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountEquity() : ::AccountInfoDouble(ACCOUNT_EQUITY));
|
|
}
|
|
|
|
static double VirtualAccountProfit( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountProfit() : ::AccountInfoDouble(ACCOUNT_PROFIT));
|
|
}
|
|
|
|
static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSelect(Index, Select, Pool) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderSelect(Index, Select, Pool)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderSelect(Index, Select, Pool)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static bool VirtualOrderClose( const TICKET_TYPE Ticket, const double dLots, const double Price, const int SlipPage, const color Arrow_Color = clrNONE )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderClose(Ticket, dLots, Price) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderClose(Ticket, dLots, Price, SlipPage, Arrow_Color)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderClose(Ticket, dLots, Price, SlipPage, Arrow_Color)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static bool VirtualOrderModify( const TICKET_TYPE Ticket, const double Price, const double SL, const double TP, const datetime Expiration, const color Arrow_Color = clrNONE )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderModify(Ticket, Price, SL, TP, Expiration) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderModify(Ticket, Price, SL, TP, Expiration, Arrow_Color)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderModify(Ticket, Price, SL, TP, Expiration, Arrow_Color)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static bool VirtualOrderCloseBy( const TICKET_TYPE Ticket, const TICKET_TYPE Opposite, const color Arrow_Color = clrNONE )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderCloseBy(Ticket, Opposite) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderCloseBy(Ticket, Opposite, Arrow_Color)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderCloseBy(Ticket, Opposite, Arrow_Color)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static bool VirtualOrderDelete( const TICKET_TYPE Ticket, const color Arrow_Color = clrNONE )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderDelete(Ticket) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderDelete(Ticket, Arrow_Color)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderDelete(Ticket, Arrow_Color)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static TICKET_TYPE VirtualOrderSend( const string Symb, const int Type, const double dVolume, const double Price, const int SlipPage, const double SL, const double TP,
|
|
const string comment = NULL, const MAGIC_TYPE magic = 0, const datetime dExpiration = 0, color arrow_color = clrNONE )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP, comment, magic, dExpiration) :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP, comment, magic, dExpiration, arrow_color)
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP, comment, magic, dExpiration, arrow_color)
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static int VirtualOrdersTotal( void )
|
|
{
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrdersTotal2() :
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrdersTotal()
|
|
#else // __MT4ORDERS__
|
|
false
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrdersTotal()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
static void VirtualOrderPrint( void )
|
|
{
|
|
if (VIRTUAL::SelectOrders)
|
|
VIRTUAL::SelectOrders.OrderPrint();
|
|
else
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderPrint();
|
|
#else // __MT4ORDERS__
|
|
::Print("");
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderPrint();
|
|
#endif // __MQL5__
|
|
|
|
return;
|
|
}
|
|
|
|
#define ORDERFUNCTION(NAME,T) \
|
|
static T VirtualOrder##NAME( void ) \
|
|
{ \
|
|
return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.Order##NAME() :
|
|
|
|
ORDERFUNCTION(sHistoryTotal, int)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrdersHistoryTotal()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrdersHistoryTotal()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Ticket, TICKET_TYPE)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderTicket()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderTicket()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Type, int)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderType()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderType()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Lots, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderLots()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderLots()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(OpenPrice, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderOpenPrice()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderOpenPrice()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(OpenTime, datetime)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderOpenTime()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderOpenTime()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(StopLoss, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderStopLoss()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderStopLoss()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(TakeProfit, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderTakeProfit()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderTakeProfit()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(ClosePrice, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderClosePrice()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderClosePrice()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(CloseTime, datetime)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderCloseTime()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderCloseTime()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Expiration, datetime)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderExpiration()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderExpiration()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(MagicNumber, MAGIC_TYPE)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderMagicNumber()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderMagicNumber()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Profit, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderProfit()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderProfit()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Commission, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderCommission()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderCommission()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Swap, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderSwap()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderSwap()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Symbol, string)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderSymbol()
|
|
#else // __MT4ORDERS__
|
|
NULL
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderSymbol()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(Comment, string)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderComment()
|
|
#else // __MT4ORDERS__
|
|
NULL
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderComment()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(OpenTimeMsc, long)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderOpenTimeMsc()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
(long)::OrderOpenTime() * 1000
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(CloseTimeMsc, long)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderCloseTimeMsc()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
(long)::OrderCloseTime() * 1000
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(OpenPriceRequest, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderOpenPriceRequest()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderOpenPrice()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(ClosePriceRequest, double)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderClosePriceRequest()
|
|
#else // __MT4ORDERS__
|
|
0
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
::OrderClosePrice()
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(OpenReason, ENUM_DEAL_REASON)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderOpenReason()
|
|
#else // __MT4ORDERS__
|
|
DEAL_REASON_CLIENT
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
DEAL_REASON_CLIENT
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
ORDERFUNCTION(CloseReason, ENUM_DEAL_REASON)
|
|
#ifdef __MQL5__
|
|
#ifdef __MT4ORDERS__
|
|
::OrderCloseReason()
|
|
#else // __MT4ORDERS__
|
|
DEAL_REASON_CLIENT
|
|
#endif // __MT4ORDERS__
|
|
#else // __MQL5__
|
|
DEAL_REASON_CLIENT
|
|
#endif // __MQL5__
|
|
);
|
|
}
|
|
|
|
#undef ORDERFUNCTION
|
|
|
|
static int Tester( const MqlTick &Ticks[], const STRATEGY Strategy, const double Balance = 0, const bool Stop = true, const bool bNetting = false )
|
|
{
|
|
const int Handle = VIRTUAL::GetHandle();
|
|
const bool Res = ::ArraySize(Ticks) && VIRTUAL::SelectByHandle(VIRTUAL::Create(Balance, Ticks[0].time - Ticks[0].time % (24 * 3600), bNetting));
|
|
|
|
if (Res)
|
|
{
|
|
VIRTUAL::NewTick(Ticks, Strategy);
|
|
|
|
if (Stop)
|
|
VIRTUAL::Stop();
|
|
}
|
|
|
|
return(Res ? Handle : -1);;
|
|
}
|
|
};
|
|
////+------------------------------------------------------------------+
|
|
////| INFO: Подключенине DoEasy |
|
|
////+------------------------------------------------------------------+
|
|
//#define order am_order
|
|
//#define list am_list
|
|
//#include <Artmedia70\DoEasy\Engine.mqh>
|
|
//#undef order
|
|
//#undef list
|
|
//
|
|
////+------------------------------------------------------------------+
|
|
|
|
static ORDERS* VIRTUAL::Orders[];
|
|
static ORDERS* VIRTUAL::SelectOrders = NULL;
|
|
static int VIRTUAL::CountHandles = 1;
|
|
|
|
static const VIRTUAL_DELETE VIRTUAL::VirtualDelete;
|
|
|
|
#define AccountBalance VIRTUAL::VirtualAccountBalance
|
|
#define AccountEquity VIRTUAL::VirtualAccountEquity
|
|
#define AccountProfit VIRTUAL::VirtualAccountProfit
|
|
|
|
#ifdef OrdersTotal
|
|
#undef OrdersTotal
|
|
#endif // OrdersTotal
|
|
|
|
#define OrderSelect VIRTUAL::VirtualOrderSelect
|
|
#define OrderClose VIRTUAL::VirtualOrderClose
|
|
#define OrderModify VIRTUAL::VirtualOrderModify
|
|
#define OrderCloseBy VIRTUAL::VirtualOrderCloseBy
|
|
#define OrderDelete VIRTUAL::VirtualOrderDelete
|
|
#define OrdersTotal VIRTUAL::VirtualOrdersTotal
|
|
#define OrderSend VIRTUAL::VirtualOrderSend
|
|
#define OrderPrint VIRTUAL::VirtualOrderPrint
|
|
|
|
#define OrdersHistoryTotal VIRTUAL::VirtualOrdersHistoryTotal
|
|
#define OrderTicket VIRTUAL::VirtualOrderTicket
|
|
#define OrderType VIRTUAL::VirtualOrderType
|
|
#define OrderLots VIRTUAL::VirtualOrderLots
|
|
#define OrderOpenPrice VIRTUAL::VirtualOrderOpenPrice
|
|
#define OrderOpenTime VIRTUAL::VirtualOrderOpenTime
|
|
#define OrderStopLoss VIRTUAL::VirtualOrderStopLoss
|
|
#define OrderTakeProfit VIRTUAL::VirtualOrderTakeProfit
|
|
#define OrderClosePrice VIRTUAL::VirtualOrderClosePrice
|
|
#define OrderCloseTime VIRTUAL::VirtualOrderCloseTime
|
|
#define OrderExpiration VIRTUAL::VirtualOrderExpiration
|
|
#define OrderMagicNumber VIRTUAL::VirtualOrderMagicNumber
|
|
#define OrderProfit VIRTUAL::VirtualOrderProfit
|
|
#define OrderCommission VIRTUAL::VirtualOrderCommission
|
|
#define OrderSwap VIRTUAL::VirtualOrderSwap
|
|
#define OrderSymbol VIRTUAL::VirtualOrderSymbol
|
|
#define OrderComment VIRTUAL::VirtualOrderComment
|
|
#define OrderOpenTimeMsc VIRTUAL::VirtualOrderOpenTimeMsc
|
|
#define OrderCloseTimeMsc VIRTUAL::VirtualOrderCloseTimeMsc
|
|
#define OrderOpenPriceRequest VIRTUAL::VirtualOrderOpenPriceRequest
|
|
#define OrderClosePriceRequest VIRTUAL::VirtualOrderClosePriceRequest
|
|
|
|
#define TimeCurrent VIRTUAL::VirtualTimeCurrent
|
|
|
|
#define SymbolInfoTick VIRTUAL::VirtualSymbolInfoTick
|
|
#define SymbolInfoInteger VIRTUAL::VirtualSymbolInfoInteger
|
|
#define SymbolInfoDouble VIRTUAL::VirtualSymbolInfoDouble
|
|
|
|
#define AccountInfoInteger VIRTUAL::VirtualAccountInfoInteger
|
|
#define AccountInfoDouble VIRTUAL::VirtualAccountInfoDouble
|
|
|
|
#ifdef VIRTUAL_TESTER
|
|
|
|
#include "Sync.mqh"
|
|
|
|
sinput bool VirtualTester = false;
|
|
sinput bool ReverseDeals = false;
|
|
|
|
const int VirtualHandle = VirtualTester ? VIRTUAL::Create() : 0;
|
|
const int ReverseHandle = ReverseDeals ? VIRTUAL::Create() : 0;
|
|
|
|
const bool VirtualInit = VIRTUAL::SelectByHandle(ReverseDeals ? ReverseHandle : VirtualHandle);
|
|
|
|
void OnTick( void )
|
|
{
|
|
VIRTUAL::NewTick();
|
|
|
|
if (ReverseHandle)
|
|
{
|
|
VIRTUAL::SelectByHandle(VirtualHandle);
|
|
VIRTUAL::NewTick();
|
|
// Comment(VIRTUAL::ToString());
|
|
|
|
VIRTUAL::SelectByHandle(ReverseHandle);
|
|
SYNC::Positions<ISTIME>(VirtualHandle, true);
|
|
}
|
|
|
|
::OldOnTick2();
|
|
|
|
if (ReverseHandle)
|
|
SYNC::Positions<ISTIME>(VirtualHandle, true);
|
|
|
|
// Comment(VIRTUAL::ToString());
|
|
|
|
return;
|
|
}
|
|
#ifndef BESTINTERVAL_ONTESTER
|
|
|
|
double OnTester()
|
|
{
|
|
VIRTUAL::SelectByHandle(VirtualHandle);
|
|
|
|
#ifdef VIRTUAL_CLOSEALL_BYEND
|
|
VIRTUAL::Stop();
|
|
#endif // VIRTUAL_CLOSEALL_BYEND
|
|
|
|
#ifdef VIRTUAL_ONTESTER_FORMULA
|
|
return(VIRTUAL_ONTESTER_FORMULA);
|
|
#else // VIRTUAL_ONTESTER_FORMULA
|
|
//return(::AccountEquity());
|
|
return ::OldOnTester2();
|
|
#endif // VIRTUAL_ONTESTER_FORMULA
|
|
}
|
|
|
|
#define OnTester OldOnTester2
|
|
|
|
#endif // BESTINTERVAL_ONTESTER
|
|
|
|
#define OnTick OldOnTick2 // TesterBenchmark.mqh ?
|
|
|
|
#endif // VIRTUAL_TESTER |