private Action <double, double> AdjustCloseLevels() { Store.SuppRes buyCloseLevel = BuyCloseSupResLevel().First(); Store.SuppRes sellCloseLevel = SellCloseSupResLevel().First(); Action <double, double> adjustExitLevels = (buyLevel, sellLevel) => { #region Set (buy/sell)Level { var d = Trades.CopyLast(1).Select(t => t.Time).FirstOrDefault(); var rateSinceTrade = EnumerableEx.If(() => !d.IsMin() && DoAdjustExitLevelByTradeTime, RatesArray .Reverse <Rate>() .TakeWhile(r => r.StartDate >= d) .Select(_priceAvg)) .Memoize(2); Func <SuppRes, IEnumerable <double> > getLevel = sr => EnumerableEx.If(() => !ExitByBuySellLevel, Trades.NetOpen().Yield()).DefaultIfEmpty(sr.Rate); Func <double, SuppRes, IEnumerable <double> > getLevels = (level, sr) => rateSinceTrade .Concat(level.Yield() .Expand(l => EnumerableEx.If(l.IsNaN().ToFunc(), getLevel(sr))) .Where(Lib.IsNotNaN) .Take(1) ); //buyLevel = getLevels(buyLevel, BuyLevel).Min(); //sellLevel = getLevels(sellLevel, SellLevel).Max(); } #endregion if (buyLevel.Min(sellLevel) < .5) { Log = new Exception(new { buyLevel, sellLevel } +""); return; } buyCloseLevel.SetPrice(CurrentExitPrice(false)); sellCloseLevel.SetPrice(CurrentExitPrice(true)); #region setExitLevel Action <SuppRes> setExitLevel = sr => { sr.RateEx = CrossLevelDefault(sr.IsSell); sr.ResetPricePosition(); }; #endregion var tradesCount = Trades.Length; if (tradesCount == 0) { //if (LevelBuyCloseBy == TradeLevelBy.None) setExitLevel(buyCloseLevel); //if (LevelSellCloseBy == TradeLevelBy.None) setExitLevel(sellCloseLevel); } else { if (!Trades.Any()) { Log = new Exception(new { AdjustCloseLevels = "Should have some trades here." } +""); //adjustExitLevels(buyLevel, sellLevel); //buyCloseLevel.ResetPricePosition(); //sellCloseLevel.ResetPricePosition(); } else { var cpBuy = CurrentExitPrice(true); var cpSell = CurrentExitPrice(false); var calculateTakeProfit = CalculateTakeProfit(); var takeProfitPips = InPips(calculateTakeProfit); var currentGrossOthers = _tradingStatistics.TradingMacros.Where(tm => tm != this).Sum(tm => tm.CurrentGross); var currentGrossOthersInPips = TradesManager.MoneyAndLotToPips(currentGrossOthers, CurrentGrossLot, Pair); var lastLoss = TradesManager.MoneyAndLotToPips(LastTradeLoss.Abs(), CurrentGrossLot, Pair); var ellasticRange = EllasticRange < 5 ? RatesDuration == 0 ? 0 : EllasticRange * RatesArray.Count / RatesDuration : EllasticRange; var ellasic = TakeProfitFunction == TradingMacroTakeProfitFunction.Pips || EllasticRange == 0 ? 0 : RatesArray.CopyLast(ellasticRange).Average(_priceAvg).Abs(RateLast.PriceAvg); var ratesHeightInPips = new[] { LimitProfitByRatesHeight?TradingDistance : double.NaN }.Min(m => InPips(m)); var takeBackInPips = (IsTakeBack ? Trades.GrossInPips() - CurrentGrossInPips - currentGrossOthersInPips + this.PriceSpreadAverageInPips : 0); var ratesShort = RatesArray.CopyLast(5); var priceAvgMax = ratesShort.Max(GetTradeExitBy(true)).Max(cpBuy - PointSize / 10); var priceAvgMin = ratesShort.Min(GetTradeExitBy(false)).Min(cpSell + PointSize / 10); var takeProfitLocal = TakeProfitFunction.IfNotDirect(takeProfitPips, tp => (tp + (UseLastLoss ? lastLoss : 0)).Max(takeBackInPips).Min(ratesHeightInPips)); Func <bool, double> levelByNetOpenAndTakeProfit = isBuy => isBuy ? Trades.IsBuy(isBuy).NetOpen() + InPoints(takeProfitLocal) : Trades.IsBuy(isBuy).NetOpen() - InPoints(takeProfitLocal); Func <bool, double> getTradeCloseLevel = isBuy => !IsTakeBack ? GetTradeCloseLevel(isBuy) : isBuy ? levelByNetOpenAndTakeProfit(isBuy).Max(GetTradeCloseLevel(isBuy)) : levelByNetOpenAndTakeProfit(isBuy).Min(GetTradeCloseLevel(isBuy)); Func <bool, double> levelByDefault = isBuy => IsTakeBack ? double.NaN : isBuy ? buyLevel + calculateTakeProfit : sellLevel - calculateTakeProfit; if (buyCloseLevel.IsGhost) { setExitLevel(buyCloseLevel); } else if (buyCloseLevel.InManual) { if (buyCloseLevel.Rate <= priceAvgMax) { buyCloseLevel.Rate = priceAvgMax; } } else if (Trades.HaveBuy()) { var signB = (_buyLevelNetOpen() - buyCloseLevel.Rate).Sign(); buyCloseLevel.RateEx = new[] { getTradeCloseLevel(true) .Min(levelByNetOpenAndTakeProfit(true)) .Min(levelByDefault(true)) , priceAvgMax }.MaxBy(l => l) /*.Select(l => setBuyExit(l))*/.First() - ellasic ; if (signB != (_buyLevelNetOpen() - buyCloseLevel.Rate).Sign()) { buyCloseLevel.ResetPricePosition(); } } else if (LevelBuyCloseBy == TradeLevelBy.None) { buyCloseLevel.RateEx = CrossLevelDefault(true); } if (sellCloseLevel.IsGhost) { setExitLevel(sellCloseLevel); } else if (sellCloseLevel.InManual) { if (sellCloseLevel.Rate >= priceAvgMin) { sellCloseLevel.Rate = priceAvgMin; } } else if (Trades.HaveSell()) { var sign = (_sellLevelNetOpen() - sellCloseLevel.Rate).Sign(); sellCloseLevel.RateEx = new[] { getTradeCloseLevel(false) .Max(levelByNetOpenAndTakeProfit(false)) .Max(levelByDefault(false)) , priceAvgMin }.MinBy(l => l) /*.Select(l => setSellExit(l))*/.First() + ellasic ; if (sign != (_sellLevelNetOpen() - sellCloseLevel.Rate).Sign()) { sellCloseLevel.ResetPricePosition(); } } else if (LevelSellCloseBy == TradeLevelBy.None) { sellCloseLevel.RateEx = CrossLevelDefault(false); } } } }; return(adjustExitLevels); }