SimpleOrderPanel

Author: Copyright 2022, Manuel Alejandro Cercós Pérez
Orders Execution
Checks for the total of open ordersIt can change open orders parameters, due to possible stepping strategyIt automatically opens orders when conditions are reachedIt Closes Orders by itself
Miscellaneous
Uses files from the file systemIt reads information from a fileIt writes information to file
0 Views
0 Downloads
0 Favorites
SimpleOrderPanel
//+------------------------------------------------------------------+
//|                                             SimpleOrderPanel.mq5 |
//|                    Copyright 2022, Manuel Alejandro Cercós Pérez |
//|                         https://www.mql5.com/en/users/alexcercos |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, Manuel Alejandro Cercós Pérez"
#property link      "https://www.mql5.com/en/users/alexcercos"
//#property icon      "\\Images\\ProgramIcons\\simplePanelLogo.ico" //Not included
#property version   "2.08"

//+------------------------------------------------------------------+
//| CHANGES NEEDED TO FIX ISSUES                                     |
//+------------------------------------------------------------------+

//  To avoid some errors, it's necessary to change code in Dialog.mqh
// file (to modify variables that are defined as private).
//  Take into consideration that changes made in standard library
// files are reverted with each terminal update. To avoid errors
// when recompiling you can:
//  - Track with git the changes made in the file to revert the deletion
//  - Copy the file "Dialog.mqh" into another folder and change
//   dependencies as needed, so it doesn't change later
//
// If you are using MT4, I recommend using the Controls classes from MT5
// To open the file, press "Alt + G" with the cursor set over the line
// "#include <Controls\Dialog.mqh>" below.
//
// The errors would appear when FIRST COMPILING or after RECOMPILING
//
//+------------------------------------------------------------------+
//| ISSUE 1: DUPLICATED OBJECTS WHEN USING TEMPLATES                 |
//+------------------------------------------------------------------+
   #define M_NAME "12345" //Override in panel identifier
//
// Change the function "CreateInstanceId" to the one below:
//+-------------------------------------------------------------------+
//  string CAppDialog::CreateInstanceId(void)
//  {
//  #ifdef M_NAME
//    return M_NAME;
//  #else 
//    return(IntegerToString(rand(),5,'0'));
//  #endif
//  }
//+-------------------------------------------------------------------+
//
// If you don't use templates and want to remove the macro M_NAME, 
// delete also the following line in this file, at the beginning of 
// OnInitEvent (line 1303):
//+-------------------------------------------------------------------+
//  ObjectsDeleteAll(0, M_NAME);
//+-------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| ISSUE 2: HEADER FONT SIZE                                        |
//+------------------------------------------------------------------+
// This issue is not as common (only if your PC has a different text 
// size setting than default). You can modify manually the font sizes
// with the input "fontSize". If you want the header text size to 
// change too:
//
// Uncomment this line (465) in CControlsDialog::Create
//+-------------------------------------------------------------------+
//  CaptionFontSize(fontSize);
//+-------------------------------------------------------------------+
//
// Add the function definition to the class CDialog (in public or 
// protected sections, between lines ~45-85)
//+-------------------------------------------------------------------+
//  void CaptionFontSize(const int size) { m_caption.FontSize(size); }
//+-------------------------------------------------------------------+

#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Edit.mqh>
#include <Controls\Label.mqh>

#ifdef __MQL5__

#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\Trade.mqh>

#define POS_TOTAL PositionsTotal()
#define ORD_TOTAL OrdersTotal()
#define ASK_PRICE SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define BID_PRICE SymbolInfoDouble(_Symbol, SYMBOL_BID)

#define POS_SELECT_BY_INDEX(i) if (!m_position.SelectByIndex(i)) continue;
#define POS_SYMBOL m_position.Symbol()
#define POS_MAGIC m_position.Magic()
#define POS_TYPE m_position.PositionType()
#define POS_OPEN m_position.PriceOpen()
#define POS_STOP m_position.StopLoss()
#define POS_TAKE_PROFIT m_position.TakeProfit()
#define POS_TICKET m_position.Ticket()

#define ORD_SELECT_BY_INDEX(i) if (!m_order.SelectByIndex(i)) continue;
#define ORD_SYMBOL m_order.Symbol()
#define ORD_MAGIC m_order.Magic()
#define ORD_TYPE m_order.OrderType()
#define ORD_OPEN m_order.PriceOpen()
#define ORD_STOP m_order.StopLoss()
#define ORD_TAKE_PROFIT m_order.TakeProfit()
#define ORD_TICKET m_order.Ticket()

#define POS_BUY(lots, price, sl, tp) m_trade.Buy(lots, _Symbol, price, sl, tp, trade_comment);
#define POS_SELL(lots, price, sl, tp) m_trade.Sell(lots, _Symbol, price, sl, tp, trade_comment);
#define ORDER_BUY_LIMIT(lots, price, sl, tp) m_trade.BuyLimit(lots, price, _Symbol, sl, tp, ORDER_TIME_GTC, 0, trade_comment);
#define ORDER_BUY_STOP(lots, price, sl, tp) m_trade.BuyStop(lots, price, _Symbol, sl, tp, ORDER_TIME_GTC, 0, trade_comment);
#define ORDER_SELL_LIMIT(lots, price, sl, tp) m_trade.SellLimit(lots, price, _Symbol, sl, tp, ORDER_TIME_GTC, 0, trade_comment);
#define ORDER_SELL_STOP(lots, price, sl, tp) m_trade.SellStop(lots, price, _Symbol, sl, tp, ORDER_TIME_GTC, 0, trade_comment);
#define POS_MODIFY(ticket, stop, take) if(!m_trade.PositionModify(ticket, stop, take)) Print("Error modyfing position: ",GetLastError());
#define POS_CLOSE(ticket) if(!m_trade.PositionClose(ticket)) Print("Error closing position, ",GetLastError());
#define POS_CLOSE_PARTIAL(ticket) if(!m_trade.PositionClosePartial(ticket, partialLots)) Print("Error closing partial position, ",GetLastError());

