//+------------------------------------------------------------------+ //| ProfitLossCalculatorRone.mqh | //| Copyright 2013, Rone | //| rone.sergey@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2013, Rone" #property link "rone.sergey@gmail.com" #property version "1.00" #property description "Profit Loss Calculator" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include #include #include #include #include #include #include #include #include "DoubleSpinEdit.mqh" //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ #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 (5) // gap by X coordinate #define CONTROLS_GAP_Y (5) // gap by Y coordinate //--- #define CONTROLS_WIDTH (70) #define CONTROLS_HEIGHT (20) #define EDIT_WIDTH (80) //--- #define FIELDS_TOTAL (6) #define LINES_TOTAL (3) #define RADIO_TOTAL (2) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum EDIT_ALIAS { ENTRY_EDIT = 0, LOT_EDIT = 1, LOSS_PIPS_EDIT = 2, PROFIT_PIPS_EDIT = 3, LOSS_MONEY_EDIT = 4, PROFIT_MONEY_EDIT = 5 }; enum LINE_ALIAS { ENTRY_LINE = 0, LOSS_LINE = 1, PROFIT_LINE = 2 }; //--- string label_name[FIELDS_TOTAL] = { "EntryLabel", "LotLabel", "LossPipsLabel", "ProfitPipsLabel", "LossMoneyLabel", "ProfitMoneyLabel" }; string label_text[FIELDS_TOTAL] = { "Entry:", "Lot:", "Loss, pips:", "Profit, pips:", "Loss, ", "Profit, " }; string spinedit_name[FIELDS_TOTAL] = { "EntryEdit", "LotEdit", "LossPipsEdit", "ProfitPipsEdit", "LossMoneyEdit", "ProfitMoneyEdit" }; string line_name[LINES_TOTAL] = { "PLC_EntryLine", "PLC_LossLine", "PLC_ProfitLine" }; color line_color[LINES_TOTAL] = { clrOrange, clrRed, clrGreen }; string radio_name[RADIO_TOTAL] = { "Buy", "Sell" }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CProfitLossCalculatorRone : public CAppDialog { private: CSymbolInfo m_sym; long m_order_type; double m_entry_price; double m_stop_price; double m_profit_price; double m_lot_value; //--- CRadioButton m_type_radio[RADIO_TOTAL]; CButton m_reset_button; CLabel m_label[FIELDS_TOTAL]; CDoubleSpinEdit m_spinedit[FIELDS_TOTAL]; CChartObjectHLine m_line[LINES_TOTAL]; public: CProfitLossCalculatorRone(); ~CProfitLossCalculatorRone(); virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2); virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam); virtual bool OnEventLine(const int id, const long &lparam, const double &dparam, const string &sparam); protected: //--- create lines and controls bool CreateLines(); bool CreateRadioButtons(); bool CreateResetButton(); bool CreateLabels(); bool CreateDoubleSpinEdits(); //--- handlers of the dependent controls events bool OnChangeType(int index); bool OnChangeDoubleSpinEdit(int index); void OnChangeEntry(); void OnChangeLot(); void OnChangeLossPips(); void OnChangeProfitPips(); void OnChangeLossMoney(); void OnChangeProfitMoney(); void OnChangeEntryLine(); void OnChangeLossLine(); void OnChangeProfitLine(); //--- void ResetData(); void UpdateProfitLoss(); int LossPips(); int MaxLossPips(); int ProfitPips(); int MaxProfitPips(); double CalculateMoney(double exit_price); double LossMoney(); double MinLossMoney(); double MaxLossMoney(); double ProfitMoney(); double MinProfitMoney(); double MaxProfitMoney(); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CProfitLossCalculatorRone::CProfitLossCalculatorRone() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CProfitLossCalculatorRone::~CProfitLossCalculatorRone() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ EVENT_MAP_BEGIN(CProfitLossCalculatorRone) ON_INDEXED_EVENT(ON_CHANGE, m_type_radio, OnChangeType) ON_EVENT(ON_CLICK, m_reset_button, ResetData) ON_INDEXED_EVENT(ON_CHANGE, m_spinedit, OnChangeDoubleSpinEdit) EVENT_MAP_END(CAppDialog) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) { //--- bool ok = true; ok &= CreateLines(); ok &= CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2); ok &= CreateRadioButtons(); ok &= CreateResetButton(); ok &= CreateLabels(); ok &= CreateDoubleSpinEdits(); ResetData(); //--- return(ok); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::CreateLines(void) { //--- bool ok = true; for(int i = 0; i < LINES_TOTAL; i++) { if(ObjectFind(0, line_name[i]) < 0) { ok = m_line[i].Create(0, line_name[i], 0, 0.0); ok &= m_line[i].Color(line_color[i]); ok &= m_line[i].Selectable(true); if(!ok) { return(false); } } } //--- return(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::CreateRadioButtons(void) { //--- int x1 = INDENT_LEFT; int y1 = INDENT_TOP; int x2 = x1 + CONTROLS_WIDTH; int y2 = y1 + CONTROLS_HEIGHT; bool ok = true; for(int i = 0; i < RADIO_TOTAL; i++) { ok = m_type_radio[i].Create(m_chart_id, m_name+radio_name[i], m_subwin, x1, y1, x2, y2); ok &= m_type_radio[i].Text(radio_name[i]); ok &= Add(m_type_radio[i]); if(!ok) { return(false); } x1 = x2 + CONTROLS_GAP_X; x2 = x1 + CONTROLS_WIDTH; } ok &= m_type_radio[0].State(true); //--- return(ok); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::CreateResetButton(void) { //--- int x1 = INDENT_LEFT + 2 * CONTROLS_WIDTH + 3 * CONTROLS_GAP_X + EDIT_WIDTH; int y1 = INDENT_TOP; int x2 = x1 + EDIT_WIDTH; int y2 = y1 + CONTROLS_HEIGHT; bool ok = m_reset_button.Create(m_chart_id, m_name+"ResetButton", m_subwin, x1, y1, x2, y2); ok &= m_reset_button.Text("Reset"); ok &= Add(m_reset_button); //--- return(ok); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::CreateLabels(void) { //--- int x1, x2, y1, y2; bool ok = true; string currency = AccountInfoString(ACCOUNT_CURRENCY); for(int row = 1, index = 0; row <= 3; row++) { y1 = INDENT_TOP + row * (CONTROLS_HEIGHT + CONTROLS_GAP_Y); y2 = y1 + CONTROLS_HEIGHT; for(int col = 0; col < 2; col++) { x1 = INDENT_LEFT + col * (CONTROLS_WIDTH + EDIT_WIDTH + 2 * CONTROLS_GAP_X); x2 = x1 + CONTROLS_WIDTH; string text = label_text[index]; if(index == LOSS_MONEY_EDIT || index == PROFIT_MONEY_EDIT) { text += currency + ":"; } ok &= m_label[index].Create(m_chart_id, m_name+label_name[index], m_subwin, x1, y1, x2, y2); ok &= m_label[index].Text(text); ok &= Add(m_label[index]); if(!ok) { return(false); } index += 1; } } //--- return(ok); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::CreateDoubleSpinEdits(void) { //--- int x1, x2, y1, y2; bool ok = true; for(int row = 1, index = 0; row <= 3; row++) { y1 = INDENT_TOP + row * (CONTROLS_HEIGHT + CONTROLS_GAP_Y); y2 = y1 + CONTROLS_HEIGHT; for(int col = 0; col < 2; col++) { x1 = INDENT_LEFT + CONTROLS_WIDTH + CONTROLS_GAP_X + col * (CONTROLS_WIDTH + EDIT_WIDTH + 2 * CONTROLS_GAP_X); x2 = x1 + EDIT_WIDTH; ok &= m_spinedit[index].Create(m_chart_id, m_name+spinedit_name[index], m_subwin, x1, y1, x2, y2); ok &= m_spinedit[index].ReadOnly(false); ok &= Add(m_spinedit[index]); if(!ok) { return(false); } PrintFormat("ok: SpinEdit[%d,%s].Create(%d,%s,%d,%d,%d,%d,%d) ... x2-x1=%d y2-y1=%d",index,EnumToString((EDIT_ALIAS)index), m_chart_id, m_name+spinedit_name[index], m_subwin, x1, y1, x2, y2, x2-x1, y2-y1); index += 1; } } //--- return(ok); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::ResetData(void) { //--- bool ok = false; double min_price = 0.0, max_price = 0.0; m_sym.Name(_Symbol); for(int tries = 1; tries < 5; tries++) { if(m_sym.IsSynchronized() && m_sym.Refresh() && ChartGetDouble(m_chart_id, CHART_PRICE_MIN, m_subwin, min_price) && ChartGetDouble(m_chart_id, CHART_PRICE_MAX, m_subwin, max_price)) { ok = true; break; } Sleep(1000); } if(ok) { //--- members m_order_type = (long)ORDER_TYPE_BUY; m_entry_price = NormalizeDouble((max_price+min_price)/2, m_sym.Digits()); m_stop_price = NormalizeDouble(m_entry_price-(m_entry_price-min_price)/2, m_sym.Digits()); m_profit_price = NormalizeDouble(max_price-(max_price-m_entry_price)/2, m_sym.Digits()); m_lot_value = NormalizeDouble(10*m_sym.LotsMin(), 2); //--- lines m_line[ENTRY_LINE].Price(0, m_entry_price); m_line[LOSS_LINE].Price(0, m_stop_price); m_line[PROFIT_LINE].Price(0, m_profit_price); for(int i = 0; i < LINES_TOTAL; i++) { m_line[i].Selected(false); } //--- controls m_type_radio[0].State(true); m_type_radio[1].State(false); m_spinedit[ENTRY_EDIT].SetParameters(m_entry_price, min_price, max_price, 100*m_sym.TickSize(), m_sym.Digits()); m_spinedit[LOT_EDIT].SetParameters(m_lot_value, m_sym.LotsMin(), m_sym.LotsMax(), 10*m_sym.LotsStep(), (int)NormalizeDouble(MathCeil(MathLog10(1/m_sym.LotsStep())), 0)); UpdateProfitLoss(); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::UpdateProfitLoss(void) { //--- m_spinedit[LOSS_PIPS_EDIT].SetParameters(LossPips(), m_sym.StopsLevel(), MaxLossPips(), 100*m_sym.TickSize()/m_sym.Point(), 0); m_spinedit[PROFIT_PIPS_EDIT].SetParameters(ProfitPips(), m_sym.StopsLevel(), MaxProfitPips(), 100*m_sym.TickSize()/m_sym.Point(), 0); m_spinedit[LOSS_MONEY_EDIT].SetParameters(LossMoney(), MinLossMoney(), MaxLossMoney(), 10, 2); m_spinedit[PROFIT_MONEY_EDIT].SetParameters(ProfitMoney(), MinProfitMoney(), MaxProfitMoney(), 10, 2); //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CProfitLossCalculatorRone::LossPips(void) { return(int(MathAbs(MathRound((m_entry_price - m_stop_price)/m_sym.Point())))); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CProfitLossCalculatorRone::MaxLossPips(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_spinedit[ENTRY_EDIT].MinValue() : m_spinedit[ENTRY_EDIT].MaxValue()); return(int(MathAbs(MathRound((m_entry_price - price)/m_sym.Point()))) + m_sym.StopsLevel()); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CProfitLossCalculatorRone::ProfitPips(void) { return(int(MathAbs(MathRound((m_entry_price - m_profit_price)/m_sym.Point())))); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CProfitLossCalculatorRone::MaxProfitPips(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_spinedit[ENTRY_EDIT].MaxValue() : m_spinedit[ENTRY_EDIT].MinValue()); return(int(MathAbs(MathRound((m_entry_price - price)/m_sym.Point()))) + m_sym.StopsLevel()); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::CalculateMoney(double exit_price) { double result = 0.0; ResetLastError(); if(!OrderCalcProfit((ENUM_ORDER_TYPE)m_order_type, m_sym.Name(), m_lot_value, m_entry_price, exit_price, result)) { Print(__FUNCTION__, ": calculating money failed. Error #", GetLastError()); } //--- return(NormalizeDouble(MathAbs(result), 2)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::LossMoney(void) { return(CalculateMoney(m_stop_price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::MinLossMoney(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_entry_price - m_sym.StopsLevel() * m_sym.Point() : m_entry_price + m_sym.StopsLevel() * m_sym.Point()); return(CalculateMoney(price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::MaxLossMoney(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_spinedit[ENTRY_EDIT].MinValue() - m_sym.StopsLevel() * m_sym.Point() : m_spinedit[ENTRY_EDIT].MaxValue() + m_sym.StopsLevel() * m_sym.Point()); return(CalculateMoney(price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::ProfitMoney(void) { return(CalculateMoney(m_profit_price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::MinProfitMoney(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_entry_price + m_sym.StopsLevel() * m_sym.Point() : m_entry_price - m_sym.StopsLevel() * m_sym.Point()); return(CalculateMoney(price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CProfitLossCalculatorRone::MaxProfitMoney(void) { double price = ((m_order_type == (long)ORDER_TYPE_BUY) ? m_spinedit[ENTRY_EDIT].MaxValue() + m_sym.StopsLevel() * m_sym.Point() : m_spinedit[ENTRY_EDIT].MinValue() - m_sym.StopsLevel() * m_sym.Point()); return(CalculateMoney(price)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::OnChangeType(int index) { //--- if(m_type_radio[index].State()) { int other_index = MathAbs(index-1); bool other_prev_state = m_type_radio[other_index].State(); m_type_radio[other_index].State(false); m_order_type = (index == 0) ? (long)ORDER_TYPE_BUY : (long)ORDER_TYPE_SELL; if(other_prev_state != m_type_radio[other_index].State()) { double tmp = m_stop_price; m_stop_price = m_profit_price; m_profit_price = tmp; m_line[LOSS_LINE].Price(0, m_stop_price); m_line[PROFIT_LINE].Price(0, m_profit_price); UpdateProfitLoss(); } } //--- return(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::OnChangeDoubleSpinEdit(int index) { //--- switch(index) { case ENTRY_EDIT: OnChangeEntry(); break; case LOT_EDIT: OnChangeLot(); break; case LOSS_PIPS_EDIT: OnChangeLossPips(); break; case PROFIT_PIPS_EDIT: OnChangeProfitPips(); break; case LOSS_MONEY_EDIT: OnChangeLossMoney(); break; case PROFIT_MONEY_EDIT: OnChangeProfitMoney(); break; } //--- return(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeEntry(void) { //--- double new_entry = m_spinedit[ENTRY_EDIT].Value(); double valid_max = MathMax(m_stop_price, m_profit_price) - m_sym.StopsLevel() * m_sym.Point(); double valid_min = MathMin(m_stop_price, m_profit_price) + m_sym.StopsLevel() * m_sym.Point(); if(new_entry > valid_max || new_entry < valid_min) { m_spinedit[ENTRY_EDIT].Value(m_entry_price); return; } if(new_entry != m_entry_price) { m_entry_price = new_entry; m_line[ENTRY_LINE].Price(0, m_entry_price); m_spinedit[LOSS_PIPS_EDIT].Value(LossPips()); m_spinedit[PROFIT_PIPS_EDIT].Value(ProfitPips()); m_spinedit[LOSS_MONEY_EDIT].Value(LossMoney()); m_spinedit[PROFIT_MONEY_EDIT].Value(ProfitMoney()); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeLot(void) { //--- double new_lot = m_spinedit[1].Value(); if(new_lot != m_lot_value) { m_lot_value = new_lot; UpdateProfitLoss(); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeLossPips(void) { //--- int old_value = LossPips(); int new_value = (int)m_spinedit[LOSS_PIPS_EDIT].Value(); if(new_value != old_value) { if(m_order_type == (long)ORDER_TYPE_BUY) { m_stop_price = NormalizeDouble(m_entry_price-new_value*m_sym.Point(), m_sym.Digits()); } else { m_stop_price = NormalizeDouble(m_entry_price+new_value*m_sym.Point(), m_sym.Digits()); } m_line[LOSS_LINE].Price(0, m_stop_price); m_spinedit[LOSS_MONEY_EDIT].Value(LossMoney()); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeProfitPips(void) { //--- int old_value = ProfitPips(); int new_value = (int)m_spinedit[PROFIT_PIPS_EDIT].Value(); if(new_value != old_value) { if(m_order_type == (long)ORDER_TYPE_BUY) { m_profit_price = NormalizeDouble(m_entry_price+new_value*m_sym.Point(), m_sym.Digits()); } else { m_profit_price = NormalizeDouble(m_entry_price-new_value*m_sym.Point(), m_sym.Digits()); } m_line[PROFIT_LINE].Price(0, m_profit_price); m_spinedit[PROFIT_MONEY_EDIT].Value(ProfitMoney()); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeLossMoney(void) { //--- double old_value = LossMoney(); double new_value = m_spinedit[LOSS_MONEY_EDIT].Value(); if(new_value != old_value) { int loss_pips = int(new_value/(m_lot_value*m_sym.TickValueLoss())); m_spinedit[LOSS_PIPS_EDIT].Value(loss_pips); if(m_order_type == (long)ORDER_TYPE_BUY) { m_stop_price = NormalizeDouble(m_entry_price-loss_pips*m_sym.Point(), m_sym.Digits()); } else { m_stop_price = NormalizeDouble(m_entry_price+loss_pips*m_sym.Point(), m_sym.Digits()); } m_line[LOSS_LINE].Price(0, m_stop_price); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeProfitMoney(void) { //--- double old_value = ProfitMoney(); double new_value = m_spinedit[PROFIT_MONEY_EDIT].Value(); if(new_value != old_value) { int profit_pips = int(new_value/(m_lot_value*m_sym.TickValueProfit())); m_spinedit[PROFIT_PIPS_EDIT].Value(profit_pips); if(m_order_type == (long)ORDER_TYPE_BUY) { m_profit_price = NormalizeDouble(m_entry_price+profit_pips*m_sym.Point(), m_sym.Digits()); } else { m_profit_price = NormalizeDouble(m_entry_price-profit_pips*m_sym.Point(), m_sym.Digits()); } m_line[PROFIT_LINE].Price(0, m_profit_price); } //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CProfitLossCalculatorRone::OnEventLine(const int id, const long &lparam, const double &dparam,const string &sparam) { //--- if(id == CHARTEVENT_OBJECT_CHANGE || id == CHARTEVENT_OBJECT_DRAG) { if(sparam == line_name[ENTRY_LINE]) { OnChangeEntryLine(); } else if(sparam == line_name[LOSS_LINE]) { OnChangeLossLine(); } else if(sparam == line_name[PROFIT_LINE]) { OnChangeProfitLine(); } } //--- return(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeEntryLine(void) { //--- double new_price = NormalizeDouble(ObjectGetDouble(0, line_name[ENTRY_LINE], OBJPROP_PRICE), _Digits); double stops_level = m_sym.StopsLevel() * m_sym.Point(); bool valid_buy_entry = (m_order_type == (long)ORDER_TYPE_SELL && new_price < m_stop_price - stops_level && new_price > m_profit_price + stops_level); bool valid_sell_entry = (m_order_type == (long)ORDER_TYPE_BUY && new_price < m_profit_price - stops_level && new_price > m_stop_price + stops_level); if(!valid_buy_entry && !valid_sell_entry) { m_line[ENTRY_LINE].Price(0, m_entry_price); ChartRedraw(); return; } m_entry_price = new_price; m_spinedit[ENTRY_EDIT].Value(new_price); m_spinedit[LOSS_PIPS_EDIT].Value(LossPips()); m_spinedit[PROFIT_PIPS_EDIT].Value(ProfitPips()); m_spinedit[LOSS_MONEY_EDIT].Value(LossMoney()); m_spinedit[PROFIT_MONEY_EDIT].Value(ProfitMoney()); //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeLossLine(void) { //--- double new_price = NormalizeDouble(ObjectGetDouble(0, line_name[LOSS_LINE], OBJPROP_PRICE), _Digits); double stops_level = m_sym.StopsLevel() * m_sym.Point(); bool valid_buy_loss = (m_order_type == (long)ORDER_TYPE_BUY && new_price >= m_spinedit[ENTRY_EDIT].MinValue() - stops_level && new_price <= m_entry_price - stops_level); bool valis_sell_loss = (m_order_type == (long)ORDER_TYPE_SELL && new_price <= m_spinedit[ENTRY_EDIT].MaxValue() + stops_level && new_price >= m_entry_price + stops_level); if(!valid_buy_loss && !valis_sell_loss) { m_line[LOSS_LINE].Price(0, m_stop_price); ChartRedraw(); return; } m_stop_price = new_price; m_spinedit[LOSS_PIPS_EDIT].Value(LossPips()); m_spinedit[LOSS_MONEY_EDIT].Value(LossMoney()); //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProfitLossCalculatorRone::OnChangeProfitLine(void) { //--- double new_price = NormalizeDouble(ObjectGetDouble(0, line_name[PROFIT_LINE], OBJPROP_PRICE), _Digits); double stops_level = m_sym.StopsLevel() * m_sym.Point(); bool valid_buy_profit = (m_order_type == (long)ORDER_TYPE_BUY && new_price <= m_spinedit[ENTRY_EDIT].MaxValue() + stops_level && new_price >= m_entry_price + stops_level); bool valid_sell_profit = (m_order_type == (long)ORDER_TYPE_SELL && new_price >= m_spinedit[ENTRY_EDIT].MinValue() - stops_level && new_price <= m_entry_price - stops_level); if(!valid_buy_profit && !valid_sell_profit) { m_line[PROFIT_LINE].Price(0, m_profit_price); ChartRedraw(); return; } m_profit_price = new_price; m_spinedit[PROFIT_PIPS_EDIT].Value(ProfitPips()); m_spinedit[PROFIT_MONEY_EDIT].Value(ProfitMoney()); //--- } //+------------------------------------------------------------------+