//+------------------------------------------------------------------+ //| Main.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372/news | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372/news" #property strict //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #define CACCOUNT_STATUS_ACTIVE_ON_POSITION_MODIFIED // https://www.mql5.com/ru/code/19703 #include #include "..\\..\\..\\PosMgmt\\Breakeven.mqh" #include //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ sinput group "" sinput group "-------| Account Status |-------" input ENUM_VERBOSE_LOG_LEVEL InpLogLevelAccountStatus = VERBOSE_LOG_LEVEL_ALL; //(Account Status|Ticket Mangement) log level: sinput group "" sinput group "-------| Breakeven |-------" input ENUM_BREAKEVEN_TYPE InpBeType = BREAKEVEN_TYPE_RR; // Calculation method (RR, ATR, or fixed points) input ENUM_VERBOSE_LOG_LEVEL InpBeLogLevel = VERBOSE_LOG_LEVEL_ALL; // Break Even log level: //+------------------------------------------------------------------+ sinput group "--- Breakeven based on Risk/Reward (RR) ---" input string InpBeRrAdv = "Requires a configured Stop Loss."; // Warning: Stop Loss is required to calculate RR input double InpBeRrRatio = 1.0; // Risk/Reward ratio to activate Breakeven (e.g. 1.0) input ENUM_TYPE_EXTRA_BE_BY_RRR InpBeRrTypeExtra = EXTRA_BE_RRR_BY_ATR;// Method to adjust Breakeven price (ATR or points) input double InpBeRrExtraPointsOrAtrMultiplier = 1.0; // Adjustment value: ATR multiplier (atr 14 period) if method = ATR, or fixed points if method = Points sinput group "--- Breakeven based solely on ATR ---" input double InpBeAtrMultiplier = 2.0; // ATR multiplier to trigger Breakeven (atr 14 period) input double InpBeAtrMultiplierExtra = 1.0; // Additional multiplier for precise Breakeven adjustment (atr 14 period) sinput group "--- Breakeven based on fixed points ---" input int InpBeFixedPointsToPutBe = 200; // Minimum distance (in points) to trigger Breakeven input int InpBeFixedPointsExtra = 100; // Extra points added when Breakeven is triggered //+------------------------------------------------------------------+ //| Resource | //+------------------------------------------------------------------+ #resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_up.bmp" #resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_down.bmp" #resource "\\Images\\EasyAndFastGUI\\Controls\\checkbox_off.bmp" #resource"\\Images\\EasyAndFastGUI\\Controls\\checkbox_on.bmp" const static string image_array[2] = { "Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_up.bmp", "Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_down.bmp" }; //+------------------------------------------------------------------+ //| Defines | //+------------------------------------------------------------------+ #define YSIZE_CAPTION 40 #define X_OFFSET_PANEL 5 #define Y_OFFSET_PANEL 5 #define TABLE_P_TICKET 0 #define TABLE_P_TYPE 1 #define TABLE_P_VOLUME 2 #define TABLE_P_ENTRY 3 #define TABLE_P_TAKEPROFIT 4 #define TABLE_P_STOPLOSS 5 #define TABLE_P_TRAILINGSTOP_CHECKBOX 6 #define PANEL_TABLE_IMAGE_IDX_UP 0 #define PANEL_TABLE_IMAGE_IDX_DOWN 1 //+------------------------------------------------------------------+ //| Global variables | //+------------------------------------------------------------------+ CAtrUltraOptimized atr_ultra_optimized; //+------------------------------------------------------------------+ //| CBreakEvenPanel class | //+------------------------------------------------------------------+ class CBreakEvenPanel : public CWndCreate { private: //--- int width_panel; ENUM_BREAKEVEN_TYPE mode_breakeven; bool enable_to_trailing; //--- CBreakEven* m_breakevens[]; CSymbolInfo* m_symbol_array[]; CHashMap hasmap_symbol_por_pos; //delveullve la poscoin en el array en base al simbolo CHashMap hashmap_pos_por_ticket; //em nase al ticket te da el idx en csymbol y trailing stop CHashMap hasmap_ticket_row; //en base al ticket te da la psocion en el array de posiciones ROnOpenClosePosition row_por_posicion[]; //--- CWindow m_window; CTabs m_tabs; //--- CTable m_table_principal; //--- CTextLabel m_label_text; CComboBox m_combox_be_type; CTextBox m_text_box1; //--- void OnChangeComboxTSL(); void RedrawCompletePanel(); //--- class CAccountGestorInt : public CAccountGestor { private: CBreakEvenPanel* m_padre; public: //--- CAccountGestorInt(CBreakEvenPanel* p) : m_padre(p) {} ~CAccountGestorInt(void) {} //--- void OnOpenClosePosition(const ROnOpenClosePosition &pos) override { m_padre.OnOpenClosePosition(pos); } void OnPositionModify(const Position& pos, const uint8_t change_flags) override { m_padre.OnPositionModify(pos, change_flags); } void OnInitNewPos(const ROnOpenClosePosition &position) override { m_padre.OnInitNewPos(position); } }; CAccountGestorInt* m_gestor; public: CBreakEvenPanel(void) : enable_to_trailing(false) { account_status.AddItemFast((m_gestor = new CAccountGestorInt(&this))); } ~CBreakEvenPanel(void) { } // Account status elimina gestor //--- void OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override; void OnDeinitEvent(const int reason); void OnTickEvent(); // void OnOpenClosePosition(const ROnOpenClosePosition &pos); void OnPositionModify(const Position& pos, const uint8_t change_flags); void OnInitNewPos(const ROnOpenClosePosition &position); //--- CAccountGestorInt* GetGestorInt() { return m_gestor; } //--- void CreateGUI(int WIDTH_PANEL, int HEIGHT_PANEL); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CBreakEvenPanel::OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_CUSTOM + ON_CLICK_CHECKBOX) { if(enable_to_trailing && lparam == m_table_principal.Id()) { string res[]; StringSplit(sparam, '_', res); int row = (int)StringToInteger(res[1]); //uint col = StringToInteger(res[1]); bool state = (bool)dparam; //Print(sparam); Print(state); if(state) { ROnOpenClosePosition pos; pos = row_por_posicion[row]; //--- Obtenemos la posicion en base al ticket int pos_index; hashmap_pos_por_ticket.TryGetValue(pos.position.ticket, pos_index); //--- Agrgamos Print(pos.position.ticket); m_breakevens[pos_index].obj.Add(pos.position.ticket); } else { ROnOpenClosePosition pos; pos = row_por_posicion[row]; //--- Obtenemos la posicion en base al ticket int pos_index; hashmap_pos_por_ticket.TryGetValue(pos.position.ticket, pos_index); //--- m_breakevens[pos_index].obj.Remove(pos.position.ticket); } } return; } if(id == CHARTEVENT_CUSTOM + ON_CLICK_COMBOBOX_ITEM) { if(lparam == m_combox_be_type.Id()) { OnChangeComboxTSL(); } return; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CBreakEvenPanel::OnChangeComboxTSL(void) { //--- const string slected = m_combox_be_type.GetValue(); const int idx = m_combox_be_type.GetListViewPointer().SelectedItemIndex(); ENUM_BREAKEVEN_TYPE mode = ENUM_BREAKEVEN_TYPE(idx); //--- for(int k = 0; k < ArraySize(m_breakevens); k++) m_breakevens[k].SetInternalPointer(mode); //--- for(int k = 0; k < (int)m_table_principal.RowsTotal(); k++) m_table_principal.ChangeImage(TABLE_P_TRAILINGSTOP_CHECKBOX, k, 0); //--- m_table_principal.Update(true); Print("Nuevo modo de breakeven: ", slected, " | ", g_breakevens_types_str[mode]); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CBreakEvenPanel::OnDeinitEvent(const int reason) { //--- for(int i = 0; i < ArraySize(m_symbol_array); i++) { delete m_symbol_array[i]; delete m_breakevens[i]; //cuidado no se elimna rel putnero interno eso lo hace account status } //--- CWndEvents::Destroy(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CBreakEvenPanel::OnTickEvent(void) { for(int i = 0; i < ArraySize(m_breakevens); i++) m_breakevens[i].obj.BreakEven(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CBreakEvenPanel::CreateGUI(int WIDTH_PANEL, int HEIGHT_PANEL) { //--- this.mode_breakeven = InpBeType; //--- width_panel = fmax(WIDTH_PANEL, 200); m_window.CaptionColor(clrGray); m_window.CaptionColorHover(clrGray); m_window.CaptionColorLocked(clrBlack); m_window.BorderColor(C'212,212,212'); m_window.BackColorPressed(clrBlue); m_window.Font("Arial Black"); CWndCreate::CreateWindow(m_window, "BreakevenManager", 0, 0, width_panel, HEIGHT_PANEL, true, false, true, true); //--- Tabs string texts[2] = { "General", "Configuracion"}; int widts[2] = {100, 90}; int x = m_window.X() + X_OFFSET_PANEL; int y = m_window.Y() + (YSIZE_CAPTION + Y_OFFSET_PANEL); int xsize_tabs = (m_window.XSize()) - (X_OFFSET_PANEL * 2); int ysize_tabs = (m_window.YSize() - YSIZE_CAPTION) - (Y_OFFSET_PANEL * 2); m_tabs.BackColor(C'191,191,191'); m_tabs.BackColorPressed(C'201,203,205'); CWndCreate::CreateTabs(m_tabs, m_window, 0, x, y, xsize_tabs, ysize_tabs, texts, widts); //--- #define X_OFFSET_INTERNO 7 x += X_OFFSET_INTERNO; y += 20; int x_table = x; int y_table = y; Print(m_tabs.YGap()); Print(m_tabs.XGap()); //--- Pestaña 1 #define COLS_TOTAL_TABLE 7 string headers[COLS_TOTAL_TABLE] = {"Ticket", "Type", "Volume", "Entry", "Takeprofit", "Stoploss", "Breakeven"}; int xsize_table = xsize_tabs - (X_OFFSET_INTERNO * 2); int ysize_table = ysize_tabs - (Y_OFFSET_PANEL * 2) - (20); //tamaño util | tmaaño dellos offeset | tamaño del header tabs #define HEADER_YSIZE_TABLE 30 m_table_principal.HeaderYSize(HEADER_YSIZE_TABLE); CWndCreate::CreateTable(m_table_principal, m_window, 0, m_tabs, 0, COLS_TOTAL_TABLE, 1, headers, x_table, y_table, xsize_table, ysize_table, false, false); ENUM_ALIGN_MODE align[COLS_TOTAL_TABLE]; ::ArrayInitialize(align, ALIGN_LEFT); //align[TABLE_P_TYPE] = ALIGN_RIGHT; //align[TABLE_P_TRAILINGSTOP_CHECKBOX] = ALIGN_LEFT; //Print(xsize_table); //--- int widths[COLS_TOTAL_TABLE]; const double col_proportions[COLS_TOTAL_TABLE] = {0.162, 0.102, 0.122, 0.142, 0.142, 0.142, 0.182}; int sum = 0; for(int i = 0; i < COLS_TOTAL_TABLE; i++) { widths[i] = (int)(xsize_table * col_proportions[i]); sum += widths[i]; } int rest = xsize_table - sum; widths[COLS_TOTAL_TABLE - 1] += rest < 0 ? 0 : rest; //ArrayPrint(widths); //Print(m_table_principal.XSize()); //--- Setemoas offeset imagen //ofeset de los iconos imagenes int imge_x_offset[COLS_TOTAL_TABLE] = {0, 8, 0, 0, 0, 0, 8}; int imge_y_offset[COLS_TOTAL_TABLE] = {0, 7, 0, 0, 0, 0, 7}; m_table_principal.ImageXOffset(imge_x_offset); m_table_principal.ImageYOffset(imge_y_offset); //--- Propiedades generales int ysize_utilizable = ysize_table - HEADER_YSIZE_TABLE; m_table_principal.TextAlign(align); m_table_principal.ColumnsWidth(widths); m_table_principal.HeadersColor(C'0x06,0x9C,0xCE'); m_table_principal.CellColor(clrWhiteSmoke); m_table_principal.CellYSize(30); //--- Array of text offset along the X axis in the columns int text_x_offset[COLS_TOTAL_TABLE]; ::ArrayInitialize(text_x_offset, 5); text_x_offset[TABLE_P_TRAILINGSTOP_CHECKBOX] += 22; text_x_offset[TABLE_P_TYPE] += 20; m_table_principal.TextXOffset(text_x_offset); m_table_principal.SetImages(TABLE_P_TYPE, 0, image_array); m_table_principal.DataType(TABLE_P_TICKET, TYPE_ULONG); m_table_principal.DataType(TABLE_P_TYPE, TYPE_STRING); m_table_principal.DataType(TABLE_P_VOLUME, TYPE_DOUBLE); m_table_principal.DataType(TABLE_P_ENTRY, TYPE_DOUBLE); m_table_principal.DataType(TABLE_P_TAKEPROFIT, TYPE_DOUBLE); m_table_principal.DataType(TABLE_P_STOPLOSS, TYPE_DOUBLE); //--- int x_label = x; int y_label = y; CWndCreate::CreateTextLabel(m_label_text, "Elija el tipo de breakeven", m_window, 0, m_tabs, 1, x_label, y_label, 210, 40); m_label_text.BackColor(C'201,203,205'); m_label_text.FontSize(12); y += 30; string trailign_stop_type[3] = { "Breakeven by rr", "Breakeven by fixed points", "Breakeven by atr"}; int pos = (int)this.mode_breakeven; CWndCreate::CreateCombobox(m_combox_be_type, "Tipo de breakeven: ", m_window, 0, m_tabs, 1, false, x, y, 262, 150, trailign_stop_type, 65, pos); m_combox_be_type.BackColor(C'201,203,205'); m_combox_be_type.FontSize(10); //--- Final CWndEvents::CompletedGUI(); } /* #define TABLE_P_TICKET 0 #define TABLE_P_TYPE 1 #define TABLE_P_VOLUME 2 #define TABLE_P_ENTRY 3 #define TABLE_P_TAKEPROFIT 4 #define TABLE_P_STOPLOSS 5 #define TABLE_P_TRAILINGSTOP_CHECKBOX 6 */ //+------------------------------------------------------------------+ void CBreakEvenPanel::OnOpenClosePosition(const ROnOpenClosePosition &pos) { if(pos.deal_entry_type == DEAL_ENTRY_IN) { enable_to_trailing = true; const string symbol_name = account_status.LastTransctionSymbol(); CSymbolInfo* ptr_symbol; int pos_symbol; //--- Obtemos info del simbolo if(hasmap_symbol_por_pos.TryGetValue(symbol_name, pos_symbol)) //obtenemos datos del simbolo { ptr_symbol = m_symbol_array[pos_symbol]; } else { ptr_symbol = new CSymbolInfo(); ptr_symbol.Name(symbol_name); ptr_symbol.Refresh(); //--- Creacion del breakeven CBreakEven* new_be = new CBreakEven(NOT_MAGIC_NUMBER, symbol_name); new_be.SetBeByAtr(InpBeAtrMultiplier, InpBeAtrMultiplierExtra, GetPointer(atr_ultra_optimized)); new_be.SetBeByFixedPoints(InpBeFixedPointsToPutBe, InpBeFixedPointsExtra); new_be.SetBeByRR(InpBeRrRatio, InpBeRrTypeExtra, InpBeRrExtraPointsOrAtrMultiplier, GetPointer(atr_ultra_optimized)); new_be.SetInternalPointer(InpBeType); new_be.obj.AddLogFlags(InpBeLogLevel); new_be.obj.Automatic(false); // No sera automatico //--- const int size = (int)m_symbol_array.Size(); //--- ArrayResize(m_symbol_array, size + 1); m_symbol_array[size] = ptr_symbol; ArrayResize(m_breakevens, size + 1); m_breakevens[size] = new_be; //--- hasmap_symbol_por_pos.Add(symbol_name, size); pos_symbol = size; } //--- Aumentamos el taamaño de tickets por row AddArrayNoVerification2(row_por_posicion, pos, 0) //--- obteneos el row, y si no coincide entonces resize int row_index = int(m_table_principal.RowsTotal() - 1); if(row_index != ArraySize(row_por_posicion) - 1) { row_index++; m_table_principal.AddRow(row_index); m_table_principal.SetImages(TABLE_P_TYPE, row_index, image_array); // Print("Resize"); } //--- hasmap_ticket_row.Add(pos.position.ticket, row_index); hashmap_pos_por_ticket.Add(pos.position.ticket, pos_symbol); //ticket -> posciion en larray //--- //PrintFormat("Row = %d | Ticket = %I64u | Digitos %d", row_index, pos.position.ticket, ptr_symbol.Digits()); //--- ticket m_table_principal.SetValue(TABLE_P_TICKET, row_index, IntegerToString(pos.position.ticket), 0); //--- Tipo const static string type_entrys[2] = { "Buy", "Sell"}; const static uint image_index[2] = { PANEL_TABLE_IMAGE_IDX_UP, PANEL_TABLE_IMAGE_IDX_DOWN}; const static color clr_index[2] = { clrGreen, clrRed}; const uint8_t t = (uint8_t)pos.position.type; //--- m_table_principal.SetValue(TABLE_P_TYPE, row_index, type_entrys[t]); m_table_principal.TextColor(TABLE_P_TYPE, row_index, clr_index[t]); m_table_principal.ChangeImage(TABLE_P_TYPE, row_index, t); //--- voluemn m_table_principal.SetValue(TABLE_P_VOLUME, row_index, DoubleToString(pos.position.volume), 3); //--- entry_price m_table_principal.SetValue(TABLE_P_ENTRY, row_index, DoubleToString(pos.position.open_price), ptr_symbol.Digits()); //--- tp m_table_principal.SetValue(TABLE_P_TAKEPROFIT, row_index, DoubleToString(pos.position.tp), ptr_symbol.Digits()); //--- sl m_table_principal.SetValue(TABLE_P_STOPLOSS, row_index, DoubleToString(pos.position.sl), ptr_symbol.Digits()); //--- trailing stop const string image_array_chekbox[2] = { "Images\\EasyAndFastGUI\\Controls\\checkbox_off.bmp", "Images\\EasyAndFastGUI\\Controls\\checkbox_on.bmp" }; //--- m_table_principal.SetImages(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, image_array_chekbox); m_table_principal.ChangeImage(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, 0); //0 por defecto m_table_principal.SetValue(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, "Breakeven", 0); m_table_principal.CellType(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, CELL_CHECKBOX); m_table_principal.Update(true); //Sleep(5000); } else if(pos.deal_entry_type == DEAL_ENTRY_OUT) { int row_index; if(hasmap_ticket_row.TryGetValue(pos.position.ticket, row_index)) //obtnemos el row de la posicion en base al ticket { //--- eliminamos la fila de la tabla if(m_table_principal.RowsTotal() > 1) //mas de 1 fila { m_table_principal.DeleteRow(row_index, true); //eliminamos la fila } else //1 fila { //--- ticket for(int i = 0; i < COLS_TOTAL_TABLE; i++) { m_table_principal.SetValue(i, 0); //reset a null } m_table_principal.Update(true); enable_to_trailing = false; } //--- hasmap_ticket_row.Remove(pos.position.ticket); //la eliminamos del hashmap de ticekt->row hashmap_pos_por_ticket.Remove(pos.position.ticket); //eliminamso del hashmap de ticket->pos(en simbolo - traiing stop) //--- eliiminamos el indice del array de posicoines [row -> (posicion = ticket)] int index_to_remove[1]; index_to_remove[0] = row_index; RemoveMultipleIndexes(row_por_posicion, index_to_remove, 0); } } } //+------------------------------------------------------------------+ // Funcion que se ejecuta en OnInit, solo si hay posiciones abiertas void CBreakEvenPanel::OnInitNewPos(const ROnOpenClosePosition &position) { enable_to_trailing = true; const string symbol_name = account_status.LastTransctionSymbol(); CSymbolInfo* ptr_symbol; int pos_symbol; //--- Obtemos info del simbolo if(hasmap_symbol_por_pos.TryGetValue(symbol_name, pos_symbol)) //obtenemos datos del simbolo { ptr_symbol = m_symbol_array[pos_symbol]; } else { ptr_symbol = new CSymbolInfo(); ptr_symbol.Name(symbol_name); ptr_symbol.Refresh(); //--- Creacion del breakeven CBreakEven* new_be = new CBreakEven(NOT_MAGIC_NUMBER, symbol_name); new_be.SetBeByAtr(InpBeAtrMultiplier, InpBeAtrMultiplierExtra, GetPointer(atr_ultra_optimized)); new_be.SetBeByFixedPoints(InpBeFixedPointsToPutBe, InpBeFixedPointsExtra); new_be.SetBeByRR(InpBeRrRatio, InpBeRrTypeExtra, InpBeRrExtraPointsOrAtrMultiplier, GetPointer(atr_ultra_optimized)); new_be.SetInternalPointer(InpBeType); new_be.obj.AddLogFlags(InpBeLogLevel); new_be.obj.Automatic(false); // No sera automatico //--- const int size = (int)m_symbol_array.Size(); //--- ArrayResize(m_symbol_array, size + 1); m_symbol_array[size] = ptr_symbol; ArrayResize(m_breakevens, size + 1); m_breakevens[size] = new_be; //--- hasmap_symbol_por_pos.Add(symbol_name, size); pos_symbol = size; } //--- Aumentamos el taamaño de tickets por row AddArrayNoVerification2(row_por_posicion, position, 0) //--- obteneos el row, y si no coincide entonces resize int row_index = int(m_table_principal.RowsTotal() - 1); if(row_index != ArraySize(row_por_posicion) - 1) { row_index++; m_table_principal.AddRow(row_index); m_table_principal.SetImages(TABLE_P_TYPE, row_index, image_array); // Print("Resize"); } //--- hasmap_ticket_row.Add(position.position.ticket, row_index); hashmap_pos_por_ticket.Add(position.position.ticket, pos_symbol); //ticket -> posciion en larray //--- PrintFormat("Row = %d | Ticket = %I64u | Digitos %d", row_index, position.position.ticket, ptr_symbol.Digits()); //--- ticket m_table_principal.SetValue(TABLE_P_TICKET, row_index, IntegerToString(position.position.ticket), 0); //--- Tipo const static string type_entrys[2] = { "Buy", "Sell"}; const static uint image_index[2] = { PANEL_TABLE_IMAGE_IDX_UP, PANEL_TABLE_IMAGE_IDX_DOWN}; const static color clr_index[2] = { clrGreen, clrRed}; const uint8_t t = (uint8_t)position.position.type; //--- m_table_principal.SetValue(TABLE_P_TYPE, row_index, type_entrys[t]); m_table_principal.TextColor(TABLE_P_TYPE, row_index, clr_index[t]); m_table_principal.ChangeImage(TABLE_P_TYPE, row_index, t); //--- voluemn m_table_principal.SetValue(TABLE_P_VOLUME, row_index, DoubleToString(position.position.volume), 3); //--- entry_price m_table_principal.SetValue(TABLE_P_ENTRY, row_index, DoubleToString(position.position.open_price), ptr_symbol.Digits()); //--- tp m_table_principal.SetValue(TABLE_P_TAKEPROFIT, row_index, DoubleToString(position.position.tp), ptr_symbol.Digits()); //--- sl m_table_principal.SetValue(TABLE_P_STOPLOSS, row_index, DoubleToString(position.position.sl), ptr_symbol.Digits()); //--- trailing stop const string image_array_chekbox[2] = { "Images\\EasyAndFastGUI\\Controls\\checkbox_off.bmp", "Images\\EasyAndFastGUI\\Controls\\checkbox_on.bmp" }; //--- m_table_principal.SetImages(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, image_array_chekbox); m_table_principal.ChangeImage(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, 0); //0 por defecto m_table_principal.SetValue(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, "Breakeven", 0); m_table_principal.CellType(TABLE_P_TRAILINGSTOP_CHECKBOX, row_index, CELL_CHECKBOX); m_table_principal.Update(true); //Sleep(5000); } //+------------------------------------------------------------------+ void CBreakEvenPanel::OnPositionModify(const Position &pos, const uchar change_flags) { int row; if(hashmap_pos_por_ticket.TryGetValue(pos.ticket, row)) { const string symbol_name = account_status.LastTransctionSymbol(); CSymbolInfo* ptr_symbol; int pos_symbol; //--- Obtemos info del simbolo hasmap_symbol_por_pos.TryGetValue(symbol_name, pos_symbol); //obtenemos datos del simbolo ptr_symbol = m_symbol_array[pos_symbol]; //--- if((change_flags & ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_SL) != 0) m_table_principal.SetValue(TABLE_P_STOPLOSS, row, DoubleToString(pos.sl), ptr_symbol.Digits()); if((change_flags & ACCOUNTSTATUS_ON_POS_MODIFY_FLAG_CHANGE_TP) != 0) m_table_principal.SetValue(TABLE_P_TAKEPROFIT, row, DoubleToString(pos.tp), ptr_symbol.Digits()); //--- m_table_principal.Update(true); } } //+------------------------------------------------------------------+