#define ORD_DELETE(ticket) if (!m_trade.OrderDelete(ticket)) Print("Error deleting order, ",GetLastError());
#define ORD_MODIFY(ticket, stop, take) if (!m_trade.OrderModify(ticket, ORD_OPEN, stop, take, ORDER_TIME_GTC, 0)) Print("Error modyfing order: ",GetLastError());

#define TRIM_STRING_LEFT(param) StringTrimLeft(param)
#define TRIM_STRING_RIGHT(param) StringTrimRight(param)

CTrade         m_trade;
CPositionInfo  m_position;
COrderInfo 		m_order;


#else //__MQL4__

#define POSITION_TYPE_BUY OP_BUY
#define POSITION_TYPE_SELL OP_SELL

#define POS_TOTAL OrdersTotal()
#define ORD_TOTAL OrdersTotal()
#define ASK_PRICE Ask
#define BID_PRICE Bid

#define POS_SELECT_BY_INDEX(i) if(!OrderSelect(i, SELECT_BY_POS,MODE_TRADES)) continue;
#define POS_SYMBOL OrderSymbol()
#define POS_MAGIC OrderMagicNumber()
#define POS_TYPE OrderType()
#define POS_OPEN OrderOpenPrice()
#define POS_STOP OrderStopLoss()
#define POS_TAKE_PROFIT OrderTakeProfit()
#define POS_TICKET OrderTicket()

#define ORD_SELECT_BY_INDEX(i) if(!OrderSelect(i, SELECT_BY_POS,MODE_TRADES)) continue;
#define ORD_SYMBOL OrderSymbol()
#define ORD_MAGIC OrderMagicNumber()
#define ORD_TYPE OrderType()
#define ORD_OPEN OrderOpenPrice()
#define ORD_STOP OrderStopLoss()
#define ORD_TAKE_PROFIT OrderTakeProfit()
#define ORD_TICKET OrderTicket()

#define POS_BUY(lots, price, sl, tp) OrderSend(_Symbol, OP_BUY, lots, price, expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define POS_SELL(lots, price, sl, tp) OrderSend(_Symbol, OP_SELL, lots, price, expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define ORDER_BUY_LIMIT(lots, price, sl, tp) OrderSend(_Symbol, OP_BUYLIMIT, lots, NormalizeDouble(price,_Digits), expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define ORDER_BUY_STOP(lots, price, sl, tp) OrderSend(_Symbol, OP_BUYSTOP, lots, NormalizeDouble(price,_Digits), expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define ORDER_SELL_LIMIT(lots, price, sl, tp) OrderSend(_Symbol, OP_SELLLIMIT, lots, NormalizeDouble(price,_Digits), expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define ORDER_SELL_STOP(lots, price, sl, tp) OrderSend(_Symbol, OP_SELLSTOP, lots, NormalizeDouble(price,_Digits), expertDeviation, sl, tp, trade_comment, expertMagic, 0, clrNONE);
#define POS_MODIFY(ticket, stop, take) if (!OrderModify(ticket, POS_OPEN, stop, take, OrderExpiration(), clrNONE)) Print("Error modyfing position: ",GetLastError());
#define POS_CLOSE(ticket) if(POS_TYPE==POSITION_TYPE_BUY) { if(!OrderClose(ticket,OrderLots(),BID_PRICE,expertDeviation)) Print("Error closing position, ",GetLastError()); } else if(POS_TYPE==POSITION_TYPE_SELL) { if(!OrderClose(ticket,OrderLots(),ASK_PRICE,expertDeviation)) Print("Error closing position, ",GetLastError()); }
#define POS_CLOSE_PARTIAL(ticket) if(POS_TYPE==POSITION_TYPE_BUY) { if(!OrderClose(ticket,MathMin(partialLots, OrderLots()),BID_PRICE,expertDeviation)) Print("Error closing partial position, ",GetLastError()); } else if(POS_TYPE==POSITION_TYPE_SELL) { if(!OrderClose(ticket,MathMin(partialLots, OrderLots()),ASK_PRICE,expertDeviation)) Print("Error closing partial position, ",GetLastError()); }

#define ORD_DELETE(ticket) if (!OrderDelete(ticket)) Print("Error deleting order, ",GetLastError());
#define ORD_MODIFY(ticket, stop, take) if (!OrderModify(ticket, ORD_OPEN, stop, take, OrderExpiration(), clrNONE)) Print("Error modyfing order: ",GetLastError());

#define TRIM_STRING_LEFT(param) param=StringTrimLeft(param)
#define TRIM_STRING_RIGHT(param) param=StringTrimRight(param)

#endif

//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT                         (11)      // indent from left (with allowance for border width)
#define INDENT_TOP                          (11)      // indent from top (with allowance for border width)
#define INDENT_RIGHT                        (11)      // indent from right (with allowance for border width)
#define INDENT_BOTTOM                       (11)      // indent from bottom (with allowance for border width)
#define CONTROLS_GAP_X                      (10)      // gap by X coordinate
#define CONTROLS_GAP_Y                      (10)      // gap by Y coordinate
//--- for buttons
#define BUTTON_WIDTH                        (100)     // size by X coordinate
#define BUTTON_HEIGHT                       (25)      // size by Y coordinate


#define RISK_LABEL 					"RISK"
#define STOP_EDIT 					"SL_EDIT"
#define TAKE_EDIT 					"TP_EDIT"
#define RISK_EDIT 					"R_EDIT"
#define BUY_BUTTON 					"BUY"
#define SELL_BUTTON 					"SELL"
#define BREAKEVEN_BUTTON 			"SL BREAKEVEN"
#define CLOSE_BUTTON 				"CLOSE ALL"
#define CLOSE_BUY_BUTTON 			"CLOSE BUYS"
#define CLOSE_SELL_BUTTON 			"CLOSE SELLS"
#define STOP_BUTTON 					"MODIFY SL"
#define TAKE_BUTTON 					"MODIFY TP"
#define PARTIAL_EDIT 				"PARTIAL_EDIT"
#define PARTIAL_BUTTON 				"CLOSE PARTIAL"
#define COMMENT_EDIT 				"COMM_EDIT"
#define BUY_PEND_BUTTON 			"PENDING BUY"
#define SELL_PEND_BUTTON 			"PENDING SELL"
#define DELETE_BUY_PEND_BUTTON 	"DEL BUY ORD."
#define DELETE_SELL_PEND_BUTTON 	"DEL SELL ORD."

