/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XCBackTesterEA // Description: Back Tester Expert Class ... // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" #include "../Classes/x-saherelm.x-alert.class.mq5" #include "../Classes/x-saherelm.x-chart.helper.class.mq5" #include "../Classes/x-saherelm.x-trade.class.mq5" #include "../Classes/x-saherelm.x-volume.class.mq5" // // Import Chart Objects ... #include #include #include #include #include #include #include #include #include #include #include // // Definitions ... // // Implementation ... class XCBackTesterEA : public XCBase { // // Public ... public: // // // Common ... long eaMagicNumber; // Magic Number int eaSlippage; // Slippgae string eaLogSuffix; // Log Suffix // // Symbol / Period ... string symbol; // Symbol ENUM_TIMEFRAMES period; // Period // // Alert ... bool eaEnableAlerts; // Enable Alerts bool eaLogAlerts; // Log Alerts bool eaMailAlerts; // Mail Alerts bool eaPushAlerts; // Push Alerts bool eaTerminalAlerts; // Terminal Alerts // // Constructor ... XCBackTesterEA() { selectedPositionID = 0; } // // Deconstructor ... ~XCBackTesterEA() { } // // Actions / Handlers ... // // Expert Advisor Event Handlers ... /** * Handle Initialization of Expert ... * * @return ( bool ) */ bool HandleOnInit() { // bool result = false; // // Validate Inputs ... result = ValidateInputs(); if (!result) { return result; } // int count = 0; bool has = false; // // Initialize Alert Handler ... eaAlert = new XCAlert(); eaAlert.SetPrefix(eaLogSuffix); eaAlert.SetLogAlerts(eaLogAlerts); eaAlert.SetMailAlerts(eaMailAlerts); eaAlert.SetPushAlerts(eaPushAlerts); eaAlert.SetEnableAlerts(eaEnableAlerts); eaAlert.SetTerminalAlerts(eaTerminalAlerts); // // Initialize Trader ... eaTrader = new XCTrade( eaSlippage, eaMagicNumber, 0, 0, 0 // ); // // Trade Handler Attachments ... // // Position Modifiy Event Handlers ... count = ArraySize(mOnModifyEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); } } // // Position Stop Loss Event Handlers ... count = ArraySize(mStopLossEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); } } // // Position Take Profit Event Handlers ... count = ArraySize(mTakeProfitEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); } } // // Position Force Close Event Handlers ... count = ArraySize(mOnForceCloseEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); } } // // Deals Changed Event Handlers ... count = ArraySize(mDealsChangedEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); } } // // Orders Changed Event Handlers ... count = ArraySize(mOrdersChangedEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); } } // // Positions Changed Event Handlers ... count = ArraySize(mPositionsChangedEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); } } // // Trade Changed Event Handlers ... count = ArraySize(mTradeStateChangedEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); } } // // Postion Partially Close Event Handlers ... count = ArraySize(mOnPartialCloseEventHandlers); has = IsValidSize(count); if (has) { // for (int i = 0; i < count; i++) { eaTrader.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); } } // // Initial GUI ... result = InitGUI(); if (!result) { return result; } // return result; } /** * Handle De Initialization of Expert ... */ void HandleOnDeInit() { // delete eaTrader; ZeroMemory(eaTrader); // SpecifiedClean(mOnModifyEventHandlers); SpecifiedClean(mStopLossEventHandlers); SpecifiedClean(mTakeProfitEventHandlers); SpecifiedClean(mOnForceCloseEventHandlers); SpecifiedClean(mDealsChangedEventHandlers); SpecifiedClean(mOrdersChangedEventHandlers); SpecifiedClean(mOnPartialCloseEventHandlers); SpecifiedClean(mPositionsChangedEventHandlers); SpecifiedClean(mTradeStateChangedEventHandlers); // DestroyGUI(); // string message = "DeInitialized Successfully ..."; eaAlert.SendAlert(message); // delete eaAlert; ZeroMemory(eaAlert); } /** * Handle Tick ... */ void HandleOnTick() { UpdateGUI(); } /** * Handle Trade ... */ void HandleOnTrade() { } /** * Handle Timer ... */ void HandleOnTimer() { } /** * Handle Chart Event ... * * @param id: int, Event id ... * @param lparam: long, Event Long Parameter ... * @param dparam: double, Event Double Parameter ... * @param sparam: string, Event String Parameter ... */ void HandleOnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam // ) { } // // Validators ... /** * Validate Inputs ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = false; // // TODO: Handle this ... result = true; // return result; } // // Trade Event Handlers ... /** * Handle Stop Loss Event Triggered ... * * @param deal: XDeal instance refrence, provides Triggered Deal info ... */ void HandleOnStopLossTriggered(const XDeal &deal) { // // Update Position Buttons ... UpdatePositionButtons(); } /** * Handle Take Profit Event Triggered ... * * @param deal: XDeal instance refrence, provides Triggered Deal info ... */ void HandleOnTakeProfitTriggered(const XDeal &deal) { // // Update Position Buttons ... UpdatePositionButtons(); } /** * Handle Position Force Closed Event ... * * @param ticket: ulong, triggered Positions ticket ... * @param position: XPosition instance refrence, Triggered Position ... * @param comment: string, Comment ... */ void HandleOnPositionForceClosed( const ulong ticket, const XPosition &position, const string comment // ) { // // Update Position Buttons ... UpdatePositionButtons(); } /** * Handle Position Partially Closed Event ... * * @param ticket: ulong, triggered Positions ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void HandleOnPositionPartialClosed( const ulong ticket, const double profit, const string comment // ) { } /** * Handle Deals Changed ... * * @param count: int, number of changes ... * if the count is positive, means new added ... * if the count is negative, means removed ... */ void HandleOnDealsChanged(int count) { } /** * Handle Orders Changed ... * * @param count: int, number of changes ... * if the count is positive, means new added ... * if the count is negative, means removed ... */ void HandleOnOrdersChanged(int count) { } /** * Handle Positions Changed ... * * @param count: int, number of changes ... * if the count is positive, means new added ... * if the count is negative, means removed ... */ void HandleOnPositionsChanged(int count) { // // Update Position Buttons ... UpdatePositionButtons(); } /** * Handle Position Modified Event ... * * @param ticket: ulong, triggered Positions ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void HandleOnPositionModified( const ulong ticket, const double profit, const string comment // ) { } /** * Handle all Trades States Changed Event ... * * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... */ void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) { } // // Props and Setter / Getter (s) ... // // Trade Event Listeners ... // void AddOnStopLossEventHandler(TOnStopLoss handler) { // if (handler == NULL) { return; } // Add( handler, mStopLossEventHandlers // ); } // void AddOnTakeProfitEventHandler(TOnTakeProfit handler) { // if (handler == NULL) { return; } // Add( handler, mTakeProfitEventHandlers // ); } // void AddOnDealsChangedEventHandler(TOnDealsChanged handler) { // if (handler == NULL) { return; } // Add( handler, mDealsChangedEventHandlers // ); } // void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) { // if (handler == NULL) { return; } // Add( handler, mOrdersChangedEventHandlers // ); } // void AddOnModifyPositionEventHandler(TOnModify handler) { // if (handler == NULL) { return; } // Add( handler, mOnModifyEventHandlers // ); } // void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) { // if (handler == NULL) { return; } // Add( handler, mPositionsChangedEventHandlers // ); } // void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) { // if (handler == NULL) { return; } // Add( handler, mTradeStateChangedEventHandlers // ); } // void AddOnForceClosePositionEventHandler(TOnForceClose handler) { // if (handler == NULL) { return; } // Add( handler, mOnForceCloseEventHandlers // ); } // void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) { // if (handler == NULL) { return; } // Add( handler, mOnPartialCloseEventHandlers // ); } // // Protected ... protected: // // Private ... private: // // Props ... // XCAlert *eaAlert; // EA Scope Alert Handler ... XCTrade *eaTrader; // EA Scope Trade Handler ... // // Trade Event Listeners ... TOnModify mOnModifyEventHandlers[]; TOnStopLoss mStopLossEventHandlers[]; TOnTakeProfit mTakeProfitEventHandlers[]; TOnForceClose mOnForceCloseEventHandlers[]; TOnDealsChanged mDealsChangedEventHandlers[]; TOnOrdersChanged mOrdersChangedEventHandlers[]; TOnPartialClose mOnPartialCloseEventHandlers[]; TOnPositionsChanged mPositionsChangedEventHandlers[]; TOnTradeStateChanged mTradeStateChangedEventHandlers[]; // XCChartHelper *mChartHelper; // Chart Helper Class ... // // Object Props ... // string objSuffix; // CButton btnBuy; CButton btnSell; CButton btnClose; CButton btnCloseAll; CEdit lblPositionId; // CArrayObj posArray; CButton *btnSelectedPosInfo; CArrayObj selectedPosInfoArr; // int btnCloseSizeX; int btnCloseSizeY; int btnCloseStartX; int btnCloseStartY; int lblPositionIdSizeX; int lblPositionIdSizeY; int lblPositionIdStartX; int lblPositionIdStartY; // ulong selectedPositionID; // // GUI Event(s) ... /** * Initialize all GUI Requirements for EA ... * * @return ( bool ) */ bool InitGUI() { // bool result = false; // int subWindow = 0; ulong chartId = ChartID(); objSuffix = eaLogSuffix + "_"; // // Initial Chart Class Instance ... mChartHelper = new XCChartHelper(chartId); // int startX = 5; int startY = 25; // int defaultGap = 5; int defaultWidth = 100; int defaultHeight = 30; // // Buy ... int btnBuyStartX = startX; int btnBuySizeX = startX + defaultWidth; int btnBuyStartY = startY; int btnBuySizeY = startY + defaultHeight; string btnBuyName = objSuffix + "BTN_BUY"; result = btnBuy.Create( chartId, btnBuyName, subWindow, btnBuyStartX, btnBuyStartY, btnBuySizeX, btnBuySizeY // ); if (result) { // // Apply Buy Button Style ... // btnBuy.Text("Buy"); btnBuy.Color(clrYellow); btnBuy.ColorBackground(clrGreen); } // // Sell ... int btnSellStartX = btnBuyStartX + btnBuySizeX; int btnSellSizeX = btnSellStartX + defaultWidth; int btnSellStartY = btnBuyStartY; int btnSellSizeY = btnBuySizeY; string btnSellName = objSuffix + "BTN_SELL"; result = btnSell.Create( chartId, btnSellName, subWindow, btnSellStartX, btnSellStartY, btnSellSizeX, btnSellSizeY // ); if (result) { // // Apply Sell Button Style ... // btnSell.Text("Sell"); btnSell.Color(clrYellow); btnSell.ColorBackground(clrDarkRed); } // // LABEL Position ID ... lblPositionIdStartX = btnBuyStartX; lblPositionIdSizeX = lblPositionIdStartX + defaultWidth; lblPositionIdStartY = btnSellSizeY + defaultGap; lblPositionIdSizeY = lblPositionIdStartY + defaultHeight; string lblPositionIdName = objSuffix + "LBL_POS_ID"; result = lblPositionId.Create( chartId, lblPositionIdName, subWindow, lblPositionIdStartX, lblPositionIdStartY, lblPositionIdSizeX, lblPositionIdSizeY // ); if (result) { // // Apply Label Position ID Style ... lblPositionId.ReadOnly(true); lblPositionId.Text("Pos ID: "); lblPositionId.Color(clrYellow); lblPositionId.ColorBackground(clrDarkGray); } // // Close ... btnCloseStartX = startX; btnCloseSizeX = btnCloseStartX + defaultWidth; btnCloseStartY = lblPositionIdSizeY + defaultGap; btnCloseSizeY = lblPositionIdSizeY + defaultHeight; string btnCloseName = objSuffix + "BTN_CLOSE"; result = btnClose.Create( chartId, btnCloseName, subWindow, btnCloseStartX, btnCloseStartY, btnCloseSizeX, btnCloseSizeY // ); if (result) { // // Apply Close Button Style ... // btnClose.Text("Close"); btnClose.Color(clrYellow); btnClose.ColorBackground(clrDarkOrange); } // // Close All ... int btnCloseAllStartX = btnCloseSizeX + defaultGap; int btnCloseAllSizeX = btnCloseAllStartX + defaultWidth; int btnCloseAllStartY = lblPositionIdSizeY + defaultGap; int btnCloseAllSizeY = lblPositionIdSizeY + defaultHeight; string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL"; result = btnCloseAll.Create( chartId, btnCloseAllName, subWindow, btnCloseAllStartX, btnCloseAllStartY, btnCloseAllSizeX, btnCloseAllSizeY // ); if (result) { // // Apply Close Button Style ... // btnCloseAll.Text("Close All"); btnCloseAll.Color(clrYellow); btnCloseAll.ColorBackground(clrDarkRed); } // UpdateGUIState(); // return result; } /** * Update GUI based on Each Ticks ... */ void UpdateGUI() { // UpdateGUIState(); // // Buy Button Pressed ... if (btnBuy.Pressed()) { // HandleBuyTrade(); btnBuy.Pressed(false); } // // Sell Button Pressed ... if (btnSell.Pressed()) { // HandleSellTrade(); btnSell.Pressed(false); } // // Close Button Pressed ... if (btnClose.Pressed()) { // if (btnClose.IsEnabled()) { // if (selectedPositionID > 0) { HandleCloseTrade(selectedPositionID); } } // btnClose.Pressed(false); } // // Close All Button Pressed ... if (btnCloseAll.Pressed()) { // if (btnCloseAll.IsEnabled()) { HandleCloseTrade(0); } // 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(); bool has = IsValidSize(posCount); if (has) { // for (int i = 0; i < posCount; i++) { // CButton *iBtn = (CButton *)posArray.At(i); // if (iBtn.Pressed()) { // if (iBtn.IsEnabled()) { // ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); if (posID > 0 && selectedPositionID != posID) { selectedPositionID = posID; UpdateGUIState(); } } // iBtn.Pressed(false); } // ZeroMemory(iBtn); } } } /** * Destroy all Initialized GUi Requirements ... */ void DestroyGUI() { // delete mChartHelper; ZeroMemory(mChartHelper); // delete btnSelectedPosInfo; ZeroMemory(btnSelectedPosInfo); } /** * Update GUI Element Styles ... */ void UpdateGUIState() { // // Update States Of Position Select Buttons ... int count = posArray.Total(); bool has = IsValidSize(count) && selectedPositionID > 0; if (has) { // for (int i = 0; i < count; i++) { // CButton *iBtn = (CButton *)posArray.At(i); // ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); // // Select Position ... XPosition iPos; bool hasPosition = eaTrader.GetPosition( posID, iPos // ); string iTooltip = !hasPosition ? "" : IsLong(iPos.type) ? "Long" : "Short"; // if (posID == selectedPositionID) { // iBtn.Disable(); iBtn.ColorBackground(clrDarkGray); } else { // iBtn.Enable(); // color iBtnBG = IsLong(iPos.type) ? clrGreen : clrDarkRed; // iBtn.ColorBackground(iBtnBG); } // ZeroMemory(iBtn); } } // // Update State of Close All ... if (has && count > 1) { // btnCloseAll.Enable(); btnCloseAll.ColorBackground(clrDarkRed); } else { // btnCloseAll.Disable(); 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 // ); // // Read All Positions ... double profits = 0; XPosition positions[]; string positionsInfo = ""; int positionsCount = eaTrader.GetPositions(positions); has = IsValidSize(positionsCount); if (has) { // for (int i = 0; i < positionsCount; i++) { profits += positions[i].profit; } // if (positionsCount > 1) { positionsInfo = "Positions Count: " + ToXString(positionsCount) + ", Profits: " + ToXString(profits); } } // if (hasPosition) { // // Preparing Position Info ... string posTicket = "Ticket: " + ToXString(selectedPosition.ticket); string posType = "Type: " + ToXString(selectedPosition.type); string posSymbolPeriod = "Symbol: " + selectedPosition.symbol + ", " + "Period: " + ToXString(selectedPosition.period); string posProfit = "Profit: " + ToXString(selectedPosition.profit); string posRiskToRewardRatio = "RiskToReward: " + ToXString(selectedPosition.GetRiskRewardRatio()); string accountInfo = "Balance: " + ToXString(eaTrader.mAccount.GetBalance()) + ", " + "Equity: " + ToXString(eaTrader.mAccount.GetEquity()); // string posInfos[]; // // Ticket ... Add( posTicket, posInfos // ); // // Type ... Add( posType, posInfos // ); // // Symbol Period ... Add( posSymbolPeriod, posInfos // ); // // Profit ... Add( posProfit, posInfos // ); // // Risk to Reward Ratio ... Add( posRiskToRewardRatio, posInfos // ); // // Add Positions Info if Exists ... if (IsSpecifiedValid(positionsInfo)) { // Add( positionsInfo, posInfos // ); // // Clear Info Array ... selectedPosInfoArr.Clear(); } // // Adding Account Info ... Add( accountInfo, posInfos // ); // // Create Button If Not Exists ... 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) && lblInfoCount == posInfoCount; // // Create info Labels ... if (!has) { // selectedPosInfoArr.Clear(); has = IsValidSize(posInfoCount); if (has) { // // Creat Info Control ... // string name = objSuffix + "LBL_SPOS_INFO"; // int lblHeight = 25; int lblWidth = 450; // int startX = chartWidth - lblWidth - 5; int sizeX = startX + lblWidth; // 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); } // SpecifiedClean(positions); } 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) { // btnClose.Disable(); btnClose.ColorBackground(clrDarkGray); } else { // btnClose.Enable(); btnClose.ColorBackground(clrDarkOrange); } } /** * Update Position's Selector Buttons ... */ void UpdatePositionButtons() { // // Retrieve Positions ... XPosition positions[]; int count = eaTrader.GetPositions( positions // ); bool has = IsValidSize(count); if (!has) { // posArray.Clear(); selectedPositionID = 0; UpdateGUIState(); return; } // posArray.Clear(); // // Selected Position ID ... 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; int youngestIDX = GetXYoungest(youngest, positions); bool hasYoungest = IsValidIndex(youngestIDX) && youngest.IsValid(); if (hasYoungest) { selectedPositionID = youngest.ticket; } // youngest.Clean(); } // int subWindow = 0; ulong chartId = mChartHelper.ChartId(); // int btnWidth = 25; // int lastX = lblPositionIdSizeX + 5; int lastSizeX = lastX + btnWidth; // int lastY = lblPositionIdStartY; int lastSizeY = lblPositionIdSizeY; // for (int i = 0; i < count; i++) { // XPosition iPos = positions[i]; // string posTypeStr = IsLong(iPos.type) ? "LONG" : "SHORT"; // int iPosBtnX = lastX; int iPosBtnSizeX = iPosBtnX + btnWidth; string iPosBtnName = objSuffix + "_" + posTypeStr + "_POS_SELECT_BTN_" + ToXString(iPos.ticket); // CButton *iPosBtn = new CButton(); has = iPosBtn.Create( chartId, iPosBtnName, subWindow, iPosBtnX, lastY, iPosBtnSizeX, lastSizeY // ); if (has) { // // Apply Styles ... string iPosBtnText = ToXString(iPos.ticket); // iPosBtn.Text(iPosBtnText); iPosBtn.Color(clrWhite); // color iPosBtnBG = IsLong(iPos.type) ? clrGreen : clrDarkRed; iPosBtn.ColorBackground(iPosBtnBG); // lastX = iPosBtnSizeX + 5; // if (selectedPositionID == iPos.ticket) { iPosBtn.Disable(); } // posArray.Add(iPosBtn); } // iPos.Clean(); } // ZeroMemory(positions); UpdateGUIState(); } // // GUI Event Handlers ... // void HandleBuyTrade() { HandleTrade(X_DIRECTION_BULLISH); } // void HandleSellTrade() { HandleTrade(X_DIRECTION_BEARISH); } // void HandleTrade(ENUM_X_DIRECTION dir) { // if (!HasDirection(dir)) { return; } // bool isBullish = IsSpecifiedBullish(dir); // double r2r = 1.5; double volume = 0.01; double riskInPoints = 100; double point = GetPoints(symbol); double entry = GetEntry(symbol, dir); // double risk = riskInPoints * point; double reward = risk * r2r; // double sl = isBullish ? entry - risk : entry + risk; double tp = isBullish ? entry + reward : entry - reward; // string comment = ShortName + "_POS_" + ToXString(dir); // if (isBullish) { // eaTrader.Buy( symbol, period, volume, entry, sl, tp, comment // ); } else { // eaTrader.Sell( symbol, period, volume, entry, sl, tp, comment // ); } } // void HandleCloseTrade(ulong positionID) { // if (positionID == 0) { // XPosition positions[]; int count = eaTrader.GetPositions( positions // ); bool has = IsValidSize(count); if (has) { // int closedCount = eaTrader.Close(positions); has = IsValidSize(closedCount); } } else { // XPosition position; bool has = eaTrader.GetPosition( positionID, position // ); if (has) { // has = eaTrader.Close(positionID); } } } // // Custom Tools ... // ulong ExtractPositionIDFromButtonName(string name) { // ulong result = 0; // string nameParts[]; int namePartsCount = SplitContent(nameParts, name, "_"); bool has = IsValidSize(namePartsCount); if (has) { // string lastPart = nameParts[namePartsCount - 1]; StringReplace(lastPart, "_", ""); result = (long)lastPart; } // ZeroMemory(nameParts); // return result; } }; //