MQLArticles/Examples/GUI/BE/Main.mqh
2025-11-28 20:22:05 -05:00

707 lines
50 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <EasyAndFastGUI\\WndCreate.mqh>
#include "..\\..\\..\\PosMgmt\\Breakeven.mqh"
#include <Trade\\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| 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<string, int> hasmap_symbol_por_pos; //delveullve la poscoin en el array en base al simbolo
CHashMap<ulong, int> hashmap_pos_por_ticket; //em nase al ticket te da el idx en csymbol y trailing stop
CHashMap<ulong, int> 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);
}
}
//+------------------------------------------------------------------+