#define GVAR_POSITION_X		"SimplePanel_positionX"
#define GVAR_POSITION_Y		"SimplePanel_positionY"
#define GVAR_RISK_NAME 		"SimplePanel_risk_percent"
#define GVAR_CALC_TYPE 		"SimplePanel_calc_mode"
#define GVAR_STOP_LOSS 		"SimplePanel_stop_loss"
#define GVAR_TAKE_PROFIT 	"SimplePanel_take_profit"
#define GVAR_PARTIAL_LOTS 	"SimplePanel_partial_close"

//+------------------------------------------------------------------+
//| Enumerators (for inputs)                                         |
//+------------------------------------------------------------------+
enum RiskMode
{
   BALANCE_PERCENT, 	//Percentage of balance
   FIXED_LOTS 			//Fixed lots
};

enum SLTPMode
{
   ST_PRICE, 	//Price
   ST_DISTANCE //Distance to open price (>0)
};

enum BidAskMode
{
   BA_NORMAL,	//Bid for sell/Ask for buy
   BA_INVERT,	//Ask for sell/Bid for buy (inv)
   BA_ONLY_ASK,//Only Ask price
   BA_ONLY_BID //Only Bid price
};

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
#ifdef __MQL5__
input group "Trade Settings"
#endif
input RiskMode riskCalculation = FIXED_LOTS; //Risk calculation mode
input SLTPMode stop_takeMode = ST_DISTANCE; // SL/TP Mode
input BidAskMode bidAskReference = BA_NORMAL; //Price reference for SL and TP
input int expertDeviation = 20; // Maximum slippage
input int expertMagic = 450913; // Expert Magic number
input bool affectOtherTrades = false; // Modify external trades (not opened by the panel)

#ifdef __MQL5__
input group "Buttons"
#endif
input bool showBuySellButtons = true; // Show Buy/Sell buttons
input bool showCloseSepButtons = false; // Show Close Buy/Sell buttons
input bool showSLBECloseAllButtons = true; // Show SL to BE and Close All buttons
input bool showModifyButtons = false; // Show Modify SL/TP buttons
input bool showPartialClose = false; // Show Partial Close
input bool showPendingOrder = false; // Show Pending Orders
input bool showDeleteOrder = false; // Show Delete Pending Orders
input bool showCommentEdit = false; // Show Edit Comment

#ifdef __MQL5__
input group "Other settings"
#endif
input bool grabSLwithDrag = false; //Pick SL values with crosshair drag (Dist. mode)
input int fontSize = 10; //Font size
input double autoSetTP = 0.0; //Auto-set TP to SL ratio (0=don't use)
input bool autoSetSL = true; //Auto-set SL to ratio from TP change
#ifdef __MQL5__
input bool asyncOperations = false; //Use asynchronous orders
#endif

int lot_digits = 2;
double riskAmount = 2.0;
double stopLoss = 0.0;
double takeProfit = 0.0;
double partialLots = 1.0;

