624 lines
19 KiB
MQL5
624 lines
19 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| ProjectName |
| |||
//| Copyright 2020, CompanyName |
| |||
//| http://www.companyname.net |
| |||
//+------------------------------------------------------------------+
| |||
| |||
| |||
#include <errordescription.mqh>
| |||
#include "Trade.mqh"
| |||
| |||
enum Signal
| |||
{
| |||
SIGNAL_BUY,
| |||
SIGNAL_SELL,
| |||
SIGNAL_NONE,
| |||
| |||
};
| |||
| |||
string tradeResponse = "";
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
class CTradeHedge : public CTrade
| |||
{
| |||
protected:
| |||
ulong OpenPosition(string pSymbol, ENUM_ORDER_TYPE pType, double pVolume, double pStop = 0, double pProfit = 0, string pComment = "Concrete Goonies");
| |||
string orderType;
| |||
public:
| |||
ulong Buy(string pSymbol, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL);
| |||
ulong Sell(string pSymbol, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL);
| |||
| |||
bool ModifyPosition(ulong pTicket, double pStop, double pProfit = 0);
| |||
bool Close(ulong pTicket, double pVolume = 0, string pComment = NULL);
| |||
};
| |||
| |||
| |||
// Open position
| |||
ulong CTradeHedge::OpenPosition(string pSymbol, ENUM_ORDER_TYPE pType, double pVolume, double pStop = 0, double pProfit = 0, string pComment = "Concrete Goonies")
| |||
{
| |||
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.volume = pVolume;
| |||
request.deviation = deviation;
| |||
request.type_filling = fillType;
| |||
request.magic = magicNumber;
| |||
| |||
int retryCount = -1;
| |||
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);
| |||
tradeResponse = "";
| |||
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);
| |||
| |||
if(checkCode == CHECK_RETCODE_OK)
| |||
{
| |||
//Comment(orderType," position #",result.order," opened at ",result.price," on ",pSymbol);
| |||
return(result.order);
| |||
}
| |||
else
| |||
return(0);
| |||
}
| |||
| |||
| |||
// Modify position
| |||
bool CTradeHedge::ModifyPosition(ulong pTicket, double pStop, double pProfit = 0)
| |||
{
| |||
ZeroMemory(request);
| |||
ZeroMemory(result);
| |||
| |||
bool select = PositionSelectByTicket(pTicket);
| |||
string symbol = PositionGetString(POSITION_SYMBOL);
| |||
double price = PositionGetDouble(POSITION_PRICE_OPEN);
| |||
| |||
request.action = TRADE_ACTION_SLTP;
| |||
request.sl = pStop;
| |||
request.tp = pProfit;
| |||
request.position = pTicket;
| |||
request.symbol = symbol;
| |||
| |||
// 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);
| |||
//Comment("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 #",pTicket,": ",result.retcode," - ",errDesc,", SL: ",request.sl,", TP: ",request.tp,", Bid: ",SymbolInfoDouble(symbol,SYMBOL_BID),", Ask: ",SymbolInfoDouble(symbol,SYMBOL_ASK),", Stop Level: ",SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL));
| |||
| |||
double pi_8 = NormalizeDouble(price, _Digits);
| |||
double pi_11 = NormalizeDouble(request.sl, _Digits);
| |||
double pi_10 = NormalizeDouble(request.tp, _Digits);
| |||
long posType = PositionGetInteger(POSITION_TYPE);
| |||
| |||
| |||
if(posType == POSITION_TYPE_BUY)
| |||
{
| |||
orderType = "Buy";
| |||
}
| |||
else
| |||
if(posType == POSITION_TYPE_SELL)
| |||
{
| |||
orderType = "Sell";
| |||
}
| |||
if(checkCode == CHECK_RETCODE_OK)
| |||
{
| |||
Alert(orderType, " - Price: ", DoubleToString(pi_8, _Digits), ", SL: ", DoubleToString(pi_11, _Digits), ", TP: ", DoubleToString(pi_10, _Digits));
| |||
| |||
/* open = DoubleToString(pi_8, _Digits);
| |||
sl = DoubleToString(pi_11, _Digits);
| |||
tp = DoubleToString(pi_10, _Digits);*/
| |||
return(true);
| |||
}
| |||
else
| |||
return(false);
| |||
| |||
}
| |||
| |||
| |||
// Close position
| |||
bool CTradeHedge::Close(ulong pTicket, double pVolume = 0, string pComment = NULL)
| |||
{
| |||
ZeroMemory(request);
| |||
ZeroMemory(result);
| |||
| |||
request.action = TRADE_ACTION_DEAL;
| |||
request.position = pTicket;
| |||
request.deviation = deviation;
| |||
request.type_filling = fillType;
| |||
request.comment = "Concrete Goonies";
| |||
double closeVol = 0;
| |||
long openType = WRONG_VALUE;
| |||
string symbol;
| |||
| |||
if(PositionSelectByTicket(pTicket) == true)
| |||
{
| |||
closeVol = PositionGetDouble(POSITION_VOLUME);
| |||
openType = PositionGetInteger(POSITION_TYPE);
| |||
symbol = PositionGetString(POSITION_SYMBOL);
| |||
}
| |||
else
| |||
return(false);
| |||
| |||
request.symbol = symbol;
| |||
| |||
if(pVolume > closeVol || pVolume <= 0)
| |||
request.volume = closeVol;
| |||
else
| |||
request.volume = pVolume;
| |||
| |||
// Order loop
| |||
int retryCount = -1;
| |||
int checkCode = 0;
| |||
| |||
do
| |||
{
| |||
if(openType == POSITION_TYPE_BUY)
| |||
{
| |||
request.type = ORDER_TYPE_SELL;
| |||
request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
| |||
}
| |||
else
| |||
if(openType == POSITION_TYPE_SELL)
| |||
{
| |||
request.type = ORDER_TYPE_BUY;
| |||
request.price = SymbolInfoDouble(symbol, 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 #",pTicket,": ",result.retcode," - ",errDesc,", Volume: ",result.volume,", Price: ",result.price);
| |||
| |||
if(checkCode == CHECK_RETCODE_OK)
| |||
{
| |||
//Comment(posType," position closed on ",symbol," at ",result.price);
| |||
return(true);
| |||
}
| |||
else
| |||
return(false);
| |||
}
| |||
| |||
| |||
// Trade opening shortcuts
| |||
ulong CTradeHedge::Buy(string pSymbol, double pVolume, double pStop , double pProfit , string pComment )
| |||
{
| |||
ulong ticket = OpenPosition(pSymbol, ORDER_TYPE_BUY, pVolume, pStop, pProfit, pComment);
| |||
return(ticket);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
ulong CTradeHedge::Sell(string pSymbol, double pVolume, double pStop = 0, double pProfit = 0, string pComment = NULL)
| |||
{
| |||
ulong ticket = OpenPosition(pSymbol, ORDER_TYPE_SELL, pVolume, pStop, pProfit, pComment);
| |||
return(ticket);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Position Tickets & Counts |
| |||
//+------------------------------------------------------------------+
| |||
| |||
| |||
// Open position information
| |||
class CPositions
| |||
{
| |||
protected:
| |||
ulong BuyTickets[];
| |||
ulong SellTickets[];
| |||
ulong Tickets[];
| |||
int BuyCount;
| |||
int SellCount;
| |||
int TotalCount;
| |||
| |||
void GetOpenPositions(ulong pMagicNumber = 0);
| |||
int ResizeArray(ulong &array[]);
| |||
| |||
| |||
public:
| |||
int Buy(ulong pMagicNumber);
| |||
int Sell(ulong pMagicNumber);
| |||
int TotalPositions(ulong pMagicNumber);
| |||
| |||
void GetBuyTickets(ulong pMagicNumber, ulong &pTickets[]);
| |||
void GetSellTickets(ulong pMagicNumber, ulong &pTickets[]);
| |||
int GetTickets(ulong pMagicNumber, ulong &pTickets[]);
| |||
};
| |||
| |||
// Get open positions
| |||
void CPositions::GetOpenPositions(ulong pMagicNumber = 0)
| |||
{
| |||
BuyCount = 0;
| |||
SellCount = 0;
| |||
TotalCount = 0;
| |||
| |||
ArrayResize(BuyTickets, 17);
| |||
ArrayInitialize(BuyTickets, 0);
| |||
| |||
ArrayResize(SellTickets, 17);
| |||
ArrayInitialize(SellTickets, 0);
| |||
| |||
ArrayResize(Tickets, 17);
| |||
ArrayInitialize(Tickets, 0);
| |||
| |||
for(int i = 0; i < PositionsTotal(); i++)
| |||
{
| |||
ulong ticket = PositionGetTicket(i);
| |||
PositionSelectByTicket(ticket);
| |||
| |||
if(PositionGetInteger(POSITION_MAGIC) != pMagicNumber && pMagicNumber > 0)
| |||
continue;
| |||
| |||
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
| |||
{
| |||
BuyCount++;
| |||
int arrayIndex = ResizeArray(BuyTickets);
| |||
BuyTickets[arrayIndex] = PositionGetInteger(POSITION_TICKET);
| |||
}
| |||
else
| |||
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
| |||
{
| |||
SellCount++;
| |||
int arrayIndex = ResizeArray(SellTickets);
| |||
SellTickets[arrayIndex] = PositionGetInteger(POSITION_TICKET);
| |||
}
| |||
| |||
TotalCount++;
| |||
int arrayIndex = ResizeArray(Tickets);
| |||
Tickets[arrayIndex] = PositionGetInteger(POSITION_TICKET);
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
int CPositions::ResizeArray(ulong &array[])
| |||
{
| |||
int arrayIndex = 0;
| |||
if(ArraySize(array) > 1)
| |||
{
| |||
int newSize = ArrayResize(array, ArraySize(array) + 1);
| |||
arrayIndex = newSize - 1;
| |||
}
| |||
| |||
return arrayIndex;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
int CPositions::Buy(ulong pMagicNumber)
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
return(BuyCount);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
int CPositions::Sell(ulong pMagicNumber)
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
return(SellCount);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
int CPositions::TotalPositions(ulong pMagicNumber)
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
return(TotalCount);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
void CPositions::GetBuyTickets(ulong pMagicNumber, ulong &pTickets[])
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
ArrayCopy(pTickets, BuyTickets);
| |||
return;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
void CPositions::GetSellTickets(ulong pMagicNumber, ulong &pTickets[])
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
ArrayCopy(pTickets, SellTickets);
| |||
return;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
int CPositions::GetTickets(ulong pMagicNumber, ulong &pTickets[])
| |||
{
| |||
GetOpenPositions(pMagicNumber);
| |||
ArrayCopy(pTickets, Tickets);
| |||
return(WRONG_VALUE);
| |||
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Position Information Functions |
| |||
//+------------------------------------------------------------------+
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
string PositionComment(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetString(POSITION_COMMENT));
| |||
else
| |||
return(NULL);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
long PositionType(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetInteger(POSITION_TYPE));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
long PositionIdentifier(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetInteger(POSITION_IDENTIFIER));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
double PositionOpenPrice(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetDouble(POSITION_PRICE_OPEN));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
long PositionOpenTime(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetInteger(POSITION_TIME));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
double PositionVolume(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetDouble(POSITION_VOLUME));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
double PositionStopLoss(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetDouble(POSITION_SL));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
double PositionTakeProfit(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetDouble(POSITION_TP));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
double PositionProfit(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetDouble(POSITION_PROFIT));
| |||
else
| |||
return(WRONG_VALUE);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
long PositionMagicNumber(ulong pTicket = 0)
| |||
{
| |||
bool select = false;
| |||
if(pTicket > 0)
| |||
select = PositionSelectByTicket(pTicket);
| |||
| |||
if(select == true)
| |||
return(PositionGetInteger(POSITION_MAGIC));
| |||
else
| |||
return(NULL);
| |||
}
| |||
//+------------------------------------------------------------------+
|