/// <summary> /// /// </summary> /// <param name="side"></param> /// <param name="retracement"></param> /// <returns></returns> protected virtual Tuple <double, double, double> GetOrderPrices(double spread, string side, Thrust thrust) { double entryPrice, stopLossPrice; FibonacciRetracement retracement = (FibonacciRetracement)thrust.Study; if (side == MACC.Constants.SignalSide.Buy) { entryPrice = retracement.LevelPrice(FibonacciLevel.R382) + (0.75 * spread); stopLossPrice = retracement.LevelPrice(FibonacciLevel.R618) - (0.75 * spread); if (thrust.FillZoneReached() && thrust.TakeProfitZoneReached()) { stopLossPrice = retracement.LevelPrice(FibonacciLevel.R500) - (0.75 * spread); } } else { entryPrice = retracement.LevelPrice(FibonacciLevel.R382) - (0.75 * spread); stopLossPrice = retracement.LevelPrice(FibonacciLevel.R618) + (0.75 * spread); if (thrust.FillZoneReached() && thrust.TakeProfitZoneReached()) { stopLossPrice = retracement.LevelPrice(FibonacciLevel.R500) + (0.75 * spread); } } int multiplier = side == MACC.Constants.SignalSide.Buy ? 1 : -1; double r382Price = retracement.LevelPrice(FibonacciLevel.R382); double takeProfitPrice = r382Price + (0.618 * Math.Abs(retracement.FocusPrice - r382Price) * multiplier); var orderPrices = Tuple.Create <double, double, double>(entryPrice, stopLossPrice, takeProfitPrice); return(orderPrices); }
public void GetFibboLevels_GivenBearishTrend_ShouldReturnExtensionLevelLessThanPointAandB(double pointA, double pointB) { //Arrange //Act var fibboLevels = FibonacciRetracement.GetFibboLevels(pointA, pointB); //Assert Assert.Less(fibboLevels.Extension1_Level_161_8, pointB); Assert.Less(fibboLevels.Extension2_Level_261_8, pointB); Assert.Less(fibboLevels.Extension3_Level_423_6, pointB); Assert.Less(fibboLevels.Extension4_Level_685_4, pointB); Assert.Less(fibboLevels.Extension5_Level_1109, pointB); Assert.Less(fibboLevels.Extension6_Level_1794_4, pointB); Assert.Less(fibboLevels.Extension7_Level_2903_4, pointB); Assert.Less(fibboLevels.Extension8_Level_4697_8, pointB); Assert.Less(fibboLevels.Extension9_Level_7601_2, pointB); Assert.Less(fibboLevels.Extension10_Level_12299, pointB); Assert.Less(fibboLevels.Extension1_Level_161_8, pointA); Assert.Less(fibboLevels.Extension2_Level_261_8, pointA); Assert.Less(fibboLevels.Extension3_Level_423_6, pointA); Assert.Less(fibboLevels.Extension4_Level_685_4, pointA); Assert.Less(fibboLevels.Extension5_Level_1109, pointA); Assert.Less(fibboLevels.Extension6_Level_1794_4, pointA); Assert.Less(fibboLevels.Extension7_Level_2903_4, pointA); Assert.Less(fibboLevels.Extension8_Level_4697_8, pointA); Assert.Less(fibboLevels.Extension9_Level_7601_2, pointA); Assert.Less(fibboLevels.Extension10_Level_12299, pointA); }
public void GetFibboLevels_GivenBearishTrend_ShouldReturnExtensionLevelsInDescendingOrder(double pointA, double pointB) { //Arrange //Act var fibboLevels = FibonacciRetracement.GetFibboLevels(pointA, pointB); //Assert Assert.Less(fibboLevels.Extension10_Level_12299, fibboLevels.Extension9_Level_7601_2); Assert.Less(fibboLevels.Extension9_Level_7601_2, fibboLevels.Extension8_Level_4697_8); Assert.Less(fibboLevels.Extension8_Level_4697_8, fibboLevels.Extension7_Level_2903_4); Assert.Less(fibboLevels.Extension7_Level_2903_4, fibboLevels.Extension6_Level_1794_4); Assert.Less(fibboLevels.Extension6_Level_1794_4, fibboLevels.Extension5_Level_1109); Assert.Less(fibboLevels.Extension5_Level_1109, fibboLevels.Extension4_Level_685_4); Assert.Less(fibboLevels.Extension4_Level_685_4, fibboLevels.Extension3_Level_423_6); Assert.Less(fibboLevels.Extension3_Level_423_6, fibboLevels.Extension2_Level_261_8); Assert.Less(fibboLevels.Extension2_Level_261_8, fibboLevels.Extension1_Level_161_8); Assert.Less(fibboLevels.Extension1_Level_161_8, pointB); Assert.AreEqual(fibboLevels.PointB, pointB); Assert.Less(fibboLevels.RetracementLevel_61_8, fibboLevels.RetracementLevel_38_2); Assert.Less(fibboLevels.RetracementLevel_38_2, fibboLevels.RetracementLevel_23_6); Assert.Less(fibboLevels.RetracementLevel_23_6, pointA); Assert.AreEqual(fibboLevels.PointA, pointA); }
public void GetFibboLevels_Given50Level_ShouldReturnLevelsWithCorrectValue(double pointA, double pointB) { //Arrange var level50Prie = (pointA + pointB) / 2; //Act var fibboLevelGivenLevel = FibonacciRetracement.GetFibboLevels(pointA, pointB, 0.5); //Assert Assert.AreEqual(level50Prie, fibboLevelGivenLevel); }
public void GetFibboLevels_GivenLevelAndBullishTrend_ShouldReturnLevelsWithCorrectValues(double pointA, double pointB, double level) { //Arrange //Act var fibboLevels = FibonacciRetracement.GetFibboLevels(pointA, pointB); var fibboLevelGivenLevel = FibonacciRetracement.GetFibboLevels(pointA, pointB, level); //Assert switch (level) { case Fibonacci.Extension1_Level_161_8: Assert.AreEqual(fibboLevels.Extension1_Level_161_8, fibboLevelGivenLevel); break; case Fibonacci.Extension2_Level_261_8: Assert.AreEqual(fibboLevels.Extension2_Level_261_8, fibboLevelGivenLevel); break; case Fibonacci.Extension3_Level_423_6: Assert.AreEqual(fibboLevels.Extension3_Level_423_6, fibboLevelGivenLevel); break; case Fibonacci.Extension4_Level_685_4: Assert.AreEqual(fibboLevels.Extension4_Level_685_4, fibboLevelGivenLevel); break; case Fibonacci.Extension5_Level_1109: Assert.AreEqual(fibboLevels.Extension5_Level_1109, fibboLevelGivenLevel); break; case Fibonacci.Extension6_Level_1794_4: Assert.AreEqual(fibboLevels.Extension6_Level_1794_4, fibboLevelGivenLevel); break; case Fibonacci.Extension7_Level_2903_4: Assert.AreEqual(fibboLevels.Extension7_Level_2903_4, fibboLevelGivenLevel); break; case Fibonacci.Extension8_Level_4697_8: Assert.AreEqual(fibboLevels.Extension8_Level_4697_8, fibboLevelGivenLevel); break; case Fibonacci.Extension9_Level_7601_2: Assert.AreEqual(fibboLevels.Extension9_Level_7601_2, fibboLevelGivenLevel); break; case Fibonacci.Extension10_Level_12299: Assert.AreEqual(fibboLevels.Extension10_Level_12299, fibboLevelGivenLevel); break; } }
protected void CreateOrUpdateFibRetracement() { FibonacciRetracement retracement = this.Study as FibonacciRetracement; if (retracement == null) { this.Study = new FibonacciRetracement() { AnchorPrice = SignalPrice, AnchorTime = SignalTime }; retracement = this.Study as FibonacciRetracement; } retracement.FocusPrice = FocusPrice; retracement.FocusTime = FocusTime; }
/// <summary> /// Sets the extrema price of the thrust Fibonacci retracement /// </summary> /// <param name="chart">The chart object that contains the retracement.</param> /// <param name="side">The direction of the entry signal associated with the retracement.</param> /// <param name="focusIndex">The chart index of the retracement focus bar.</param> /// <returns></returns> protected virtual Thrust SetThrustRetracementExtrema(Chart chart, Thrust thrust) { int focusIndex = GetFocusIndex(chart, thrust); FibonacciRetracement retracement = thrust.Study as FibonacciRetracement; double?extremaPrice = null; // only if the chart has post-focus frames int i = focusIndex + 1; if (i < chart.Frames.Count) { // initialize if (thrust.Side == MACC.Constants.SignalSide.Buy) { extremaPrice = chart.Frames[focusIndex].Bar.highMid; } else { extremaPrice = chart.Frames[focusIndex].Bar.lowMid; } // discover for (; i < chart.Frames.Count; i++) { if (thrust.Side == MACC.Constants.SignalSide.Buy) { extremaPrice = Math.Min(extremaPrice.Value, chart.Frames[i].Bar.lowMid); } else { extremaPrice = Math.Max(extremaPrice.Value, chart.Frames[i].Bar.highMid); } } } retracement.ExtremaPrice = extremaPrice; if (retracement.ExtremaChanged()) { retracement.ExtremaIndex = i; } return(thrust); }
/// <summary> /// /// </summary> /// <param name="chart"></param> /// <param name="side"></param> /// <param name="state"></param> /// <returns></returns> public virtual double?GetAdjustedStopLossPrice(Chart chart, IParameters parameters, IDictionary <string, object> state) { string side; Thrust thrust; bool hasProfit; #region state validation string stateItem = ""; try { stateItem = "side"; side = (string)state[stateItem]; stateItem = "thrust"; thrust = (Thrust)state[stateItem]; stateItem = "hasProfit"; hasProfit = Convert.ToBoolean(state[stateItem]); } catch (Exception ex) { throw new ArgumentException(string.Format("State argument is missing or invalid: {0}.", stateItem), ex); } #endregion #region logic // if a buy ... // move the stop to the lower of the .500 fib price or [patern lowBid price set by the post-fill price action] // if a sell ... // move the stop to the higher of the .500 fib price or [patern highBid price set by the post-fill price action] #endregion FibonacciRetracement retracement = (FibonacciRetracement)thrust.Study; if (!retracement.ExtremaPrice.HasValue) { return(null); } double?stopLossPrice = null; double r500Price = retracement.LevelPrice(FibonacciLevel.R500); double lastPrice = chart.Frames.Last().Bar.closeMid; double extrema500Delta = 0; double extremaPrice = retracement.ExtremaPrice.Value; double extremaTakeProfitDelta = Math.Abs(thrust.TakeProfitPrice.Value - extremaPrice); double takeProfitZoneReachedExtremaCoefficient = parameters.GetDouble("takeProfitZoneReachedExtremaCoefficient") ?? 0.5; if (side == MACC.Constants.SignalSide.Buy) { extrema500Delta = extremaPrice - r500Price; if (hasProfit) { if (thrust.TakeProfitZoneReached()) { stopLossPrice = extremaPrice + (takeProfitZoneReachedExtremaCoefficient * extremaTakeProfitDelta); } else if (extrema500Delta >= 0 && !thrust.ProfitWindowClosed) { stopLossPrice = null; } else if (extrema500Delta >= 0 && thrust.ProfitWindowClosed) // set to extrema or 500? { stopLossPrice = r500Price; } else if (extrema500Delta < 0 && !thrust.ProfitWindowClosed) { stopLossPrice = extremaPrice; } else // extrema500Delta < 0 && profitWindowClosed .. set to r500 { stopLossPrice = r500Price; } } else { if (thrust.TakeProfitZoneReached()) { stopLossPrice = -1; } if (thrust.ProfitWindowClosed && lastPrice > r500Price) { stopLossPrice = r500Price; } else if (thrust.ProfitWindowClosed && lastPrice <= r500Price) { stopLossPrice = -1; // kill trade } else { stopLossPrice = null; } } if (stopLossPrice.HasValue) { // stopLoss should never move down if (stopLossPrice <= thrust.StopLossPrice) { stopLossPrice = null; } else { stopLossPrice -= chart.HistoricBidAskSpread; } } } else { extrema500Delta = r500Price - extremaPrice; if (hasProfit) { if (thrust.TakeProfitZoneReached()) { stopLossPrice = extremaPrice - (takeProfitZoneReachedExtremaCoefficient * extremaTakeProfitDelta); } else if (extrema500Delta >= 0 && !thrust.ProfitWindowClosed) { stopLossPrice = null; } else if (extrema500Delta >= 0 && thrust.ProfitWindowClosed) { stopLossPrice = extremaPrice; } else if (extrema500Delta < 0 && !thrust.ProfitWindowClosed) { stopLossPrice = extremaPrice; } else // extrema500Delta < 0 && profitWindowClosed { stopLossPrice = r500Price; } } else { if (thrust.TakeProfitZoneReached()) { stopLossPrice = -1; } else if (lastPrice < r500Price && thrust.ProfitWindowClosed) { stopLossPrice = r500Price; } else if (lastPrice >= r500Price && thrust.ProfitWindowClosed) { stopLossPrice = -1; // kill trade .. if not already stopped out } else { stopLossPrice = null; } } if (stopLossPrice.HasValue) { // stopLoss should never move up if (stopLossPrice >= thrust.StopLossPrice) { stopLossPrice = null; } else { stopLossPrice += chart.HistoricBidAskSpread; } } } if (stopLossPrice.HasValue) { stopLossPrice = Math.Round(stopLossPrice.Value, retracement.LevelPlaces()); } return(stopLossPrice); }
/// <summary> /// /// </summary> /// <param name="chart"></param> /// <param name="retracement"></param> /// <param name="side"></param> /// <returns></returns> protected virtual double?GetAdjustedTakeProfitPrice(Chart chart, string side, FibonacciRetracement retracement) { #region logic // if a buy ... // move the profit target to 1 or 2 pips under .618 * (thrust.FocusPrice - [pattern lowMid price set by the post-fill price action]) // if a sell ... // move the profit target to 1 or 2 pips above .618 * ([pattern lowMid price set by the post-fill price action] - thrust.FocusPrice) #endregion if (_takeProfitPriceCalculator == null) { _takeProfitPriceCalculator = ObjectBase.Container.GetExportedValue <ITakeProfitPriceCalculator>("ThrustTakeProfitPriceCalculator"); } Dictionary <string, object> state = new Dictionary <string, object>(); state.Add("side", side); state.Add("retracement", retracement); return(_takeProfitPriceCalculator.GetAdjustedTakeProfitPrice(chart, Parameters, state)); }
/// <summary> /// /// </summary> /// <param name="chart"></param> /// <param name="thrust"></param> /// <param name="retracement"></param> protected virtual async void ManageOrder(Chart chart, Thrust thrust) { StrategyTransaction[] transactions = null; StrategyTransaction orderTransaction, fillTransaction, cancelTransaction, exitTransaction; // get transaction collection from db int orderTransactionID = thrust.StrategyTransactionID.GetValueOrDefault(); transactions = await StrategyCaller.Instance().GetStrategyTransactionsCollectionAsync(orderTransactionID); orderTransaction = transactions.FirstOrDefault(t => t.StrategyTransactionID == orderTransactionID); fillTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderFilled); cancelTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderCancel); exitTransaction = transactions.FirstOrDefault(t => t.BrokerTradeID != null && t.Type != MACC.Constants.TransactionTypes.TradeUpdate); bool purgeInActiveThrust = true; if (fillTransaction == null) { if (cancelTransaction != null) { // order cancelled thrust.Active = false; } else { // order open if (!thrust.Active) { // cancel the order // the cancel transaction will be written to the db by the event stream handler await Rest.DeleteOrderAsync(_accountId, Convert.ToInt64(orderTransaction.BrokerTransactionID)); } else { if (thrust.FocusChanged() || (thrust.FillZoneReached() && thrust.TakeProfitZoneReached())) { AddAlgorithmMessage(string.Format("UPDATE ORDER: {0}: FCH-{1}: FZR-{2}: TPR-{3}", orderTransaction.Instrument, thrust.FocusChanged(), thrust.FillZoneReached(), thrust.TakeProfitZoneReached())); UpdateEntryOrder(orderTransaction, chart, thrust); } } } } else { if (exitTransaction == null) { // order filled purgeInActiveThrust = false; FibonacciRetracement retracement = (FibonacciRetracement)thrust.Study; #region get open trade info long tradeId = Convert.ToInt64(fillTransaction.BrokerTransactionID); Frame fillFrame = chart.Frames.LastOrDefault(f => Convert.ToDateTime(f.Bar.time).ToUniversalTime() <= fillTransaction.Time); int fillIndex = chart.Frames.IndexOf(fillFrame); #endregion #region get takeProfitPrice and stopLossPrice int profitWaitPeriods = Parameters.GetInteger("thrustProfitWaitPeriods") ?? 6; thrust.ProfitWindowClosed = (fillIndex + profitWaitPeriods) < chart.Frames.Count; IPriceBar lastBar = chart.Frames.Last().Bar; bool hasProfit = orderTransaction.Side == MACC.Constants.SignalSide.Buy ? lastBar.closeMid > fillTransaction.Price : lastBar.closeMid < fillTransaction.Price; #region stopLossPrice & takeProfitPrice logic // adjust stopLossPrice and takeProfitPrice // if a buy ... // move the stop to the lower of the .500 fib price or [patern lowMid price set by the post-fill price action] // move the profit target to 1 or 2 pips under .618 * (thrust.FocusPrice - [pattern lowMid price set by the post-fill price action]) // if a sell ... // move the stop to the higher of the .500 fib price or [patern highMid price set by the post-fill price action] // move the profit target to 1 or 2 pips above .618 * ([pattern lowMid price set by the post-fill price action] - thrust.FocusPrice) #endregion double?takeProfitPrice = GetAdjustedTakeProfitPrice(chart, thrust.Side, retracement); AddAlgorithmMessage(string.Format("GET SLP: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: PFT-{5}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, hasProfit)); double?stopLossPrice = GetAdjustedStopLossPrice(chart, thrust.Side, thrust, hasProfit); #endregion #region kill or update the trade // not profitable && beyond r500 .. kill it if (stopLossPrice.GetValueOrDefault() == -1) { thrust.Active = false; purgeInActiveThrust = true; try { await Rest.DeleteTradeAsync(_accountId, tradeId); } catch (Exception e) { AddAlgorithmMessage(string.Format("CLOSE TRADE {0} Failed: {1}", tradeId, e.Message), true, TraceEventType.Error); } } else { if ((takeProfitPrice ?? thrust.TakeProfitPrice) != thrust.TakeProfitPrice || (stopLossPrice ?? thrust.StopLossPrice) != thrust.StopLossPrice) { AddAlgorithmMessage(string.Format("UPDATE TRADE: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: TP-{5}: TTP-{6}: SL-{7}: TSL-{8}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, takeProfitPrice, thrust.TakeProfitPrice, stopLossPrice, thrust.StopLossPrice)); UpdateOpenTrade(thrust, tradeId, takeProfitPrice, stopLossPrice, retracement.LevelPlaces()); } } #endregion } else { // trade closed #region about closed trades // if coll includes a stopLossFilled or takeProfitFilled .. // set thrust.Active = false // this be done server side when the strategyTransaction from the stream is saved // the signal should be found on the server and signal.Active should be set to false // do it here also #endregion thrust.Active = false; } } if (!thrust.Active && purgeInActiveThrust) { await PurgeThrust(chart, thrust); } }
protected Thrust SetThrustActive(Chart chart, Thrust thrust, bool isNewThrust) { thrust.Active = true; List <Frame> afterFocusFrames = chart.Frames.Skip(GetFocusIndex(chart, thrust) + 1).ToList(); if (isNewThrust) { // should an order be placed? // thrust range must be >= _percentRange // should some consideration of the time frame happen? // .006 is for hourly // use a lower value for lower time frame scalping? if (Math.Abs(thrust.FocusPrice - thrust.SignalPrice) / thrust.SignalPrice < _minThrustPercentRange) { thrust.Active = false; return(thrust); } if (thrust.ReactionToFocusSpan < _minReactionToFocusSpan) { thrust.Active = false; return(thrust); } if (afterFocusFrames.Count() == 0) { return(thrust); } else { FibonacciRetracement retracement = thrust.Study as FibonacciRetracement; Frame r382ReachedOrExceededFrame = afterFocusFrames.FirstOrDefault(frame => { if (thrust.Direction == EPatternDirection.Up) { if (frame.Bar.lowMid <= retracement.LevelPrice(FibonacciLevel.R382)) { return(true); } } else { if (frame.Bar.highMid >= retracement.LevelPrice(FibonacciLevel.R382)) { return(true); } } return(false); }); thrust.Active = r382ReachedOrExceededFrame == null; return(thrust); } } else { // should the order be cancelled if not yet filled? // if filled, a 'false' from this doesn't matter #region afterFocusAcross3x3Count function Func <EPatternDirection, short> afterFocusAcross3x3Count = (direction) => { short across3x3Count = 0; Frame firstConfirmedAcross3x3 = null; foreach (Frame frame in afterFocusFrames) { IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); if (direction == EPatternDirection.Up) { // grab the first bar below the 3x3 on close if (frame.Bar.closeMid < displaced3x3.Value && firstConfirmedAcross3x3 == null) { firstConfirmedAcross3x3 = frame; continue; } if (firstConfirmedAcross3x3 != null && frame.Bar.lowMid < displaced3x3.Value) { across3x3Count++; } } else { // grab the first bar above the 3x3 on close if (frame.Bar.closeMid > displaced3x3.Value && firstConfirmedAcross3x3 == null) { firstConfirmedAcross3x3 = frame; continue; } if (firstConfirmedAcross3x3 != null && frame.Bar.highMid > displaced3x3.Value) { across3x3Count++; } } } return(across3x3Count); }; #endregion // enforce a reactionToFocusSpan of 9 bars to filter out 'turn' thrusts // turn thrusts happen detection triggers on bars at turns in price // these are new thrusts but need 'seasoning' (ie. >= 9 bars) to be trade worthy // enforce Dinapoli rule on no more than 3 bars across 3x3 after initial closing bar across 3x3 thrust.Active = afterFocusAcross3x3Count(thrust.Direction) <= _maxAfterFocusAcross3x3Count; return(thrust); } }
protected virtual Thrust SetThrustTakeProfitZoneReached(Chart chart, Thrust thrust) { FibonacciRetracement retracement = thrust.Study as FibonacciRetracement; #region did price reach the takeProfit zone? if (thrust.FillZoneReached()) { double? searchTakeProfitPrice = null; List <Frame> searchFrames = null; if (!thrust.TakeProfitZoneReached()) { searchTakeProfitPrice = thrust.TakeProfitPrice.Value; searchFrames = chart.Frames.Skip(thrust.FillZoneReachedIndex.Value + 1).ToList(); } else { if (retracement.ExtremaChanged()) { int multiplier = thrust.Side == MACC.Constants.SignalSide.Buy ? 1 : -1; double r382Price = retracement.LevelPrice(FibonacciLevel.R382); searchTakeProfitPrice = r382Price + (0.618 * Math.Abs(retracement.FocusPrice - r382Price) * multiplier); searchFrames = chart.Frames.Skip(retracement.ExtremaIndex.Value + 1).ToList(); } } Frame takeProfitZoneReachedFrame = searchFrames.FirstOrDefault(frame => { double extremaToTakeProfitZoneDelta = _takeProfitZoneReachedCoefficient * Math.Abs(searchTakeProfitPrice.Value - retracement.ExtremaPrice.Value); bool takeProfitZoneReached = false; if (thrust.Direction == EPatternDirection.Up) { takeProfitZoneReached = (frame.Bar.highMid >= retracement.ExtremaPrice.Value + extremaToTakeProfitZoneDelta); } else { takeProfitZoneReached = (frame.Bar.lowMid <= retracement.ExtremaPrice.Value - extremaToTakeProfitZoneDelta); } if (takeProfitZoneReached) { thrust.TakeProfitZoneReachedIndex = chart.Frames.IndexOf(frame); thrust.TakeProfitZoneReachedFocusPrice = thrust.FocusPrice; return(true); } return(false); }); } #endregion // is it a breakout? if (thrust.TakeProfitZoneReached()) { double breakoutDelta = thrust.SignalPrice * _focusBreakoutCoefficient * _minThrustPercentRange; if (thrust.Direction == EPatternDirection.Up) { thrust.Breakout = thrust.FocusPrice >= thrust.TakeProfitZoneReachedFocusPrice.Value + breakoutDelta; } else { thrust.Breakout = thrust.FocusPrice <= thrust.TakeProfitZoneReachedFocusPrice.Value - breakoutDelta; } if (thrust.Breakout) { thrust.FillZoneReachedIndex = null; thrust.TakeProfitZoneReachedIndex = null; thrust.TakeProfitZoneReachedFocusPrice = null; } } return(thrust); }