internal void PendingOrderFilled(PendingOrderFilledEventArgs result) { //add routine for Trap model, close all pending orders when first order is activated/filled if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap && result.Position.Label == TMLabel + "-I" + (1).ToString("#000") + PositionSessionNumber) { foreach (var to in tmBot.PendingOrders) { tmBot.CancelPendingOrderAsync(to); } } if (result.Position.Label == TMLabel + GetPositionIndexNumber(0) + PositionSessionNumber) { Statistics.SetMaxBounce(tmBot.Positions.Count, tmBot.Time); LastTradeType = result.Position.TradeType; TunnelStatus = enTunnelStatus.Pending; LastVolume = result.Position.VolumeInUnits * tmBot.config.LotMultiplier; tmBot.PlaceStopOrderAsync((result.Position.TradeType == TradeType.Buy ? TradeType.Sell : TradeType.Buy), tmBot.config.SessionDates.Enabled ? GetSymbolName(ParsedSessionDates.First()) : tmBot.Symbol.Name, result.Position.VolumeInUnits * tmBot.config.LotMultiplier, (result.Position.TradeType == TradeType.Buy ? TunnelFloor : TunnelCeiling), TMLabel + GetPositionIndexNumber() + PositionSessionNumber, AnotherOrderPlaced); } TunnelChartObjects.DrawDirection(tmBot, Direction); //no IF, executes every pending order filled UpdateTargetLines(result.Position.EntryPrice); }
internal void Initialize() { TunnelStatus = enTunnelStatus.Inactive; LastVolume = tmBot.LotToVolume(tmBot.config.StartingLotSize); if (tmBot.config != null) { if (!tmBot.config.SessionDates.Enabled) // if SessionDates is not enabled { TunnelStatus = enTunnelStatus.Pending; if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysBuy || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Buy)) { tmBot.ExecuteMarketOrderAsync(cAlgo.API.TradeType.Buy, tmBot.Symbol.Name, LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } else if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysSell || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Sell)) { tmBot.ExecuteMarketOrderAsync(cAlgo.API.TradeType.Sell, tmBot.Symbol.Name, LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } else if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap && tmBot.Positions.Count == 0) { var HalfHeight = Math.Abs(tmBot.config.TunnelHeight / 2); TunnelCeiling = tmBot.ShiftPrice(tmBot.Symbol.Ask, HalfHeight); tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelFloor = tmBot.ShiftPrice(tmBot.Symbol.Bid, -HalfHeight); tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCenter = tmBot.ShiftPrice(TunnelFloor, (int)Math.Ceiling((double)(tmBot.config.TunnelHeight / 2))); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawMainLinesHistory(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter, TMLabel + PositionSessionNumber); TunnelChartObjects.DrawDirection(tmBot, Direction); tmBot.PlaceStopOrderAsync(TradeType.Buy, tmBot.Symbol.Name, LastVolume, TunnelCeiling, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); tmBot.PlaceStopOrderAsync(TradeType.Sell, tmBot.Symbol.Name, LastVolume, TunnelFloor, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); } else { tmBot.Print("Open Cycle Method: '{0}' is not implemented", tmBot.config.OpenCycleMethod.ToString()); } } else { ParsedSessionDates = GetParsedSessionDates(); if (ParsedSessionDates.Count > 0) { tmBot.Print("Session Dates found {0} records. The next is at: {1:dd MMM yyyy HH:mm:ss}.", ParsedSessionDates.Count, ParsedSessionDates.First().ActualDate); } else { tmBot.Print("No more Session Dates."); } } } else { throw new InvalidOperationException("Configuration is not properly loaded."); } }
internal Tunnel(TunnelMartingaleBot robot) { //Ask is always higher than Bid, Buy is always take the Ask while Sell is always take the Bid. tmBot = robot; LastTradeType = new Random().Next(1, 2) == 1 ? TradeType.Buy : TradeType.Sell; SessionNumber = 0; Statistics = new TunnelStatistics(); TunnelChartObjects = new TunnelChartObjects(); Initialize(); }
internal void TickCheck() { if (TunnelStatus == enTunnelStatus.Running || TunnelStatus == enTunnelStatus.PendingOrders) { //when it's a trap, and out of the validity period if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap && tmPositions.Count() == 0 && tmBot.config.Trap.Validity != TimeSpan.Zero && tmBot.TimeInUtc >= CurrentSessionDate.ActualStartDate.Add(tmBot.config.Trap.Validity).ToUniversalTime()) { tmBot.Print("Validity period is over now at: {0:dd MMM yyyy HH:mm:ss}, closing all and repeating stuff.", CurrentSessionDate.ActualStartDate.Add(tmBot.config.Trap.Validity)); EndTunnel(); } //when using SmartBucket if (TunnelStatus == enTunnelStatus.Running && UsesAnySmartBucket && IsSmartBucketInCycle && JustPassedCenterTunnel) { RetreatTunnel(); } if (TunnelStatus == enTunnelStatus.Running && OnTarget) { EndTunnel(); } } else if (TunnelStatus == enTunnelStatus.Inactive) { if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap && ((UseSessionDates && IsWithinCurrentSessionTime) || (!UseSessionDates && IsTrapTime))) { TunnelStatus = enTunnelStatus.PendingActivation; SessionNumber += 1; //executing for Trap method var HalfHeight = Math.Abs(TunnelHeight / 2); TunnelCeiling = tmBot.ShiftPriceInPips(tmBot.Symbol.Ask, HalfHeight); tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelFloor = tmBot.ShiftPriceInPips(tmBot.Symbol.Bid, -HalfHeight); tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCenter = TunnelCeiling.FindCenterAgainst(TunnelFloor, tmBot.Symbol.Digits); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawMainLinesHistory(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter, TMLabel + PositionSessionNumber); TunnelChartObjects.DrawDirection(tmBot, Direction); LastVolume = tmBot.LotToVolume(StartingLotSize); tmBot.PlaceStopOrderAsync(TradeType.Buy, tmBot.Symbol.Name, LastVolume, TunnelCeiling, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); tmBot.PlaceStopOrderAsync(TradeType.Sell, tmBot.Symbol.Name, LastVolume, TunnelFloor, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); } else if (UseSessionDates && IsWithinCurrentSessionTime && tmBot.config.OpenCycleMethod != enOpenCycleMethod.Trap) { TunnelStatus = enTunnelStatus.PendingActivation; SessionNumber += 1; LastVolume = tmBot.LotToVolume(StartingLotSize); tmBot.ExecuteMarketOrderAsync(CurrentSessionDate.SessionTradeType, GetSymbolName(CurrentSessionDate), LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } } }
internal TunnelMartingaleEngine(TunnelMartingaleBot robot) { //Ask is always higher than Bid, Buy is always take the Ask while Sell is always take the Bid. tmBot = robot; LastTradeType = new Random().Next(1, 2) == 1 ? TradeType.Buy : TradeType.Sell; SessionNumber = 0; Statistics = new TunnelStatistics(); TunnelChartObjects = new TunnelChartObjects(); rsi = tmBot.Indicators.RelativeStrengthIndex(tmBot.Bars.ClosePrices, tmBot.RSIPeriods); bb = tmBot.Indicators.BollingerBands(tmBot.Bars.ClosePrices, tmBot.BBPeriods, 2, tmBot.BBMAType); if (tmBot.config.InitialBucket.IsPositive()) { NetLossBucket = !tmBot.config.InitialBucket.IsNegative() ? -tmBot.config.InitialBucket : tmBot.config.InitialBucket; tmBot.Print("Initial bucket set at {0:#,##0.00}", NetLossBucket); } Initialize(); }
internal void UpdateTargetLines(double EntryPrice) { double breakEvenPrice = LastTradeType == TradeType.Buy ? tmBot.Positions.FindNetBreakEvenPrice(EntryPrice, tmBot.ShiftPrice(EntryPrice, tmBot.config.TunnelHeight), tmBot.Symbol.Digits) : tmBot.Positions.FindNetBreakEvenPrice(EntryPrice, tmBot.ShiftPrice(EntryPrice, -tmBot.config.TunnelHeight), tmBot.Symbol.Digits); tmBot.Print("Break Even Price is at: {0}", breakEvenPrice); BreakEven = breakEvenPrice; TunnelChartObjects.DrawBreakEvenPrice(tmBot, BreakEven); double targetPrice = LastTradeType == TradeType.Buy ? tmBot.Positions.FindTargetPrice(EntryPrice, tmBot.ShiftPrice(EntryPrice, tmBot.config.TunnelHeight), tmBot.Symbol.Digits, WhatIfProfit()) : tmBot.Positions.FindTargetPrice(EntryPrice, tmBot.ShiftPrice(EntryPrice, -tmBot.config.TunnelHeight), tmBot.Symbol.Digits, WhatIfProfit()); tmBot.Print("Target Price is at: {0}", targetPrice); TunnelChartObjects.DrawTargetPrice(tmBot, targetPrice); }
private void InitialPositionOpened(TradeResult result) { if (result.IsSuccessful) { if ((tmBot.config.SessionDates.Enabled && ParsedSessionDates.First().SessionTradeType == TradeType.Buy) || tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysBuy || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Buy)) { TunnelCeiling = result.Position.EntryPrice; tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelFloor = tmBot.ShiftPrice(TunnelCeiling, (int)tmBot.config.TunnelHeight * -1); tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCenter = tmBot.ShiftPrice(TunnelFloor, (int)Math.Ceiling((double)(tmBot.config.TunnelHeight / 2))); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawDirection(tmBot, Direction); LastVolume = result.Position.VolumeInUnits * tmBot.config.LotMultiplier; tmBot.PlaceStopOrderAsync(TradeType.Sell, tmBot.config.SessionDates.Enabled ? GetSymbolName(ParsedSessionDates.First()) : tmBot.Symbol.Name, LastVolume, TunnelFloor, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, AnotherOrderPlaced); } else if ((tmBot.config.SessionDates.Enabled && ParsedSessionDates.First().SessionTradeType == TradeType.Sell) || tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysSell || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Sell)) { TunnelFloor = result.Position.EntryPrice; tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCeiling = tmBot.ShiftPrice(TunnelFloor, (int)tmBot.config.TunnelHeight); tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelCenter = tmBot.ShiftPrice(TunnelFloor, (int)Math.Ceiling((double)(tmBot.config.TunnelHeight / 2))); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawDirection(tmBot, Direction); LastVolume = result.Position.VolumeInUnits * tmBot.config.LotMultiplier; tmBot.PlaceStopOrderAsync(TradeType.Buy, tmBot.config.SessionDates.Enabled ? GetSymbolName(ParsedSessionDates.First()) : tmBot.Symbol.Name, LastVolume, TunnelCeiling, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, AnotherOrderPlaced); } Statistics.SetMaxBounce(tmBot.Positions.Count + 1, tmBot.Time); } else { tmBot.Print("FAILED: Order failed to place at InitialPositionOpened, reason: '" + (result.Error.HasValue ? result.Error.Value.ToString() : "no valid error") + "'."); } }
internal void EndTunnel() { if (TunnelStatus == enTunnelStatus.Running) { foreach (var tp in tmBot.Positions.OrderByDescending(x => x.NetProfit)) { tmBot.ClosePosition(tp); } foreach (var to in tmBot.PendingOrders) { tmBot.CancelPendingOrder(to); } TunnelChartObjects.RemoveAll(tmBot); } NetLossBucket = 0; LastVolume = tmBot.LotToVolume(tmBot.config.StartingLotSize); if (TunnelStatus != enTunnelStatus.Inactive) { TunnelStatus = enTunnelStatus.Inactive; } }
internal void PendingOrderFilled(PendingOrderFilledEventArgs result) { if (result.Position.Label.StartsWith(TMLabel + TMLabelSeparator)) { //add routine for Trap model, close all pending orders when first order is activated/filled if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap && result.Position.Label == TMLabel + TMLabelSeparator + "I" + (1).ToString("#000") + PositionSessionNumber) { TunnelStatus = enTunnelStatus.PendingActivation; foreach (var to in tmBot.PendingOrders) { tmBot.CancelPendingOrderAsync(to); } } if (result.Position.Label == TMLabel + GetPositionIndexNumber(0) + PositionSessionNumber) //check whether this order filled is the last position, if yes then... { Statistics.SetMaxBounce(tmPositions.Count(), tmBot.Time); LastTradeType = result.Position.TradeType; TunnelStatus = enTunnelStatus.PendingActivation; LastVolume = tmBot.Symbol.NormalizeVolumeInUnits(result.Position.VolumeInUnits * tmBot.config.LotMultiplier); tmBot.Print("LastVolume: {0:#,##0}, Previous Trade: {1}", LastVolume, LastTradeType.ToString()); tmBot.PlaceStopOrderAsync(result.Position.TradeType == TradeType.Buy ? TradeType.Sell : TradeType.Buy, tmBot.config.SessionDates.Enabled ? GetSymbolName(CurrentSessionDate) : tmBot.Symbol.Name, LastVolume, (result.Position.TradeType == TradeType.Buy ? TunnelFloor : TunnelCeiling), TMLabel + GetPositionIndexNumber() + PositionSessionNumber, AnotherOrderPlaced); } TunnelChartObjects.DrawDirection(tmBot, Direction); //no IF, executes every pending order filled UpdateTargetLines(result.Position.EntryPrice); } }
internal void TickCheck() { //this is when Session Dates is enabled if (tmBot.config.SessionDates.Enabled && ParsedSessionDates != null && TunnelStatus == enTunnelStatus.Inactive) { if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap) //for Trap { if (ParsedSessionDates.Count > 0 && tmBot.TimeInUtc >= ParsedSessionDates.First().ActualDate.ToUniversalTime() && tmBot.TimeInUtc <= ParsedSessionDates.First().ActualDate.ToUniversalTime().Add(tmBot.config.SessionDates.Interval)) { TunnelStatus = enTunnelStatus.Pending; SessionNumber += 1; //executing for Trap method var HalfHeight = Math.Abs(tmBot.config.TunnelHeight / 2); TunnelCeiling = tmBot.ShiftPrice(tmBot.Symbol.Ask, HalfHeight); tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelFloor = tmBot.ShiftPrice(tmBot.Symbol.Bid, -HalfHeight); tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCenter = tmBot.ShiftPrice(TunnelFloor, (int)Math.Ceiling((double)(tmBot.config.TunnelHeight / 2))); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawMainLinesHistory(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter, TMLabel + PositionSessionNumber); TunnelChartObjects.DrawDirection(tmBot, Direction); LastVolume = tmBot.LotToVolume(tmBot.config.StartingLotSize); tmBot.PlaceStopOrderAsync(TradeType.Buy, tmBot.Symbol.Name, LastVolume, TunnelCeiling, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); tmBot.PlaceStopOrderAsync(TradeType.Sell, tmBot.Symbol.Name, LastVolume, TunnelFloor, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); } } else { if (ParsedSessionDates.Count > 0 && tmBot.TimeInUtc >= ParsedSessionDates.First().ActualDate.ToUniversalTime() && tmBot.TimeInUtc <= ParsedSessionDates.First().ActualDate.ToUniversalTime().Add(tmBot.config.SessionDates.Interval)) { TunnelStatus = enTunnelStatus.Pending; SessionNumber += 1; LastVolume = tmBot.LotToVolume(tmBot.config.StartingLotSize); tmBot.ExecuteMarketOrderAsync(ParsedSessionDates.First().SessionTradeType, GetSymbolName(ParsedSessionDates.First()), LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } } } if (tmBot.config.RunningCycleMethod == enRunningCycleMethod.NormalSmartBucket && JustPassedCenterTunnel) { RetreatTunnel(); } if (OnTarget) { EndTunnel(); Initialize(); /* * var lastTrans = (GetLatestTransDate() - tmBot.TimeInUtc); * * if (lastTrans.TotalDays >= 1 || (lastTrans.TotalDays < 1 && GetLatestTransDate().DayOfWeek != tmBot.TimeInUtc.DayOfWeek)) { * } */ } }
internal void EndTunnel() { if (TunnelStatus != enTunnelStatus.Inactive) { //Positions closing if (tmPositions.Count().IsZero()) { tmBot.Print("No position to close."); if (NetLossBucket.IsNegative()) { tmBot.Print("Net Loss Bucket: {0:#,##0.00} will be brought over to the next session date.", NetLossBucket); } } else { var closingPosIDs = new List <int>(); //to feed stuff so that the code below can only execute after all been closed closingPosIDs.AddRange(PositionsToClose.Select(x => x.Id)); foreach (var tp in PositionsToClose) { //tmBot.ClosePositionAsync(tp, AfterEndTunnelPosition); tmBot.ClosePositionAsync(tp, poscloseResult => { if (poscloseResult.IsSuccessful) { closingPosIDs.RemoveAll(x => x == poscloseResult.Position.Id); ActualProfit += poscloseResult.Position.NetProfit; tmBot.Print("Temporary Actual Profit: {0:#,##0.00}.", ActualProfit); if (closingPosIDs.Count.IsZero()) //when there's no more position on the line { tmBot.Print("No more positions, Final Actual Profit: {0:#,##0.00}.", ActualProfit); if (UsesAnySmartBucket) { if (IsSmartBucketAcrossCycle && ActualProfit.IsNegative()) { NetLossBucket = ActualProfit; tmBot.Print("Net Loss Bucket: {0:#,##0.00} will be brought over to the next session date.", NetLossBucket); } else { NetLossBucket = 0; tmBot.Print("Net Loss Bucket resets to zero (0)."); } } ActualProfit = 0; //reset the Actual Profit } } }); //tmBot.ClosePosition(tp); } } //Pending Orders closing if (tmBot.PendingOrders.Count.IsZero()) { tmBot.Print("No pending order to close."); //in case no pending orders, things must be reset first. tmBot.Print("Removing chart objects, set the initial volume back, and set tunnel to inactive, then re-initialize."); TunnelChartObjects.RemoveAll(tmBot); LastVolume = tmBot.LotToVolume(StartingLotSize); if (TunnelStatus != enTunnelStatus.Inactive) { TunnelStatus = enTunnelStatus.Inactive; } Initialize(); } else { var closingPendOrderIDs = new List <int>(); //to feed stuff so that the code below can only execute after all been closed closingPendOrderIDs.AddRange(tmBot.PendingOrders.Select(x => x.Id)); foreach (var to in tmBot.PendingOrders) { //tmBot.CancelPendingOrderAsync(to, AfterEndTunnelPendingOrder); tmBot.CancelPendingOrderAsync(to, orderCloseResult => { if (orderCloseResult.IsSuccessful) { closingPendOrderIDs.RemoveAll(x => x == orderCloseResult.PendingOrder.Id); if (closingPendOrderIDs.Count.IsZero()) //when there's no more position on the line { tmBot.Print("Removing chart objects, set the initial volume back, and set tunnel to inactive, then re-initialize."); TunnelChartObjects.RemoveAll(tmBot); LastVolume = tmBot.LotToVolume(StartingLotSize); if (TunnelStatus != enTunnelStatus.Inactive) { TunnelStatus = enTunnelStatus.Inactive; } Initialize(); } } }); //tmBot.CancelPendingOrder(to); } } } }
internal void Initialize() { tmBot.Print("»»»»»»»» Initializing..."); TunnelStatus = enTunnelStatus.Inactive; LastVolume = tmBot.LotToVolume(StartingLotSize); if (tmBot.config != null) { if (!tmBot.config.SessionDates.Enabled) // if SessionDates is not enabled { TunnelStatus = enTunnelStatus.PendingActivation; if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysBuy || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Buy)) { tmBot.ExecuteMarketOrderAsync(TradeType.Buy, tmBot.Symbol.Name, LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } else if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.AlwaysSell || (tmBot.config.OpenCycleMethod == enOpenCycleMethod.RememberLastProfitable && LastTradeType == TradeType.Sell)) { tmBot.ExecuteMarketOrderAsync(TradeType.Sell, tmBot.Symbol.Name, LastVolume, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, InitialPositionOpened); } else if (tmBot.config.OpenCycleMethod == enOpenCycleMethod.Trap) { if (tmPositions.Count() == 0 && IsTrapTime) { int HalfHeight = Math.Abs(TunnelHeight / 2); TunnelCeiling = tmBot.ShiftPriceInPips(tmBot.Symbol.Ask, HalfHeight); tmBot.Print("Tunnel Ceiling set at {0}", TunnelCeiling.ToString()); TunnelFloor = tmBot.ShiftPriceInPips(tmBot.Symbol.Bid, -HalfHeight); tmBot.Print("Tunnel Floor set at {0}", TunnelFloor.ToString()); TunnelCenter = TunnelCeiling.FindCenterAgainst(TunnelFloor, tmBot.Symbol.Digits); tmBot.Print("Tunnel Center set at {0}", TunnelCenter.ToString()); TunnelChartObjects.DrawMainLines(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter); TunnelChartObjects.DrawMainLinesHistory(tmBot, TunnelFloor, TunnelCeiling, TunnelCenter, TMLabel + PositionSessionNumber); TunnelChartObjects.DrawDirection(tmBot, Direction); tmBot.PlaceStopOrderAsync(TradeType.Buy, tmBot.Symbol.Name, LastVolume, TunnelCeiling, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); tmBot.PlaceStopOrderAsync(TradeType.Sell, tmBot.Symbol.Name, LastVolume, TunnelFloor, TMLabel + GetPositionIndexNumber() + PositionSessionNumber, TrapStarted); } else { tmBot.Print("BollingerBandsDistance: {0}", BollingerBandsDistance); TunnelStatus = enTunnelStatus.Inactive; } } else { tmBot.Print("Open Cycle Method: '{0}' is not implemented", tmBot.config.OpenCycleMethod.ToString()); TunnelStatus = enTunnelStatus.Inactive; } } else { // if SessionDates is enabled ParsedSessionDates = GetParsedSessionDates(); CurrentSessionDate = UseSessionDates ? ParsedSessionDates.First() : null; if (ParsedSessionDates.Count > 0) { tmBot.Print("Session Dates found {0} records. The next is at: {1:dd MMM yyyy HH:mm:ss}.", ParsedSessionDates.Count, CurrentSessionDate.ActualStartDate); } else { tmBot.Print("No more Session Dates."); } } } else { throw new InvalidOperationException("Configuration is not properly loaded."); } }