string trade_comment = NULL;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CControlsDialog : public CAppDialog
{
private:
   CLabel            m_label, m_stoploss_label, m_takeprofit_label;
   CEdit             m_edit, m_stoploss_edit, m_takeprofit_edit;
   CButton           m_buy_button, m_sell_button, m_breakeven_button, m_close_button, m_modify_sl_button, m_modify_tp_button;
   CButton				m_close_buys_button, m_close_sell_button, m_buy_order_button, m_sell_order_button, m_delete_buy_button, m_delete_sell_button;
   CEdit					m_partial_edit;
   CButton				m_partial_button;
   CEdit					m_comment_edit;

public:
   //--- create
   virtual bool      Create(const string name);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

   double            GetRiskPercent();
   double            GetStopLoss();
   double            GetTakeProfit();
   double            GetPartialLots();

   void              SetStopLoss(int stop);

protected:
   //--- create dependent controls
   bool              CreateButton(CButton &button, string name, int x1, int y1, int x2, int y2, color clr_back=clrDarkCyan);
   bool              CreateEdit(CEdit &edit, string name, string editText, int x1, int y1, int x2, int y2);
   bool              CreateLabel(CLabel &label, string name, int x1, int y1, int x2, int y2);
   //--- handlers of the dependent controls events
   void              OnEndEditRisk(void);
   void              OnEndEditSL(void);
   void              OnEndEditTP(void);
   void              OnClickBuyButton(void);
   void              OnClickSellButton(void);
   void              OnClickBreakevenButton(void);
   void              OnClickCloseButton(void);
   void              OnClickCloseBuyButton(void);
   void              OnClickCloseSellButton(void);
   void              OnClickModifySLButton(void);
   void              OnClickModifyTPButton(void);
   void              OnEditPartialClose(void);
   void              OnClickPartialCloseButton(void);
   void              OnEditComment(void);
   void              OnClickBuyOrderButton(void);
   void              OnClickSellOrderButton(void);
   void              OnClickDeleteBuyOrders(void);
   void              OnClickDeleteSellOrders(void);

   void              WriteExpertSettings();
   void              RestoreExpertSettings();
   void              RestoreStopTakeValues();

   void              RestoreComment();
   void              SaveComment();

   double            NormalizeLots(double lots);
};

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CControlsDialog)
ON_EVENT(ON_END_EDIT, m_edit, OnEndEditRisk)
ON_EVENT(ON_END_EDIT, m_stoploss_edit, OnEndEditSL)
ON_EVENT(ON_END_EDIT, m_takeprofit_edit, OnEndEditTP)
if (showBuySellButtons)
{
   ON_EVENT(ON_CLICK, m_buy_button, OnClickBuyButton)
   ON_EVENT(ON_CLICK, m_sell_button, OnClickSellButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showCloseSepButtons)
{
   ON_EVENT(ON_CLICK, m_close_buys_button, OnClickCloseBuyButton)
   ON_EVENT(ON_CLICK, m_close_sell_button, OnClickCloseSellButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showSLBECloseAllButtons)
{
   ON_EVENT(ON_CLICK, m_breakeven_button, OnClickBreakevenButton)
   ON_EVENT(ON_CLICK, m_close_button, OnClickCloseButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showModifyButtons)
{
   ON_EVENT(ON_CLICK, m_modify_sl_button, OnClickModifySLButton)
   ON_EVENT(ON_CLICK, m_modify_tp_button, OnClickModifyTPButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showPartialClose)
{
   ON_EVENT(ON_END_EDIT, m_partial_edit, OnEditPartialClose)
   ON_EVENT(ON_CLICK, m_partial_button, OnClickPartialCloseButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showCommentEdit)
{
   ON_EVENT(ON_END_EDIT, m_comment_edit, OnEditComment)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showPendingOrder)
{
   ON_EVENT(ON_CLICK, m_buy_order_button, OnClickBuyOrderButton)
   ON_EVENT(ON_CLICK, m_sell_order_button, OnClickSellOrderButton)
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
if (showDeleteOrder)
{
   ON_EVENT(ON_CLICK, m_delete_buy_button, OnClickDeleteBuyOrders)
   ON_EVENT(ON_CLICK, m_delete_sell_button, OnClickDeleteSellOrders)
}
EVENT_MAP_END(CAppDialog)


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CControlsDialog::Create(const string name)
{
   stopLoss = 0.0;
   takeProfit = 0.0;
   partialLots = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

   RestoreExpertSettings();

   int rows = 3;

   if (showBuySellButtons) rows++;
   if (showCloseSepButtons) rows++;
   if (showSLBECloseAllButtons) rows++;
   if (showModifyButtons) rows++;
   if (showPartialClose) rows++;
   if (showCommentEdit) rows++;
   if (showPendingOrder) rows++;
   if (showDeleteOrder) rows++;

   if (rows == 3)
   {
      Print("Error: no buttons are being shown");
      return false;
   }

//Get position
   int x1 = 100;
   int y1 = 40;
   if (GlobalVariableCheck(GVAR_POSITION_X))
      x1 = (int)GlobalVariableGet(GVAR_POSITION_X);
   else
      GlobalVariableSet(GVAR_POSITION_X, x1);

   if (GlobalVariableCheck(GVAR_POSITION_Y))
      y1 = (int)GlobalVariableGet(GVAR_POSITION_Y);
   else
      GlobalVariableSet(GVAR_POSITION_Y, y1);


   int x2 = 8 + x1 + INDENT_LEFT + 2 * BUTTON_WIDTH  + CONTROLS_GAP_X + INDENT_RIGHT;
   int y2 = 30 + y1 + INDENT_TOP + rows * BUTTON_HEIGHT + (rows - 1) * CONTROLS_GAP_Y + INDENT_BOTTOM;

   if(!CAppDialog::Create(0, name, 1, x1, y1, x2, y2))
      return(false);
//CaptionFontSize(fontSize); //CUSTOM function defined in CDialog


   int bx1=INDENT_LEFT;
   int by1=INDENT_TOP;
   int bx2=bx1+BUTTON_WIDTH;
   int by2=by1+BUTTON_HEIGHT;

#define NEXT_COLUMN \
   	bx1 += (BUTTON_WIDTH+CONTROLS_GAP_X); \
   	bx2 += (BUTTON_WIDTH+CONTROLS_GAP_X);

#define PREV_COLUMN \
   	bx1 -= (BUTTON_WIDTH+CONTROLS_GAP_X); \
   	bx2 -= (BUTTON_WIDTH+CONTROLS_GAP_X);

#define NEXT_ROW \
   	by1 += (BUTTON_HEIGHT+CONTROLS_GAP_Y); \
   	by2 += (BUTTON_HEIGHT+CONTROLS_GAP_Y);


   if(!CreateLabel(m_label, riskCalculation==BALANCE_PERCENT?"RISK %":"LOTS", bx1+BUTTON_WIDTH/2, by1, bx2, by2))
      return(false);

   NEXT_COLUMN

   string riskText;
   if (riskCalculation == BALANCE_PERCENT)
      riskText = DoubleToString(riskAmount, 2) + " %";
   else
      riskText = DoubleToString(riskAmount, lot_digits);

   if(!CreateEdit(m_edit, RISK_EDIT, riskText, bx1, by1, bx2, by2))
      return(false);

   PREV_COLUMN
   NEXT_ROW

   if(!CreateLabel(m_stoploss_label, stop_takeMode==ST_DISTANCE?"SL (points)":"SL (price)", bx1+BUTTON_WIDTH/3, by1, bx2, by2))
      return(false);

   NEXT_COLUMN

   string sl_edit_str = stop_takeMode==ST_DISTANCE?DoubleToString(stopLoss, 0):DoubleToString(stopLoss, _Digits);

   if(!CreateEdit(m_stoploss_edit, STOP_EDIT, sl_edit_str, bx1, by1, bx2, by2))
      return(false);

   PREV_COLUMN
   NEXT_ROW

   if(!CreateLabel(m_takeprofit_label, stop_takeMode==ST_DISTANCE?"TP (points)":"TP (price)", bx1+BUTTON_WIDTH/3, by1, bx2, by2))
      return(false);

   NEXT_COLUMN

   string tp_edit_str = stop_takeMode==ST_DISTANCE?DoubleToString(takeProfit, 0):DoubleToString(takeProfit, _Digits);

   if(!CreateEdit(m_takeprofit_edit, TAKE_EDIT, tp_edit_str, bx1, by1, bx2, by2))
      return(false);

   if (showBuySellButtons)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_buy_button, BUY_BUTTON, bx1, by1, bx2, by2, clrGreen))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_sell_button, SELL_BUTTON, bx1, by1, bx2, by2, clrRed))
         return(false);
   }


   if (showCloseSepButtons)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_close_buys_button, CLOSE_BUY_BUTTON, bx1, by1, bx2, by2, clrDarkSlateGray))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_close_sell_button, CLOSE_SELL_BUTTON, bx1, by1, bx2, by2, clrDarkRed))
         return(false);
   }

   if (showSLBECloseAllButtons)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_breakeven_button, BREAKEVEN_BUTTON, bx1, by1, bx2, by2, clrGray))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_close_button, CLOSE_BUTTON, bx1, by1, bx2, by2, clrBlue))
         return(false);
   }

   if (showModifyButtons)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_modify_sl_button, STOP_BUTTON, bx1, by1, bx2, by2, clrIndianRed))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_modify_tp_button, TAKE_BUTTON, bx1, by1, bx2, by2, clrDarkCyan))
         return(false);
   }

   if (showPartialClose)
   {
      PREV_COLUMN
      NEXT_ROW

      string partialEdit = DoubleToString(partialLots, lot_digits);
      if(!CreateEdit(m_partial_edit, PARTIAL_EDIT, partialEdit, bx1, by1, bx2, by2))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_partial_button, PARTIAL_BUTTON, bx1, by1, bx2, by2, clrSlateBlue))
         return(false);
   }

   if (showPendingOrder)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_buy_order_button, BUY_PEND_BUTTON, bx1, by1, bx2, by2, clrLimeGreen))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_sell_order_button, SELL_PEND_BUTTON, bx1, by1, bx2, by2, clrOrangeRed))
         return(false);
   }

   if (showDeleteOrder)
   {
      PREV_COLUMN
      NEXT_ROW

      if(!CreateButton(m_delete_buy_button, DELETE_BUY_PEND_BUTTON, bx1, by1, bx2, by2, clrDarkGreen))
         return(false);

      NEXT_COLUMN

      if(!CreateButton(m_delete_sell_button, DELETE_SELL_PEND_BUTTON, bx1, by1, bx2, by2, clrMaroon))
         return(false);
   }

   if (showCommentEdit)
   {
      bx1 -= (BUTTON_WIDTH+CONTROLS_GAP_X); //Keep bx2 at the end
      NEXT_ROW

      if(!CreateEdit(m_comment_edit, COMMENT_EDIT, trade_comment, bx1, by1, bx2, by2))
         return(false);
   }

