877 lines
No EOL
26 KiB
MQL5
877 lines
No EOL
26 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| Trade.mqh |
| |
//| Andrew Young |
| |
//| http://www.expertadvisorbook.com |
| |
//+------------------------------------------------------------------+
| |
| |
#property copyright "Andrew Young"
| |
#property link "http://www.expertadvisorbook.com"
| |
| |
/*
| |
Creative Commons Attribution-NonCommercial 3.0 Unported
| |
http://creativecommons.org/licenses/by-nc/3.0/
| |
| |
You may use this file in your own personal projects. You may
| |
modify it if necessary. You may even share it, provided the
| |
copyright above is present. No commercial use is permitted.
| |
*/
| |
| |
| |
#define MAX_RETRIES 5 // Max retries on error
| |
#define RETRY_DELAY 3000 // Retry delay in ms
| |
| |
#include <errordescription.mqh>
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| CTrade Class - Open, Close and Modify Orders |
| |
//+------------------------------------------------------------------+
| |
| |
class CTrade
| |
{
| |
protected:
| |
MqlTradeRequest request;
| |
| |
bool OpenPosition(string pSymbol, ENUM_ORDER_TYPE pType, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL);
| |
bool OpenPending(string pSymbol, ENUM_ORDER_TYPE pType, double pVolume, double pPrice, double pStop = 0, double pProfit = 0, double pStopLimit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
void LogTradeRequest();
| |
| |
ulong magicNumber;
| |
ulong deviation;
| |
ENUM_ORDER_TYPE_FILLING fillType;
| |
| |
public:
| |
MqlTradeResult result;
| |
| |
bool Buy(string pSymbol, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL);
| |
bool Sell(string pSymbol, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL);
| |
bool BuyStop(string pSymbol, double pVolume, double pPrice, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
bool SellStop(string pSymbol, double pVolume, double pPrice, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
bool BuyLimit(string pSymbol, double pVolume, double pPrice, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
bool SellLimit(string pSymbol, double pVolume, double pPrice, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
bool BuyStopLimit(string pSymbol, double pVolume, double pPrice, double pStopLimit, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
bool SellStopLimit(string pSymbol, double pVolume, double pPrice, double pStopLimit, double pStop = 0, double pProfit = 0, datetime pExpiration = 0, string pComment = NULL);
| |
| |
bool ModifyPosition(string pSymbol, double pStop, double pProfit = 0);
| |
bool ModifyPending(ulong pTicket, double pPrice, double pStop, double pProfit, datetime pExpiration = 0);
| |
bool Close(string pSymbol, double pVolume = 0, string pComment = NULL);
| |
bool Delete(ulong pTicket);
| |
| |
void MagicNumber(ulong pMagic);
| |
void Deviation(ulong pDeviation);
| |
void FillType(ENUM_ORDER_TYPE_FILLING pFill);
| |
};
| |
| |
| |
// Open position
| |
bool CTrade::OpenPosition(string pSymbol, ENUM_ORDER_TYPE pType, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_DEAL;
| |
request.symbol = pSymbol;
| |
request.type = pType;
| |
request.sl = pStop;
| |
request.tp = pProfit;
| |
request.comment = pComment;
| |
request.deviation = deviation;
| |
request.type_filling = fillType;
| |
request.magic = magicNumber;
| |
| |
// Calculate lot size
| |
double positionVol = 0;
| |
long positionType = WRONG_VALUE;
| |
| |
if(PositionSelect(pSymbol) == true)
| |
{
| |
positionVol = PositionGetDouble(POSITION_VOLUME);
| |
positionType = PositionGetInteger(POSITION_TYPE);
| |
}
| |
| |
if((pType == ORDER_TYPE_BUY && positionType == POSITION_TYPE_SELL) || (pType == ORDER_TYPE_SELL && positionType == POSITION_TYPE_BUY))
| |
{
| |
request.volume = pVolume + positionVol;
| |
}
| |
else request.volume = pVolume;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
Print( SymbolInfoDouble(pSymbol,SYMBOL_ASK));
| |
do
| |
{
| |
if(pType == ORDER_TYPE_BUY) request.price = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
else if(pType == ORDER_TYPE_SELL) request.price = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Open market order: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
string orderType = CheckOrderType(pType);
| |
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Print("Open ",orderType," order #",result.order,": ",result.retcode," - ",errDesc,", Volume: ",result.volume,", Price: ",result.price,", Bid: ",result.bid,", Ask: ",result.ask);
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment(orderType," position opened at ",result.price," on ",pSymbol);
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
// Open pending order
| |
bool CTrade::OpenPending(string pSymbol,ENUM_ORDER_TYPE pType,double pVolume,double pPrice,double pStop=0,double pProfit=0,double pStopLimit = 0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_PENDING;
| |
request.symbol = pSymbol;
| |
request.type = pType;
| |
request.sl = pStop;
| |
request.tp = pProfit;
| |
request.comment = pComment;
| |
request.price = pPrice;
| |
request.volume = pVolume;
| |
request.stoplimit = pStopLimit;
| |
request.deviation = deviation;
| |
request.type_filling = fillType;
| |
request.magic = magicNumber;
| |
| |
if(pExpiration > 0)
| |
{
| |
request.expiration = pExpiration;
| |
request.type_time = ORDER_TIME_SPECIFIED;
| |
}
| |
else request.type_time = ORDER_TIME_GTC;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
| |
do
| |
{
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Open pending order: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
string orderType = CheckOrderType(pType);
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
| |
Print("Open ",orderType," order #",result.order,": ",result.retcode," - ",errDesc,", Volume: ",result.volume,", Price: ",request.price,
| |
", Bid: ",SymbolInfoDouble(pSymbol,SYMBOL_BID),", Ask: ",SymbolInfoDouble(pSymbol,SYMBOL_ASK),", SL: ",request.sl,", TP: ",request.tp,
| |
", Stop Limit: ",request.stoplimit,", Expiration: ",request.expiration);
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment(orderType," order opened at ",request.price," on ",pSymbol);
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
// Modify position
| |
bool CTrade::ModifyPosition(string pSymbol,double pStop,double pProfit=0)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_SLTP;
| |
request.symbol = pSymbol;
| |
request.sl = pStop;
| |
request.tp = pProfit;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
| |
do
| |
{
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Modify position: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Print("Modify position: ",result.retcode," - ",errDesc,", SL: ",request.sl,", TP: ",request.tp,", Bid: ",SymbolInfoDouble(pSymbol,SYMBOL_BID),", Ask: ",SymbolInfoDouble(pSymbol,SYMBOL_ASK),", Stop Level: ",SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL));
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment("Position modified on ",pSymbol,", SL: ",request.sl,", TP: ",request.tp);
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
// Modify pending order
| |
bool CTrade::ModifyPending(ulong pTicket,double pPrice,double pStop,double pProfit,datetime pExpiration=0)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_MODIFY;
| |
request.order = pTicket;
| |
request.sl = pStop;
| |
request.tp = pProfit;
| |
| |
bool select = OrderSelect(pTicket);
| |
| |
if(pPrice > 0) request.price = pPrice;
| |
else request.price = OrderGetDouble(ORDER_PRICE_OPEN);
| |
| |
if(pExpiration > 0)
| |
{
| |
request.expiration = pExpiration;
| |
request.type_time = ORDER_TIME_SPECIFIED;
| |
}
| |
else request.type_time = ORDER_TIME_GTC;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
| |
do
| |
{
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Modify pending order: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
select = OrderSelect(pTicket);
| |
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Print("Modify pending order #",pTicket,": ",result.retcode," - ",errDesc,", Price: ",OrderGetDouble(ORDER_PRICE_OPEN),", SL: ",request.sl,", TP: ",request.tp,", Expiration: ",request.expiration);
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment("Pending order ",pTicket," modified,"," Price: ",OrderGetDouble(ORDER_PRICE_OPEN),", SL: ",request.sl,", TP: ",request.tp);
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
// Close position
| |
bool CTrade::Close(string pSymbol,double pVolume=0,string pComment=NULL)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_DEAL;
| |
request.symbol = pSymbol;
| |
request.deviation = deviation;
| |
request.type_filling = fillType;
| |
request.magic = magicNumber;
| |
| |
double closeVol = 0;
| |
long openType = WRONG_VALUE;
| |
| |
if(PositionSelect(pSymbol) == true)
| |
{
| |
closeVol = PositionGetDouble(POSITION_VOLUME);
| |
openType = PositionGetInteger(POSITION_TYPE);
| |
}
| |
else return(false);
| |
| |
if(pVolume > closeVol || pVolume <= 0) request.volume = closeVol;
| |
else request.volume = pVolume;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
| |
do
| |
{
| |
if(openType == POSITION_TYPE_BUY)
| |
{
| |
request.type = ORDER_TYPE_SELL;
| |
request.price = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
}
| |
else if(openType == POSITION_TYPE_SELL)
| |
{
| |
request.type = ORDER_TYPE_BUY;
| |
request.price = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
}
| |
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Close position: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
string posType;
| |
if(openType == POSITION_TYPE_BUY) posType = "Buy";
| |
else if(openType == POSITION_TYPE_SELL) posType = "Sell";
| |
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Print("Close ",posType," position #",result.order,": ",result.retcode," - ",errDesc,", Volume: ",result.volume,", Price: ",result.price,", Bid: ",result.bid,", Ask: ",result.ask);
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment(posType," position closed on ",pSymbol," at ",result.price);
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
// Delete pending order
| |
bool CTrade::Delete(ulong pTicket)
| |
{
| |
ZeroMemory(request);
| |
ZeroMemory(result);
| |
| |
request.action = TRADE_ACTION_REMOVE;
| |
request.order = pTicket;
| |
| |
// Order loop
| |
int retryCount = 0;
| |
int checkCode = 0;
| |
| |
do
| |
{
| |
bool sent = OrderSend(request,result);
| |
| |
checkCode = CheckReturnCode(result.retcode);
| |
| |
if(checkCode == CHECK_RETCODE_OK) break;
| |
else if(checkCode == CHECK_RETCODE_ERROR)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Delete order: Error ",result.retcode," - ",errDesc);
| |
LogTradeRequest();
| |
break;
| |
}
| |
else
| |
{
| |
Print("Server error detected, retrying...");
| |
Sleep(RETRY_DELAY);
| |
retryCount++;
| |
}
| |
}
| |
while(retryCount < MAX_RETRIES);
| |
| |
if(retryCount >= MAX_RETRIES)
| |
{
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
| |
}
| |
| |
string errDesc = TradeServerReturnCodeDescription(result.retcode);
| |
Print("Delete order #",pTicket,": ",result.retcode," - ",errDesc);
| |
| |
if(checkCode == CHECK_RETCODE_OK)
| |
{
| |
Comment("Pending order ",pTicket," deleted");
| |
return(true);
| |
}
| |
else return(false);
| |
}
| |
| |
| |
void CTrade::LogTradeRequest()
| |
{
| |
Print("MqlTradeRequest - action:",request.action,", comment:",request.comment,", deviation:",request.deviation,", expiration:",request.expiration,", magic:",request.magic,", order:",request.order,", position:",request.position,", position_by:",request.position_by,", price:",request.price,", ls:",request.sl,", stoplimit:",request.stoplimit,", symbol:",request.symbol,", tp:",request.tp,", type:",request.type,", type_filling:",request.type_filling,", type_time:",request.type_time,", volume:",request.volume);
| |
Print("MqlTradeResult - ask:",result.ask,", bid:",result.bid,", comment:",result.comment,", deal:",result.deal,", order:",result.order,", price:",result.price,", request_id:",result.request_id,", retcode:",result.retcode,", retcode_external:",result.retcode_external,", volume:",result.volume);
| |
}
| |
| |
| |
// Trade opening shortcuts
| |
bool CTrade::Buy(string pSymbol,double pVolume,double pStop=0,double pProfit=0,string pComment=NULL)
| |
{
| |
bool success = OpenPosition(pSymbol,ORDER_TYPE_BUY,pVolume,pStop,pProfit,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::Sell(string pSymbol,double pVolume,double pStop=0,double pProfit=0,string pComment=NULL)
| |
{
| |
bool success = OpenPosition(pSymbol,ORDER_TYPE_SELL,pVolume,pStop,pProfit,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::BuyLimit(string pSymbol,double pVolume,double pPrice,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_BUY_LIMIT,pVolume,pPrice,pStop,pProfit,0,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::SellLimit(string pSymbol,double pVolume,double pPrice,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_SELL_LIMIT,pVolume,pPrice,pStop,pProfit,0,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::BuyStop(string pSymbol,double pVolume,double pPrice,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_BUY_STOP,pVolume,pPrice,pStop,pProfit,0,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::SellStop(string pSymbol,double pVolume,double pPrice,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_SELL_STOP,pVolume,pPrice,pStop,pProfit,0,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::BuyStopLimit(string pSymbol,double pVolume,double pPrice,double pStopLimit,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_BUY_STOP_LIMIT,pVolume,pPrice,pStop,pProfit,pStopLimit,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
bool CTrade::SellStopLimit(string pSymbol,double pVolume,double pPrice,double pStopLimit,double pStop=0,double pProfit=0,datetime pExpiration=0,string pComment=NULL)
| |
{
| |
bool success = OpenPending(pSymbol,ORDER_TYPE_SELL_STOP_LIMIT,pVolume,pPrice,pStop,pProfit,pStopLimit,pExpiration,pComment);
| |
return(success);
| |
}
| |
| |
| |
// Set magic number
| |
void CTrade::MagicNumber(ulong pMagic)
| |
{
| |
magicNumber = pMagic;
| |
}
| |
| |
| |
// Set deviation
| |
void CTrade::Deviation(ulong pDeviation)
| |
{
| |
deviation = pDeviation;
| |
}
| |
| |
| |
// Set fill type
| |
void CTrade::FillType(ENUM_ORDER_TYPE_FILLING pFill)
| |
{
| |
fillType = pFill;
| |
}
| |
| |
| |
// Return code check
| |
int CheckReturnCode(uint pRetCode)
| |
{
| |
int status;
| |
switch(pRetCode)
| |
{
| |
case TRADE_RETCODE_REQUOTE:
| |
case TRADE_RETCODE_CONNECTION:
| |
case TRADE_RETCODE_PRICE_CHANGED:
| |
case TRADE_RETCODE_TIMEOUT:
| |
case TRADE_RETCODE_PRICE_OFF:
| |
case TRADE_RETCODE_REJECT:
| |
case TRADE_RETCODE_ERROR:
| |
| |
status = CHECK_RETCODE_RETRY;
| |
break;
| |
| |
case TRADE_RETCODE_DONE:
| |
case TRADE_RETCODE_DONE_PARTIAL:
| |
case TRADE_RETCODE_PLACED:
| |
case TRADE_RETCODE_NO_CHANGES:
| |
| |
status = CHECK_RETCODE_OK;
| |
break;
| |
| |
default: status = CHECK_RETCODE_ERROR;
| |
}
| |
| |
return(status);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Stop Loss & Take Profit Calculation Functions |
| |
//+------------------------------------------------------------------+
| |
| |
double BuyStopLoss(string pSymbol,int pStopPoints, double pOpenPrice = 0)
| |
{
| |
if(pStopPoints <= 0) return(0);
| |
| |
double openPrice;
| |
if(pOpenPrice > 0) openPrice = pOpenPrice;
| |
else openPrice = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLoss = openPrice - (pStopPoints * point);
| |
| |
long digits = SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
| |
stopLoss = NormalizeDouble(stopLoss,(int)digits);
| |
| |
return(stopLoss);
| |
}
| |
| |
| |
double SellStopLoss(string pSymbol,int pStopPoints, double pOpenPrice = 0)
| |
{
| |
if(pStopPoints <= 0) return(0);
| |
| |
double openPrice;
| |
if(pOpenPrice > 0) openPrice = pOpenPrice;
| |
else openPrice = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLoss = openPrice + (pStopPoints * point);
| |
| |
long digits = SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
| |
stopLoss = NormalizeDouble(stopLoss,(int)digits);
| |
| |
return(stopLoss);
| |
}
| |
| |
double SellStopLoss(string pSymbol,double pStopPoints, double pOpenPrice = 0)
| |
{
| |
if(pStopPoints <= 0) return(0);
| |
| |
/*double openPrice;
| |
if(pOpenPrice > 0) openPrice = pOpenPrice;
| |
else openPrice = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLoss = openPrice + (pStopPoints * point);
| |
| |
long digits = SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
| |
stopLoss = NormalizeDouble(stopLoss,(int)digits);*/
| |
| |
return(pStopPoints);
| |
}
| |
| |
| |
| |
| |
| |
| |
| |
double BuyTakeProfit(string pSymbol,int pProfitPoints, double pOpenPrice = 0)
| |
{
| |
if(pProfitPoints <= 0) return(0);
| |
| |
double openPrice;
| |
if(pOpenPrice > 0) openPrice = pOpenPrice;
| |
else openPrice = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double takeProfit = openPrice + (pProfitPoints * point);
| |
| |
long digits = SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
| |
takeProfit = NormalizeDouble(takeProfit,(int)digits);
| |
return(takeProfit);
| |
}
| |
| |
| |
double SellTakeProfit(string pSymbol,int pProfitPoints, double pOpenPrice = 0)
| |
{
| |
if(pProfitPoints <= 0) return(0);
| |
| |
double openPrice;
| |
if(pOpenPrice > 0) openPrice = pOpenPrice;
| |
else openPrice = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double takeProfit = openPrice - (pProfitPoints * point);
| |
| |
long digits = SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
| |
takeProfit = NormalizeDouble(takeProfit,(int)digits);
| |
return(takeProfit);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Stop Level Verification |
| |
//+------------------------------------------------------------------+
| |
| |
| |
// Check stop level (no adjust)
| |
bool CheckAboveStopLevel(string pSymbol, double pPrice, int pPoints = 10)
| |
{
| |
double currPrice = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLevel = SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL) * point;
| |
double stopPrice = currPrice + stopLevel;
| |
double addPoints = pPoints * point;
| |
| |
if(pPrice >= stopPrice + addPoints) return(true);
| |
else return(false);
| |
}
| |
| |
| |
bool CheckBelowStopLevel(string pSymbol, double pPrice, int pPoints = 10)
| |
{
| |
double currPrice = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLevel = SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL) * point;
| |
double stopPrice = currPrice - stopLevel;
| |
double addPoints = pPoints * point;
| |
| |
if(pPrice <= stopPrice - addPoints) return(true);
| |
else return(false);
| |
}
| |
| |
| |
// Adjust stop level
| |
double AdjustAboveStopLevel(string pSymbol, double pPrice, int pPoints = 10)
| |
{
| |
double currPrice = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLevel = SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL) * point;
| |
double stopPrice = currPrice + stopLevel;
| |
double addPoints = pPoints * point;
| |
| |
if(pPrice > stopPrice + addPoints) return(pPrice);
| |
else
| |
{
| |
double newPrice = stopPrice + addPoints;
| |
Print("Price adjusted above stop level to "+DoubleToString(newPrice));
| |
return(newPrice);
| |
}
| |
}
| |
| |
| |
double AdjustBelowStopLevel(string pSymbol, double pPrice, int pPoints = 10)
| |
{
| |
double currPrice = SymbolInfoDouble(pSymbol,SYMBOL_BID);
| |
double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
| |
double stopLevel = SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL) * point;
| |
double stopPrice = currPrice - stopLevel;
| |
double addPoints = pPoints * point;
| |
| |
if(pPrice < stopPrice - addPoints) return(pPrice);
| |
else
| |
{
| |
double newPrice = stopPrice - addPoints;
| |
Print("Price adjusted below stop level to "+DoubleToString(newPrice));
| |
return(newPrice);
| |
}
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Position Information |
| |
//+------------------------------------------------------------------+
| |
| |
| |
string PositionComment(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetString(POSITION_COMMENT));
| |
else return(NULL);
| |
}
| |
| |
| |
long PositionType(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetInteger(POSITION_TYPE));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
long PositionIdentifier(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetInteger(POSITION_IDENTIFIER));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
double PositionOpenPrice(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetDouble(POSITION_PRICE_OPEN));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
long PositionOpenTime(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetInteger(POSITION_TIME));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
double PositionVolume(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetDouble(POSITION_VOLUME));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
double PositionStopLoss(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetDouble(POSITION_SL));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
double PositionTakeProfit(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetDouble(POSITION_TP));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
double PositionProfit(string pSymbol = NULL)
| |
{
| |
if(pSymbol == NULL) pSymbol = _Symbol;
| |
bool select = PositionSelect(pSymbol);
| |
if(select == true) return(PositionGetDouble(POSITION_PROFIT));
| |
else return(WRONG_VALUE);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Miscellaneous Functions & Enumerations |
| |
//+------------------------------------------------------------------+
| |
| |
| |
enum ENUM_CHECK_RETCODE
| |
{
| |
CHECK_RETCODE_OK,
| |
CHECK_RETCODE_ERROR,
| |
CHECK_RETCODE_RETRY
| |
};
| |
| |
| |
string CheckOrderType(ENUM_ORDER_TYPE pType)
| |
{
| |
string orderType;
| |
if(pType == ORDER_TYPE_BUY) orderType = "buy";
| |
else if(pType == ORDER_TYPE_SELL) orderType = "sell";
| |
else if(pType == ORDER_TYPE_BUY_STOP) orderType = "buy stop";
| |
else if(pType == ORDER_TYPE_BUY_LIMIT) orderType = "buy limit";
| |
else if(pType == ORDER_TYPE_SELL_STOP) orderType = "sell stop";
| |
else if(pType == ORDER_TYPE_SELL_LIMIT) orderType = "sell limit";
| |
else if(pType == ORDER_TYPE_BUY_STOP_LIMIT) orderType = "buy stop limit";
| |
else if(pType == ORDER_TYPE_SELL_STOP_LIMIT) orderType = "sell stop limit";
| |
else orderType = "invalid order type";
| |
return(orderType);
| |
} |