//+------------------------------------------------------------------+ //| 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 " 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 #include #include #include #ifdef __MQL5__ #include #include #include #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 = 10001; // 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); }