new version update
This commit is contained in:
@@ -0,0 +1,890 @@
|
||||
//
|
||||
// Copyright 2018, Artur Zas
|
||||
// https://www.az-invest.eu
|
||||
// https://www.mql5.com/en/users/arturz
|
||||
//
|
||||
|
||||
#ifdef __MQL5__
|
||||
//--- class for performing trade operations
|
||||
#include <Trade\Trade.mqh>
|
||||
CTrade trade;
|
||||
//--- class for working with orders
|
||||
#include <Trade\OrderInfo.mqh>
|
||||
COrderInfo orderinfo;
|
||||
//--- class for working with positions
|
||||
#include <Trade\PositionInfo.mqh>
|
||||
CPositionInfo positioninfo;
|
||||
|
||||
//--- introduce the predefined variables from MQL4 for versatility of the code
|
||||
#define Ask SymbolInfoDouble(_symbol,SYMBOL_ASK)
|
||||
#define Bid SymbolInfoDouble(_symbol,SYMBOL_BID)
|
||||
|
||||
#endif
|
||||
|
||||
#define _point SymbolInfoDouble(_symbol,SYMBOL_POINT)
|
||||
|
||||
//--- redefine the order types from MQL5 to MQL4 for use in common code
|
||||
#ifdef __MQL4__
|
||||
#define ORDER_TYPE_BUY OP_BUY
|
||||
#define ORDER_TYPE_SELL OP_SELL
|
||||
#define ORDER_TYPE_BUY_LIMIT OP_BUYLIMIT
|
||||
#define ORDER_TYPE_SELL_LIMIT OP_SELLLIMIT
|
||||
#define ORDER_TYPE_BUY_STOP OP_BUYSTOP
|
||||
#define ORDER_TYPE_SELL_STOP OP_SELLSTOP
|
||||
#endif
|
||||
|
||||
enum ENUM_TC_ERROR
|
||||
{
|
||||
tcErrorNONE = 0,
|
||||
tcErrorNotEnoughMoney,
|
||||
tcErrorInvalidStops,
|
||||
tcErrorOrderLimitReached,
|
||||
tcErrorFreezeLevel,
|
||||
tcErrorNothingChanged,
|
||||
tcErrorInvalidPrice,
|
||||
};
|
||||
|
||||
class CTradingChecks
|
||||
{
|
||||
private:
|
||||
|
||||
ENUM_TC_ERROR _err;
|
||||
|
||||
public:
|
||||
|
||||
CTradingChecks();
|
||||
~CTradingChecks();
|
||||
|
||||
string GetCheckErrorToString();
|
||||
|
||||
bool OkToOpenOrder(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice, double sl, double tp);
|
||||
bool OkToModifyOrder(string _symbol,ulong ticket,double price, double sl, double tp);
|
||||
#ifdef __MQL5__
|
||||
bool OkToOpenPosition(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice, double sl, double tp);
|
||||
bool OkToModifyPosition(string _symbol,ulong ticket, double sl, double tp);
|
||||
#endif
|
||||
};
|
||||
|
||||
CTradingChecks::CTradingChecks(void)
|
||||
{
|
||||
}
|
||||
|
||||
CTradingChecks::~CTradingChecks(void)
|
||||
{
|
||||
}
|
||||
|
||||
string CTradingChecks::GetCheckErrorToString(void)
|
||||
{
|
||||
switch(_err)
|
||||
{
|
||||
case tcErrorNONE:
|
||||
return "No Error";
|
||||
case tcErrorNotEnoughMoney:
|
||||
return "Not enough money (check previous message in Experts log)";
|
||||
case tcErrorInvalidStops:
|
||||
return "Invalid stops (check previous message in Experts log)";
|
||||
case tcErrorOrderLimitReached:
|
||||
return "Maximum order limit reached";
|
||||
case tcErrorFreezeLevel:
|
||||
return "Freeze level (check previous message in Experts log)";
|
||||
case tcErrorNothingChanged:
|
||||
return "Nothing to change";
|
||||
case tcErrorInvalidPrice:
|
||||
return "Invalid entry price for this order type";
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool CTradingChecks::OkToOpenOrder(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice,double sl, double tp)
|
||||
{
|
||||
if(!IsNewPendingOrderAllowed())
|
||||
{
|
||||
_err = tcErrorOrderLimitReached;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CheckStopLoss_Takeprofit(_symbol,type,entryPrice,sl,tp))
|
||||
{
|
||||
_err = tcErrorInvalidStops;
|
||||
return false;
|
||||
}
|
||||
|
||||
_err = tcErrorNONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __MQL5__
|
||||
bool CTradingChecks::OkToOpenPosition(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice,double sl, double tp)
|
||||
{
|
||||
#ifdef __MQL5__
|
||||
if(!CheckMoneyForTrade(_symbol,lots,type))
|
||||
{
|
||||
_err = tcErrorNotEnoughMoney;
|
||||
return false;
|
||||
}
|
||||
// if(NewOrderAllowedVolume(_symbol) < lots)
|
||||
// return false;
|
||||
#else
|
||||
if(!CheckMoneyForTrade(_symbol,lots,(int)type))
|
||||
{
|
||||
_err = tcErrorNotEnoughMoney;
|
||||
return false;
|
||||
}
|
||||
if(!IsNewPendingOrderAllowed())
|
||||
{
|
||||
_err = tcErrorOrderLimitReached;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!CheckStopLoss_Takeprofit(_symbol,type,entryPrice,sl,tp))
|
||||
{
|
||||
_err = tcErrorInvalidStops;
|
||||
return false;
|
||||
}
|
||||
|
||||
_err = tcErrorNONE;
|
||||
return true;
|
||||
}
|
||||
#endif;
|
||||
|
||||
bool CTradingChecks::OkToModifyOrder(string _symbol, ulong ticket,double price, double sl, double tp)
|
||||
{
|
||||
#ifdef __MQL5__
|
||||
if(!OrderModifyCheck(ticket,price,sl,tp))
|
||||
{
|
||||
_err = tcErrorNothingChanged;
|
||||
return false;
|
||||
}
|
||||
if(!CheckOrderForFREEZE_LEVEL(_symbol,ticket))
|
||||
{
|
||||
_err = tcErrorFreezeLevel;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if(!OrderModifyCheck((int)ticket,price,sl,tp))
|
||||
{
|
||||
_err = tcErrorNothingChanged;
|
||||
return false;
|
||||
}
|
||||
if(!CheckOrderForFREEZE_LEVEL(_symbol,(int)ticket))
|
||||
{
|
||||
_err = tcErrorFreezeLevel;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!CheckPendingOrderEntryChange(_symbol,ticket,price))
|
||||
{
|
||||
_err = tcErrorInvalidPrice;
|
||||
return false;
|
||||
}
|
||||
|
||||
_err = tcErrorNONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __MQL5__
|
||||
bool CTradingChecks::OkToModifyPosition(string _symbol, ulong ticket,double sl,double tp)
|
||||
{
|
||||
if(!PositionModifyCheck(ticket,sl,tp))
|
||||
{
|
||||
_err = tcErrorNothingChanged;
|
||||
return false;
|
||||
}
|
||||
if(!CheckPositionForFREEZE_LEVEL(_symbol,ticket))
|
||||
{
|
||||
_err = tcErrorFreezeLevel;
|
||||
return false;
|
||||
}
|
||||
|
||||
_err = tcErrorNONE;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Helper functions from https://www.mql5.com/en/articles/2555
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __MQL5__
|
||||
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
|
||||
{
|
||||
//--- Getting the opening price
|
||||
MqlTick mqltick;
|
||||
SymbolInfoTick(symb,mqltick);
|
||||
double price=mqltick.ask;
|
||||
if(type==ORDER_TYPE_SELL)
|
||||
price=mqltick.bid;
|
||||
//--- values of the required and free margin
|
||||
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
|
||||
//--- call of the checking function
|
||||
if(!OrderCalcMargin(type,symb,lots,price,margin))
|
||||
{
|
||||
//--- something went wrong, report and return false
|
||||
Print("Error in ",__FUNCTION__," code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
//--- if there are insufficient funds to perform the operation
|
||||
if(margin>free_margin)
|
||||
{
|
||||
//--- report the error and return false
|
||||
Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
|
||||
Print("Required margin:"+DoubleToString(margin,2)+"; free margin:"+DoubleToString(free_margin,2));
|
||||
return(false);
|
||||
}
|
||||
//--- checking successful
|
||||
return(true);
|
||||
}
|
||||
#else
|
||||
bool CheckMoneyForTrade(string symb, double lots,int type)
|
||||
{
|
||||
double free_margin=AccountFreeMarginCheck(symb,type, lots);
|
||||
//-- if there is not enough money
|
||||
if(free_margin<0)
|
||||
{
|
||||
string oper=(type==OP_BUY)? "Buy":"Sell";
|
||||
Print("Not enough money for ", oper," ",lots, " ", symb, " Error code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
//--- checking successful
|
||||
return(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if another order can be placed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsNewPendingOrderAllowed()
|
||||
{
|
||||
//--- get the number of pending orders allowed on the account
|
||||
int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);
|
||||
|
||||
//--- if there is no limitation, return true; you can send an order
|
||||
if(max_allowed_orders==0) return(true);
|
||||
|
||||
//--- if we passed to this line, then there is a limitation; find out how many orders are already placed
|
||||
int orders=OrdersTotal();
|
||||
|
||||
//--- return the result of comparing
|
||||
return(orders<max_allowed_orders);
|
||||
}
|
||||
|
||||
#ifdef __MQL5__
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return the size of position on the specified symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
double PositionVolume(string symbol)
|
||||
{
|
||||
//--- try to select position by a symbol
|
||||
bool selected=PositionSelect(symbol);
|
||||
//--- there is a position
|
||||
if(selected)
|
||||
//--- return volume of the position
|
||||
return(PositionGetDouble(POSITION_VOLUME));
|
||||
else
|
||||
{
|
||||
//--- report a failure to select position
|
||||
Print(__FUNCTION__," Failed to perform PositionSelect() for symbol ",
|
||||
symbol," Error ",GetLastError());
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| returns the volume of current pending order by a symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
double PendingsVolume(string symbol)
|
||||
{
|
||||
double volume_on_symbol=0;
|
||||
ulong ticket;
|
||||
//--- get the number of all currently placed orders by all symbols
|
||||
int all_orders=OrdersTotal();
|
||||
|
||||
//--- get over all orders in the loop
|
||||
for(int i=0;i<all_orders;i++)
|
||||
{
|
||||
//--- get the ticket of an order by its position in the list
|
||||
ticket = OrderGetTicket(i);
|
||||
if((bool)ticket)
|
||||
{
|
||||
//--- if our symbol is specified in the order, add the volume of this order
|
||||
if(symbol==OrderGetString(ORDER_SYMBOL))
|
||||
volume_on_symbol+=OrderGetDouble(ORDER_VOLUME_INITIAL);
|
||||
}
|
||||
}
|
||||
//--- return the total volume of currently placed pending orders for a specified symbol
|
||||
return(volume_on_symbol);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return the maximum allowed volume for an order on the symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
double NewOrderAllowedVolume(string symbol)
|
||||
{
|
||||
double allowed_volume=0;
|
||||
//--- get the limitation on the maximal volume of an order
|
||||
double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
|
||||
//--- get the limitation on the volume by a symbol
|
||||
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
|
||||
|
||||
//--- get the volume of the open position by a symbol
|
||||
double opened_volume=PositionVolume(symbol);
|
||||
if(opened_volume>=0)
|
||||
{
|
||||
//--- if we have exhausted the volume
|
||||
if(max_volume-opened_volume<=0)
|
||||
return(0);
|
||||
|
||||
//--- volume of the open position doesn't exceed max_volume
|
||||
double orders_volume_on_symbol=PendingsVolume(symbol);
|
||||
allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
|
||||
if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
|
||||
}
|
||||
return(allowed_volume);
|
||||
}
|
||||
#endif
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check the correctness of StopLoss and TakeProfit |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckStopLoss_Takeprofit(string _symbol, ENUM_ORDER_TYPE type,double price,double SL,double TP)
|
||||
{
|
||||
//--- get the SYMBOL_TRADE_STOPS_LEVEL level
|
||||
int stops_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
||||
if(stops_level!=0)
|
||||
{
|
||||
PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
|
||||
" not be nearer than %d points from the closing price",stops_level,stops_level);
|
||||
}
|
||||
//---
|
||||
bool SL_check=false,TP_check=false;
|
||||
//--- check the order type
|
||||
switch(type)
|
||||
{
|
||||
//--- Buy operation
|
||||
case ORDER_TYPE_BUY:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : (Bid-SL>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
|
||||
" (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,Bid-stops_level*_point,Bid,stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : (TP-Bid>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
|
||||
" (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,Bid+stops_level*_point,Bid,stops_level);
|
||||
//--- return the result of checking
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
//--- Sell operation
|
||||
case ORDER_TYPE_SELL:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : (SL-Ask>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
|
||||
" (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,Ask+stops_level*_point,Ask,stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : (Ask-TP>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
|
||||
" (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,Ask-stops_level*_point,Ask,stops_level);
|
||||
//--- return the result of checking
|
||||
return(TP_check&&SL_check);
|
||||
}
|
||||
break;
|
||||
//--- BuyLimit pending order
|
||||
case ORDER_TYPE_BUY_LIMIT:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : ((price-SL)>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
|
||||
" (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,price-stops_level*_point,(int)((price-SL)/_point),stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : ((TP-price)>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
|
||||
" (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,price+stops_level*_point,(int)((TP-price)/_point),stops_level);
|
||||
//--- return the result of checking
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
//--- SellLimit pending order
|
||||
case ORDER_TYPE_SELL_LIMIT:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : ((SL-price)>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
|
||||
" (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,price+stops_level*_point,(int)((SL-price)/_point),stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : ((price-TP)>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
|
||||
" (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,price-stops_level*_point,(int)((price-TP)/_point),stops_level);
|
||||
//--- return the result of checking
|
||||
return(TP_check&&SL_check);
|
||||
}
|
||||
break;
|
||||
//--- BuyStop pending order
|
||||
case ORDER_TYPE_BUY_STOP:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : ((price-SL)>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
|
||||
" (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,price-stops_level*_point,(int)((price-SL)/_point),stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : ((TP-price)>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
|
||||
" (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,price-stops_level*_point,(int)((TP-price)/_point),stops_level);
|
||||
//--- return the result of checking
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
//--- SellStop pending order
|
||||
case ORDER_TYPE_SELL_STOP:
|
||||
{
|
||||
//--- check the StopLoss
|
||||
SL_check= (SL==0) ? true : ((SL-price)>stops_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
|
||||
" (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),SL,price+stops_level*_point,(int)((SL-price)/_point),stops_level);
|
||||
//--- check the TakeProfit
|
||||
TP_check= (TP==0) ? true : ((price-TP)>stops_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
|
||||
" (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
|
||||
EnumToString(type),TP,price-stops_level*_point,(int)((price-TP)/_point),stops_level);
|
||||
//--- return the result of checking
|
||||
return(TP_check&&SL_check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//---
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __MQL5__
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checking the new values of levels before order modification |
|
||||
//+------------------------------------------------------------------+
|
||||
bool OrderModifyCheck(ulong ticket,double price,double sl,double tp)
|
||||
{
|
||||
//--- select order by ticket
|
||||
if(orderinfo.Select(ticket))
|
||||
{
|
||||
//--- point size and name of the symbol, for which a pending order was placed
|
||||
string symbol=orderinfo.Symbol();
|
||||
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||||
int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
|
||||
//--- check if there are changes in the Open price
|
||||
bool PriceOpenChanged=(MathAbs(orderinfo.PriceOpen()-price)>point);
|
||||
//--- check if there are changes in the StopLoss level
|
||||
bool StopLossChanged=(MathAbs(orderinfo.StopLoss()-sl)>point);
|
||||
//--- check if there are changes in the Takeprofit level
|
||||
bool TakeProfitChanged=(MathAbs(orderinfo.TakeProfit()-tp)>point);
|
||||
//--- if there are any changes in levels
|
||||
if(PriceOpenChanged || StopLossChanged || TakeProfitChanged)
|
||||
return(true); // order can be modified
|
||||
//--- there are no changes in the Open, StopLoss and Takeprofit levels
|
||||
else
|
||||
//--- notify about the error
|
||||
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
|
||||
ticket,orderinfo.PriceOpen(),orderinfo.StopLoss(),orderinfo.TakeProfit());
|
||||
}
|
||||
//--- came to the end, no changes for the order
|
||||
return(false); // no point in modifying
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checking the new values of levels before order modification |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionModifyCheck(ulong ticket,double sl,double tp)
|
||||
{
|
||||
//--- select order by ticket
|
||||
if(positioninfo.SelectByTicket(ticket))
|
||||
{
|
||||
//--- point size and name of the symbol, for which a pending order was placed
|
||||
string symbol=positioninfo.Symbol();
|
||||
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||||
//--- check if there are changes in the StopLoss level
|
||||
bool StopLossChanged=(MathAbs(positioninfo.StopLoss()-sl)>point);
|
||||
//--- check if there are changes in the Takeprofit level
|
||||
bool TakeProfitChanged=(MathAbs(positioninfo.TakeProfit()-tp)>point);
|
||||
//--- if there are any changes in levels
|
||||
if(StopLossChanged || TakeProfitChanged)
|
||||
return(true); // position can be modified
|
||||
//--- there are no changes in the StopLoss and Takeprofit levels
|
||||
else
|
||||
//--- notify about the error
|
||||
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
|
||||
ticket,orderinfo.PriceOpen(),orderinfo.StopLoss(),orderinfo.TakeProfit());
|
||||
}
|
||||
//--- came to the end, no changes for the order
|
||||
return(false); // no point in modifying
|
||||
}
|
||||
#else
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checking the new values of levels before order modification |
|
||||
//+------------------------------------------------------------------+
|
||||
bool OrderModifyCheck(int ticket,double price,double sl,double tp)
|
||||
{
|
||||
//--- select order by ticket
|
||||
if(OrderSelect(ticket,SELECT_BY_TICKET))
|
||||
{
|
||||
//--- point size and name of the symbol, for which a pending order was placed
|
||||
string symbol=OrderSymbol();
|
||||
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||||
//--- check if there are changes in the Open price
|
||||
bool PriceOpenChanged=true;
|
||||
int type=OrderType();
|
||||
if(!(type==OP_BUY || type==OP_SELL))
|
||||
{
|
||||
PriceOpenChanged=(MathAbs(OrderOpenPrice()-price)>point);
|
||||
}
|
||||
//--- check if there are changes in the StopLoss level
|
||||
bool StopLossChanged=(MathAbs(OrderStopLoss()-sl)>point);
|
||||
//--- check if there are changes in the Takeprofit level
|
||||
bool TakeProfitChanged=(MathAbs(OrderTakeProfit()-tp)>point);
|
||||
//--- if there are any changes in levels
|
||||
if(PriceOpenChanged || StopLossChanged || TakeProfitChanged)
|
||||
return(true); // order can be modified
|
||||
//--- there are no changes in the Open, StopLoss and Takeprofit levels
|
||||
else
|
||||
//--- notify about the error
|
||||
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
|
||||
ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
|
||||
}
|
||||
//--- came to the end, no changes for the order
|
||||
return(false); // no point in modifying
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __MQL5__
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check the distance from opening price to activation price |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckOrderForFREEZE_LEVEL(string _symbol, ulong ticket)
|
||||
{
|
||||
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
|
||||
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
|
||||
if(freeze_level!=0)
|
||||
{
|
||||
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
|
||||
" nearer than %d points from the activation price",freeze_level,freeze_level);
|
||||
}
|
||||
//--- select order for working
|
||||
if(!OrderSelect(ticket))
|
||||
{
|
||||
//--- failed to select order
|
||||
return(false);
|
||||
}
|
||||
//--- get the order data
|
||||
double price=OrderGetDouble(ORDER_PRICE_OPEN);
|
||||
double sl=OrderGetDouble(ORDER_SL);
|
||||
double tp=OrderGetDouble(ORDER_TP);
|
||||
ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
||||
//--- result of checking
|
||||
bool check=false;
|
||||
//--- check the order type
|
||||
switch(type)
|
||||
{
|
||||
//--- BuyLimit pending order
|
||||
case ORDER_TYPE_BUY_LIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((Ask-price)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
EnumToString(type),ticket,(int)((Ask-price)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
//--- BuyLimit pending order
|
||||
case ORDER_TYPE_SELL_LIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((price-Bid)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified: Open-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
EnumToString(type),ticket,(int)((price-Bid)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
//--- BuyStop pending order
|
||||
case ORDER_TYPE_BUY_STOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((price-Ask)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
EnumToString(type),ticket,(int)((price-Ask)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
//--- SellStop pending order
|
||||
case ORDER_TYPE_SELL_STOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((Bid-price)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified: Bid-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
EnumToString(type),ticket,(int)((Bid-price)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//--- order did not pass the check
|
||||
return (false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if the TP and SL are too close to activation price |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPositionForFREEZE_LEVEL(string _symbol, ulong ticket)
|
||||
{
|
||||
|
||||
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
|
||||
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
|
||||
if(freeze_level!=0)
|
||||
{
|
||||
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
|
||||
" nearer than %d points from the activation price",freeze_level,freeze_level);
|
||||
}
|
||||
//--- select position for working
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
{
|
||||
//--- failed to select position
|
||||
return(false);
|
||||
}
|
||||
//--- get the order data
|
||||
ENUM_POSITION_TYPE pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
double sl=PositionGetDouble(POSITION_SL);
|
||||
double tp=PositionGetDouble(POSITION_TP);
|
||||
//--- result of checking StopLoss and TakeProfit
|
||||
bool SL_check=false,TP_check=false;
|
||||
//--- position type
|
||||
switch(pos_type)
|
||||
{
|
||||
//--- buy
|
||||
case POSITION_TYPE_BUY:
|
||||
{
|
||||
SL_check=(sl == 0) ? true: (Bid-sl>freeze_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("Position %s #%d cannot be modified: Bid-StopLoss=%d points"+
|
||||
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
|
||||
EnumToString(pos_type),ticket,(int)((Bid-sl)/_point),freeze_level);
|
||||
TP_check=(tp == 0) ? true: (tp-Bid>freeze_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("Position %s #%d cannot be modified: TakeProfit-Bid=%d points"+
|
||||
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
|
||||
EnumToString(pos_type),ticket,(int)((tp-Bid)/_point),freeze_level);
|
||||
//--- return the result of checking
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
break;
|
||||
//--- sell
|
||||
case POSITION_TYPE_SELL:
|
||||
{
|
||||
SL_check=(sl == 0) ? true: (sl-Ask>freeze_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("Position %s cannot be modified: StopLoss-Ask=%d points"+
|
||||
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
|
||||
EnumToString(pos_type),(int)((sl-Ask)/_point),freeze_level);
|
||||
TP_check=(tp == 0) ? true: (Ask-tp>freeze_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("Position %s cannot be modified: Ask-TakeProfit=%d points"+
|
||||
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
|
||||
EnumToString(pos_type),(int)((Ask-tp)/_point),freeze_level);
|
||||
//--- return the result of checking
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//--- position did not pass the check
|
||||
return (false);
|
||||
}
|
||||
#else
|
||||
bool CheckOrderForFREEZE_LEVEL(string _symbol,int ticket)
|
||||
{
|
||||
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
|
||||
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
|
||||
if(freeze_level!=0)
|
||||
{
|
||||
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
|
||||
" nearer than %d points from the activation price",freeze_level,freeze_level);
|
||||
}
|
||||
//--- select order for working
|
||||
if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
|
||||
{
|
||||
//--- failed to select order
|
||||
return (false);
|
||||
}
|
||||
//--- get the order data
|
||||
double price=OrderOpenPrice();
|
||||
double sl=OrderStopLoss();
|
||||
double tp=OrderTakeProfit();
|
||||
int type=OrderType();
|
||||
//--- result of checking
|
||||
bool check=false;
|
||||
//--- check the order type
|
||||
switch(type)
|
||||
{
|
||||
//--- BuyLimit pending order
|
||||
case OP_BUYLIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((Ask-price)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order OP_BUYLIMIT #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((Ask-price)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
//--- BuyLimit pending order
|
||||
case OP_SELLLIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((price-Bid)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order OP_SELLLIMIT #%d cannot be modified: Open-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((price-Bid)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
//--- BuyStop pending order
|
||||
case OP_BUYSTOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((price-Ask)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order OP_BUYSTOP #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((price-Ask)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
//--- SellStop pending order
|
||||
case OP_SELLSTOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=((Bid-price)>freeze_level*_point);
|
||||
if(!check)
|
||||
PrintFormat("Order OP_SELLSTOP #%d cannot be modified: Bid-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((Bid-price)/_point),freeze_level);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
//--- checking opened Buy order
|
||||
case OP_BUY:
|
||||
{
|
||||
//--- check TakeProfit distance to the activation price
|
||||
bool TP_check=(tp == 0) ? true: (tp-Bid>freeze_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((tp-Bid)/_point),freeze_level);
|
||||
//--- check TakeProfit distance to the activation price
|
||||
bool SL_check=(sl == 0) ? true: (Bid-sl>freeze_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((Bid-sl)/_point),freeze_level);
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
break;
|
||||
//--- checking opened Sell order
|
||||
case OP_SELL:
|
||||
{
|
||||
//--- check TakeProfit distance to the activation price
|
||||
bool TP_check=(tp == 0) ? true: (Ask-tp>freeze_level*_point);
|
||||
if(!TP_check)
|
||||
PrintFormat("Order OP_SELL %d cannot be modified: Ask-TakeProfit=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((Ask-tp)/_point),freeze_level);
|
||||
//--- check TakeProfit distance to the activation price
|
||||
bool SL_check=(sl == 0) ? true: (sl-Ask>freeze_level*_point);
|
||||
if(!SL_check)
|
||||
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
|
||||
ticket,(int)((sl-Ask)/_point),freeze_level);
|
||||
return(SL_check&&TP_check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//--- order did not pass the check
|
||||
return (false);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CheckPendingOrderEntryChange(string _symbol, ulong ticket, double newEntryPrice)
|
||||
{
|
||||
//--- select order for working
|
||||
if(!OrderSelect(ticket))
|
||||
{
|
||||
//--- failed to select order
|
||||
return(false);
|
||||
}
|
||||
//--- get the order data
|
||||
ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
|
||||
//--- result of checking
|
||||
bool check=false;
|
||||
//--- check the order type
|
||||
switch(type)
|
||||
{
|
||||
//--- BuyLimit pending order
|
||||
case ORDER_TYPE_BUY_LIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check= (newEntryPrice < Ask);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified",
|
||||
EnumToString(type),ticket);
|
||||
return(check);
|
||||
}
|
||||
//--- BuyLimit pending order
|
||||
case ORDER_TYPE_SELL_LIMIT:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=(newEntryPrice > Bid);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified",
|
||||
EnumToString(type),ticket);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
//--- BuyStop pending order
|
||||
case ORDER_TYPE_BUY_STOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=(newEntryPrice > Ask);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified",
|
||||
EnumToString(type),ticket);
|
||||
return(check);
|
||||
}
|
||||
//--- SellStop pending order
|
||||
case ORDER_TYPE_SELL_STOP:
|
||||
{
|
||||
//--- check the distance from the opening price to the activation price
|
||||
check=(newEntryPrice < Bid);
|
||||
if(!check)
|
||||
PrintFormat("Order %s #%d cannot be modified",
|
||||
EnumToString(type),ticket);
|
||||
return(check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//--- order did not pass the check
|
||||
return (false);
|
||||
}
|
||||
Reference in New Issue
Block a user