707 lines
50 KiB
MQL5
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);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|