217 lines
No EOL
5.3 KiB
MQL5
217 lines
No EOL
5.3 KiB
MQL5
#include "Virtual.mqh"
|
|
|
|
struct MT4ORDER
|
|
{
|
|
datetime OpenTime;
|
|
double OpenPrice;
|
|
double TP;
|
|
double Lots;
|
|
|
|
MT4ORDER( void ) : Lots(0), TP(0)
|
|
{
|
|
}
|
|
|
|
void Set( void )
|
|
{
|
|
this.OpenTime = OrderOpenTime();
|
|
this.OpenPrice = OrderOpenPrice();
|
|
this.TP = OrderTakeProfit();
|
|
this.Lots = OrderLots();
|
|
|
|
return;
|
|
}
|
|
|
|
bool operator !=( const MT4ORDER &MT4Order ) const
|
|
{
|
|
return((this.OpenPrice != MT4Order.OpenPrice) || (this.TP != MT4Order.TP));
|
|
}
|
|
};
|
|
|
|
class ISTIME
|
|
{
|
|
public:
|
|
static bool IsTime( const datetime time )
|
|
{
|
|
return(true);
|
|
}
|
|
};
|
|
|
|
class SYNC
|
|
{
|
|
private:
|
|
template <typename T>
|
|
static double GetNettingPosition( const string &Symb )
|
|
{
|
|
double Res = 0;
|
|
|
|
for (int i = OrdersTotal() - 1; i >= 0; i--)
|
|
if (OrderSelect(i, SELECT_BY_POS) && T::IsTime(OrderOpenTime())/* && (OrderSymbol() == Symb)*/)
|
|
{
|
|
if (OrderType() == OP_BUY)
|
|
Res += OrderLots();
|
|
else if (OrderType() == OP_SELL)
|
|
Res -= OrderLots();
|
|
}
|
|
|
|
return(Res);
|
|
}
|
|
|
|
static int OrderScan( const int Type )
|
|
{
|
|
int Res = -1;
|
|
|
|
for (int i = OrdersTotal() - 1; i >= 0; i--)
|
|
if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type)/* && (OrderSymbol() == _Symbol)*/)
|
|
{
|
|
Res = Type;
|
|
|
|
break;
|
|
}
|
|
|
|
return(Res);
|
|
}
|
|
|
|
static void CloseBy( void )
|
|
{
|
|
if (SYNC::OrderScan(OP_SELL) == OP_SELL)
|
|
{
|
|
const TICKET_TYPE SellTicket = OrderTicket();
|
|
|
|
if (SYNC::OrderScan(OP_BUY) == OP_BUY)
|
|
OrderCloseBy(OrderTicket(), SellTicket);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void NewOrderSend( const string &Symb, const int &Type, double dLots,
|
|
const double &Price, const int Slip, const double SL, const double TP)
|
|
{
|
|
while (dLots && (SYNC::OrderScan(1 - Type) == 1 - Type))
|
|
{
|
|
const double SelectLots = OrderLots();
|
|
const bool Flag = (SelectLots >= dLots);
|
|
|
|
const double CloseLots = Flag ? dLots : SelectLots;
|
|
|
|
if (OrderClose(OrderTicket(), CloseLots, Price, Slip))
|
|
dLots = Flag ? 0 : ::NormalizeDouble(dLots - CloseLots, 2);
|
|
}
|
|
|
|
if (dLots)
|
|
OrderSend(Symb, Type, dLots, Price, Slip, SL, TP);
|
|
|
|
return;
|
|
}
|
|
|
|
public:
|
|
template <typename T>
|
|
static void Positions( const int Handle = 0, const bool Reverse = false )
|
|
{
|
|
const int PrevHandle = VIRTUAL::GetHandle();
|
|
|
|
if (Handle != PrevHandle)
|
|
{
|
|
const double PrevLots = SYNC::GetNettingPosition<T>(_Symbol);
|
|
|
|
if (VIRTUAL::SelectByHandle(Handle))
|
|
{
|
|
const double NewLots = SYNC::GetNettingPosition<ISTIME>(_Symbol);
|
|
const double AddLots = ::NormalizeDouble(PrevLots - (Reverse ? -NewLots : NewLots), 2);
|
|
|
|
if (AddLots)
|
|
{
|
|
const int TypeBuy = Reverse ? OP_SELL : OP_BUY;
|
|
const int Type = (AddLots > 0) ? TypeBuy : 1 - TypeBuy;
|
|
const double Price = ::SymbolInfoDouble(_Symbol, Type ? SYMBOL_BID : SYMBOL_ASK);
|
|
|
|
SYNC::NewOrderSend(_Symbol, Type, ::MathAbs(AddLots), Price, 100, 0, 0);
|
|
|
|
/* OrderSend(_Symbol, Type, ::MathAbs(AddLots), Price, 100, 0, 0);
|
|
|
|
// https://www.mql5.com/ru/forum/283611/page3#comment_9038400
|
|
if (!VIRTUAL::IsNetting())
|
|
SYNC::CloseBy(); */
|
|
}
|
|
|
|
VIRTUAL::SelectByHandle(PrevHandle);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void NewOrderSend( const int Type, const MT4ORDER &NewLimit )
|
|
{
|
|
MT4ORDER CurrentLimit;
|
|
|
|
if ((SYNC::OrderScan(Type) == Type))
|
|
CurrentLimit.Set();
|
|
|
|
if (CurrentLimit.Lots != NewLimit.Lots)
|
|
{
|
|
if (CurrentLimit.Lots)
|
|
OrderDelete(OrderTicket());
|
|
|
|
if (NewLimit.Lots)
|
|
OrderSend(_Symbol, Type, NewLimit.Lots, NewLimit.OpenPrice, 100, 0, NewLimit.TP);
|
|
}
|
|
else if (CurrentLimit.Lots && (CurrentLimit != NewLimit))
|
|
OrderModify(OrderTicket(), NewLimit.OpenPrice, 0, NewLimit.TP, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
template <typename T>
|
|
static void Limits( datetime CurrentTime, const int Handle = 0 )
|
|
{
|
|
static double PrevMarketLots = 0;
|
|
static double PrevLimitLots = 0;
|
|
|
|
const int PrevHandle = VIRTUAL::GetHandle();
|
|
|
|
if (Handle != PrevHandle)
|
|
{
|
|
MT4ORDER BuyLimit;
|
|
MT4ORDER SellLimit;
|
|
MT4ORDER Buy;
|
|
MT4ORDER Sell;
|
|
|
|
if ((SYNC::OrderScan(OP_BUYLIMIT) == OP_BUYLIMIT))
|
|
BuyLimit.Set();
|
|
|
|
if (SYNC::OrderScan(OP_SELLLIMIT) == OP_SELLLIMIT)
|
|
SellLimit.Set();
|
|
|
|
if ((SYNC::OrderScan(OP_BUY) == OP_BUY))
|
|
Buy.Set();
|
|
else if (SYNC::OrderScan(OP_SELL) == OP_SELL)
|
|
Sell.Set();
|
|
|
|
if (BuyLimit.Lots && !T::IsTime(CurrentTime))
|
|
BuyLimit.Lots = Sell.Lots;
|
|
|
|
if (BuyLimit.Lots && !T::IsTime(Sell.OpenTime))
|
|
BuyLimit.Lots -= Sell.Lots;
|
|
|
|
if (SellLimit.Lots && !T::IsTime(CurrentTime))
|
|
SellLimit.Lots = Buy.Lots;
|
|
|
|
if (SellLimit.Lots && !T::IsTime(Buy.OpenTime))
|
|
SellLimit.Lots -= Buy.Lots;
|
|
|
|
BuyLimit.Lots = ::NormalizeDouble(BuyLimit.Lots, 2);
|
|
SellLimit.Lots = ::NormalizeDouble(SellLimit.Lots, 2);
|
|
|
|
if (VIRTUAL::SelectByHandle(Handle))
|
|
{
|
|
SYNC::NewOrderSend(OP_BUYLIMIT, BuyLimit);
|
|
SYNC::NewOrderSend(OP_SELLLIMIT, SellLimit);
|
|
}
|
|
|
|
VIRTUAL::SelectByHandle(PrevHandle);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}; |