877 lines
26 KiB
MQL5
877 lines
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);
| |||
}
|