2026-08-28 22:40:45 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| 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
|
| | |
|
| | | //---
|
| | | // 1. Siempre primero as cases de MQLArticles
|
| | | #include "..\\..\\..\\PosMgmt\\Breakeven.mqh"
|
| | | #include "..\\..\\..\\Utils\\FA\\AutoDelete.mqh"
|
| | | #include <Trade\\SymbolInfo.mqh>
|
| | |
|
| | | //---
|
| | | #define private public
|
| | | #define protected public
|
| | | // https://forge.mql5.io/nique_372/EasyAndFastMod
|
| | |
|
| | | #include "..\\..\\..\\..\\EasyAndFastMod\\WndCreate.mqh"
|
| | | #undef private
|
| | | #undef protected
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| 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 |-------"
|
2026-09-13 08:47:52 -05:00 | | | input TSN::ENUM_BREAKEVEN_TYPE InpBeType = TSN::BREAKEVEN_TYPE_RR; // Calculation method (RR, ATR, or fixed points)
|
2026-08-28 22:40:45 -05:00 | | | 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)
|
2026-09-13 08:47:52 -05:00 | | | input TSN::ENUM_TYPE_EXTRA_BE_BY_RRR InpBeRrTypeExtra = TSN::EXTRA_BE_RRR_BY_ATR;// Method to adjust Breakeven price (ATR or points)
|
2026-08-28 22:40:45 -05:00 | | | 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
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define BREAKEVEN_PANEL_MAX_POS (256)
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Global variables |
|
| | | //+------------------------------------------------------------------+
|
2026-09-13 08:47:52 -05:00 | | | TSN::CAtrUltraOptimized atr_ultra_optimized;
|
2026-08-28 22:40:45 -05:00 | | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| CBreakEvenPanel class |
|
| | | //+------------------------------------------------------------------+
|
| | | class CBreakEvenPanel : public CWndCreate
|
| | | {
|
| | | private:
|
| | | //---
|
| | | int m_width_panel;
|
2026-09-13 08:47:52 -05:00 | | | TSN::ENUM_BREAKEVEN_TYPE m_mode_breakeven;
|
2026-08-28 22:40:45 -05:00 | | | bool m_enable_to_trailing;
|
| | |
|
| | | //---
|
2026-09-13 08:47:52 -05:00 | | | TSN::CBreakEven* m_breakevens[BREAKEVEN_PANEL_MAX_POS];
|
2026-08-28 22:40:45 -05:00 | | | CSymbolInfo* m_symbol_array[BREAKEVEN_PANEL_MAX_POS];
|
| | | int m_data_s;
|
| | |
|
2026-09-13 08:47:52 -05:00 | | | TSN::ROnOpenPosition m_row_por_posicion[BREAKEVEN_PANEL_MAX_POS];
|
2026-08-28 22:40:45 -05:00 | | | int m_row_por_posicion_s;
|
| | |
|
| | | //---
|
| | | CHashMapFast(string, int) m_hasmap_symbol_por_pos; // delveullve la poscoin en el array en base al simbolo
|
| | | CHashMapFastP(ulong, int, _fibbo) m_hashmap_pos_por_ticket; // em nase al ticket te da el idx en csymbol y trailing stop
|
| | | CHashMapFastP(ulong, int, _fibbo) m_hhasmap_ticket_row; // en base al ticket te da la psocion en el array de posiciones
|
| | |
|
| | | //---
|
| | | 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();
|
| | |
|
| | | //---
|
2026-09-13 08:47:52 -05:00 | | | class CAccountGestorInt : public TSN::CAccountGestor
|
2026-08-28 22:40:45 -05:00 | | | {
|
| | | private:
|
| | | CBreakEvenPanel* m_padre;
|
| | |
|
| | | public:
|
| | | //--- Constructor
|
| | | CAccountGestorInt(CBreakEvenPanel* p) : m_padre(p)
|
| | | {
|
2026-09-13 08:47:52 -05:00 | | | TSN::account_status.RegisterEvents(&this,
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS);
|
2026-08-28 22:40:45 -05:00 | | | }
|
| | |
|
| | | //--- Destructor
|
| | | ~CAccountGestorInt(void)
|
| | | {
|
2026-09-13 08:47:52 -05:00 | | | if(TSN::account_status.IsActive())
|
| | | TSN::account_status.UnregisterEvents(&this,
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_CLOSE_POSITION |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_OPEN_POSITION |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_POSITION_MODIFY |
|
| | | ACCOUNT_STATUS_REG_FLAG_ON_INIT_NEW_POS);
|
2026-08-28 22:40:45 -05:00 | | | }
|
| | |
|
| | | //---
|
2026-09-13 08:47:52 -05:00 | | | void OnOpenPosition(const TSN::ROnOpenPosition &pos) override final { m_padre.OnOpenPosition(pos); }
|
| | | void OnClosePosition(const TSN::ROnClosePosition &pos, const int global_pos_index) override final { m_padre.OnClosePosition(pos, global_pos_index); }
|
| | | void OnPositionModify(const TSN::Position& pos, const uint8_t change_flags) override final { m_padre.OnPositionModify(pos, change_flags); }
|
| | | void OnInitNewPos(const TSN::ROnOpenPosition &position) override final { m_padre.OnInitNewPos(position); }
|
2026-08-28 22:40:45 -05:00 | | | };
|
| | | CAccountGestorInt* m_gestor;
|
| | |
|
| | |
|
| | | public:
|
| | | CBreakEvenPanel();
|
| | | ~CBreakEvenPanel() { if(m_gestor != NULL) delete m_gestor; }
|
| | |
|
| | | //---
|
| | | void OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
|
| | | void OnDeinitEvent(const int reason);
|
| | | void OnTickEvent();
|
| | |
|
| | | //
|
2026-09-13 08:47:52 -05:00 | | | void OnOpenPosition(const TSN::ROnOpenPosition &pos);
|
| | | void OnClosePosition(const TSN::ROnClosePosition &pos, const int global_pos_index);
|
| | | void OnPositionModify(const TSN::Position& pos, const uint8_t change_flags);
|
| | | void OnInitNewPos(const TSN::ROnOpenPosition &position);
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //---
|
| | | CAccountGestorInt* GetGestorInt() { return m_gestor; }
|
| | |
|
| | | //---
|
| | | void CreateGUI(int WIDTH_PANEL, int HEIGHT_PANEL);
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | CBreakEvenPanel::CBreakEvenPanel(void)
|
| | | : m_row_por_posicion_s(0), m_data_s(0),
|
| | | m_hasmap_symbol_por_pos(BREAKEVEN_PANEL_MAX_POS), m_hashmap_pos_por_ticket(BREAKEVEN_PANEL_MAX_POS), m_hhasmap_ticket_row(BREAKEVEN_PANEL_MAX_POS),
|
| | | m_enable_to_trailing(false)
|
| | | {
|
| | | m_gestor = new CAccountGestorInt(&this);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CBreakEvenPanel::OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
| | | {
|
| | | if(id == CHARTEVENT_CUSTOM + ON_CLICK_CHECKBOX)
|
| | | {
|
| | | if(m_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)
|
| | | {
|
2026-09-13 08:47:52 -05:00 | | | const ulong pos = m_row_por_posicion[row].position.ticket;
|
| | | // pos
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //--- Obtenemos la posicion en base al ticket
|
| | | int pos_index;
|
2026-09-13 08:47:52 -05:00 | | | m_hashmap_pos_por_ticket.TryGet(pos, pos_index);
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //--- Agrgamos
|
2026-09-13 08:47:52 -05:00 | | | Print(pos);
|
2026-08-28 22:40:45 -05:00 | | |
|
2026-09-13 08:47:52 -05:00 | | | m_breakevens[pos_index].obj.Add(pos);
|
2026-08-28 22:40:45 -05:00 | | | }
|
| | | else
|
| | | {
|
2026-09-13 08:47:52 -05:00 | | | const ulong pos = m_row_por_posicion[row].position.ticket;
|
| | | // pos
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //--- Obtenemos la posicion en base al ticket
|
| | | int pos_index;
|
2026-09-13 08:47:52 -05:00 | | | m_hashmap_pos_por_ticket.TryGet(pos, pos_index);
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //---
|
2026-09-13 08:47:52 -05:00 | | | m_breakevens[pos_index].obj.Remove(pos);
|
2026-08-28 22:40:45 -05:00 | | | }
|
| | | }
|
| | | 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();
|
2026-09-13 08:47:52 -05:00 | | | TSN::ENUM_BREAKEVEN_TYPE mode = (TSN::ENUM_BREAKEVEN_TYPE)idx;
|
2026-08-28 22:40:45 -05:00 | | |
|
| | | //---
|
| | | for(int k = 0; k < m_data_s; 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);
|
2026-09-13 08:47:52 -05:00 | | | Print("Nuevo modo de breakeven: ", slected, " | ", TSN::g_breakevens_types_str[mode]);
|
2026-08-28 22:40:45 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CBreakEvenPanel::OnDeinitEvent(const int reason)
|
| | | {
|
| | | //---
|
| | | for(int i = 0; i < m_data_s; 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 < m_data_s; i++)
|
| | | m_breakevens[i].obj.BreakEven();
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CBreakEvenPanel::CreateGUI(int WIDTH_PANEL, int HEIGHT_PANEL)
|
| | | {
|
| | | //---
|
| | | this.m_mode_breakeven = InpBeType;
|
| | |
|
| | | //---
|
| | | m_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, m_width_panel, HEIGHT_PANEL, true, false, true, true);
|
| | |
|
| | |
|
| | | //--- Tabs
|
| | | string texts[2] = { "General", "Configuracion"};
|
| | | int widts[2] = {100, 90};
|
| | | color clrs[2] = {clrNONE, clrNONE}; // defa
|
| | |
|
| | | 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, clrs, clrs);
|
| | |
|
| | | //---
|
| | | #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.m_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
|
| | |
|
| | | */
|
| | | //+------------------------------------------------------------------+
|
2026-09-13 08:47:52 -05:00 | | | void CBreakEvenPanel::OnOpenPosition(const TSN::ROnOpenPosition &pos)
|
2026-08-28 22:40:45 -05:00 | | | {
|
| | | m_enable_to_trailing = true;
|
2026-09-13 08:47:52 -05:00 | | | const string symbol_name = TSN::account_status.LastTransctionSymbol();
|
2026-08-28 22:40:45 -05:00 | | | CSymbolInfo* ptr_symbol;
|
| | | int pos_symbol;
|
| | |
|
| | | //--- Obtemos info del simbolo
|
| | | if(m_hasmap_symbol_por_pos.TryGet(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
|
2026-09-13 08:47:52 -05:00 | | | TSN::CBreakEven* new_be = new TSN::CBreakEven(NOT_MAGIC_NUMBER, symbol_name); // DAdo que siempre se leimiarna en OnDeinit
|
2026-08-28 22:40:45 -05:00 | | | 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
|
| | |
|
| | | //---
|
| | | m_symbol_array[m_data_s] = ptr_symbol;
|
| | | m_breakevens[m_data_s] = new_be;
|
| | |
|
| | | //---
|
| | | m_hasmap_symbol_por_pos.Add(symbol_name, m_data_s);
|
| | | pos_symbol = m_data_s++;
|
| | | }
|
| | |
|
| | |
|
| | | //--- Aumentamos el taamaño de tickets por row
|
| | | m_row_por_posicion[m_row_por_posicion_s++] = pos;
|
| | |
|
| | | //--- obteneos el row, y si no coincide entonces resize
|
| | | int row_index = int(m_table_principal.RowsTotal() - 1);
|
| | | if(row_index != m_row_por_posicion_s - 1)
|
| | | {
|
| | | row_index++;
|
| | | m_table_principal.AddRow(row_index);
|
| | | m_table_principal.SetImages(TABLE_P_TYPE, row_index, image_array);
|
| | | }
|
| | |
|
| | | //---
|
| | | m_hhasmap_ticket_row.Add(pos.position.ticket, row_index);
|
| | | m_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);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-13 08:47:52 -05:00 | | | void CBreakEvenPanel::OnClosePosition(const TSN::ROnClosePosition &pos, const int global_pos_index)
|
2026-08-28 22:40:45 -05:00 | | | {
|
| | | int row_index;
|
| | | if(m_hhasmap_ticket_row.TryGet(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);
|
| | | m_enable_to_trailing = false;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_hhasmap_ticket_row.Remove(pos.position.ticket); //la eliminamos del hashmap de ticekt->row
|
| | | m_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;
|
| | | RemoveMultipleIndexesWithVSize(m_row_por_posicion, m_row_por_posicion_s, index_to_remove);
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | // Funcion que se ejecuta en OnInit, solo si hay posiciones abiertas
|
2026-09-13 08:47:52 -05:00 | | | void CBreakEvenPanel::OnInitNewPos(const TSN::ROnOpenPosition &position)
|
2026-08-28 22:40:45 -05:00 | | | {
|
| | | m_enable_to_trailing = true;
|
2026-09-13 08:47:52 -05:00 | | | const string symbol_name = TSN::account_status.LastTransctionSymbol();
|
2026-08-28 22:40:45 -05:00 | | | CSymbolInfo* ptr_symbol;
|
| | | int pos_symbol;
|
| | |
|
| | | //--- Obtemos info del simbolo
|
| | | if(m_hasmap_symbol_por_pos.TryGet(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
|
2026-09-13 08:47:52 -05:00 | | | TSN::CBreakEven* new_be = new TSN::CBreakEven(NOT_MAGIC_NUMBER, symbol_name);
|
2026-08-28 22:40:45 -05:00 | | | 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
|
| | |
|
| | | //---
|
| | | m_symbol_array[m_data_s] = ptr_symbol;
|
| | | m_breakevens[m_data_s] = new_be;
|
| | |
|
| | | //---
|
| | | m_hasmap_symbol_por_pos.Add(symbol_name, m_data_s);
|
| | | pos_symbol = m_data_s++;
|
| | | }
|
| | |
|
| | |
|
| | | //--- Aumentamos el taamaño de tickets por row
|
| | | m_row_por_posicion[m_row_por_posicion_s++] = position;
|
| | |
|
| | | //--- obteneos el row, y si no coincide entonces resize
|
| | | int row_index = int(m_table_principal.RowsTotal() - 1);
|
| | | if(row_index != m_row_por_posicion_s - 1)
|
| | | {
|
| | | row_index++;
|
| | | m_table_principal.AddRow(row_index);
|
| | | m_table_principal.SetImages(TABLE_P_TYPE, row_index, image_array);
|
| | | // Print("Resize");
|
| | | }
|
| | |
|
| | | //---
|
| | | m_hhasmap_ticket_row.Add(position.position.ticket, row_index);
|
| | | m_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);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-13 08:47:52 -05:00 | | | void CBreakEvenPanel::OnPositionModify(const TSN::Position &pos, const uchar change_flags)
|
2026-08-28 22:40:45 -05:00 | | | {
|
| | | int row;
|
| | | if(m_hashmap_pos_por_ticket.TryGet(pos.ticket, row))
|
| | | {
|
2026-09-13 08:47:52 -05:00 | | | const string symbol_name = TSN::account_status.LastTransctionSymbol();
|
2026-08-28 22:40:45 -05:00 | | | CSymbolInfo* ptr_symbol;
|
| | | int pos_symbol;
|
| | |
|
| | | //--- Obtemos info del simbolo
|
| | | m_hasmap_symbol_por_pos.TryGet(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);
|
| | | }
|
| | | }
|
| | | //+------------------------------------------------------------------+
|