//+------------------------------------------------------------------+ //| ProjectName | //| Copyright 2020, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #include #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); } //+------------------------------------------------------------------+