/// <summary> /// Stops connection to MT /// </summary> private void Disconnect() { nullPing = true; pingAttempt = 0; if (Data.IsConnected && Configs.PlaySounds) { Data.SoundDisconnect.Play(); } Data.IsConnected = false; StopTrade(); JournalMessage jmsg = new JournalMessage(JournalIcons.Blocked, DateTime.Now, Language.T("Not Connected")); AppendJournalMessage(jmsg); Data.Bid = 0; Data.Ask = 0; Data.SetCurrentAccount(DateTime.MinValue, 0, 0, 0, 0); bool poschanged = Data.SetCurrentPosition(0, -1, 0, 0, DateTime.MinValue, 0, 0, 0, ""); ShowCurrentPosition(poschanged); SetEquityInfoText(string.Format("{0} {1}", 0, Data.AccountCurrency)); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetConnMarketText(Language.T("Not Connected")); SetLblConnectionText(Language.T("Not Connected")); SetConnIcon(0); SetTickInfoText(""); SetLblSymbolText(""); SetFormText(); }
/// <summary> /// Shows current position on the status bar. /// </summary> void ShowCurrentPosition(bool showInJournal) { if (!Data.IsConnected) { SetPositionInfoText(null, String.Empty); return; } string format = Data.FF; string text = Language.T("Square"); JournalIcons icon = JournalIcons.PosSquare; Image img = Properties.Resources.pos_square; if (Data.PositionTicket > 0) { img = (Data.PositionType == 0 ? Properties.Resources.pos_buy : Properties.Resources.pos_sell); icon = (Data.PositionType == 0 ? JournalIcons.PosBuy : JournalIcons.PosSell); text = string.Format((Data.PositionType == 0 ? Language.T("Long") : Language.T("Short")) + " {0} " + (Data.PositionLots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}, " + Language.T("Profit") + " {4} " + Data.AccountCurrency, Data.PositionLots, Data.PositionOpenPrice.ToString(format), Data.PositionStopLoss.ToString(format), Data.PositionTakeProfit.ToString(format), Data.PositionProfit.ToString("F2")); } SetPositionInfoText(img, text); if (showInJournal) { JournalMessage jmsg = new JournalMessage(icon, DateTime.Now, string.Format(Data.Symbol + " " + Data.PeriodMTStr + " " + text)); AppendJournalMessage(jmsg); } return; }
/// <summary> /// Adds a message to the journal. /// </summary> protected void AppendJournalMessage(JournalMessage message) { _messages.Add(message); if (_messages.Count > Configs.JournalLength) _messages.RemoveRange(0, _messages.Count - Configs.JournalLength); UpdateJournal(_messages); }
/// <summary> /// Stops trade and shows a message. /// </summary> void AfterStrategyOpening() { StopTrade(); JournalMessage msg = new JournalMessage(JournalIcons.Information, DateTime.Now, Language.T("Strategy") + " \"" + Data.Strategy.StrategyName + "\" " + Language.T("loaded successfully.")); AppendJournalMessage(msg); return; }
/// <summary> /// Adds a message to the journal. /// </summary> protected void AppendJournalMessage(JournalMessage message) { _messages.Add(message); if (_messages.Count > Configs.JournalLength) { _messages.RemoveRange(0, _messages.Count - Configs.JournalLength); } UpdateJournal(_messages); }
/// <summary> /// Stops trade and shows a message. /// </summary> private void AfterStrategyOpening() { StopTrade(); string message = Language.T("Strategy") + " \"" + Data.Strategy.StrategyName + "\" " + Language.T("loaded successfully."); var jmsg = new JournalMessage(JournalIcons.Information, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); }
/// <summary> /// Adds a message. /// </summary> public void AppendMessage(JournalMessage message) { messages.Add(message); rows = messages.Count; requiredHeight = rows * rowHeight; CalculateScrollBarStatus(); Invalidate(); return; }
/// <summary> /// Stops the trade. /// </summary> void StopTrade() { if (!isTrading) { return; } isTrading = false; DeinitTrade(); Data.SetStopTradingTime(); JournalMessage msg = new JournalMessage(JournalIcons.StopTrading, DateTime.Now, Language.T("Automatic trade stopped.")); AppendJournalMessage(msg); SetTradeStrip(); return; }
/// <summary> /// Starts the trade. /// </summary> void StartTrade() { isTrading = true; // Resets trade global variables. InitTrade(); Data.SetStartTradingTime(); JournalMessage msg = new JournalMessage(JournalIcons.StartTrading, DateTime.Now, Language.T("Automatic trade started.")); AppendJournalMessage(msg); symbolReconnect = Data.Symbol; periodReconnect = Data.Period; accountReconnect = Data.AccountNumber; barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; SetTradeStrip(); return; }
/// <summary> /// Sets and sends an entry order. /// </summary> bool DoEntryTrade(TradeDirection tradeDir) { bool responseOK = false; double price; OrderDirection ordDir; OperationType opType; MT4Bridge.OrderType type; JournalIcons icon; if (timeLastEntryBar != Data.Time[Data.Bars - 1]) isEnteredLong = isEnteredShort = false; if (tradeDir == TradeDirection.Long) { // Buy if (isEnteredLong) return false; // Only one long entry is allowed. price = Data.Ask; ordDir = OrderDirection.Buy; opType = OperationType.Buy; type = MT4Bridge.OrderType.Buy; icon = JournalIcons.OrderBuy; } else if (tradeDir == TradeDirection.Short) { // Sell if (isEnteredShort) return false; // Only one short entry is allowed. price = Data.Bid; ordDir = OrderDirection.Sell; opType = OperationType.Sell; type = MT4Bridge.OrderType.Sell; icon = JournalIcons.OrderSell; } else { // Wrong direction of trade. return false; } PosDirection newPosDir = PosDirection.None; double size = AnalyseEntrySize(ordDir, ref newPosDir); if (size < Data.InstrProperties.MinLot / 2) { // The entry trade is cancelled. return false; } string symbol = Data.Symbol; double lots = size; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; double stoploss = GetStopLossPips(size); double takeprofit = GetTakeProfitPips(); double point = Data.InstrProperties.Point; string sStopLoss = "0"; if (stoploss > 0) { double stopLossPrice = 0; if (newPosDir == PosDirection.Long) stopLossPrice = Data.Bid - stoploss * point; else if (newPosDir == PosDirection.Short) stopLossPrice = Data.Ask + stoploss * point; sStopLoss = stopLossPrice.ToString(Data.FF); } string sTakeProfit = "0"; if (takeprofit > 0) { double takeProfitPrice = 0; if (newPosDir == PosDirection.Long) takeProfitPrice = Data.Bid + takeprofit * point; else if (newPosDir == PosDirection.Short) takeProfitPrice = Data.Ask - takeprofit * point; sTakeProfit = takeProfitPrice.ToString(Data.FF); } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); JournalMessage jmsg = new JournalMessage(icon, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T(ordDir.ToString()) + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), sStopLoss, sTakeProfit)); AppendJournalMessage(jmsg); string parameters = OrderParameters(); int response = bridge.OrderSend(symbol, type, lots, price, slippage, stoploss, takeprofit, parameters); if (response >= 0) { // The order was executed successfully. responseOK = true; Data.AddBarStats(opType, lots, price); timeLastEntryBar = Data.Time[Data.Bars - 1]; if (type == MT4Bridge.OrderType.Buy) isEnteredLong = true; else isEnteredShort = true; Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. responseOK = false; if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); Data.WrongStopLoss = (int)stoploss; Data.WrongTakeProf = (int)takeprofit; } return responseOK; }
/// <summary> /// Sets the instrument's properties after connecting; /// </summary> private bool UpdateDataFeedInfo(DateTime time, string symbol, DataPeriods period) { lock (_lockerDataFeed) { Data.ResetBidAskClose(); Data.ResetAccountStats(); Data.ResetPositionStats(); Data.ResetBarStats(); Data.ResetTicks(); // Reads market info from the chart MT4Bridge.MarketInfo marketInfo = _bridge.GetMarketInfoAll(symbol); if (marketInfo == null) { if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot update market info.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } // Sets instrument properties Data.Period = period; Data.InstrProperties.Symbol = symbol; Data.InstrProperties.LotSize = (int) marketInfo.ModeLotSize; Data.InstrProperties.MinLot = marketInfo.ModeMinLot; Data.InstrProperties.MaxLot = marketInfo.ModeMaxLot; Data.InstrProperties.LotStep = marketInfo.ModeLotStep; Data.InstrProperties.Digits = (int) marketInfo.ModeDigits; Data.InstrProperties.Spread = marketInfo.ModeSpread; Data.InstrProperties.SwapLong = marketInfo.ModeSwapLong; Data.InstrProperties.SwapShort = marketInfo.ModeSwapShort; Data.InstrProperties.TickValue = marketInfo.ModeTickValue; Data.InstrProperties.StopLevel = marketInfo.ModeStopLevel; Data.InstrProperties.MarginRequired = marketInfo.ModeMarginRequired; SetNumUpDownLots(marketInfo.ModeMinLot, marketInfo.ModeLotStep, marketInfo.ModeMaxLot); // Sets Market Info var values = new[] { symbol, Data.DataPeriodToString(period), marketInfo.ModeLotSize.ToString(CultureInfo.InvariantCulture), marketInfo.ModePoint.ToString("F" + marketInfo.ModeDigits.ToString(CultureInfo.InvariantCulture)), marketInfo.ModeSpread.ToString(CultureInfo.InvariantCulture), marketInfo.ModeSwapLong.ToString(CultureInfo.InvariantCulture), marketInfo.ModeSwapShort.ToString(CultureInfo.InvariantCulture) }; UpdateStatusPageMarketInfo(values); Bars bars = _bridge.GetBars(symbol, (PeriodType) (int) period); if (bars == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (bars.Count < MaxBarsCount((int) period)) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Market data updated, bars downloaded.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } // Account Information. AccountInfo account = _bridge.GetAccountInfo(); if (account == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Cannot receive account information!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } return false; } if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (PeriodType) (int) period + " " + Language.T("Account information received.")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } Data.AccountName = account.Name; Data.IsDemoAccount = account.IsDemo; Data.AccountCurrency = account.Currency; Data.SetCurrentAccount(time, account.Balance, account.Equity, account.Profit, account.FreeMargin); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetLblSymbolText(symbol); } return true; }
/// <summary> /// Bridge OnTick /// </summary> void Bridge_OnTick(object source, MT4Bridge.TickEventArgs tea) { lock (lockerTickPing) { if (pingAttempt > 0 && JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, tea.Symbol + " " + tea.Period.ToString() + " " + Language.T("Tick received after an unsuccessful ping.")); AppendJournalMessage(jmsgsys); } pingAttempt = 0; if (!Data.IsConnected) { return; } tickLocalTime = DateTime.Now; tickServerTime = tea.Time; if (IsChartChangeged(tea.Symbol, (DataPeriods)(int)tea.Period)) { StopTrade(); Data.IsConnected = false; SetFormText(); if (Configs.PlaySounds) { Data.SoundDisconnect.Play(); } JournalMessage jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, tea.Symbol + " " + tea.Period.ToString() + " " + Language.T("Tick received from a different chart!")); AppendJournalMessage(jmsg); return; } bool bNewPrice = Math.Abs(Data.Bid - tea.Bid) > Data.InstrProperties.Point / 2; Data.Bid = tea.Bid; Data.Ask = tea.Ask; Data.InstrProperties.Spread = tea.Spread; Data.InstrProperties.TickValue = tea.TickValue; Data.ServerTime = tea.Time; Data.SetTick(tea.Bid); bool isAccChanged = Data.SetCurrentAccount(tea.Time, tea.AccountBalance, tea.AccountEquity, tea.AccountProfit, tea.AccountFreeMargin); bool isPosChanged = Data.SetCurrentPosition(tea.PositionTicket, tea.PositionType, tea.PositionLots, tea.PositionOpenPrice, tea.PositionOpenTime, tea.PositionStopLoss, tea.PositionTakeProfit, tea.PositionProfit, tea.PositionComment); bool updateData = true; SetDataAndCalculate(tea.Symbol, tea.Period, tea.Time, bNewPrice, updateData); string bidText = tea.Bid.ToString(Data.FF); string askText = tea.Ask.ToString(Data.FF); SetLblBidAskText(bidText + " / " + askText); // Tick data label if (JournalShowTicks) { string tickInfo = string.Format("{0} {1} {2} {3} / {4}", tea.Symbol, tea.Period, tea.Time.ToString("HH:mm:ss"), bidText, askText); JournalMessage jmsg = new JournalMessage(JournalIcons.Globe, DateTime.Now, tickInfo); AppendJournalMessage(jmsg); } UpdateTickChart(Data.InstrProperties.Point, Data.ListTicks.ToArray()); SetEquityInfoText(string.Format("{0:F2} {1}", tea.AccountEquity, Data.AccountCurrency)); ShowCurrentPosition(isPosChanged); if (isAccChanged) { JournalMessage jmsg = new JournalMessage(JournalIcons.Currency, DateTime.Now, string.Format(Language.T("Account Balance") + " {0:F2}, " + Language.T("Equity") + " {1:F2}, " + Language.T("Profit") + ", {2:F2}, " + Language.T("Free Margin") + " {3:F2}", tea.AccountBalance, tea.AccountEquity, tea.AccountProfit, tea.AccountFreeMargin)); AppendJournalMessage(jmsg); } if (Data.IsBalanceDataChganged) { UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); } SetTickInfoText(string.Format("{0} {1} / {2}", tea.Time.ToString("HH:mm:ss"), bidText, askText)); SetConnIcon(2); // Sends OrderModify on SL/TP errors if (IsWrongStopsExecution()) { ResendWrongStops(); } } return; }
/// <summary> /// Copies data to Data and calculates. /// </summary> void SetDataAndCalculate(string symbol, MT4Bridge.PeriodType period, DateTime time, bool isPriceChange, bool isUpdateData) { lock (lockerDataFeed) { bool isUpdateChart = isUpdateData; MT4Bridge.Bars bars = bridge.GetBars(symbol, period); if (bars == null && JournalShowSystemMessages) { isSetRootDataError = true; Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + period.ToString() + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsg); return; } if (bars.Count < MaxBarsCount((int)period) && JournalShowSystemMessages) { isSetRootDataError = true; Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + period.ToString() + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsg); return; } if (isSetRootDataError && JournalShowSystemMessages) { isSetRootDataError = false; JournalMessage jmsg = new JournalMessage(JournalIcons.Information, DateTime.Now, symbol + " " + period.ToString() + " " + Language.T("Enough bars received!")); AppendJournalMessage(jmsg); } int countBars = bars.Count; if (countBars < 400) { return; } if (Data.Bars != countBars || Data.Time[countBars - 1] != bars.Time[countBars - 1] || Data.Volume[countBars - 1] != bars.Volume[countBars - 1] || Data.Close[countBars - 1] != bars.Close[countBars - 1]) { if (Data.Bars == countBars && Data.Time[countBars - 1] == bars.Time[countBars - 1] && Data.Time[countBars - 10] == bars.Time[countBars - 10]) { // Update the last bar only. Data.Open [countBars - 1] = bars.Open [countBars - 1]; Data.High [countBars - 1] = bars.High [countBars - 1]; Data.Low [countBars - 1] = bars.Low [countBars - 1]; Data.Close [countBars - 1] = bars.Close [countBars - 1]; Data.Volume[countBars - 1] = bars.Volume[countBars - 1]; } else { // Update all the bars. Data.Bars = countBars; Data.Time = new DateTime[countBars]; Data.Open = new double[countBars]; Data.High = new double[countBars]; Data.Low = new double[countBars]; Data.Close = new double[countBars]; Data.Volume = new int[countBars]; bars.Time.CopyTo(Data.Time, 0); bars.Open.CopyTo(Data.Open, 0); bars.High.CopyTo(Data.High, 0); bars.Low.CopyTo(Data.Low, 0); bars.Close.CopyTo(Data.Close, 0); bars.Volume.CopyTo(Data.Volume, 0); } // Calculate the strategy indicators. CalculateStrategy(true); isUpdateChart = true; } bool isBarChanged = IsBarChanged(Data.Time[Data.Bars - 1]); if (isTrading) { TickType tickType = GetTickType((DataPeriods)(int)period, Data.Time[Data.Bars - 1], time, Data.Volume[Data.Bars - 1]); if (tickType == TickType.Close || isPriceChange || isBarChanged) { if (JournalShowSystemMessages && tickType != TickType.Regular) { JournalIcons icon = JournalIcons.Warning; string text = string.Empty; if (tickType == TickType.Open) { icon = JournalIcons.BarOpen; text = Language.T("A Bar Open event!"); } else if (tickType == TickType.Close) { icon = JournalIcons.BarClose; text = Language.T("A Bar Close event!"); } else if (tickType == TickType.AfterClose) { icon = JournalIcons.Warning; text = Language.T("A new tick arrived after a Bar Close event!"); } JournalMessage jmsg = new JournalMessage(icon, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " " + text); AppendJournalMessage(jmsg); } if (isBarChanged && tickType == TickType.Regular) { if (JournalShowSystemMessages) { JournalMessage jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " A Bar Changed event!"); AppendJournalMessage(jmsg); } tickType = TickType.Open; } if (tickType == TickType.Open && barOpenTimeForLastCloseEvent == Data.Time[Data.Bars - 3]) { if (JournalShowSystemMessages) { JournalMessage jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " A secondary Bar Close event!"); AppendJournalMessage(jmsg); } tickType = TickType.OpenClose; } CalculateTrade(tickType); isUpdateChart = true; if (tickType == TickType.Close || tickType == TickType.OpenClose) { barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; } } } if (isUpdateChart) { UpdateChart(); } } return; }
/// <summary> /// Close warning message and stop resending. /// </summary> private void RecoverFailedCloseOrder() { string message = Language.T("Deactivated resending of failed close orders."); var jmsg = new JournalMessage(JournalIcons.Information, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); DeactivateWarningMessage(); }
/// <summary> /// Shows current position on the status bar. /// </summary> private void ShowCurrentPosition(bool showInJournal) { if (!Data.IsConnected) { SetPositionInfoText(null, String.Empty); return; } string format = Data.FF; string text = Language.T("Square"); JournalIcons icon = JournalIcons.PosSquare; Image img = Resources.pos_square; if (Data.PositionTicket > 0) { img = (Data.PositionType == 0 ? Resources.pos_buy : Resources.pos_sell); icon = (Data.PositionType == 0 ? JournalIcons.PosBuy : JournalIcons.PosSell); text = string.Format((Data.PositionType == 0 ? Language.T("Long") : Language.T("Short")) + " {0} " + LotOrLots(Data.PositionLots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}, " + Language.T("Profit") + " {4} " + Data.AccountCurrency, Data.PositionLots, Data.PositionOpenPrice.ToString(format), Data.PositionStopLoss.ToString(format), Data.PositionTakeProfit.ToString(format), Data.PositionProfit.ToString("F2")); } SetPositionInfoText(img, text); if (showInJournal) { string message = string.Format(Data.Symbol + " " + Data.PeriodMTStr + " " + text); var jmsg = new JournalMessage(icon, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); } }
/// <summary> /// Sets SL and TP after wrong execution. /// </summary> private void ResendWrongStops() { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); double stoploss = Data.WrongStopLoss; double takeprofit = Data.WrongTakeProf; string stopLoss = "0"; if (stoploss > 0) { double stopLossPrice = 0; if (Data.PositionDirection == PosDirection.Long) stopLossPrice = Data.Bid - stoploss*Data.InstrProperties.Point; else if (Data.PositionDirection == PosDirection.Short) stopLossPrice = Data.Ask + stoploss*Data.InstrProperties.Point; stopLoss = stopLossPrice.ToString(Data.FF); } string takeProfit = "0"; if (takeprofit > 0) { double takeProfitPrice = 0; if (Data.PositionDirection == PosDirection.Long) takeProfitPrice = Data.Bid + takeprofit*Data.InstrProperties.Point; else if (Data.PositionDirection == PosDirection.Short) takeProfitPrice = Data.Ask - takeprofit*Data.InstrProperties.Point; takeProfit = takeProfitPrice.ToString(Data.FF); } string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", stopLoss, takeProfit); var jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + 0 + ";BRE=" + 0; bool responseOK = _bridge.OrderModify(ticket, price, stoploss, takeprofit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { ReportOperationError(); Data.WrongStopsRetry++; } }
/// <summary> /// Stops connection to MT /// </summary> private void Disconnect() { _nullPing = true; _pingAttempt = 0; if (Data.IsConnected && Configs.PlaySounds) Data.SoundDisconnect.Play(); Data.IsConnected = false; StopTrade(); string message = Language.T("Not Connected"); var jmsg = new JournalMessage(JournalIcons.Blocked, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); Data.Bid = 0; Data.Ask = 0; Data.SetCurrentAccount(DateTime.MinValue, 0, 0, 0, 0); bool isPosChanged = Data.SetCurrentPosition(0, -1, 0, 0, DateTime.MinValue, 0, 0, 0, ""); ShowCurrentPosition(isPosChanged); SetEquityInfoText(string.Format("{0} {1}", 0, Data.AccountCurrency)); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetConnMarketText(Language.T("Not Connected")); SetLblConnectionText(Language.T("Not Connected")); SetConnIcon(0); SetTickInfoText(""); SetLblSymbolText(""); SetFormText(); }
/// <summary> /// Manual operation execution. /// </summary> public override void BtnOperationClick(object sender, EventArgs e) { if (!Data.IsConnected) { if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } var btn = (Button)sender; switch (btn.Name) { case "btnBuy": { const OrderType type = OrderType.Buy; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? Data.Bid - Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Bid + Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Buy") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderBuy, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = _bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Buy, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnSell": { const OrderType type = OrderType.Sell; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Bid; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? Data.Ask + Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Ask - Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Sell") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderSell, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = _bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Sell, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnClose": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (ticket == 0) { // No position. if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); bool responseOK = _bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) { Data.AddBarStats(OperationType.Close, lots, price); } else { ReportOperationError(); } Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } break; case "btnModify": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; double sign = Data.PositionDirection == PosDirection.Long ? 1 : -1; if (ticket == 0) { // No position. if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? price - sign * Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? price + sign * Data.InstrProperties.Point * OperationTakeProfit : 0; string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.Recalculate, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; bool responseOK = _bridge.OrderModify(ticket, price, stopLossPips, OperationTakeProfit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; } }
/// <summary> /// Logs operation error in journal and log file. /// </summary> private void ReportOperationError() { if (Configs.PlaySounds) Data.SoundError.Play(); string message; JournalMessage journalMessage; if (_bridge.LastError == 0) { message = Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName); journalMessage = new JournalMessage(JournalIcons.Warning, DateTime.Now, message); } else { message = Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Errors.ErrorDescription(_bridge.LastError); journalMessage = new JournalMessage(JournalIcons.Error, DateTime.Now, message); } AppendJournalMessage(journalMessage); Log(message); }
/// <summary> /// Adds a message to the journal. /// </summary> protected void AppendJournalMessage(JournalMessage message) { messages.Add(message); if (messages.Count > Configs.JournalLength) messages.RemoveRange(0, messages.Count - Configs.JournalLength); UpdateJournal(messages); return; }
/// <summary> /// Sets SL and TP after wrong execution. /// </summary> void ResendWrongStops() { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); double stoploss = Data.WrongStopLoss; double takeprofit = Data.WrongTakeProf; string sStopLoss = "0"; if (stoploss > 0) { double stopLossPrice = 0; if (Data.PositionDirection == PosDirection.Long) stopLossPrice = Data.Bid - stoploss * Data.InstrProperties.Point; else if (Data.PositionDirection == PosDirection.Short) stopLossPrice = Data.Ask + stoploss * Data.InstrProperties.Point; sStopLoss = stopLossPrice.ToString(Data.FF); } string sTakeProfit = "0"; if (takeprofit > 0) { double takeProfitPrice = 0; if (Data.PositionDirection == PosDirection.Long) takeProfitPrice = Data.Bid + takeprofit * Data.InstrProperties.Point; else if (Data.PositionDirection == PosDirection.Short) takeProfitPrice = Data.Ask - takeprofit * Data.InstrProperties.Point; sTakeProfit = takeProfitPrice.ToString(Data.FF); } JournalMessage jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", sStopLoss, sTakeProfit)); AppendJournalMessage(jmsg); string parameters = "TS1=" + 0 + ";BRE=" + 0; bool responseOK = bridge.OrderModify(ticket, price, stoploss, takeprofit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); Data.WrongStopsRetry++; } }
/// <summary> /// Manual operation execution. /// </summary> protected override void BtnOperation_Click(object sender, EventArgs e) { if (!Data.IsConnected) { if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } Button btn = (Button)sender; switch (btn.Name) { case "btnBuy": { MT4Bridge.OrderType type = MT4Bridge.OrderType.Buy; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? Data.Bid - Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Bid + Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } JournalMessage jmsg = new JournalMessage(JournalIcons.OrderBuy, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Buy") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Buy, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. if (Configs.PlaySounds) { Data.SoundError.Play(); } if (bridge.LastError == 0) { jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); } else { jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); } AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnSell": { MT4Bridge.OrderType type = MT4Bridge.OrderType.Sell; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Bid; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? Data.Ask + Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Ask - Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } JournalMessage jmsg = new JournalMessage(JournalIcons.OrderSell, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Sell") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Sell, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. if (Configs.PlaySounds) { Data.SoundError.Play(); } if (bridge.LastError == 0) { jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); } else { jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); } AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnClose": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (ticket == 0) { // No position. if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } JournalMessage jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF))); AppendJournalMessage(jmsg); bool responseOK = bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) { Data.AddBarStats(OperationType.Close, lots, price); } else { if (Configs.PlaySounds) { Data.SoundError.Play(); } if (bridge.LastError == 0) { jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); } else { jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); } AppendJournalMessage(jmsg); } Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } break; case "btnModify": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; double sign = Data.PositionDirection == PosDirection.Long ? 1 : -1; if (ticket == 0) { // No position. if (Configs.PlaySounds) { Data.SoundError.Play(); } return; } if (Configs.PlaySounds) { Data.SoundOrderSent.Play(); } int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) { stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); } else { stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); } double stoploss = stopLossPips > 0 ? price - sign * Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? price + sign * Data.InstrProperties.Point * OperationTakeProfit : 0; JournalMessage jmsg = new JournalMessage(JournalIcons.Recalculate, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; bool responseOK = bridge.OrderModify(ticket, price, stopLossPips, OperationTakeProfit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { if (Configs.PlaySounds) { Data.SoundError.Play(); } if (bridge.LastError == 0) { jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); } else { jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); } AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; default: break; } return; }
/// <summary> /// Show warning message and start resending. /// </summary> private void ActivateFailedCloseOrder() { string message = Language.T("Activated resending of failed close orders."); var jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); ActivateWarningMessage(); }
/// <summary> /// Manual operation execution. /// </summary> public override void BtnOperationClick(object sender, EventArgs e) { if (!Data.IsConnected) { if (Configs.PlaySounds) Data.SoundError.Play(); return; } var btn = (Button) sender; switch (btn.Name) { case "btnBuy": { const OrderType type = OrderType.Buy; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Ask; int slippage = Configs.AutoSlippage ? (int) Data.InstrProperties.Spread*3 : Configs.SlippageEntry; int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? Data.Bid - Data.InstrProperties.Point*stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Bid + Data.InstrProperties.Point*OperationTakeProfit : 0; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Buy") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderBuy, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = _bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Buy, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnSell": { const OrderType type = OrderType.Sell; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Bid; int slippage = Configs.AutoSlippage ? (int) Data.InstrProperties.Spread*3 : Configs.SlippageEntry; int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? Data.Ask + Data.InstrProperties.Point*stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Ask - Data.InstrProperties.Point*OperationTakeProfit : 0; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Sell") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderSell, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = _bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Sell, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnClose": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int) Data.InstrProperties.Spread*6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (ticket == 0) { // No position. if (Configs.PlaySounds) Data.SoundError.Play(); return; } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); bool responseOK = _bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) Data.AddBarStats(OperationType.Close, lots, price); else ReportOperationError(); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } break; case "btnModify": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; double sign = Data.PositionDirection == PosDirection.Long ? 1 : -1; if (ticket == 0) { // No position. if (Configs.PlaySounds) Data.SoundError.Play(); return; } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); int stopLossPips; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? price - sign*Data.InstrProperties.Point*stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? price + sign*Data.InstrProperties.Point*OperationTakeProfit : 0; string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.Recalculate, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; bool responseOK = _bridge.OrderModify(ticket, price, stopLossPips, OperationTakeProfit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { ReportOperationError(); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; } }
/// <summary> /// Bridge OnTick /// </summary> private void Bridge_OnTick(object source, TickEventArgs tea) { lock (_lockerTickPing) { if (_pingAttempt > 0 && JournalShowSystemMessages) { string msgsys = tea.Symbol + " " + tea.Period + " " + Language.T("Tick received after an unsuccessful ping."); var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, msgsys); AppendJournalMessage(jmsgsys); Log(msgsys); } _pingAttempt = 0; if (!Data.IsConnected) return; _tickLocalTime = DateTime.Now; _tickServerTime = tea.Time; if (IsChartChangeged(tea.Symbol, (DataPeriods) (int) tea.Period)) { StopTrade(); Data.IsConnected = false; SetFormText(); if (Configs.PlaySounds) Data.SoundDisconnect.Play(); string message = tea.Symbol + " " + tea.Period + " " + Language.T("Tick received from a different chart!"); var jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); return; } bool bNewPrice = Math.Abs(Data.Bid - tea.Bid) > Data.InstrProperties.Point/2; Data.Bid = tea.Bid; Data.Ask = tea.Ask; Data.InstrProperties.Spread = tea.Spread; Data.InstrProperties.TickValue = tea.TickValue; Data.ServerTime = tea.Time; Data.SetTick(tea.Bid); bool isAccChanged = Data.SetCurrentAccount(tea.Time, tea.AccountBalance, tea.AccountEquity, tea.AccountProfit, tea.AccountFreeMargin); bool isPosChanged = Data.SetCurrentPosition(tea.PositionTicket, tea.PositionType, tea.PositionLots, tea.PositionOpenPrice, tea.PositionOpenTime, tea.PositionStopLoss, tea.PositionTakeProfit, tea.PositionProfit, tea.PositionComment); ParseAndSetParametrs(tea.Parameters); LogActivatedSLTP(); const bool updateData = true; SetDataAndCalculate(tea.Symbol, tea.Period, tea.Time, bNewPrice, updateData); string bidText = tea.Bid.ToString(Data.FF); string askText = tea.Ask.ToString(Data.FF); SetLblBidAskText(bidText + " / " + askText); // Tick data label if (JournalShowTicks) { string tickInfo = string.Format("{0} {1} {2} {3} / {4}", tea.Symbol, tea.Period, tea.Time.ToString("HH:mm:ss"), bidText, askText); var jmsg = new JournalMessage(JournalIcons.Globe, DateTime.Now, tickInfo); AppendJournalMessage(jmsg); } UpdateTickChart(Data.InstrProperties.Point, Data.ListTicks.ToArray()); SetEquityInfoText(string.Format("{0:F2} {1}", tea.AccountEquity, Data.AccountCurrency)); ShowCurrentPosition(isPosChanged); if (isAccChanged) { string message = string.Format( Language.T("Account Balance") + " {0:F2}, " + Language.T("Equity") + " {1:F2}, " + Language.T("Profit") + " {2:F2}, " + Language.T("Free Margin") + " {3:F2}", tea.AccountBalance, tea.AccountEquity, tea.AccountProfit, tea.AccountFreeMargin); var jmsg = new JournalMessage(JournalIcons.Currency, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); } if (Data.IsBalanceDataChganged) UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTickInfoText(string.Format("{0} {1} / {2}", tea.Time.ToString("HH:mm:ss"), bidText, askText)); SetConnIcon(2); // Sends OrderModify on SL/TP errors if (IsWrongStopsExecution()) ResendWrongStops(); // Check for failed close order. CheckForFailedCloseOrder(tea.PositionLots); } }
/// <summary> /// Pings the server in order to check the connection. /// </summary> void TimerPing_Tick(object sender, EventArgs e) { if (DateTime.Now < tickLocalTime.AddSeconds(1)) { return; // The last tick was soon enough. } lock (lockerTickPing) { MT4Bridge.PingInfo ping = bridge.GetPingInfo(); if (ping == null && !nullPing) { // Wrong ping. pingAttempt++; if ((pingAttempt == 1 || pingAttempt % 10 == 0) && JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, Language.T("Unsuccessful ping") + " No " + pingAttempt + "."); AppendJournalMessage(jmsgsys); } if (pingAttempt == 30) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("There is no connection with MetaTrader.")); AppendJournalMessage(jmsgsys); if (Configs.PlaySounds) { Data.SoundError.Play(); } } if (pingAttempt < 60) { SetConnIcon(pingAttempt < 30 ? 3 : 4); return; } Disconnect(); } else if (ping != null) { // Successful ping. nullPing = false; bool bUpdateData = false; if (!Data.IsConnected || IsChartChangeged(ping.Symbol, (DataPeriods)(int)ping.Period)) { // Disconnected or chart change. pingAttempt = 0; if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, ping.Symbol + " " + ping.Period.ToString() + " " + Language.T("Successful ping.")); AppendJournalMessage(jmsgsys); } StopTrade(); if (!UpdateDataFeedInfo(ping.Time, ping.Symbol, (DataPeriods)(int)ping.Period)) { return; } Data.Bid = ping.Bid; Data.Ask = ping.Ask; Data.InstrProperties.Spread = ping.Spread; Data.InstrProperties.TickValue = ping.TickValue; Data.IsConnected = true; bUpdateData = true; SetFormText(); SetConnIcon(1); SetTradeStrip(); if (Configs.PlaySounds) { Data.SoundConnect.Play(); } MT4Bridge.TerminalInfo te = bridge.GetTerminalInfo(); string connection = Language.T("Connected to a MetaTrader terminal."); if (te != null) { connection = string.Format(Language.T("Connected to") + " {0} " + Language.T("by") + " {1}", te.TerminalName, te.TerminalCompany); Data.ExpertVersion = te.ExpertVersion; Data.LibraryVersion = te.LibraryVersion; Data.TerminalName = te.TerminalName; } SetLblConnectionText(connection); string market = string.Format("{0} {1}", ping.Symbol, ping.Period); SetConnMarketText(market); JournalMessage jmsg = new JournalMessage(JournalIcons.OK, DateTime.Now, market + " " + connection); AppendJournalMessage(jmsg); // Check for reconnection. if (symbolReconnect == Data.Symbol && periodReconnect == Data.Period && accountReconnect == Data.AccountNumber) { StartTrade(); // Restart trade. } } else if (pingAttempt > 0 && JournalShowSystemMessages) { // After a wrong ping. pingAttempt = 0; JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, ping.Symbol + " " + ping.Period.ToString() + " " + Language.T("Successful ping.")); AppendJournalMessage(jmsgsys); } bool isNewPrice = Math.Abs(Data.Bid - ping.Bid) > Data.InstrProperties.Point / 2; DateTime dtPingServerTime = tickServerTime.Add(DateTime.Now - tickLocalTime); string sBid = ping.Bid.ToString(Data.FF); string sAsk = ping.Ask.ToString(Data.FF); SetLblBidAskText(sBid + " / " + sAsk); Data.Bid = ping.Bid; Data.Ask = ping.Ask; Data.InstrProperties.Spread = ping.Spread; Data.InstrProperties.TickValue = ping.TickValue; Data.ServerTime = ping.Time; bool isAccChanged = Data.SetCurrentAccount(ping.Time, ping.AccountBalance, ping.AccountEquity, ping.AccountProfit, ping.AccountFreeMargin); bool isPosChanged = Data.SetCurrentPosition(ping.PositionTicket, ping.PositionType, ping.PositionLots, ping.PositionOpenPrice, ping.PositionOpenTime, ping.PositionStopLoss, ping.PositionTakeProfit, ping.PositionProfit, ping.PositionComment); SetDataAndCalculate(ping.Symbol, ping.Period, dtPingServerTime, isNewPrice, bUpdateData); SetEquityInfoText(string.Format("{0:F2} {1}", ping.AccountEquity, Data.AccountCurrency)); ShowCurrentPosition(isPosChanged); if (isAccChanged) { JournalMessage jmsg = new JournalMessage(JournalIcons.Currency, DateTime.Now, string.Format(Language.T("Account Balance") + " {0:F2}, " + Language.T("Equity") + " {1:F2}, " + Language.T("Profit") + ", {2:F2}, " + Language.T("Free Margin") + " {3:F2}", ping.AccountBalance, ping.AccountEquity, ping.AccountProfit, ping.AccountFreeMargin)); AppendJournalMessage(jmsg); } if (Data.IsBalanceDataChganged) { UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); } SetTickInfoText(string.Format("{0} {1} / {2}", ping.Time.ToString("HH:mm:ss"), sBid, sAsk)); SetConnIcon(1); // Sends OrderModify on SL/TP errors if (IsWrongStopsExecution()) { ResendWrongStops(); } } } return; }
private void LogActivatedSLTP() { if (Data.ActivatedStopLoss < Epsilon && Data.ActivatedTakeProfit < Epsilon) { // There is nothing to report. _activationReportedAt = 0; return; } if (Data.ActivatedStopLoss > Epsilon && Math.Abs(Data.ActivatedStopLoss - _activationReportedAt) < Epsilon || Data.ActivatedTakeProfit > Epsilon && Math.Abs(Data.ActivatedTakeProfit - _activationReportedAt) < Epsilon) { // Activation was already reported. return; } if (Data.ActivatedStopLoss > Epsilon && Data.ActivatedTakeProfit > Epsilon) { // Expert was not sure which one was activated, so reported both. Data.AddBarStats(OperationType.Close, Data.ClosedSLTPLots, Data.ActivatedStopLoss); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Position closed at") + " " + Data.ActivatedStopLoss.ToString(Data.FF) + ", " + Language.T("Closed Lots") + " " + Data.ClosedSLTPLots.ToString("F2"); var msg = new JournalMessage(JournalIcons.Information, DateTime.Now, message); AppendJournalMessage(msg); Log(message); _activationReportedAt = Data.ActivatedStopLoss; } else if (Data.ActivatedStopLoss > Epsilon) { // Activated Stop Loss Data.AddBarStats(OperationType.Close, Data.ClosedSLTPLots, Data.ActivatedStopLoss); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Activated Stop Loss at") + " " + Data.ActivatedStopLoss.ToString(Data.FF) + ", " + Language.T("Closed Lots") + " " + Data.ClosedSLTPLots.ToString("F2"); var msg = new JournalMessage(JournalIcons.Information, DateTime.Now, message); AppendJournalMessage(msg); Log(message); _activationReportedAt = Data.ActivatedStopLoss; } else if (Data.ActivatedTakeProfit > Epsilon) { // Activated Take Profit Data.AddBarStats(OperationType.Close, Data.ClosedSLTPLots, Data.ActivatedTakeProfit); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Activated Take Profit at") + " " + Data.ActivatedTakeProfit.ToString(Data.FF) + ", " + Language.T("Closed Lots") + " " + Data.ClosedSLTPLots.ToString("F2"); var msg = new JournalMessage(JournalIcons.Information, DateTime.Now, message); AppendJournalMessage(msg); Log(message); _activationReportedAt = Data.ActivatedTakeProfit; } }
/// <summary> /// Stops the trade. /// </summary> void StopTrade() { if (!isTrading) return; isTrading = false; DeinitTrade(); Data.SetStopTradingTime(); JournalMessage msg = new JournalMessage(JournalIcons.StopTrading, DateTime.Now, Language.T("Automatic trade stopped.")); AppendJournalMessage(msg); SetTradeStrip(); return; }
/// <summary> /// Copies data to Data and calculates. /// </summary> private void SetDataAndCalculate(string symbol, PeriodType period, DateTime time, bool isPriceChange, bool isUpdateData) { lock (_lockerDataFeed) { bool isUpdateChart = isUpdateData; Bars bars = _bridge.GetBars(symbol, period); if (bars == null && JournalShowSystemMessages) { _isSetRootDataError = true; Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + period + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); return; } if (bars != null && (bars.Count < MaxBarsCount((int) period) && JournalShowSystemMessages)) { _isSetRootDataError = true; Data.SoundError.Play(); var jmsgsys = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + period + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); return; } if (_isSetRootDataError && JournalShowSystemMessages) { _isSetRootDataError = false; var jmsgsys = new JournalMessage(JournalIcons.Information, DateTime.Now, symbol + " " + period + " " + Language.T("Enough bars received!")); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } if (bars != null) { int countBars = bars.Count; if (countBars < 400) return; if (Data.Bars != countBars || Data.Time[countBars - 1] != bars.Time[countBars - 1] || Data.Volume[countBars - 1] != bars.Volume[countBars - 1] || Math.Abs(Data.Close[countBars - 1] - bars.Close[countBars - 1]) > Data.InstrProperties.Point/2d) { if (Data.Bars == countBars && Data.Time[countBars - 1] == bars.Time[countBars - 1] && Data.Time[countBars - 10] == bars.Time[countBars - 10]) { // Update the last bar only. Data.Open[countBars - 1] = bars.Open[countBars - 1]; Data.High[countBars - 1] = bars.High[countBars - 1]; Data.Low[countBars - 1] = bars.Low[countBars - 1]; Data.Close[countBars - 1] = bars.Close[countBars - 1]; Data.Volume[countBars - 1] = bars.Volume[countBars - 1]; } else { // Update all the bars. Data.Bars = countBars; Data.Time = new DateTime[countBars]; Data.Open = new double[countBars]; Data.High = new double[countBars]; Data.Low = new double[countBars]; Data.Close = new double[countBars]; Data.Volume = new int[countBars]; bars.Time.CopyTo(Data.Time, 0); bars.Open.CopyTo(Data.Open, 0); bars.High.CopyTo(Data.High, 0); bars.Low.CopyTo(Data.Low, 0); bars.Close.CopyTo(Data.Close, 0); bars.Volume.CopyTo(Data.Volume, 0); } Data.LastClose = Data.Close[countBars - 1]; CalculateStrategy(true); isUpdateChart = true; } } bool isBarChanged = IsBarChanged(Data.Time[Data.Bars - 1]); if (_isTrading) { TickType tickType = GetTickType((DataPeriods) (int) period, Data.Time[Data.Bars - 1], time, Data.Volume[Data.Bars - 1]); if (tickType == TickType.Close || isPriceChange || isBarChanged) { if (JournalShowSystemMessages && tickType != TickType.Regular) { JournalIcons icon = JournalIcons.Warning; string text = string.Empty; if (tickType == TickType.Open) { icon = JournalIcons.BarOpen; text = Language.T("A Bar Open event!"); } else if (tickType == TickType.Close) { icon = JournalIcons.BarClose; text = Language.T("A Bar Close event!"); } else if (tickType == TickType.AfterClose) { icon = JournalIcons.Warning; text = Language.T("A new tick arrived after a Bar Close event!"); } var jmsgsys = new JournalMessage(icon, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " " + text); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } if (isBarChanged && tickType == TickType.Regular) { if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.Warning, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " A Bar Changed event!"); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } tickType = TickType.Open; } if (tickType == TickType.Open && _barOpenTimeForLastCloseEvent == Data.Time[Data.Bars - 3]) { if (JournalShowSystemMessages) { var jmsgsys = new JournalMessage(JournalIcons.Warning, DateTime.Now, symbol + " " + Data.PeriodMTStr + " " + time.ToString("HH:mm:ss") + " A secondary Bar Close event!"); AppendJournalMessage(jmsgsys); Log(jmsgsys.Message); } tickType = TickType.OpenClose; } CalculateTrade(tickType); isUpdateChart = true; if (tickType == TickType.Close || tickType == TickType.OpenClose) _barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; } } if (isUpdateChart) UpdateChart(); } }
/// <summary> /// Starts the trade. /// </summary> private void StartTrade() { _isTrading = true; // Resets trade global variables. InitTrade(); Data.SetStartTradingTime(); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Automatic trade started."); var msg = new JournalMessage(JournalIcons.StartTrading, DateTime.Now, message); AppendJournalMessage(msg); Log(message); _symbolReconnect = Data.Symbol; _periodReconnect = Data.Period; _accountReconnect = Data.AccountNumber; _barOpenTimeForLastCloseEvent = Data.Time[Data.Bars - 1]; SetTradeStrip(); }
/// <summary> /// Stops the trade. /// </summary> private void StopTrade() { if (!_isTrading) return; _isTrading = false; DeinitTrade(); Data.SetStopTradingTime(); string message = Data.Symbol + " " + Data.PeriodMTStr + " " + Language.T("Automatic trade stopped."); var msg = new JournalMessage(JournalIcons.StopTrading, DateTime.Now, message); AppendJournalMessage(msg); Log(message); SetTradeStrip(); }
/// <summary> /// Sets the instrument's properties after connecting; /// </summary> bool UpdateDataFeedInfo(DateTime time, string symbol, DataPeriods period) { lock (lockerDataFeed) { Data.ResetBidAsk(); Data.ResetAccountStats(); Data.ResetPositionStats(); Data.ResetBarStats(); Data.ResetTicks(); // Reads market info from the chart MT4Bridge.MarketInfo marketInfo = bridge.GetMarketInfoAll(symbol); if (marketInfo == null) { if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot update market info.")); AppendJournalMessage(jmsgsys); } return(false); } // Sets instrument properties Data.Period = period; Data.InstrProperties.Symbol = symbol; Data.InstrProperties.LotSize = (int)marketInfo.ModeLotSize; Data.InstrProperties.MinLot = marketInfo.ModeMinLot; Data.InstrProperties.MaxLot = marketInfo.ModeMaxLot; Data.InstrProperties.LotStep = marketInfo.ModeLotStep; Data.InstrProperties.Digits = (int)marketInfo.ModeDigits; Data.InstrProperties.Spread = marketInfo.ModeSpread; Data.InstrProperties.SwapLong = marketInfo.ModeSwapLong; Data.InstrProperties.SwapShort = marketInfo.ModeSwapShort; Data.InstrProperties.TickValue = marketInfo.ModeTickValue; Data.InstrProperties.StopLevel = marketInfo.ModeStopLevel; Data.InstrProperties.MarginRequired = marketInfo.ModeMarginRequired; SetNumUpDownLots(marketInfo.ModeMinLot, marketInfo.ModeLotStep, marketInfo.ModeMaxLot); // Sets Market Info string[] values = new string[] { symbol, Data.DataPeriodToString(period), marketInfo.ModeLotSize.ToString(), marketInfo.ModePoint.ToString("F" + marketInfo.ModeDigits.ToString()), marketInfo.ModeSpread.ToString(), marketInfo.ModeSwapLong.ToString(), marketInfo.ModeSwapShort.ToString() }; UpdateStatusPageMarketInfo(values); MT4Bridge.Bars bars = bridge.GetBars(symbol, (MT4Bridge.PeriodType)(int) period); if (bars == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive bars!")); AppendJournalMessage(jmsgsys); } return(false); } if (bars.Count < MaxBarsCount((int)period)) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive enough bars!")); AppendJournalMessage(jmsg); } return(false); } if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Market data updated, bars downloaded.")); AppendJournalMessage(jmsgsys); } // Account Information. MT4Bridge.AccountInfo account = bridge.GetAccountInfo(); if (account == null) { if (JournalShowSystemMessages) { Data.SoundError.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Cannot receive account information!")); AppendJournalMessage(jmsg); } return(false); } if (JournalShowSystemMessages) { JournalMessage jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, symbol + " " + (MT4Bridge.PeriodType)(int) period + " " + Language.T("Account information received.")); AppendJournalMessage(jmsgsys); } Data.AccountName = account.Name; Data.IsDemoAccount = account.IsDemo; Data.AccountCurrency = account.Currency; Data.SetCurrentAccount(time, account.Balance, account.Equity, account.Profit, account.FreeMargin); UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTradeStrip(); SetLblSymbolText(symbol); } return(true); }
/// <summary> /// Pings the server in order to check the connection. /// </summary> private void TimerPingTick(object sender, EventArgs e) { if (DateTime.Now < _tickLocalTime.AddSeconds(1)) return; // The last tick was soon enough. lock (_lockerTickPing) { PingInfo ping = _bridge.GetPingInfo(); if (ping == null && !_nullPing) { // Wrong ping. _pingAttempt++; if ((_pingAttempt == 1 || _pingAttempt%10 == 0) && JournalShowSystemMessages) { string message = Language.T("Unsuccessful ping") + " No " + _pingAttempt + "."; var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, message); AppendJournalMessage(jmsgsys); Log(message); } if (_pingAttempt == 30) { string message = Language.T("There is no connection with MetaTrader."); var jmsgsys = new JournalMessage(JournalIcons.Warning, DateTime.Now, message); AppendJournalMessage(jmsgsys); if (Configs.PlaySounds) Data.SoundError.Play(); Log(message); } if (_pingAttempt < 60) { SetConnIcon(_pingAttempt < 30 ? 3 : 4); return; } Disconnect(); } else if (ping != null) { // Successful ping. _nullPing = false; bool bUpdateData = false; if (!Data.IsConnected || IsChartChangeged(ping.Symbol, (DataPeriods) (int) ping.Period)) { // Disconnected or chart change. _pingAttempt = 0; if (JournalShowSystemMessages) { var msgsys = ping.Symbol + " " + ping.Period.ToString() + " " + Language.T("Successful ping."); var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, msgsys); AppendJournalMessage(jmsgsys); Log(msgsys); } StopTrade(); if (!UpdateDataFeedInfo(ping.Time, ping.Symbol, (DataPeriods) (int) ping.Period)) return; Data.Bid = ping.Bid; Data.Ask = ping.Ask; Data.InstrProperties.Spread = ping.Spread; Data.InstrProperties.TickValue = ping.TickValue; Data.IsConnected = true; bUpdateData = true; SetFormText(); SetConnIcon(1); SetTradeStrip(); if (Configs.PlaySounds) Data.SoundConnect.Play(); TerminalInfo te = _bridge.GetTerminalInfo(); string connection = Language.T("Connected to a MetaTrader terminal."); if (te != null) { connection = string.Format( Language.T("Connected to") + " {0} " + Language.T("by") + " {1}", te.TerminalName, te.TerminalCompany); Data.ExpertVersion = te.ExpertVersion; Data.LibraryVersion = te.LibraryVersion; Data.TerminalName = te.TerminalName; if (Configs.WriteLogFile) { string fileNameHeader = ping.Symbol + "_" + ping.Period + "_" + "ID" + Data.ConnectionID + "_"; Data.Logger.CreateLogFile(fileNameHeader); } } SetLblConnectionText(connection); string market = string.Format("{0} {1}", ping.Symbol, ping.Period); SetConnMarketText(market); string message = market + " " + connection; var jmsg = new JournalMessage(JournalIcons.OK, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); // Check for reconnection. if (IsRestartTrade()) StartTrade(); // Restart trade. } else if (_pingAttempt > 0 && JournalShowSystemMessages) { // After a wrong ping. _pingAttempt = 0; string message = ping.Symbol + " " + ping.Period.ToString() + " " + Language.T("Successful ping."); var jmsgsys = new JournalMessage(JournalIcons.System, DateTime.Now, message); AppendJournalMessage(jmsgsys); Log(message); } bool isNewPrice = Math.Abs(Data.Bid - ping.Bid) > Data.InstrProperties.Point/2; DateTime dtPingServerTime = _tickServerTime.Add(DateTime.Now - _tickLocalTime); string sBid = ping.Bid.ToString(Data.FF); string sAsk = ping.Ask.ToString(Data.FF); SetLblBidAskText(sBid + " / " + sAsk); Data.Bid = ping.Bid; Data.Ask = ping.Ask; Data.InstrProperties.Spread = ping.Spread; Data.InstrProperties.TickValue = ping.TickValue; Data.ServerTime = ping.Time; bool isAccChanged = Data.SetCurrentAccount(ping.Time, ping.AccountBalance, ping.AccountEquity, ping.AccountProfit, ping.AccountFreeMargin); bool isPosChanged = Data.SetCurrentPosition(ping.PositionTicket, ping.PositionType, ping.PositionLots, ping.PositionOpenPrice, ping.PositionOpenTime, ping.PositionStopLoss, ping.PositionTakeProfit, ping.PositionProfit, ping.PositionComment); ParseAndSetParametrs(ping.Parameters); LogActivatedSLTP(); SetDataAndCalculate(ping.Symbol, ping.Period, dtPingServerTime, isNewPrice, bUpdateData); SetEquityInfoText(string.Format("{0:F2} {1}", ping.AccountEquity, Data.AccountCurrency)); ShowCurrentPosition(isPosChanged); if (isAccChanged) { string message = string.Format( Language.T("Account Balance") + " {0:F2}, " + Language.T("Equity") + " {1:F2}, " + Language.T("Profit") + " {2:F2}, " + Language.T("Free Margin") + " {3:F2}", ping.AccountBalance, ping.AccountEquity, ping.AccountProfit, ping.AccountFreeMargin); var jmsg = new JournalMessage(JournalIcons.Currency, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); } if (Data.IsBalanceDataChganged) UpdateBalanceChart(Data.BalanceData, Data.BalanceDataPoints); SetTickInfoText(string.Format("{0} {1} / {2}", ping.Time.ToString("HH:mm:ss"), sBid, sAsk)); SetConnIcon(1); // Sends OrderModify on SL/TP errors if (IsWrongStopsExecution()) ResendWrongStops(); // Check for failed close order. CheckForFailedCloseOrder(ping.PositionLots); } } }
/// <summary> /// Sets and sends an entry order. /// </summary> private void DoEntryTrade(TradeDirection tradeDir) { double price; OrderDirection ordDir; OperationType opType; OrderType type; JournalIcons icon; if (_timeLastEntryBar != Data.Time[Data.Bars - 1]) _isEnteredLong = _isEnteredShort = false; switch (tradeDir) { case TradeDirection.Long: // Buy if (_isEnteredLong) return; price = Data.Ask; ordDir = OrderDirection.Buy; opType = OperationType.Buy; type = OrderType.Buy; icon = JournalIcons.OrderBuy; break; case TradeDirection.Short: // Sell if (_isEnteredShort) return; price = Data.Bid; ordDir = OrderDirection.Sell; opType = OperationType.Sell; type = OrderType.Sell; icon = JournalIcons.OrderSell; break; default: // Wrong direction of trade. return; } PosDirection newPosDir = PosDirection.None; double size = AnalyseEntrySize(ordDir, ref newPosDir); if (size < Data.InstrProperties.MinLot/2) { // The entry trade is cancelled. return; } string symbol = Data.Symbol; double lots = size; int slippage = Configs.AutoSlippage ? (int) Data.InstrProperties.Spread*3 : Configs.SlippageEntry; double stoploss = GetStopLossPips(size); double takeprofit = GetTakeProfitPips(); double point = Data.InstrProperties.Point; string stopLoss = "0"; if (stoploss > 0) { double stopLossPrice = 0; if (newPosDir == PosDirection.Long) stopLossPrice = Data.Bid - stoploss*point; else if (newPosDir == PosDirection.Short) stopLossPrice = Data.Ask + stoploss*point; stopLoss = stopLossPrice.ToString(Data.FF); } string takeProfit = "0"; if (takeprofit > 0) { double takeProfitPrice = 0; if (newPosDir == PosDirection.Long) takeProfitPrice = Data.Bid + takeprofit*point; else if (newPosDir == PosDirection.Short) takeProfitPrice = Data.Ask - takeprofit*point; takeProfit = takeProfitPrice.ToString(Data.FF); } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T(ordDir.ToString()) + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stopLoss, takeProfit); var jmsg = new JournalMessage(icon, DateTime.Now, message); AppendJournalMessage(jmsg); Log(message); string parameters = OrderParameters(); int response = _bridge.OrderSend(symbol, type, lots, price, slippage, stoploss, takeprofit, parameters); if (response >= 0) { // The order was executed successfully. Data.AddBarStats(opType, lots, price); _timeLastEntryBar = Data.Time[Data.Bars - 1]; if (type == OrderType.Buy) _isEnteredLong = true; else _isEnteredShort = true; Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. ReportOperationError(); Data.WrongStopLoss = (int) stoploss; Data.WrongTakeProf = (int) takeprofit; } }
/// <summary> /// Sets and sends an exit order. /// </summary> bool DoExitTrade() { string symbol = Data.Symbol; double lots = Data.PositionLots; double price = Data.PositionType == (int)MT4Bridge.OrderType.Buy ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF))); AppendJournalMessage(jmsg); bool responseOK = bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) Data.AddBarStats(OperationType.Close, lots, price); else { if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); } Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; return responseOK; }
/// <summary> /// Sets and sends an exit order. /// </summary> private bool DoExitTrade() { string symbol = Data.Symbol; double lots = Data.PositionLots; double price = Data.PositionType == (int) OrderType.Buy ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int) Data.InstrProperties.Spread*6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); string message = string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + LotOrLots(lots) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF)); var jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now,message); AppendJournalMessage(jmsg); Log(message); if (!Data.IsFailedCloseOrder) Data.IsSentCloseOrder = true; Data.CloseOrderTickCounter = 0; bool responseOK = _bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) Data.AddBarStats(OperationType.Close, lots, price); else ReportOperationError(); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; return responseOK; }
/// <summary> /// Manual operation execution. /// </summary> protected override void BtnOperation_Click(object sender, EventArgs e) { if (!Data.IsConnected) { if (Configs.PlaySounds) Data.SoundError.Play(); return; } Button btn = (Button)sender; switch (btn.Name) { case "btnBuy": { MT4Bridge.OrderType type = MT4Bridge.OrderType.Buy; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? Data.Bid - Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Bid + Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.OrderBuy, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Buy") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Buy, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnSell": { MT4Bridge.OrderType type = MT4Bridge.OrderType.Sell; string symbol = Data.Symbol; double lots = NormalizeEntrySize(OperationLots); double price = Data.Bid; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 3 : Configs.SlippageEntry; int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? Data.Ask + Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? Data.Ask - Data.InstrProperties.Point * OperationTakeProfit : 0; if (Configs.PlaySounds) Data.SoundOrderSent.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.OrderSell, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An entry order sent") + ": " + Language.T("Sell") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}, " + Language.T("Stop Loss") + " {2}, " + Language.T("Take Profit") + " {3}", lots, price.ToString(Data.FF), stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; int response = bridge.OrderSend(symbol, type, lots, price, slippage, stopLossPips, OperationTakeProfit, parameters); if (response >= 0) { Data.AddBarStats(OperationType.Sell, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { // Error in operation execution. if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; case "btnClose": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int slippage = Configs.AutoSlippage ? (int)Data.InstrProperties.Spread * 6 : Configs.SlippageExit; int ticket = Data.PositionTicket; if (ticket == 0) { // No position. if (Configs.PlaySounds) Data.SoundError.Play(); return; } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); JournalMessage jmsg = new JournalMessage(JournalIcons.OrderClose, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("An exit order sent") + ": " + Language.T("Close") + " {0} " + (lots == 1 ? Language.T("lot") : Language.T("lots")) + " " + Language.T("at") + " {1}", lots, price.ToString(Data.FF))); AppendJournalMessage(jmsg); bool responseOK = bridge.OrderClose(ticket, lots, price, slippage); if (responseOK) Data.AddBarStats(OperationType.Close, lots, price); else { if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); } Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } break; case "btnModify": { string symbol = Data.Symbol; double lots = NormalizeEntrySize(Data.PositionLots); double price = Data.PositionDirection == PosDirection.Long ? Data.Bid : Data.Ask; int ticket = Data.PositionTicket; double sign = Data.PositionDirection == PosDirection.Long ? 1 : -1; if (ticket == 0) { // No position. if (Configs.PlaySounds) Data.SoundError.Play(); return; } if (Configs.PlaySounds) Data.SoundOrderSent.Play(); int stopLossPips = 0; if (OperationStopLoss > 0 && OperationTrailingStop > 0) stopLossPips = Math.Min(OperationStopLoss, OperationTrailingStop); else stopLossPips = Math.Max(OperationStopLoss, OperationTrailingStop); double stoploss = stopLossPips > 0 ? price - sign * Data.InstrProperties.Point * stopLossPips : 0; double takeprofit = OperationTakeProfit > 0 ? price + sign * Data.InstrProperties.Point * OperationTakeProfit : 0; JournalMessage jmsg = new JournalMessage(JournalIcons.Recalculate, DateTime.Now, string.Format(symbol + " " + Data.PeriodMTStr + " " + Language.T("A modify order sent") + ": " + Language.T("Stop Loss") + " {0}, " + Language.T("Take Profit") + " {1}", stoploss.ToString(Data.FF), takeprofit.ToString(Data.FF))); AppendJournalMessage(jmsg); string parameters = "TS1=" + OperationTrailingStop + ";BRE=" + OperationBreakEven; bool responseOK = bridge.OrderModify(ticket, price, stopLossPips, OperationTakeProfit, parameters); if (responseOK) { Data.AddBarStats(OperationType.Modify, lots, price); Data.WrongStopLoss = 0; Data.WrongTakeProf = 0; Data.WrongStopsRetry = 0; } else { if (Configs.PlaySounds) Data.SoundError.Play(); if (bridge.LastError == 0) jmsg = new JournalMessage(JournalIcons.Warning, DateTime.Now, Language.T("Operation execution") + ": " + Language.T("MetaTrader is not responding!").Replace("MetaTrader", Data.TerminalName)); else jmsg = new JournalMessage(JournalIcons.Error, DateTime.Now, Language.T("MetaTrader failed to execute order! Returned").Replace("MetaTrader", Data.TerminalName) + ": " + MT4Bridge.MT4_Errors.ErrorDescription(bridge.LastError)); AppendJournalMessage(jmsg); Data.WrongStopLoss = stopLossPips; Data.WrongTakeProf = OperationTakeProfit; } } break; default: break; } return; }