diff --git a/Classes/x-saherelm.x-chart.helper.class.mq5 b/Classes/x-saherelm.x-chart.helper.class.mq5 index 9a647cf3..43156c89 100644 --- a/Classes/x-saherelm.x-chart.helper.class.mq5 +++ b/Classes/x-saherelm.x-chart.helper.class.mq5 @@ -322,6 +322,46 @@ class XCChartHelper : public XCBase return (ChartGetDouble(mChartID, CHART_PRICE_MAX, subWindow)); } + /** + * Get Chart Width in Pixel ... + * + * @param subWindow: int ... + * + * @return ( int ) + */ + int Width(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (int)ChartGetInteger(mChartID, CHART_WIDTH_IN_PIXELS, subWindow); + } + + /** + * Get Chart Height in Pixel ... + * + * @param subWindow: int ... + * + * @return ( int ) + */ + int Height(int subWindow = 0) + { + // + // Normalize Subwindow ... + if (subWindow <= 0) + { + subWindow = 0; + } + + // + return (int)ChartGetInteger(mChartID, CHART_HEIGHT_IN_PIXELS, subWindow); + } + // // Protected ... protected: diff --git a/Classes/x-saherelm.x-trade.class.mq5 b/Classes/x-saherelm.x-trade.class.mq5 index 62b0f9ff..4fd81d05 100644 --- a/Classes/x-saherelm.x-trade.class.mq5 +++ b/Classes/x-saherelm.x-trade.class.mq5 @@ -1930,7 +1930,7 @@ class XCTrade : public XCBase // Close a Collection of Positions ... int Close( XPosition &positions[], // Collection of Positions - string comment // Close Comment + string comment = NULL // Close Comment ) { // diff --git a/Experts/x-saherelm.backtester.mq5 b/Experts/x-saherelm.backtester.mq5 index df6f8bd0..f0b390c1 100644 --- a/Experts/x-saherelm.backtester.mq5 +++ b/Experts/x-saherelm.backtester.mq5 @@ -84,14 +84,25 @@ CButton btnBuy; CButton btnSell; CButton btnClose; CButton btnCloseAll; -CButton btnSelectedPosInfo; // CEdit lblPositionId; + +// +CButton *btnSelectedPosInfo; +CArrayObj selectedPosInfoArr; + +// +int btnCloseSizeX = 0; +int btnCloseSizeY = 0; +int btnCloseStartX = 0; +int btnCloseStartY = 0; int lblPositionIdSizeX = 0; int lblPositionIdSizeY = 0; int lblPositionIdStartX = 0; int lblPositionIdStartY = 0; + +// ulong selectedPositionID = 0; // @@ -463,10 +474,10 @@ bool InitGUI() // // Close ... - int btnCloseStartX = startX; - int btnCloseSizeX = btnCloseStartX + 100; - int btnCloseStartY = lblPositionIdSizeY + 5; - int btnCloseSizeY = lblPositionIdSizeY + 50; + btnCloseStartX = startX; + btnCloseSizeX = btnCloseStartX + 100; + btnCloseStartY = lblPositionIdSizeY + 5; + btnCloseSizeY = lblPositionIdSizeY + 50; string btnCloseName = objSuffix + "BTN_CLOSE"; result = btnClose.Create( chartId, @@ -580,6 +591,59 @@ void UpdateGUI() btnCloseAll.Pressed(false); } + // + // Check Show Hide Selected Position Info ... + if (btnSelectedPosInfo != NULL) + { + // + if (btnSelectedPosInfo.Pressed()) + { + // + // Check Enable ... + if (btnSelectedPosInfo.IsEnabled()) + { + // + // Handle Toggle Show/Hide lblSelectedPositionInfo ... + CEdit *iLbl = NULL; + bool isVisible = false; + int count = selectedPosInfoArr.Total(); + if (IsValidSize(count)) + { + // + // Loop Through Labels ... + for (int i = 0; i < count; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + isVisible = iLbl.IsVisible(); + if (isVisible) + { + iLbl.Hide(); + } + else + { + iLbl.Show(); + } + } + + // + // Update Button Text ... + isVisible = iLbl.IsVisible(); + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + } + + // + ZeroMemory(iLbl); + } + + // + btnSelectedPosInfo.Pressed(false); + } + } + // // Check Positions Buttons ... int posCount = posArray.Total(); @@ -604,7 +668,6 @@ void UpdateGUI() { selectedPositionID = posID; UpdateGUIState(); - Print("Changed Selected Pos ID: ", selectedPositionID); } } @@ -628,6 +691,8 @@ void DestroyGUI() ZeroMemory(mChartHelper); // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); } // @@ -640,6 +705,8 @@ void DestroyGUI() */ void OnStopLossTriggered(const XDeal &deal) { + // + UpdatePositionButtons(); } /** @@ -649,6 +716,8 @@ void OnStopLossTriggered(const XDeal &deal) */ void OnTakeProfitTriggered(const XDeal &deal) { + // + UpdatePositionButtons(); } /** @@ -664,6 +733,8 @@ void OnPositionForceClosed( const string comment // ) { + // + UpdatePositionButtons(); } /** @@ -824,14 +895,31 @@ void HandleCloseTrade(ulong positionID) if (positionID == 0) { // - // Force Close All ... - Print("Close All Positions ..."); + XPosition positions[]; + int count = eaTrader.GetPositions( + positions // + ); + bool has = IsValidSize(count); + if (has) + { + // + int closedCount = eaTrader.Close(positions); + has = IsValidSize(closedCount); + } } else { // - // Close Specified Position ... - Print("Close Position: ", positionID); + XPosition position; + bool has = eaTrader.GetPosition( + positionID, + position // + ); + if (has) + { + // + has = eaTrader.Close(positionID); + } } } @@ -854,7 +942,7 @@ ulong ExtractPositionIDFromButtonName(string name) } // - SpecifiedClean(nameParts); + ZeroMemory(nameParts); // return result; @@ -875,6 +963,7 @@ void UpdatePositionButtons() // posArray.Clear(); selectedPositionID = 0; + UpdateGUIState(); return; } @@ -883,7 +972,24 @@ void UpdatePositionButtons() // // Selected Position ID ... - if (selectedPositionID == 0) + bool isSelectdPositionIDExists = false; + if (has && selectedPositionID > 0) + { + // + for (int i = 0; i < count; i++) + { + // + if (!isSelectdPositionIDExists && + positions[i].ticket == selectedPositionID) + { + // + isSelectdPositionIDExists = true; + break; + } + } + } + if (!isSelectdPositionIDExists || + selectedPositionID == 0) { // XPosition youngest; @@ -922,8 +1028,8 @@ void UpdatePositionButtons() // string posTypeStr = IsLong(iPos.type) - ? "LONG" - : "SHORT"; + ? "LONG" + : "SHORT"; // int iPosBtnX = lastX; @@ -975,7 +1081,7 @@ void UpdatePositionButtons() } // - SpecifiedClean(positions); + ZeroMemory(positions); UpdateGUIState(); } @@ -1052,6 +1158,220 @@ void UpdateGUIState() btnCloseAll.ColorBackground(clrDarkGray); } + // + // Update Selected Position Info Button State ... + if (has) + { + // + // Reading Global Chart Info ... + int subWindow = 0; + int chartWidth = mChartHelper.Width(); + ulong chartId = mChartHelper.ChartId(); + + // + // Read Selected Position ... + XPosition selectedPosition; + bool hasPosition = eaTrader.GetPosition( + selectedPositionID, + selectedPosition // + ); + if (hasPosition) + { + // + // Preparing Position Info ... + string posTicket = "Ticket: " + ToXString(selectedPosition.ticket); + string posType = "Type: " + ToXString(selectedPosition.type); + string posProfit = "Profit: " + ToXString(selectedPosition.profit); + string posRiskToRewardRatio = "RiskToReward: " + ToXString(selectedPosition.GetRiskRewardRatio()); + + // + string posInfos[] = { + posTicket, + posType, + posProfit, + posRiskToRewardRatio, // + }; + + // + if (btnSelectedPosInfo == NULL) + { + // + btnSelectedPosInfo = new CButton(); + + // + string name = objSuffix + "BTN_TOOGLE_SPOS_INFO"; + + // + int btnStartX = btnCloseStartX; + int btnSizeX = btnStartX + 200 + 5; + + // + int btnStartY = btnCloseSizeY + 5; + int btnSizeY = btnStartY + 50; + + // + bool isCreated = btnSelectedPosInfo.Create( + chartId, + name, + subWindow, + btnStartX, + btnStartY, + btnSizeX, + btnSizeY // + ); + if (!isCreated) + { + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + else + { + // + // Apply Styles ... + btnSelectedPosInfo.Color(clrYellow); + btnSelectedPosInfo.ColorBackground(clrDarkBlue); + } + } + + // + // Check Btn Exists ... + has = btnSelectedPosInfo != NULL; + if (has) + { + // + int posInfoCount = ArraySize(posInfos); + int lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount); + + // + // Create info Labels ... + if (!has) + { + // + has = IsValidSize(posInfoCount); + if (has) + { + // + // Creat Info Control ... + + // + string name = objSuffix + "LBL_SPOS_INFO"; + + // + int lblHeight = 25; + + // + int startX = chartWidth - 300 - 5; + int sizeX = startX + 300; + + // + int startY = 5; + int sizeY = startY + lblHeight; + + // + // Loop through Position Info's Array to Create Label Controls ... + for (int i = 0; i < posInfoCount; i++) + { + // + string iText = posInfos[i]; + string iTextMD5 = ToMD5(iText); + + // + string iName = name + "_" + iTextMD5; + + // + int iX1 = startX; + int iX2 = sizeX; + + // + int iY1 = startY; + int iY2 = startY + lblHeight; + + // + CEdit *iLbl = new CEdit(); + bool isCreated = iLbl.Create( + chartId, + iName, + subWindow, + iX1, + iY1, + iX2, + iY2 // + ); + if (isCreated) + { + // + iLbl.Text(iText); + iLbl.Color(clrYellow); + iLbl.ColorBorder(clrDarkSlateGray); + iLbl.ColorBackground(clrDarkSlateGray); + + // + selectedPosInfoArr.Add(iLbl); + + // + startY = iY2; + } + } + } + } + + // + // Update Info Labels ... + lblInfoCount = selectedPosInfoArr.Total(); + has = IsValidSize(lblInfoCount); + if (has) + { + // + CEdit *iLbl = NULL; + + // + // Loop Through Infos ... + for (int i = 0; i < lblInfoCount; i++) + { + // + iLbl = (CEdit *)selectedPosInfoArr.At(i); + + // + iLbl.Text(posInfos[i]); + } + + // + bool isVisible = iLbl.IsVisible(); + string btnText = isVisible + ? "Hide Info" + : "Show Info"; + btnSelectedPosInfo.Text(btnText); + + // + ZeroMemory(iLbl); + } + } + + // + ZeroMemory(posInfos); + } + } + else + { + // + // Toggle Selected Position Btn ... + if (btnSelectedPosInfo != NULL) + { + // + btnSelectedPosInfo.Destroy(); + + // + delete btnSelectedPosInfo; + ZeroMemory(btnSelectedPosInfo); + } + + // + // Selected Position Lbls ... + selectedPosInfoArr.Clear(); + } + // // Update State of BtnClose and BtnClose All ... if (selectedPositionID == 0) diff --git a/Libraries/x-saherelm.common.extensions.lib.mq5 b/Libraries/x-saherelm.common.extensions.lib.mq5 index 5ffe946e..f8be0216 100644 --- a/Libraries/x-saherelm.common.extensions.lib.mq5 +++ b/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -1489,6 +1489,7 @@ string ToMD5(T content) result = md5.Hash(strContent); // + delete md5; ZeroMemory(md5); // @@ -3903,7 +3904,12 @@ template void Clean(T &buffer[]) { // - ArrayResize(buffer, 0); + if (!HasChild(buffer)) { + return; + } + + // + // ArrayResize(buffer, 0); ArrayFree(buffer); ZeroMemory(buffer); } diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 7ac2a1c2..4667e0fa 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -198,6 +198,10 @@ string ToString(ENUM_X_POSITION_TYPES value) // return result; } +string ToXString(ENUM_X_POSITION_TYPES value) +{ + return ToString(value); +} // bool IsLong(ENUM_X_POSITION_TYPES value)