new version update

This commit is contained in:
9nix6
2018-12-13 00:19:34 +01:00
parent 75a0f76352
commit 38937ddce1
5 changed files with 1521 additions and 91 deletions
Binary file not shown.
+52
View File
@@ -0,0 +1,52 @@
//
// Copyright 2017-2018, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
// Normalizing functions
//
double NormalizeLots(string symbol, double InputLots)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
int lotsDigits = (int) - MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP));
if(InputLots < lotsMin)
InputLots = lotsMin;
if(InputLots > lotsMax)
InputLots = lotsMax;
return NormalizeDouble(InputLots, lotsDigits);
}
double VtcNormalizeLots(string symbol, double lotsToNormalize)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
double lotsStep = SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
if (lotsToNormalize == 0)
return lotsMin;
int a = (int)(lotsToNormalize / lotsStep);
double Lots = a * lotsStep;
if(Lots < lotsMin)
Lots = lotsMin;
if(Lots > lotsMax)
Lots = lotsMax;
return Lots;
}
double NormalizePrice(string symbol, double price, double tick = 0)
{
double _tick = tick ? tick : SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
int _digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if (tick)
return NormalizeDouble(MathRound(price/_tick)*_tick,_digits);
else
return NormalizeDouble(price,_digits);
}
+34 -11
View File
@@ -6,15 +6,38 @@
#ifdef SHOW_INDICATOR_INPUTS
input int barSizeInTicks = 100; // Range bar size (in points)
input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input int atrPeriod = 14; // ATR period
input int atrPercentage = 10; // Use percentage of ATR
ENUM_BOOL useRealVolume = false; // Use real volume ( false for FX )
ENUM_TICK_PRICE_TYPE plotPrice = tickBid; // Build chart using
input int showNumberOfDays = 14; // Show history for number of days
input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#ifdef MQL5_MARKET_DEMO
int barSizeInTicks = 210; // Range bar size (in points)
ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
int atrPeriod = 14; // ATR period
int atrPercentage = 10; // Use percentage of ATR
ENUM_BOOL useRealVolume = false; // Use real volume ( false for FX )
ENUM_TICK_PRICE_TYPE plotPrice = tickBid; // Build chart using
int showNumberOfDays = 7; // Show history for number of days
ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#ifdef USE_CUSTOM_SYMBOL
string customChartName = ""; // Override default custom chart name with
string applyTemplate = "default"; // Apply template to custom chart
#endif
#else
input int barSizeInTicks = 100; // Range bar size (in points)
input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input int atrPeriod = 14; // ATR period
input int atrPercentage = 10; // Use percentage of ATR
ENUM_BOOL useRealVolume = false; // Use real volume ( false for FX )
ENUM_TICK_PRICE_TYPE plotPrice = tickBid; // Build chart using
input int showNumberOfDays = 14; // Show history for number of days
input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#ifdef USE_CUSTOM_SYMBOL
input string customChartName = ""; // Override default custom chart name with
input string applyTemplate = "default"; // Apply template to custom chart
#endif
#endif
#ifndef USE_CUSTOM_SYMBOL
input double TopBottomPaddingPercentage = 0.30; // Use padding top/bottom (0.0 - 1.0)
@@ -30,7 +53,7 @@ input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synch
input color HighThresholdIndicatorColor = clrLime; // Bullish bar projection color
input color LowThresholdIndicatorColor = clrRed; // Bearish bar projection color
input ENUM_BOOL showCurrentBarOpenTime = true; // Display chart info and current bar's open time
input color InfoTextColor = clrWhite; // Current bar's open time info color
input color InfoTextColor = clrNONE; // Current bar's open time info color
input ENUM_BOOL NewBarAlert = false; // Alert on new a bar
input ENUM_BOOL ReversalBarAlert = false; // Alert on reversal bar
@@ -56,7 +79,7 @@ input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synch
input ENUM_MA_METHOD_EXT MA3method = _VWAP_TICKVOL; // 3rd MA method
input ENUM_APPLIED_PRICE MA3applyTo = PRICE_CLOSE; // 3rd MA apply to
input int MA3shift = 0; // 3rd MA shift
input ENUM_CHANNEL_TYPE ShowChannel = None; // Show Channel
input ENUM_CHANNEL_TYPE ShowChannel = _None; // Show Channel
input string Channel_Settings = "-------------------"; // Channel settings
input int DonchianPeriod = 20; // Donchian Channel period
input ENUM_APPLIED_PRICE BBapplyTo = PRICE_CLOSE; // Bollinger Bands apply to
+545 -80
View File
@@ -1,11 +1,13 @@
//+------------------------------------------------------------------+
//| TradeFunctions.mqh |
//| Copyright 2017, AZ-iNVEST |
//| http://www.az-invest.eu |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, AZ-iNVEST"
#property link "http://www.az-invest.eu"
//
// Copyright 2017-2018, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
#include <Trade\Trade.mqh>
#include <AZ-INVEST/SDK/Normailze.mqh>
#include <AZ-INVEST/SDK/TradingChecks.mqh>
CTradingChecks tradingChecks;
#define POSITION_TYPE_NONE -1
@@ -15,40 +17,58 @@
struct CMarketOrderParameters
{
bool m_async_mode; // trade mode
ulong m_magic; // expert magic number
ulong m_deviation; // deviation default
bool m_async_mode; // trade mode
ulong m_magic; // expert magic number
ulong m_deviation; // deviation default
ENUM_ORDER_TYPE_FILLING m_type_filling;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
};
class CMarketOrder
{
protected:
CTrade * ctrade;
CTrade *ctrade;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
bool initialized;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
public:
CMarketOrder(void);
CMarketOrder(CMarketOrderParameters &params);
~CMarketOrder(void);
bool Long(string symbol, double lots, uint stoploss = 0, uint takeprofit = 0);
bool Long(string symbol,double lots, double priceSL=0,double priceTP=0);
bool Short(string symbol,double lots, uint stoploss = 0, uint takeprofit = 0);
bool Short(string symbol,double lots, double priceSL=0,double priceTP=0);
bool Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0);
bool Initialize(CMarketOrderParameters &params);
bool IsInitialized() {return initialized;};
bool Long(string symbol, double lots, uint stoploss = 0, uint takeprofit = 0,bool stopsInPips = true, string comment = "");
bool Long(string symbol,double lots, double priceSL=0,double priceTP=0, string comment = "");
bool Short(string symbol,double lots, uint stoploss = 0, uint takeprofit = 0,bool stopsInPips = true, string comment = "");
bool Short(string symbol,double lots, double priceSL=0,double priceTP=0, string comment = "");
bool PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "");
bool PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "");
bool PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "");
bool PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "");
bool Modify(ulong ticket, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1);
bool Modify(ulong ticket, double priceSL=0,double priceTP=0);
bool ModifyPending(ulong ticket, double entry, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0);
bool ModifyPending(ulong ticket, double entry, double priceSL=0, double priceTP=0, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0);
bool Close(ulong ticket);
bool ClosePartial(ulong ticket, double lots);
bool CloseAll(string symbol = "");
bool Delete(ulong ticket);
bool Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0);
bool Reverse(ulong ticket,double lots = 0, double priceSL=0,double priceTP=0);
bool IsOpen(string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0);
@@ -57,8 +77,13 @@ class CMarketOrder
bool IsOpen(ulong &ticket, string symbol, long magicNumber = 0);
bool IsOpen(ulong &ticket, ENUM_POSITION_TYPE &type, string symbol, long magicNumber = 0);
bool GetPositionType(ulong ticket, ENUM_POSITION_TYPE &_pType);
string PositionTypeToString(ENUM_POSITION_TYPE t);
string OrderTypeToString(ENUM_ORDER_TYPE t);
ENUM_ORDER_TYPE TradeBias(ENUM_ORDER_TYPE t);
bool RetryOrderRequest(int retryNumber);
void SetTradeId(ulong tradeId);
private:
@@ -68,19 +93,31 @@ class CMarketOrder
};
CMarketOrder::CMarketOrder(void)
{
ctrade = new CTrade();
this.initialized = false;
}
CMarketOrder::CMarketOrder(CMarketOrderParameters &params)
{
ctrade = new CTrade();
Initialize(params);
}
bool CMarketOrder::Initialize(CMarketOrderParameters &params)
{
ctrade.SetExpertMagicNumber(params.m_magic);
ctrade.SetDeviationInPoints(params.m_deviation);
ctrade.SetTypeFilling(params.m_type_filling);
ctrade.SetAsyncMode(params.m_async_mode);
this.numberOfRetries = (params.numberOfRetries == 0) ? 25 : params.numberOfRetries;
this.busyTimeout_ms = (params.busyTimeout_ms == 0) ? 1000 : params.busyTimeout_ms;
this.requoteTimeout_ms = (params.requoteTimeout_ms == 0) ? 250 : params.requoteTimeout_ms;
this.numberOfRetries = (params.numberOfRetries == 0) ? 25 : params.numberOfRetries;
this.busyTimeout_ms = (params.busyTimeout_ms == 0) ? 1000 : params.busyTimeout_ms;
this.requoteTimeout_ms = (params.requoteTimeout_ms == 0) ? 250 : params.requoteTimeout_ms;
this.initialized = true;
return this.initialized;
}
CMarketOrder::~CMarketOrder(void)
@@ -89,7 +126,7 @@ CMarketOrder::~CMarketOrder(void)
delete ctrade;
}
bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprofit=0)
bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
int counter = 0;
@@ -97,14 +134,21 @@ bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprof
while(!IsStopped() && !result)
{
double price = SymbolInfoDouble(symbol,SYMBOL_ASK);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : 0.0);
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_BUY,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -121,7 +165,7 @@ bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprof
return false;
}
bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double priceTP=0)
bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double priceTP=0, string comment = "")
{
bool result = false;
int counter = 0;
@@ -130,8 +174,15 @@ bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double price
{
double price = SymbolInfoDouble(symbol,SYMBOL_ASK);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_BUY,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -148,7 +199,7 @@ bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double price
return false;
}
bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takeprofit=0)
bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
int counter = 0;
@@ -156,14 +207,21 @@ bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takepro
while(!IsStopped() && !result)
{
double price = SymbolInfoDouble(symbol,SYMBOL_BID);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : 0.0);
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_SELL,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -180,7 +238,7 @@ bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takepro
return false;
}
bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double priceTP=0)
bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double priceTP=0, string comment = "")
{
bool result = false;
int counter = 0;
@@ -189,8 +247,15 @@ bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double pric
{
double price = SymbolInfoDouble(symbol,SYMBOL_BID);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_SELL,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -207,24 +272,202 @@ bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double pric
return false;
}
bool CMarketOrder::Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0)
bool CMarketOrder::PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to place buy
if(orderType == ORDER_TYPE_BUY_LIMIT)
result = ctrade.BuyLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_BUY_STOP)
result = ctrade.BuyStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
if(orderType == ORDER_TYPE_BUY_LIMIT)
result = ctrade.BuyLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_BUY_STOP)
result = ctrade.BuyStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
if(orderType == ORDER_TYPE_SELL_LIMIT)
result = ctrade.SellLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_SELL_STOP)
result = ctrade.SellStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
if(orderType == ORDER_TYPE_SELL_LIMIT)
result = ctrade.SellLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_SELL_STOP)
result = ctrade.SellStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::Modify(ulong ticket, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1)
{
if(!PositionSelectByTicket(ticket))
return false;
string symbol = PositionGetString(POSITION_SYMBOL);
double price = PositionGetDouble(POSITION_PRICE_CURRENT);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double price = PositionGetDouble(POSITION_PRICE_OPEN);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double priceSL;
double priceTP;
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : PositionGetDouble(POSITION_SL));
priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : PositionGetDouble(POSITION_TP));
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
priceSL = (stoploss < 0)
? PositionGetDouble(POSITION_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,price - stoploss*point);
priceTP = (takeprofit < 0)
? PositionGetDouble(POSITION_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,price + takeprofit*point);
// priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : PositionGetDouble(POSITION_SL));
// priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : PositionGetDouble(POSITION_TP));
}
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : PositionGetDouble(POSITION_SL));
priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : PositionGetDouble(POSITION_TP));
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
// priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : PositionGetDouble(POSITION_SL));
// priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : PositionGetDouble(POSITION_TP));
priceSL = (stoploss < 0)
? PositionGetDouble(POSITION_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,price + stoploss*point);
priceTP = (takeprofit < 0)
? PositionGetDouble(POSITION_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,price - takeprofit*point);
}
else
return false;
@@ -232,15 +475,25 @@ bool CMarketOrder::Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0)
//there's no change in SL or TP - do nothing!
if (priceSL == PositionGetDouble(POSITION_SL)
&& priceTP == PositionGetDouble(POSITION_TP))
return true;
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyPosition(symbol,ticket,priceSL,priceTP))
{
Alert("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.PositionModify(symbol,priceSL,priceTP);
if(_IsNettingAccount())
result = ctrade.PositionModify(symbol,priceSL,priceTP);
else
result = ctrade.PositionModify(ticket,priceSL,priceTP);
if(result)
{
@@ -263,21 +516,167 @@ bool CMarketOrder::Modify(ulong ticket, double priceSL=0,double priceTP=0)
return false;
string symbol = PositionGetString(POSITION_SYMBOL);
double price = PositionGetDouble(POSITION_PRICE_CURRENT);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double price = PositionGetDouble(POSITION_PRICE_OPEN);
//double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//there's no change in SL or TP - do nothing!
if (priceSL == PositionGetDouble(POSITION_SL)
&& priceTP == PositionGetDouble(POSITION_TP))
return true;
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyPosition(symbol,ticket,priceSL,priceTP))
{
Alert("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.PositionModify(symbol,priceSL,priceTP);
if(_IsNettingAccount())
result = ctrade.PositionModify(symbol,priceSL,priceTP);
else
result = ctrade.PositionModify(ticket,priceSL,priceTP);
if(result)
{
Sleep(500);
return true;
}
else
{
if(!RetryOrderRequest(++counter))
return false;
}
}
return false;
}
bool CMarketOrder::ModifyPending(ulong ticket, double entry, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0)
{
if(!OrderSelect(ticket))
return false;
string symbol = OrderGetString(ORDER_SYMBOL);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
if(entry == 0)
entry = OrderGetDouble(ORDER_PRICE_OPEN);
double priceSL;
double priceTP;
if((OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP_LIMIT))
{
priceSL = (stoploss < 0)
? OrderGetDouble(ORDER_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,entry - stoploss*point);
priceTP = (takeprofit < 0)
? OrderGetDouble(ORDER_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,entry + takeprofit*point);
}
else if((OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP_LIMIT))
{
priceSL = (stoploss < 0)
? OrderGetDouble(ORDER_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,entry + stoploss*point);
priceTP = (takeprofit < 0)
? OrderGetDouble(ORDER_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,entry - takeprofit*point);
}
else
return false;
//there's no change in parameters - do nothing!
if (priceSL == OrderGetDouble(ORDER_SL)
&& priceTP == OrderGetDouble(ORDER_TP)
&& entry == OrderGetDouble(ORDER_PRICE_OPEN)
&& orderTypeTime == OrderGetInteger(ORDER_TYPE_TIME)
&& expires == OrderGetInteger(ORDER_TIME_EXPIRATION))
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyOrder(symbol,ticket,entry,priceSL,priceTP))
{
Alert("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.OrderModify(ticket,entry,priceSL,priceTP,orderTypeTime,expires);
if(result)
{
Sleep(500);
return true;
}
else
{
if(!RetryOrderRequest(++counter))
return false;
}
}
return false;
}
bool CMarketOrder::ModifyPending(ulong ticket, double entry, double priceSL=0, double priceTP=0, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0)
{
if(!OrderSelect(ticket))
return false;
string symbol = OrderGetString(ORDER_SYMBOL);
if(entry == 0)
entry = OrderGetDouble(ORDER_PRICE_OPEN);
//there's no change in parameters - do nothing!
if (priceSL == OrderGetDouble(ORDER_SL)
&& priceTP == OrderGetDouble(ORDER_TP)
&& entry == OrderGetDouble(ORDER_PRICE_OPEN)
&& orderTypeTime == OrderGetInteger(ORDER_TYPE_TIME)
&& expires == OrderGetInteger(ORDER_TIME_EXPIRATION))
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyOrder(symbol,ticket,entry,priceSL,priceTP))
{
Alert("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.OrderModify(ticket,entry,priceSL,priceTP,orderTypeTime,expires);
if(result)
{
@@ -350,6 +749,11 @@ bool CMarketOrder::ClosePartial(ulong ticket, double lots)
return false;
}
bool CMarketOrder::Delete(ulong ticket)
{
return ctrade.OrderDelete(ticket);
}
bool CMarketOrder::Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0)
{
if(!PositionSelectByTicket(ticket))
@@ -420,6 +824,44 @@ bool CMarketOrder::IsOpen(ulong &ticket, string symbol, long magicNumber = 0)
return this._IsOpen(ticket,symbol,magicNumber);
}
bool CMarketOrder::CloseAll(string symbol = "")
{
int positions=PositionsTotal();
ulong ticketsToClose[];
int ticketsToCloseCounter = 0;
if(positions > 0)
ArrayResize(ticketsToClose,positions);
else
return false;
for(int i=0;i<positions;i++)
{
// ResetLastError();
ulong _ticket=PositionGetTicket(i);
if(_ticket!=0)
{
if(PositionSelectByTicket(_ticket))
{
if((PositionGetString(POSITION_SYMBOL) == symbol) || (symbol == ""))
{
ticketsToClose[ticketsToCloseCounter] = _ticket;
ticketsToCloseCounter++;
}
}
}
}
ArrayResize(ticketsToClose,ticketsToCloseCounter);
for(int i=0;i<ticketsToCloseCounter;i++)
{
this.Close(ticketsToClose[i]);
}
return true;
}
bool CMarketOrder::IsOpen(ulong &ticket,ENUM_POSITION_TYPE &type,string symbol,long magicNumber=0)
{
int positions=PositionsTotal();
@@ -458,6 +900,15 @@ bool CMarketOrder::IsOpen(ulong &ticket,ENUM_POSITION_TYPE &type,string symbol,l
}
bool CMarketOrder::GetPositionType(ulong ticket, ENUM_POSITION_TYPE &_pType)
{
if(!PositionSelectByTicket(ticket))
return false;
_pType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
return true;
}
bool CMarketOrder::_IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber)
{
int positions=PositionsTotal();
@@ -546,8 +997,43 @@ string CMarketOrder::PositionTypeToString(ENUM_POSITION_TYPE t)
return "-";
}
string CMarketOrder::OrderTypeToString(ENUM_ORDER_TYPE t)
{
if(t == ORDER_TYPE_BUY)
return "Buy";
else if(t == ORDER_TYPE_BUY_LIMIT)
return "Buy Limit";
else if(t == ORDER_TYPE_BUY_STOP)
return "Buy Stop";
else if(t == ORDER_TYPE_BUY_STOP_LIMIT)
return "Buy Stop Limit";
else if(t == ORDER_TYPE_SELL)
return "Sell";
else if(t == ORDER_TYPE_SELL_LIMIT)
return "Sell Limit";
else if(t == ORDER_TYPE_SELL_STOP)
return "Sell Stop";
else if(t == ORDER_TYPE_SELL_STOP_LIMIT)
return "Sell Stop Limit";
else
return "-";
}
ENUM_ORDER_TYPE CMarketOrder::TradeBias(ENUM_ORDER_TYPE t)
{
if((t == ORDER_TYPE_BUY) ||
(t == ORDER_TYPE_BUY_LIMIT) ||
(t == ORDER_TYPE_BUY_STOP) ||
(t == ORDER_TYPE_BUY_STOP_LIMIT))
return ORDER_TYPE_BUY;
else
return ORDER_TYPE_SELL;
}
bool CMarketOrder::RetryOrderRequest(int retryNumber)
{
Print(ctrade.ResultRetcodeDescription());
if(retryNumber >= this.numberOfRetries)
{
PrintFormat("Giving up on maximum number of retries (%d)",this.numberOfRetries);
@@ -575,37 +1061,16 @@ bool CMarketOrder::RetryOrderRequest(int retryNumber)
break;
default:
MessageBox(ctrade.ResultRetcodeDescription(),"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
//+------------------------------------------------------------------+
//| Normalizing |
//+------------------------------------------------------------------+
double NormalizeLots(string symbol, double InputLots)
void CMarketOrder::SetTradeId(ulong tradeId)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
int lotsDigits = (int) - MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP));
if(InputLots < lotsMin)
InputLots = lotsMin;
if(InputLots > lotsMax)
InputLots = lotsMax;
return NormalizeDouble(InputLots, lotsDigits);
ctrade.SetExpertMagicNumber(tradeId);
}
double NormalizePrice(string symbol, double price, double tick = 0)
{
double _tick = tick ? tick : SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
int _digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if (tick)
return NormalizeDouble(MathRound(price/_tick)*_tick,_digits);
else
return NormalizeDouble(price,_digits);
}
+890
View File
@@ -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);
}