//--- succeed
   return(true);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateButton(CButton &button, string name,int x1,int y1,int x2,int y2, color clr_back=clrDarkCyan)
{
//--- create
   if(!button.Create(m_chart_id, m_name+name, m_subwin, x1, y1, x2, y2))
      return(false);
   if(!button.Text(name))
      return(false);
   if (!button.FontSize(fontSize))
      return(false);
   button.ColorBorder(clrBlack);
   button.Color(clrWhite);
   button.ColorBackground(clr_back);

   if(!Add(button))
      return(false);
//--- succeed
   return(true);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CControlsDialog::GetRiskPercent(void)
{
   if (riskCalculation == FIXED_LOTS)
      return NormalizeLots(StringToDouble(m_edit.Text()));
   return MathMin(MathMax(StringToDouble(m_edit.Text()), 0.0), 100.0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CControlsDialog::GetStopLoss(void)
{
   return MathMax(StringToDouble(m_stoploss_edit.Text()), 0.0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CControlsDialog::GetTakeProfit(void)
{
   return MathMax(StringToDouble(m_takeprofit_edit.Text()), 0.0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CControlsDialog::GetPartialLots(void)
{
   return NormalizeLots(StringToDouble(m_partial_edit.Text()));
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateEdit(CEdit &edit, string name, string editText, int x1, int y1, int x2, int y2)
{
//--- create
   if(!edit.Create(m_chart_id,m_name+name,m_subwin,x1,y1,x2,y2))
      return(false);

   if(!edit.ReadOnly(false))
      return(false);

   if(!edit.Text(editText))
      return(false);
   if (!edit.FontSize(fontSize))
      return(false);
   if(!edit.TextAlign(ALIGN_CENTER))
      return(false);
   if(!Add(edit))
      return(false);
//--- succeed
   return(true);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateLabel(CLabel &label,string name,int x1,int y1,int x2,int y2)
{
//--- create
   if(!label.Create(m_chart_id,m_name+name,m_subwin,x1,y1,x2,y2))
      return(false);
   if(!label.Text(name))
      return(false);
   if (!label.FontSize(fontSize))
      return(false);
   if(!Add(label))
      return(false);
//--- succeed
   return(true);
}

#define PENDING_SETLINE "SOP_setline"

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickBuyButton(void)
{
   Print("Buy pressed");

   RecalculateValues(POSITION_TYPE_BUY);

   if (!CheckLots()) return;

   double ask = ASK_PRICE;

   double sl = 0.0;
   double tp = 0.0;

   if (stop_takeMode == ST_PRICE)
   {
      sl = stopLoss;
      tp = takeProfit;
   }
   else
   {
      double ref = (bidAskReference==BA_NORMAL || bidAskReference==BA_ONLY_ASK)?ask:BID_PRICE;

      if (stopLoss != 0.0)
         sl = ref - stopLoss  * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
      if (takeProfit != 0.0)
         tp = ref + takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   }

   POS_BUY(totalLots, ask, sl, tp)
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickBuyOrderButton(void)
{
   Print("Pending Buy pressed");

   setting_buy = true;
   setting_sell = false;

   CreatePendingSetLine(clrGreen, ASK_PRICE);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickSellButton(void)
{
   Print("Sell pressed");

   RecalculateValues(POSITION_TYPE_SELL);

   if (!CheckLots()) return;

   double bid = BID_PRICE;

   double sl = 0.0;
   double tp = 0.0;

   if (stop_takeMode == ST_PRICE)
   {
      sl = stopLoss;
      tp = takeProfit;
   }
   else
   {
      double ref = (bidAskReference==BA_NORMAL || bidAskReference==BA_ONLY_BID)?bid:ASK_PRICE;

      if (stopLoss !=0.0)
         sl = ref + stopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
      if (takeProfit != 0.0)
         tp = ref - takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   }

   POS_SELL(totalLots, bid, sl, tp)
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickSellOrderButton(void)
{
   Print("Pending Sell pressed");

   setting_sell = true;
   setting_buy = false;

   CreatePendingSetLine(clrRed, BID_PRICE);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickBreakevenButton(void)
{
   Print("Breakeven pressed");


   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         if (POS_TYPE == POSITION_TYPE_BUY)
         {
            double bid = BID_PRICE;
            if (bid <= POS_OPEN)
            {
               continue;
            }
         }
         else if (POS_TYPE == POSITION_TYPE_SELL)
         {
            double ask = ASK_PRICE;
            if (ask >= POS_OPEN)
            {
               continue;
            }
         }
         else
            continue; //Pending orders

         if (POS_OPEN == POS_STOP)
         {
            continue;
         }

         POS_MODIFY(POS_TICKET, POS_OPEN, POS_TAKE_PROFIT)

      }
   }

}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickCloseButton(void)
{
   Print("Close pressed");


   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         POS_CLOSE(POS_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickCloseBuyButton(void)
{
   Print("Close Buy pressed");


   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if (POS_TYPE == POSITION_TYPE_SELL) continue;

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         POS_CLOSE(POS_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickDeleteBuyOrders(void)
{
   Print("Delete Pending Buys pressed");

   for (int j=ORD_TOTAL-1; j>=0; j--)
   {
      ORD_SELECT_BY_INDEX(j)

      if (ORD_TYPE != ORDER_TYPE_BUY_LIMIT && ORD_TYPE != ORDER_TYPE_BUY_STOP) continue;

      if (ORD_SYMBOL==_Symbol && (affectOtherTrades || ORD_MAGIC==expertMagic))
      {
         ORD_DELETE(ORD_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickCloseSellButton(void)
{
   Print("Close Sell pressed");

   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if (POS_TYPE == POSITION_TYPE_BUY) continue;

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         POS_CLOSE(POS_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickDeleteSellOrders(void)
{
   Print("Delete Pending Sell pressed");

   for (int j=ORD_TOTAL-1; j>=0; j--)
   {
      ORD_SELECT_BY_INDEX(j)

      if (ORD_TYPE != ORDER_TYPE_SELL_LIMIT && ORD_TYPE != ORDER_TYPE_SELL_STOP) continue;

      if (ORD_SYMBOL==_Symbol && (affectOtherTrades || ORD_MAGIC==expertMagic))
      {
         ORD_DELETE(ORD_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickModifySLButton(void)
{
   Print("Modify Stop Loss pressed");

   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         double sl = 0.0;

         if (stop_takeMode == ST_PRICE)
         {
            sl = stopLoss;
         }
         else
         {

            if (stopLoss !=0.0)
            {
               if (POS_TYPE == POSITION_TYPE_BUY) sl = BID_PRICE - stopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
               else if (POS_TYPE == POSITION_TYPE_SELL) sl = ASK_PRICE + stopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
               else continue; //Pending orders

            }
         }

         if (sl != POS_STOP)
         {
            POS_MODIFY(POS_TICKET, sl, POS_TAKE_PROFIT)
         }
         else
         {
            Print("Stop Loss is already " + (string)sl);
         }

      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickModifyTPButton(void)
{
   Print("Modify Take Profit pressed");

   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         double tp = 0.0;

         if (stop_takeMode == ST_PRICE)
         {
            tp = takeProfit;
         }
         else
         {

            if (takeProfit !=0.0)
            {
               if (POS_TYPE == POSITION_TYPE_BUY) tp = ASK_PRICE + takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
               else if (POS_TYPE == POSITION_TYPE_SELL) tp = BID_PRICE - takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
               else continue;
            }
         }

         if (tp != POS_TAKE_PROFIT)
         {
            POS_MODIFY(POS_TICKET, POS_STOP, tp)
         }
         else
         {
            Print("Take Profit is already " + (string)tp);
         }
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnClickPartialCloseButton(void)
{
   Print("Close Partial pressed");

   for(int i = POS_TOTAL-1; i>=0; i--)
   {
      POS_SELECT_BY_INDEX(i)

      if(POS_SYMBOL==_Symbol && (affectOtherTrades || POS_MAGIC==expertMagic))
      {
         POS_CLOSE_PARTIAL(POS_TICKET)
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnEndEditRisk(void)
{
   riskAmount = GetRiskPercent();
   if (riskCalculation == BALANCE_PERCENT)
      m_edit.Text(DoubleToString(riskAmount, 2) + " %");
   else
      m_edit.Text(DoubleToString(riskAmount, lot_digits));
   WriteExpertSettings();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnEndEditSL(void)
{
   stopLoss = GetStopLoss();


   if (stop_takeMode== ST_PRICE)
      m_stoploss_edit.Text(DoubleToString(stopLoss, _Digits));
   else
      m_stoploss_edit.Text(DoubleToString(stopLoss, 0));

   if (autoSetTP>0.0 && stop_takeMode==ST_DISTANCE)
   {
      takeProfit = MathRound(stopLoss*autoSetTP);
      m_takeprofit_edit.Text(DoubleToString(takeProfit,0));
   }

   WriteExpertSettings();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnEndEditTP(void)
{
   takeProfit = GetTakeProfit();

   if (stop_takeMode== ST_PRICE)
      m_takeprofit_edit.Text(DoubleToString(takeProfit, _Digits));
   else
      m_takeprofit_edit.Text(DoubleToString(takeProfit, 0));

   if (autoSetSL && autoSetTP>0.0 && stop_takeMode==ST_DISTANCE)
   {
      stopLoss = MathRound(takeProfit/autoSetTP);
      m_stoploss_edit.Text(DoubleToString(stopLoss,0));
   }

   WriteExpertSettings();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnEditPartialClose(void)
{
   partialLots = GetPartialLots();

   m_partial_edit.Text(DoubleToString(partialLots, lot_digits));

   WriteExpertSettings();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::OnEditComment(void)
{
   trade_comment = m_comment_edit.Text();
   SaveComment();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::RestoreExpertSettings(void)
{
   if (showCommentEdit)
      RestoreComment();
   else
      trade_comment=NULL;

   if (GlobalVariableCheck(GVAR_RISK_NAME))
   {
      riskAmount = GlobalVariableGet(GVAR_RISK_NAME);
      if (riskCalculation==FIXED_LOTS)
         riskAmount = NormalizeLots(riskAmount);
      partialLots = NormalizeLots(GlobalVariableGet(GVAR_PARTIAL_LOTS));

      RestoreStopTakeValues();
   }
   else
   {
      WriteExpertSettings();
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::WriteExpertSettings(void)
{
   GlobalVariableSet(GVAR_RISK_NAME, riskAmount);
   GlobalVariableSet(GVAR_CALC_TYPE, stop_takeMode);
   GlobalVariableSet(GVAR_STOP_LOSS, stopLoss);
   GlobalVariableSet(GVAR_TAKE_PROFIT, takeProfit);
   GlobalVariableSet(GVAR_PARTIAL_LOTS, partialLots);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::RestoreStopTakeValues(void)
{
   if (GlobalVariableCheck(GVAR_CALC_TYPE))
   {
      int typeCalc = (int)GlobalVariableGet(GVAR_CALC_TYPE);

      if (typeCalc == stop_takeMode)
      {
         stopLoss = GlobalVariableGet(GVAR_STOP_LOSS);
         takeProfit = GlobalVariableGet(GVAR_TAKE_PROFIT);

         return;
      }
   }

   WriteExpertSettings();

}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::RestoreComment(void)
{
   if (!FileIsExist("SOP_SavedComment.txt"))
      return;

   int file = FileOpen("SOP_SavedComment.txt", FILE_READ|FILE_TXT|FILE_SHARE_READ);

   if (file==INVALID_HANDLE)
   {
      Print("Error reading comment in file");
      return;
   }
   trade_comment = FileReadString(file);
   FileClose(file);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::SaveComment(void)
{
   int file = FileOpen("SOP_SavedComment.txt", FILE_WRITE|FILE_TXT);

   if (file==INVALID_HANDLE)
   {
      Print("Error saving comment in file");
      return;
   }

   FileWrite(file, trade_comment);
   FileClose(file);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CControlsDialog::NormalizeLots(double lots)
{
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   return MathMax(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN),
                  MathMin(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX),
                          MathFloor(lots / lotStep) * lotStep));
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CControlsDialog::SetStopLoss(int stop)
{
   stopLoss = stop;
   m_stoploss_edit.Text(IntegerToString(stop));

   if (autoSetTP>0.0 && stop_takeMode==ST_DISTANCE)
   {
      takeProfit = MathRound(stopLoss*autoSetTP);
      m_takeprofit_edit.Text(DoubleToString(takeProfit,0));
   }

   ChartRedraw();
   WriteExpertSettings();
}

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
CControlsDialog ExtDialog;

double totalLots;
MqlRates currentRates[2];

bool is_tracking=false;
double recorded_price = 0.0;

bool setting_buy=false;
bool setting_sell=false;
int xysub;
double xyprice;
datetime xytime;

//+------------------------------------------------------------------+
//| Event handlers                                                   |
//+------------------------------------------------------------------+
int OnInitEvent()
{
   ObjectsDeleteAll(0, M_NAME); //Remove elements in chart (for template issues)
   lot_digits = int(-MathLog10(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)));

   if(!ExtDialog.Create("Simple Panel"))
      return(INIT_FAILED);

   ExtDialog.Run();

#ifdef __MQL5__
   m_trade.SetExpertMagicNumber(expertMagic);
   m_trade.SetDeviationInPoints(expertDeviation);
   if (asyncOperations) m_trade.SetAsyncMode(true);
#endif

   setting_buy = false;
   setting_sell = false;

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinitEvent(const int reason)
{
   GlobalVariableSet(GVAR_POSITION_X, ExtDialog.Left());
   GlobalVariableSet(GVAR_POSITION_Y, ExtDialog.Top());

   DeletePendingSetLine();
   Comment("");
   ExtDialog.Destroy(reason);
}

#define MASK_RIGHT_CLICK 2
#define MASK_RIGHT_MIDDLE 16

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CommonChartEvent(const int id,       // event ID
                      const long& lparam,   	// event parameter of the long type
                      const double& dparam, 	// event parameter of the double type
                      const string& sparam) 	// event parameter of the string type
{
   if (setting_buy || setting_sell)
   {
      int smask = (int)StringToInteger(sparam);

      if ((id==CHARTEVENT_KEYDOWN && lparam==27) || //ESC
            (id==CHARTEVENT_MOUSE_MOVE &&
             ((smask&MASK_RIGHT_CLICK)>0 ||
              (smask&MASK_RIGHT_MIDDLE)>0)
            )
         )
      {
         DeletePendingSetLine();

         setting_buy = false;
         setting_sell = false;
         return;
      }
   }
   if (setting_buy)
   {
      if (id==CHARTEVENT_CLICK)
      {
         DeletePendingSetLine();

         ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);
         OpenBuyPendingOrder(xyprice);

         setting_buy = false;
         return;
      }
      if (id==CHARTEVENT_MOUSE_MOVE)
      {
         ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);
         MovePendingSetLine(xyprice);
         return;
      }
   }
   if (setting_sell)
   {
      if (id==CHARTEVENT_CLICK)
      {
         DeletePendingSetLine();

         ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);
         OpenSellPendingOrder(xyprice);

         setting_sell = false;
         return;
      }
      if (id==CHARTEVENT_MOUSE_MOVE)
      {
         ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);
         MovePendingSetLine(xyprice);
         return;
      }
   }


   if (!grabSLwithDrag || stop_takeMode == ST_PRICE)
      return;

   if (id==CHARTEVENT_CLICK)
   {
      if (!is_tracking) return;

      if (!(recorded_price>0.0))
      {
         is_tracking=false;
         return;
      }

      ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);
#ifdef __MQL5__
      int pips = (int)MathRound(MathAbs(xyprice-recorded_price)/SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
#else
      int pips = (int)(MathAbs(xyprice-recorded_price)/SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
#endif

      if (pips>0)
         ExtDialog.SetStopLoss(pips);


      is_tracking = false;
      recorded_price = 0.0;

   }

   if (id==CHARTEVENT_MOUSE_MOVE)
   {
      if (sparam!="1") return;

      if (is_tracking) return;

      ChartXYToTimePrice(ChartID(), (int)lparam, (int)dparam, xysub, xytime, xyprice);

      if (xysub>0) return;


      recorded_price = xyprice;
      is_tracking = true;
   }

   if (id==CHARTEVENT_CHART_CHANGE || id==CHARTEVENT_CUSTOM+ON_DRAG_PROCESS) //Stop on drag panel
   {
      if (recorded_price>0)
         recorded_price=0.0;
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CreatePendingSetLine(color clr, double line_price)
{
   if (ObjectFind(ChartID(), PENDING_SETLINE)<0)
      ObjectCreate(ChartID(), PENDING_SETLINE, OBJ_HLINE, 0, 0, line_price);
   ObjectSetInteger(ChartID(), PENDING_SETLINE, OBJPROP_COLOR, clr);
   ObjectSetInteger(ChartID(), PENDING_SETLINE, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(ChartID(), PENDING_SETLINE, OBJPROP_HIDDEN, false);
   ObjectSetString(ChartID(), PENDING_SETLINE, OBJPROP_TOOLTIP, "\n");

   ChartRedraw();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void MovePendingSetLine(double line_price)
{
   ObjectSetDouble(ChartID(), PENDING_SETLINE, OBJPROP_PRICE, line_price);
   ChartRedraw();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DeletePendingSetLine()
{
   ObjectDelete(ChartID(), PENDING_SETLINE);
   ChartRedraw();
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void RecalculateValues(int position, double price_ref=0.0)
{
   if (riskCalculation == FIXED_LOTS)
   {
      totalLots = riskAmount;
      return;
   }

   double riskTotal = AccountInfoDouble(ACCOUNT_BALANCE) * riskAmount / 100.0;
//Si risk es 0, puede ser por cadena invalida

   double sl = 0.0;
   if (stop_takeMode == ST_PRICE)
   {
      if (stopLoss !=0.0)
      {
         if (price_ref>0.0) //pending
            sl = MathAbs(price_ref-stopLoss);
         else
         {
            if (position == POSITION_TYPE_BUY) sl = ASK_PRICE - stopLoss;
            else if (position == POSITION_TYPE_SELL) sl = stopLoss - BID_PRICE;
         }
      }
   }
   else
   {
      sl = stopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   }

	if (sl == 0.0)	
	{
	   totalLots = 0.0;
	   Print("Stop Loss Cannot be 0 with risk percent");
	   return;
	}
	
	sl  /= SymbolInfoDouble(_Symbol, SYMBOL_POINT);
	
	double lotValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE_LOSS);
	double pointValue = riskTotal / sl;
	
	if (pointValue < 0)
	{
	   totalLots = 0.0;
	   Print("Invalid stop");
	   return;
	}
	
	double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
	
	totalLots = MathFloor((pointValue / lotValue) / lotStep) * lotStep;
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CheckLots()
{
   if (totalLots < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN))
   {
      Print("Risk is too small to Open a trade");
      return false;
   }
   if (totalLots > SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX))
   {
      Print("Lots are too big to Open a trade");
      return false;
   }
   return true;
}

//+------------------------------------------------------------------+
//| Pending orders                                                   |
//+------------------------------------------------------------------+
void OpenBuyPendingOrder(double order_price)
{
   Print("Open Buy pending");

   RecalculateValues(POSITION_TYPE_BUY, order_price);


   if (!CheckLots()) return;


   double sl = 0.0;
   double tp = 0.0;

   if (stop_takeMode == ST_PRICE)
   {
      sl = stopLoss;
      tp = takeProfit;
   }
   else
   {
      if (stopLoss != 0.0)
         sl = order_price - stopLoss  * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
      if (takeProfit != 0.0)
         tp = order_price + takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   }

   if (order_price>ASK_PRICE)
   {
      ORDER_BUY_STOP(totalLots, order_price, sl, tp)
   }
   else
   {
      ORDER_BUY_LIMIT(totalLots, order_price, sl, tp)
   }


}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenSellPendingOrder(double order_price)
{
   Print("Open Sell pending");

   RecalculateValues(POSITION_TYPE_SELL, order_price);


   if (!CheckLots()) return;


   double sl = 0.0;
   double tp = 0.0;

   if (stop_takeMode == ST_PRICE)
   {
      sl = stopLoss;
      tp = takeProfit;
   }
   else
   {
      if (stopLoss != 0.0)
         sl = order_price + stopLoss  * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
      if (takeProfit != 0.0)
         tp = order_price - takeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   }

   if (order_price<BID_PRICE)
   {
      ORDER_SELL_STOP(totalLots, order_price, sl, tp)
   }
   else
   {
      ORDER_SELL_LIMIT(totalLots, order_price, sl, tp)
   }
}
//+------------------------------------------------------------------+


int OnInit()
{
   return OnInitEvent();
}

void OnDeinit(const int reason)
{
   OnDeinitEvent(reason);
}

void OnChartEvent(const int id,         // event ID
                  const long& lparam,   // event parameter of the long type
                  const double& dparam, // event parameter of the double type
                  const string& sparam) // event parameter of the string type
{
   ExtDialog.ChartEvent(id,lparam,dparam,sparam);
   CommonChartEvent(id,lparam,dparam,sparam);
}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---