protected PriceBar[] FetchPriceBars(TradingMacro tradingMacro, int rowOffset, bool reversePower, DateTime dateStart)
        {
            var isLong          = dateStart == DateTime.MinValue;
            var rs              = tradingMacro.UseRates(ra => ra.Where(r => r.StartDate >= dateStart).GroupTicksToRates()).Concat();
            var ratesForDensity = (reversePower ? rs.OrderBarsDescending() : rs.OrderBars()).ToArray();

            SetPriceBars(tradingMacro, isLong, ratesForDensity.GetPriceBars(TradesManager.GetPipSize(tradingMacro.Pair), rowOffset));
            return(GetPriceBars(tradingMacro, isLong));
        }
        void SubscribeToEntryOrderRelatedEvents()
        {
            var bsThrottleTimeSpan    = 0.1.FromSeconds();
            var cpThrottleTimeSpan    = 0.25.FromSeconds();
            var buySelPropsExceptions = new[] { "CanTradeEx", "IsGhost" };
            Func <IReactivePropertyChangedEventArgs <SuppRes>, bool> buySellPropsFilter = _ => !buySelPropsExceptions.Contains(_.PropertyName);

            //ISubject<Action> fxWraper = new Subject<Action>();
            //fxWraper.ObserveOn(TradesManagerStatic.TradingScheduler).Subscribe(a => a(), () => { Debugger.Break(); });

            #region SetTradeNet
            Action <Trade, double, double> SetTradeNet = (trade, limit, stop) => {
                //fxWraper.OnNext(() => {
                var fw = TradesManager;
                if (!limit.IsNaN())
                {
                    try {
                        if (fw.GetNetOrderRate(Pair, false).Abs(limit) > InPoints(1))
                        {
                            //Log = new Exception("FixOrderSetLimit:" + new { trade.Pair, limit = limit.Round(Digits()) });
                            fw.FixOrderSetLimit(trade.Id, limit, "");
                        }
                    } catch (Exception exc) { Log = exc; }
                }
                if (!stop.IsNaN())
                {
                    try {
                        if (fw.GetNetOrderRate(Pair, true).Abs(stop) > InPoints(1))
                        {
                            //Log = new Exception("FixOrderSetStop:" + new { trade.Pair, stop = stop.Round(Digits()) });
                            fw.FixOrderSetStop(trade.Id, stop, "");
                        }
                    } catch (Exception exc) { Log = exc; }
                }
                TradeLastChangeDate = DateTime.Now;
                //});
            };
            Action <Trade, double> SetTradeNetLimit = (trade, limit) => SetTradeNet(trade, limit, double.NaN);
            Action <Trade, double> SetTradeNetStop  = (trade, stop) => SetTradeNet(trade, double.NaN, stop);
            Action CloseAllNetLimits = () => Trades.Take(1).ForEach(trade => SetTradeNetLimit(trade, 0));
            Action CloseAllNetStops  = () => Trades.Take(1).ForEach(trade => SetTradeNetStop(trade, 0));
            #endregion

            #region startBuySellLevelsTracking
            Action startBuySellLevelsTracking = () => {
                #region updateEntryOrders
                Action <string> updateEntryOrders = (reason) => {
                    try {
                        var buySellLevels = new[] { BuyLevel, SellLevel };
                        GetEntryOrders().GroupBy(eo => eo.IsBuy).SelectMany(eog => eog.Skip(1)).ForEach(OnDeletingOrder);
                        Func <SuppRes, bool> canTrade = (sr) =>/* IsTradingHour() &&*/
                                                        sr.CanTrade && sr.TradesCount <= 0 &&
                                                        !Trades.IsBuy(sr.IsBuy).Any();
                        Func <bool, int> lotSize = isBuy =>
                                                   (buySellLevels.Where(sr => sr.IsBuy == isBuy).Any(canTrade) ? (isBuy ? LotSizeByLossBuy : LotSizeByLossSell) : 0)
                                                   + (TradesManager.GetNetOrderRate(Pair, true) > 0 ? 0 : Trades.IsBuy(!isBuy).Lots());
                        buySellLevels.Select(sr => new { sr.IsBuy, sr.Rate, lotSize = lotSize(sr.IsBuy) })
                        .Do(sr => GetEntryOrders(sr.IsBuy).Where(a => sr.lotSize == 0).ForEach(OnDeletingOrder))
                        .Where(sr => sr.lotSize > 0 && !GetEntryOrders(sr.IsBuy).Any())
                        .ForEach(level => OnCreateEntryOrder(level.IsBuy, level.lotSize, level.Rate));

                        Action <Order> changeLimit = eo => TradesManager.YieldIf(!IsInVirtualTrading && eo.Lot.Ratio(lotSize(eo.IsBuy)) > 1.025)
                                                     .ForEach(fw => {
                            //Log = new Exception("ChangeEntryOrderLot:" + reason);
                            fw.ChangeEntryOrderLot(eo.OrderID, lotSize(eo.IsBuy));
                        });

                        Func <bool, double> orderRate  = isBuy => buySellLevels.Where(sr => sr.IsBuy == isBuy).First().Rate;
                        Action <Order>      changeRate = eo => TradesManager.YieldIf(!IsInVirtualTrading && eo.Rate.Abs(orderRate(eo.IsBuy)) > PointSize)
                                                         .ForEach(fw => {
                            //Log = new Exception("ChangeEntryOrderRate:" + reason);
                            fw.ChangeEntryOrderRate(eo.OrderID, orderRate(eo.IsBuy));
                        });

                        GetEntryOrders().ForEach(eo => {
                            changeLimit(eo);
                            changeRate(eo);
                        });
                    } catch (Exception exc) { Log = exc; }
                };
                #endregion
                _reactiveBuySellLevels = new[] { BuyLevel, SellLevel, BuyCloseLevel, SellCloseLevel }.CreateDerivedCollection(sr => sr);
                _reactiveBuySellLevels.ChangeTrackingEnabled = true;
                _reactiveBuySellLevelsSubscribtion           = (CompositeDisposable)
                                                               _reactiveBuySellLevels.ItemChanged
                                                               .Where(buySellPropsFilter)
                                                               .Sample(bsThrottleTimeSpan)
                                                               //.Do(_ => Log = new Exception(new { Name = "startBuySellLevelsTracking", _.PropertyName, Value = _.Value + "" } + ""))
                                                               .Select(_ => _.Sender.IsBuy ? "Buy" + (_.Sender.IsExitOnly ? "Close" : "") + "Level" : "Sell" + (_.Sender.IsExitOnly ? "Close" : "") + "Level")
                                                               .Merge(ReactiveTrades.ItemChanged.Where(_ => _.PropertyName == "Stop").Select(_ => _.Sender.IsBuy ? "BuyTrade" : "SellTrade"))
                                                               .Merge(Observable.FromEventPattern <EventHandler <OrderEventArgs>, OrderEventArgs>(
                                                                          h => TradesManager.OrderAdded += h, h => TradesManager.OrderAdded -= h).Select(e => "OrderAdded"))
                                                               .Merge(Observable.FromEventPattern <EventHandler <OrderEventArgs>, OrderEventArgs>(
                                                                          h => TradesManager.OrderChanged += h, h => TradesManager.OrderChanged -= h).Select(e => "OrderChanged"))
                                                               .Merge(Observable.FromEvent <OrderRemovedEventHandler, Order>(h => TradesManager.OrderRemoved += h, h => TradesManager.OrderRemoved -= h).Select(_ => "OrderRemoved"))
                                                               .Merge(this.WhenAny(tm => tm.CurrentPrice, tm => "CurrentPrice").Sample(cpThrottleTimeSpan))
                                                               .Merge(this.WhenAny(tm => tm.CanDoEntryOrders, tm => "CanDoEntryOrders"))
                                                               .Merge(this.WhenAny(tm => tm.CanDoNetStopOrders, tm => "CanDoNetStopOrders"))
                                                               .Subscribe(reason => _updateEntryOrdersBuffer.Push(() => updateEntryOrders(reason)));
                updateEntryOrders("Start Tracking");
            };
            #endregion
            #region startBuySellCloseLevelsTracking
            #region Net Update Implementations
            var    bsCloseLevels          = MonoidsCore.ToFunc(() => new[] { BuyCloseLevel, SellCloseLevel }.Where(sr => sr != null));
            Action updateTradeLimitOrders = () => {
                Func <Trade, double[]> levelRate  = trade => bsCloseLevels().Where(sr => sr.IsBuy == !trade.IsBuy).Select(sr => sr.Rate).Take(1).ToArray();
                Action <Trade>         changeRate = trade => levelRate(trade)
                                                    .Where(_ => !IsInVirtualTrading)
                                                    .Where(lr => trade.Limit.Abs(lr) > PointSize)
                                                    .ForEach(lr => SetTradeNetLimit(trade, lr));
                Trades.Take(1).ForEach(changeRate);
            };
            Func <Trade, double[]> getDefaultStop = trade => // Take care of reversed corridor
                                                    bsCloseLevels()
                                                    .Where(_ => SellLevel.Rate > BuyLevel.Rate)
                                                    .Where(bs => bs.IsBuy != trade.IsBuy)
                                                    .Select(bs => trade.Open.Abs(bs.Rate) * 2)
                                                    .Select(stop => trade.IsBuy ? -stop : stop)
                                                    .Select(stop => trade.Open + stop)
                                                    .ToArray();
            Action updateTradeStopOrders = () => {
                var bsLevels = new[] { BuyLevel, SellLevel }.Where(sr => sr != null);
                Func <Trade, IEnumerable <double> > levelRate = trade =>
                                                                getDefaultStop(trade)
                                                                .Concat(bsLevels
                                                                        .Where(sr => sr.IsBuy == !trade.IsBuy && (!CanDoEntryOrders || !sr.CanTrade))
                                                                        .Select(t => t.Rate)
                                                                        .Take(1)
                                                                        )
                                                                .Take(1);
                Action <Trade> changeRate = trade => TradesManager.YieldNotNull(levelRate(trade).Any(rate => trade.Stop.Abs(rate) > PointSize))
                                            .ForEach(fw => levelRate(trade).ForEach(rate => SetTradeNetStop(trade, rate)));
                Trades.Take(1).ForEach(changeRate);
            };
            #endregion
            // New Limit
            Action startBuySellCloseLimitTracking = () => {
                _reactiveBuySellLimitLevels = new[] { BuyCloseLevel, SellCloseLevel, BuyLevel, SellLevel }
                .CreateDerivedCollection(sr => sr);
                _reactiveBuySellLimitLevels.ChangeTrackingEnabled = true;
                _reactiveBuySellCloseLimitSubscribtion            = (CompositeDisposable)_reactiveBuySellLimitLevels
                                                                    .ItemChanged
                                                                    .Where(buySellPropsFilter)
                                                                    .Sample(bsThrottleTimeSpan)
                                                                    //.Do(_ => Log = new Exception(new { Name = "startBuySellCloseLevelsTracking", _.PropertyName, Value = _.Value + "" } + ""))
                                                                    .Select(_ => _.Sender.IsBuy ? "Buy(Close)Level" : "Sell(Close)Level")
                                                                    .Merge(this.WhenAny(tm => tm.CurrentPrice, tm => "CurrentPrice").Sample(cpThrottleTimeSpan))
                                                                    .Merge(this.WhenAny(tm => tm.CanDoEntryOrders, tm => "CanDoEntryOrders"))
                                                                    .Merge(this.WhenAny(tm => tm.CanDoNetStopOrders, tm => "CanDoNetStopOrders"))
                                                                    .Merge(this.WhenAny(tm => tm.IsTrader, tm => "IsTrader"))
                                                                    .Subscribe(_ => {
                    if (CanDoNetLimitOrders)
                    {
                        updateTradeLimitOrders();
                    }
                    else
                    {
                        CloseAllNetLimits();
                    }
                });
            };
            // New Stop
            Action startBuySellCloseStopTracking = () => {
                _reactiveBuySellStopLevels = new[] { BuyCloseLevel, SellCloseLevel, BuyLevel, SellLevel }
                .CreateDerivedCollection(sr => sr);
                _reactiveBuySellStopLevels.ChangeTrackingEnabled = true;
                _reactiveBuySellCloseStopSubscribtion            = (CompositeDisposable)_reactiveBuySellStopLevels
                                                                   .ItemChanged
                                                                   .Where(buySellPropsFilter)
                                                                   .Sample(bsThrottleTimeSpan)
                                                                   //.Do(_ => Log = new Exception(new { Name = "startBuySellCloseLevelsTracking", _.PropertyName, Value = _.Value + "" } + ""))
                                                                   .Select(_ => _.Sender.IsBuy ? "Buy(Close)Level" : "Sell(Close)Level")
                                                                   .Merge(this.WhenAny(tm => tm.CurrentPrice, tm => "CurrentPrice").Sample(cpThrottleTimeSpan))
                                                                   .Merge(this.WhenAny(tm => tm.CanDoEntryOrders, tm => "CanDoEntryOrders"))
                                                                   .Merge(this.WhenAny(tm => tm.CanDoNetStopOrders, tm => "CanDoNetStopOrders"))
                                                                   .Merge(this.WhenAny(tm => tm.IsTrader, tm => "IsTrader"))
                                                                   .Subscribe(_ => {
                    if (CanDoNetStopOrders)
                    {
                        updateTradeStopOrders();
                    }
                    else
                    {
                        CloseAllNetStops();
                    }
                });
            };
            #endregion

            #region Init BuySellLevels
            this.WhenAny(tm => tm.Strategy
                         , tm => tm.TrailingDistanceFunction
                         , tm => tm.HasBuyLevel
                         , tm => tm.HasSellLevel
                         , tm => tm.CanDoEntryOrders
                         , tm => tm.CanDoNetLimitOrders
                         , tm => tm.MustStopTrading
                         , (s, t, eo, no, ta, bl, sl) =>
                         Strategy == Strategies.Universal && HasBuyLevel && HasSellLevel && CanDoEntryOrders && !MustStopTrading && !IsInVirtualTrading
                         )
            .DistinctUntilChanged()
            .Sample(bsThrottleTimeSpan)
            .Subscribe(st => { // Turn on/off live entry orders
                try {
                    if (st)    // Subscribe to events in order to update live entry orders
                    //Log = new Exception("startBuySellLevelsTracking");
                    {
                        startBuySellLevelsTracking();
                    }
                    else if (_reactiveBuySellLevelsSubscribtion != null)
                    {
                        try {
                            GetEntryOrders().ToList().ForEach(order => OnDeletingOrder(order.OrderID));
                        } catch (Exception exc) { Log = exc; }
                        CleanReactiveBuySell(ref _reactiveBuySellLevelsSubscribtion, ref _reactiveBuySellLevels);
                    }
                } catch (Exception exc) { Log = exc; }
            });
            #endregion
            #region Init BuySellCloseLevels
            //this.WhenAny(
            //    tm => tm.BuyCloseLevel
            //  , tm => tm.SellCloseLevel
            //  , tm => tm.CanDoNetLimitOrders
            //  , tm => tm.CanDoNetStopOrders
            //  , tm => tm.CanDoEntryOrders
            //  , (b, s, non, nos, eo) =>
            //    BuyCloseLevel != null && SellCloseLevel != null && CanDoNetOrders && !IsInVitualTrading)
            //    .DistinctUntilChanged()
            //    .Sample(bsThrottleTimeSpan)
            //    .Subscribe(st => {// Turn on/off live net orders
            //      try {
            //        CleanReactiveBuySell(ref _reactiveBuySellCloseLevelsSubscribtion, ref _reactiveBuySellCloseLevels);
            //        if (!CanDoNetLimitOrders) CloseAllNetLimits();
            //        if (!CanDoNetStopOrders) CloseAllNetStops();
            //        if (st) {// (Re)Subscribe to events in order to update live net orders
            //          Log = new Exception("startBuySellCloseLevelsTracking");
            //          startBuySellCloseLevelsTracking();
            //        }
            //      } catch (Exception exc) { Log = exc; }
            //    });
            // New Limit
            this.WhenAny(
                tm => tm.HasBuyCloseLevel
                , tm => tm.HasSellCloseLevel
                , tm => tm.CanDoNetLimitOrders
                , (b, s, non) =>
                HasBuyCloseLevel && HasSellCloseLevel && CanDoNetLimitOrders && !IsInVirtualTrading)
            .DistinctUntilChanged()
            .Sample(bsThrottleTimeSpan)
            .Subscribe(st => {// Turn on/off live net orders
                try {
                    CleanReactiveBuySell(ref _reactiveBuySellCloseLimitSubscribtion, ref _reactiveBuySellLimitLevels);
                    if (!CanDoNetLimitOrders)
                    {
                        //Log = new Exception("Stop Limit Tracking");
                        CloseAllNetLimits();
                    }
                    if (st)// (Re)Subscribe to events in order to update live net orders
                    //Log = new Exception("Start Limit Tracking");
                    {
                        startBuySellCloseLimitTracking();
                    }
                } catch (Exception exc) { Log = exc; }
            });
            // Net Stop
            this.WhenAny(
                tm => tm.HasBuyCloseLevel
                , tm => tm.HasSellCloseLevel
                , tm => tm.CanDoNetStopOrders
                , (b, s, non) =>
                HasBuyCloseLevel && HasSellCloseLevel && CanDoNetStopOrders && !IsInVirtualTrading)
            .DistinctUntilChanged()
            .Sample(bsThrottleTimeSpan)
            .Subscribe(st => {// Turn on/off live net orders
                try {
                    CleanReactiveBuySell(ref _reactiveBuySellCloseStopSubscribtion, ref _reactiveBuySellStopLevels);
                    if (!CanDoNetStopOrders)
                    {
                        //Log = new Exception("Stop Stop Tracking");
                        CloseAllNetStops();
                    }
                    if (st)// (Re)Subscribe to events in order to update live net orders
                    //Log = new Exception("Start Stop Tracking");
                    {
                        startBuySellCloseStopTracking();
                    }
                } catch (Exception exc) { Log = exc; }
            });
            #endregion
        }
Example #3
0
 public IEnumerable <TM_HEDGE> HedgeBuySell(bool isBuy) =>
 (TradesManager?.GetAccount()?.Equity *TradingRatio / 2).YieldNotNull(equity => {
 void OrderToNoLossHandler(object sender, OrderEventArgs e)
 {
     TradesManager.DeleteEntryOrderLimit(e.Order.OrderID);
 }
Example #5
0
        private void StrategyEnterUniversal()
        {
            if (!RatesArray.Any() || !IsTrader)
            {
                return;
            }

            #region ============ Local globals ============
            #region Loss/Gross
            Func <double> currentGrossInPips = () => CurrentGrossInPipTotal;
            Func <double> currentLoss        = () => CurrentLoss;
            Func <double> currentGross       = () => CurrentGross;
            Func <bool>   isCurrentGrossOk   = () => CurrentGrossInPips >= -SpreadForCorridorInPips;
            #endregion
            var reverseStrategy          = new ObservableValue <bool>(false);
            Func <SuppRes, bool> isBuyR  = sr => reverseStrategy.Value ? !sr.IsBuy : sr.IsBuy;
            Func <SuppRes, bool> isSellR = sr => reverseStrategy.Value ? !sr.IsSell : sr.IsSell;
            Action resetCloseAndTrim     = () => CloseAtZero = false;
            Func <bool, double> enter    = isBuy => CalculateLastPrice(RateLast, GetTradeEnterBy(isBuy));
            #endregion

            #region ============ Init =================
            bool _useSms = false;
            if (_strategyExecuteOnTradeClose == null)
            {
                Func <SuppRes, IObservable <EventPattern <EventArgs> > > onCanTrade = sr => Observable.FromEventPattern <EventHandler <EventArgs>, EventArgs>(h => h, h => sr.CanTradeChanged += h, h => sr.CanTradeChanged -= h);
                if (IsInVirtualTrading && Trades.Any())
                {
                    throw new Exception("StrategyEnterUniversal: All trades must be closed befor strategy init.");
                }
                if (IsInVirtualTrading)
                {
                    TurnOffSuppRes(RatesArray.Select(r => r.PriceAvg).DefaultIfEmpty().Average());
                }
                Func <bool, Func <Rate, double> > tradeExit = isBuy => MustExitOnReverse ? _priceAvg : GetTradeExitBy(isBuy);
                Action onEOW = () => { };
                #region Exit Funcs
                #region exitOnFriday
                Func <bool> exitOnFriday = () => {
                    if (!SuppRes.Any(sr => sr.InManual))
                    {
                        bool isEOW = IsAutoStrategy && IsEndOfWeek();
                        if (isEOW)
                        {
                            if (Trades.Any())
                            {
                                CloseTrades(Trades.Lots(), "exitOnFriday");
                            }
                            BuyLevel.CanTrade = SellLevel.CanTrade = false;
                            return(true);
                        }
                    }
                    return(false);
                };
                Func <bool?> exitOnCorridorTouch = () => {
                    var mustSell    = false;
                    var mustBuy     = false;
                    var currentBuy  = CalculateLastPrice(_priceAvg);
                    var currentSell = currentBuy;
                    if (currentBuy >= RateLast.PriceAvg2)
                    {
                        mustSell = true;
                    }
                    if (currentSell <= RateLast.PriceAvg3)
                    {
                        mustBuy = true;
                    }
                    if (Trades.HaveBuy() && mustSell || Trades.HaveSell() && mustBuy)
                    {
                        MustExitOnReverse = true;
                    }
                    return(mustBuy ? mustBuy : mustSell?false : (bool?)null);
                };
                #endregion
                #region exitByLimit
                Action exitByLimit = () => {
                    if (!exitOnFriday() && CurrentGross > 0 && TradesManager.MoneyAndLotToPips(OpenTradesGross, Trades.Lots(), Pair) >= CalculateTakeProfitInPips() * ProfitToLossExitRatio)
                    {
                        CloseAtZero = true;
                    }
                };
                #endregion

                //TradesManager.MoneyAndLotToPips(-currentGross(), LotSizeByLossBuy, Pair)
                #region exitVoid
                Action exitVoid = () => { };
                #endregion
                #region exitFunc
                Func <Action> exitFunc = () => {
                    if (!Trades.Any())
                    {
                        return () => { }
                    }
                    ;
                    switch (ExitFunction)
                    {
                    case Store.ExitFunctions.Void:
                        return(exitVoid);

                    case Store.ExitFunctions.Friday:
                        return(() => exitOnFriday());

                    case Store.ExitFunctions.Limit:
                        return(exitByLimit);

                    case Store.ExitFunctions.CorrTouch:
                        return(() => exitOnCorridorTouch());
                    }
                    throw new NotSupportedException(ExitFunction + " exit function is not supported.");
                };
                #endregion
                #endregion
                #region TurnOff Funcs
                Action <double, Action> turnOffIfCorridorInMiddle_ = (sections, a) => {
                    var segment    = RatesHeight / sections;
                    var rest       = (RatesHeight - segment) / 2;
                    var bottom     = _RatesMin + rest;
                    var top        = _RatesMax - rest;
                    var tradeLevel = (BuyLevel.Rate + SellLevel.Rate) / 2;
                    if ((BuyLevel.CanTrade || SellLevel.CanTrade) && IsAutoStrategy && tradeLevel.Between(bottom, top))
                    {
                        a();
                    }
                };
                Action <Action> turnOffByCrossCount = a => { if (BuyLevel.TradesCount.Min(SellLevel.TradesCount) < TradeCountMax)
                                                             {
                                                                 a();
                                                             }
                };
                Action <Action> turnOffByWaveHeight = a => { if (WaveShort.RatesHeight < RatesHeight * .75)
                                                             {
                                                                 a();
                                                             }
                };
                Action <Action> turnOffByWaveShortLeft = a => { if (WaveShort.Rates.Count < WaveShortLeft.Rates.Count)
                                                                {
                                                                    a();
                                                                }
                };
                Action <Action> turnOffByWaveShortAndLeft = a => { if (WaveShortLeft.Rates.Count < CorridorDistanceRatio && WaveShort.Rates.Count < WaveShortLeft.Rates.Count)
                                                                   {
                                                                       a();
                                                                   }
                };
                Action <Action> turnOff = a => {
                    switch (TurnOffFunction)
                    {
                    case Store.TurnOffFunctions.Void:
                        return;

                    case Store.TurnOffFunctions.WaveHeight:
                        turnOffByWaveHeight(a);
                        return;

                    case Store.TurnOffFunctions.WaveShortLeft:
                        turnOffByWaveShortLeft(a);
                        return;

                    case Store.TurnOffFunctions.WaveShortAndLeft:
                        turnOffByWaveShortAndLeft(a);
                        return;

                    case Store.TurnOffFunctions.InMiddle_4:
                        turnOffIfCorridorInMiddle_(4, a);
                        return;

                    case Store.TurnOffFunctions.InMiddle_5:
                        turnOffIfCorridorInMiddle_(5, a);
                        return;

                    case Store.TurnOffFunctions.InMiddle_6:
                        turnOffIfCorridorInMiddle_(6, a);
                        return;

                    case Store.TurnOffFunctions.InMiddle_7:
                        turnOffIfCorridorInMiddle_(7, a);
                        return;

                    case Store.TurnOffFunctions.CrossCount:
                        turnOffByCrossCount(a);
                        return;
                    }
                    throw new NotSupportedException(TurnOffFunction + " Turnoff function is not supported.");
                };
                #endregion
                if (_adjustEnterLevels != null)
                {
                    _adjustEnterLevels.GetInvocationList().Cast <Action>().ForEach(d => _adjustEnterLevels -= d);
                }
                if (BuyLevel != null)
                {
                    BuyLevel.Crossed -= null;
                }
                if (SellLevel != null)
                {
                    SellLevel.Crossed -= null;
                }
                Action <Trade> onCloseTradeLocal = null;
                Action <Trade> onOpenTradeLocal  = null;

                #region Levels
                if (SuppResLevelsCount < 2)
                {
                    SuppResLevelsCount = 2;
                }
                if (SuppRes.Do(sr => sr.IsExitOnly = false).Count() == 0)
                {
                    return;
                }
                ;

                if (!IsInVirtualTrading)
                {
                    var buySellCanTradeObservable = onCanTrade(BuyLevel).Merge(onCanTrade(SellLevel))
                                                    .Select(e => e.Sender as SuppRes)
                                                    .DistinctUntilChanged(sr => sr.CanTrade)
                                                    .Where(sr => _useSms && sr.CanTrade)
                                                    .Subscribe(sr => SendSms(Pair + "::", new { sr.CanTrade }, false));
                }
                if (BuyLevel.Rate.Min(SellLevel.Rate) == 0)
                {
                    BuyLevel.RateEx = SellLevel.RateEx = RatesArray.Middle();
                }
                BuyLevel.CanTrade = SellLevel.CanTrade = false;
                var                        _buySellLevels = new[] { BuyLevel, SellLevel }.ToList();
                Action <Action>            onCorridorCrossesMaximumExeeded = a => _buySellLevels.Where(bs => - bs.TradesCount >= TradeCountMax).Take(1).ForEach(_ => a());
                ObservableValue <double>   ghostLevelOffset                = new ObservableValue <double>(0);
                Action <Action <SuppRes> > _buySellLevelsForEach           = a => _buySellLevels.ForEach(sr => a(sr));
                Action <Func <SuppRes, bool>, Action <SuppRes> > _buySellLevelsForEachWhere = (where, a) => _buySellLevels.Where(where).ToList().ForEach(sr => a(sr));
                _buySellLevelsForEach(sr => sr.ResetPricePosition());
                Action <SuppRes, bool> setCloseLevel = (sr, overWrite) => {
                    if (!overWrite && sr.InManual)
                    {
                        return;
                    }
                    sr.InManual = false;
                    sr.CanTrade = false;
                    if (sr.TradesCount != 9)
                    {
                        sr.TradesCount = 9;
                    }
                };
                Func <SuppRes, SuppRes> suppResNearest = supRes => _suppResesForBulk().Where(sr => sr.IsSupport != supRes.IsSupport).OrderBy(sr => (sr.Rate - supRes.Rate).Abs()).First();
                Action <bool>           setCloseLevels = (overWrite) => setCloseLevel(BuyCloseLevel, overWrite);
                setCloseLevels += (overWrite) => setCloseLevel(SellCloseLevel, overWrite);
                ForEachSuppRes(sr => {
                    if (IsInVirtualTrading)
                    {
                        sr.InManual = false;
                    }
                    sr.ResetPricePosition();
                    sr.ClearCrossedHandlers();
                });
                setCloseLevels(true);
                #region updateTradeCount
                Action <SuppRes, SuppRes> updateTradeCount = (supRes, other) => {
                    if (supRes.TradesCount <= other.TradesCount && new[] { supRes, other }.Any(sr => sr.CanTrade))
                    {
                        other.TradesCount = supRes.TradesCount - 1;
                    }
                };
                Func <SuppRes, SuppRes> updateNeares = supRes => {
                    var other = suppResNearest(supRes);
                    updateTradeCount(supRes, other);
                    return(other);
                };
                #endregion
                Func <bool, bool>    onCanTradeLocal = canTrade => canTrade;
                Func <SuppRes, bool> canTradeLocal   = sr => {
                    var ratio      = CanTradeLocalRatio;
                    var corr       = BuyLevel.Rate.Abs(SellLevel.Rate);
                    var tradeDist  = (sr.IsBuy ? (CurrentPrice.Ask - BuyLevel.Rate) : (SellLevel.Rate - CurrentPrice.Bid));
                    var tradeRange = ((sr.IsBuy ? (CurrentPrice.Ask - SellLevel.Rate) : (BuyLevel.Rate - CurrentPrice.Bid))) / corr;
                    var canTrade   = IsPrimaryMacro && (tradeRange < ratio || tradeDist <= PriceSpreadAverage);
                    //if (!canTrade)
                    //Log = new Exception(canTrade + "");
                    return(onCanTradeLocal(canTrade));
                };
                Func <bool>          isTradingHourLocal = () => IsTradingHour() && IsTradingDay();
                Func <bool>          isLastRateHeightOk = () => RateLast.Yield().All(rl => (rl.AskHigh - rl.BidLow) / RatesHeight < 0.05);
                Func <SuppRes, bool> suppResCanTrade    = (sr) =>
                                                          !CanDoEntryOrders && IsTradingActive &&
                                                          isTradingHourLocal() &&
                                                          sr.CanTrade &&
                                                          sr.TradesCount <= 0 &&
                                                          canTradeLocal(sr) &&
                                                          IsPriceSpreadOk &&
                                                          !IsEndOfWeek();
                Func <bool> isProfitOk = () => Trades.HaveBuy() && RateLast.BidHigh > BuyCloseLevel.Rate ||
                                         Trades.HaveSell() && RateLast.AskLow < SellCloseLevel.Rate;
                #endregion

                #region SuppRes Event Handlers
                Func <bool>          isCrossActive   = () => _buySellLevels.Any(sr => !sr.CanTrade) || BuyLevel.Rate.Abs(SellLevel.Rate) > InPoints(1);
                Func <SuppRes, bool> isCrossDisabled = sr =>
                                                       //!isCrossActive() ||
                                                       !IsTradingActive ||
                                                       !IsPrimaryMacro ||
                                                       (!sr.IsExitOnly && !sr.InManual && !CanOpenTradeByDirection(sr.IsBuy));
                Action <double> onTradesCount = tc => { };
                if (_strategyTradesCountHandler == null)
                {
                    _strategyTradesCountHandler = BuyLevel.WhenAnyValue(x => x.TradesCount).Merge(SellLevel.WhenAnyValue(x => x.TradesCount))
                                                  .Throttle(TimeSpan.FromSeconds(.5))
                                                  .Subscribe(tc => onTradesCount(tc));
                }
                #region enterCrossHandler
                Func <SuppRes, bool> enterCrossHandler = (suppRes) => {
                    if (CanDoEntryOrders || CanDoNetStopOrders || (reverseStrategy.Value && !suppRes.CanTrade) || isCrossDisabled(suppRes) || HaveTrades(suppRes.IsBuy) || isHedgeChild || IsHedgedTrading)
                    {
                        return(false);
                    }
                    if (suppRes.InManual || BuyLevel.Rate > SellLevel.Rate || suppRes.CanTrade)
                    {
                        var isBuy    = isBuyR(suppRes);
                        var lot      = Trades.IsBuy(!isBuy).Lots();
                        var canTrade = suppResCanTrade(suppRes);
                        if (canTrade)
                        {
                            lot += AllowedLotSizeCore(isBuy);
                            suppRes.TradeDate = ServerTime;
                        }
                        //var ghost = SuppRes.SingleOrDefault(sr => sr.IsExitOnly && sr.IsBuy == isBuy && sr.InManual && sr.CanTrade && sr.TradesCount <= 0);
                        //if (ghost != null) {
                        //  var real = _buySellLevels.Single(sr => sr.IsBuy == isBuy);
                        //  if (real.IsBuy && real.Rate < ghost.Rate || real.IsSell && real.Rate > ghost.Rate)
                        //    real.Rate = ghost.Rate;
                        //}
                        OpenTrade(isBuy, lot, "enterCrossHandler:" + new { isBuy, suppRes.IsExitOnly });
                        return(canTrade);
                    }
                    else
                    {
                        return(false);
                    }
                };
                #endregion
                #region exitCrossHandler
                Action <SuppRes> exitCrossHandler = (sr) => {
                    if ((!IsInVirtualTrading && CanDoNetLimitOrders) || isCrossDisabled(sr) || IsHedgedTrading || isHedgeChild || HaveHedgedTrades())
                    {
                        return;
                    }
                    var lot = Trades.Lots();
                    resetCloseAndTrim();
                    if (TradingStatistics.TradingMacros.Distinct(tm => tm.Pair).Count() > 1 && (
                            CurrentGrossInPipTotal > PriceSpreadAverageInPips || CurrentGrossInPipTotal >= _tradingStatistics.GrossToExitInPips)
                        )
                    {
                        CloseTrading(new { exitCrossHandler = "", CurrentGrossInPipTotal, _tradingStatistics.GrossToExitInPips } +"");
                    }
                    else
                    {
                        CloseTrades(lot, "exitCrossHandler:" + new { sr.IsBuy, sr.IsExitOnly, CloseAtZero });
                    }
                };
                #endregion
                #endregion

                #region Crossed Events
                #region Enter Levels
                #region crossedEnter
                EventHandler <SuppRes.CrossedEvetArgs> crossedEnter = (s, e) => {
                    var sr = (SuppRes)s;
                    if (sr.IsBuy && e.Direction == -1 || sr.IsSell && e.Direction == 1)
                    {
                        return;
                    }
                    var srNearest = new Lazy <SuppRes>(() => suppResNearest(sr));
                    updateTradeCount(sr, srNearest.Value);
                    if (enterCrossHandler(sr))
                    {
                        setCloseLevels(true);
                    }
                };
                #endregion
                BuyLevel.Crossed  += crossedEnter;
                SellLevel.Crossed += crossedEnter;
                #endregion
                #region ExitLevels
                Action <SuppRes> handleActiveExitLevel = (srExit) => {
                    updateNeares(srExit);
                    if (enterCrossHandler(srExit))
                    {
                        setCloseLevels(true);
                    }
                };
                EventHandler <SuppRes.CrossedEvetArgs> crossedExit = (s, e) => {
                    var sr = (SuppRes)s;
                    //if (reverseStrategy.Value && Trades.Any(t => t.IsBuy != sr.IsSell)) {
                    //  exitCrossHandler(sr);
                    //  return;
                    //}
                    if (sr.IsBuy && e.Direction == -1 || sr.IsSell && e.Direction == 1)
                    {
                        return;
                    }
                    if (sr.CanTrade)
                    {
                        if (sr.InManual)
                        {
                            handleActiveExitLevel(sr);
                        }
                        else
                        {
                            crossedEnter(s, e);
                        }
                    }
                    else if (Trades.Any(t => t.IsBuy == sr.IsSell))
                    {
                        exitCrossHandler(sr);
                    }
                };
                BuyCloseLevel.Crossed  += crossedExit;
                SellCloseLevel.Crossed += crossedExit;
                #endregion
                #endregion

                #region adjustExitLevels
                Action <double, double> adjustExitLevels = AdjustCloseLevels();
                Action adjustExitLevels0 = () => adjustExitLevels(double.NaN, double.NaN);
                Action adjustExitLevels1 = () => {
                    if (DoAdjustExitLevelByTradeTime)
                    {
                        AdjustExitLevelsByTradeTime(adjustExitLevels);
                    }
                    else
                    {
                        adjustExitLevels(BuyLevel.Rate, SellLevel.Rate);
                    }
                };
                Action adjustExitLevels2 = () => {
                    if (DoAdjustExitLevelByTradeTime)
                    {
                        AdjustExitLevelsByTradeTime(adjustExitLevels);
                    }
                    else
                    {
                        adjustExitLevels0();
                    }
                };
                #endregion

                #region adjustLevels
                var firstTime = true;
                #region Watchers
                var watcherCanTrade = new ObservableValue <bool>(true, true);

                var corridorMovedTrigger = new ValueTrigger <ValueTrigger <bool> >(false)
                {
                    Value = new ValueTrigger <bool>(false)
                };
                var      dateTrigger = new ValueTrigger <DateTime>(false);
                object[] bag         = null;
                #region Workflow tuple factories
                Func <List <object> > emptyWFContext = () => new List <object>();
                Func <List <object>, Tuple <int, List <object> > > tupleNext       = e => Tuple.Create(1, e ?? new List <object>());
                Func <object, Tuple <int, List <object> > >        tupleNextSingle = e => tupleNext(new List <object> {
                    e
                });
                Func <Tuple <int, List <object> > > tupleNextEmpty                 = () => tupleNext(emptyWFContext());
                Func <List <object>, Tuple <int, List <object> > > tupleStay       = e => Tuple.Create(0, e ?? new List <object>());
                Func <object, Tuple <int, List <object> > >        tupleStaySingle = e => tupleStay(new[] { e }.ToList());
                Func <Tuple <int, List <object> > > tupleStayEmpty                 = () => tupleStay(emptyWFContext());
                Func <List <object>, Tuple <int, List <object> > > tuplePrev       = e => Tuple.Create(-1, e ?? new List <object>());
                Func <List <object>, Tuple <int, List <object> > > tupleCancel     = e => Tuple.Create(int.MaxValue / 2, e ?? new List <object>());
                Func <Tuple <int, List <object> > > tupleCancelEmpty               = () => tupleCancel(emptyWFContext());
                Func <IList <object>, Dictionary <string, object> > getWFDict      = l => l.OfType <Dictionary <string, object> >().SingleOrDefault();
                Func <IList <object>, Dictionary <string, object> > addWFDict      = l => { var d = new Dictionary <string, object>(); l.Add(d); return(d); };
                Func <IList <object>, Dictionary <string, object> > getAddWFDict   = l => getWFDict(l) ?? addWFDict(l);
                #endregion
                Func <bool> cancelWorkflow     = () => CloseAtZero;
                var         workflowSubject    = new Subject <IList <Func <List <object>, Tuple <int, List <object> > > > >();
                var         workFlowObservable = workflowSubject
                                                 .Scan(new { i = 0, o = emptyWFContext(), c = cancelWorkflow }, (i, wf) => {
                    if (i.i >= wf.Count || i.c() || i.o.OfType <WF.MustExit>().Any(me => me()))
                    {
                        i.o.OfType <WF.OnExit>().ForEach(a => a());
                        i.o.Clear();
                        i = new { i = 0, o = i.o, i.c };
                    }
                    var o = wf[i.i](i.o);// Side effect
                    o.Item2.OfType <WF.OnLoop>().ToList().ForEach(ol => ol(o.Item2));
                    try {
                        return(new { i = (i.i + o.Item1).Max(0), o = o.Item2, i.c });
                    } finally {
                        if (o.Item1 != 0)
                        {
                            workflowSubject.Repeat(1);
                        }
                    }
                });

                var workflowSubjectDynamic    = new Subject <IList <Func <ExpandoObject, Tuple <int, ExpandoObject> > > >();
                var workFlowObservableDynamic = workflowSubjectDynamic.WFFactory(cancelWorkflow);
                #endregion

                #region Funcs
                Func <Func <Rate, double>, double> getRateLast = (f) => f(RateLast) > 0 ? f(RateLast) : f(RatePrev);
                Func <bool> runOnce = null;
                #endregion

                #region adjustEnterLevels
                Func <Trade, bool> minPLOk         = t => IsAutoStrategy && false ? CurrentGrossInPips == 0 : t.NetPL2 > 0;
                Action <Action>    firstTimeAction = a => {
                    if (firstTime)
                    {
                        Log = new Exception(new { CorrelationMinimum, CorridorDistance } +"");
                        workFlowObservableDynamic.Subscribe();
                        #region onCloseTradeLocal
                        onCanTradeLocal    = canTrade => canTrade || Trades.Any();
                        onCloseTradeLocal += t => {
                            var tpByGross = InPoints(_tradingStatistics.GetNetInPips()).Min(0).Abs() / 3;
                            TakeProfitManual = (t.PL < 0 ? InPoints(t.PL.Abs() * 1.4).Max(TakeProfitManual) : double.NaN).Max(tpByGross);
                            TakeProfitManual = double.NaN;
                            BroadcastCloseAllTrades(this, tm => OnCloseTradeLocal(new[] { t }, tm));
                        };
                        #endregion
                        if (a != null)
                        {
                            a();
                        }
                    }
                };
                Action adjustEnterLevels = () => {
                    if (firstTime)
                    {
                        onOpenTradeLocal += t => { };
                    }
                    switch (TrailingDistanceFunction)
                    {
                        #region SimpleMove
                    case TrailingWaveMethod.SimpleMove: {
                        var conditions = MonoidsCore.ToFunc(() => new { TrailingDistanceFunction });
                        var tci_       = MonoidsCore.ToFunc(() => TradeConditionsInfo((d, p, n) => new { n, v = d(), d }).ToArray());

                        var    toai      = MonoidsCore.ToFunc(() => TradeOpenActionsInfo((d, n) => new { n, d }).ToArray());
                        Action setLevels = () => {
                            if (IsAsleep || IsHedgedTrading || isHedgeChild)
                            {
                                TradingMacrosByPair()
                                .OrderByDescending(tm => tm._RatesMax - tm._RatesMin)
                                .Take(1)
                                .ForEach(tm => {
                                        var offset     = (tm._RatesMax - tm._RatesMin) / 20;
                                        SellLevel.Rate = tm._RatesMax + offset;
                                        BuyLevel.Rate  = tm._RatesMin - offset;
                                    });
                            }
                            else if (!TradeConditionsHaveSetCorridor())
                            {
                                TradeConditionsCanSetCorridor()
                                .Where(td => td.HasAny())
                                .ForEach(_ => SetTradeLevelsToLevelBy(GetTradeLevel)());
                            }
                            if (IsTrader)
                            {
                                adjustExitLevels2();
                            }
                        };
                        #region FirstTime
                        if (firstTime && IsTrader)
                        {
                            WorkflowStep = "";
                            Log          = new Exception(conditions() + "");
                            ResetTakeProfitManual();

                            #region onCloseTradeLocal
                            onCanTradeLocal = canTrade => canTrade || Trades.Any();
                            var canTradeOff = !IsAutoStrategy;
                            #region turnItOff
                            Action <bool, Action> turnItOff = (should, a) => _buySellLevels
                                                              .Where(_ => should)
                                                              .Do(sr => {
                                    //if(!TradeConditionsHave(Tip2Ok))
                                    sr.InManual    = false;
                                    sr.CanTrade    = !IsAutoStrategy;
                                    sr.TradesCount = TradeCountStart;
                                })
                                                              .ToArray()
                                                              .Take(1)
                                                              .Do(_ => {
                                    UnFreezeCorridorStartDate();
                                })
                                                              .Where(_ => a != null)
                                                              .ForEach(_ => a());
                            #endregion
                            var hasTradeCountOff = _buySellLevels.Where(sr => sr.TradesCount < -TradeCountMax);
                            onCloseTradeLocal += t => {
                                //if(!HaveTrades()) {
                                if (_buySellLevels.All(sr => sr.InManual && !sr.CanTrade))
                                {
                                    _buySellLevelsForEach(sr => sr.InManual = false);
                                }
                                if (minPLOk(t) || hasTradeCountOff.Any())
                                {
                                    BuyLevel.InManual = SellLevel.InManual = false;
                                    turnItOff(true, () => {
                                            if (canTradeOff)
                                            {
                                                IsTradingActive = false;
                                            }
                                        });
                                }
                                if (false && CurrentGrossInPipTotal > 0)
                                {
                                    BroadcastCloseAllTrades();
                                }
                                BuyCloseLevel.InManual = SellCloseLevel.InManual = false;
                                CorridorStartDate      = null;
                                //}
                                setLevels();
                            };
                            #endregion

                            Action <Trade> canTradeByTradeCount = t =>
                                                                  hasTradeCountOff
                                                                  .Take(1)
                                                                  .ForEach(_ => {
                                    _buySellLevels
                                    .ForEach(sr => {
                                        sr.CanTrade    = false;
                                        sr.TradesCount = TradeCountStart;
                                    });
                                });
                            onOpenTradeLocal += t => {
                                canTradeByTradeCount(t);
                                toai().ForEach(x => {
                                        Log = new Exception(nameof(TradeOpenAction) + ": " + x.n);
                                        x.d(t);
                                    });
                            };
                        }
                        #endregion
                        setLevels();
                        if (IsTrader)
                        {
                            exitFunc();
                            try {
                                TradeDirectionTriggersRun();
                                TradeConditionsTrigger();
                            } catch (Exception exc) {
                                Log = exc;
                            }
                        }
                    }
                    break;
                        #endregion
                    }
                    if (firstTime)
                    {
                        firstTime = false;
                        ResetBarsCountCalc();
                        ForEachSuppRes(sr => sr.ResetPricePosition());
                        LogTrades = !IsInVirtualTrading;
                    }
                };
                #endregion
                #endregion

                #region On Trade Close
                _strategyExecuteOnTradeClose = t => {
                    if (!Trades.Any() && isCurrentGrossOk())
                    {
                        CorridorStartDate = null;
                        CorridorStopDate  = DateTime.MinValue;
                    }

                    if (onCloseTradeLocal != null)
                    {
                        onCloseTradeLocal(t);
                    }
                    if (TurnOffOnProfit && t.PL >= PriceSpreadAverageInPips)
                    {
                        Strategy = Strategy & ~Strategies.Auto;
                    }
                    CloseAtZero = false;
                };
                #endregion

                #region On Trade Open
                _strategyExecuteOnTradeOpen = trade => {
                    SuppRes.ForEach(sr => sr.ResetPricePosition());
                    onOpenTradeLocal?.Invoke(trade);
                    IsTradingActive = IsTradingActive || IsInVirtualTrading;
                };
                #endregion

                #region _adjustEnterLevels
                Action setLevelPrices = () => {
                    try {
                        if (IsTradingActive)
                        {
                            BuyLevel.SetPrice(enter(true));
                            SellLevel.SetPrice(enter(false));
                            BuyCloseLevel.SetPrice(CurrentExitPrice(true));
                            SellCloseLevel.SetPrice(CurrentExitPrice(false));
                        }
                        else
                        {
                            SuppRes.ForEach(sr => sr.ResetPricePosition());
                        }
                    } catch (Exception exc) { Log = exc; }
                };
                _adjustEnterLevels += setLevelPrices;
                _adjustEnterLevels += adjustEnterLevels;
                _adjustEnterLevels += () => turnOff(() => _buySellLevelsForEach(sr => { if (IsAutoStrategy)
                                                                                        {
                                                                                            sr.CanTradeEx = false;
                                                                                        }
                                                                                }));
                _adjustEnterLevels += () => exitFunc()();
                _adjustEnterLevels += setLevelPrices;
                _adjustEnterLevels += () => { if (runOnce != null && runOnce())
                                              {
                                                  runOnce = null;
                                              }
                };
                #endregion
            }

            #region if (!IsInVitualTrading) {
            if (!IsInVirtualTrading)
            {
                this.TradesManager.TradeClosed += TradeCloseHandler;
                this.TradesManager.TradeAdded  += TradeAddedHandler;
            }
            #endregion

            #endregion

            #region ============ Run =============
            _adjustEnterLevels();
            #endregion
        }
Example #6
0
        void StartReplayInternal(TradingMacro tmOriginal, TestParam testParameter, Action <Task> continueWith)
        {
            if (IsInVirtualTrading)
            {
                while (_replayTasks.ToArray().Any(t => t.Status == TaskStatus.Running))
                {
                    Log = new Exception("Replay is running.");
                    Thread.Sleep(1000);
                    continue;
                }
                _replayTasks.Clear();
                MasterModel.AccountModel.Balance            = MasterModel.AccountModel.Equity = 50000;
                MasterModel.AccountModel.CurrentGrossInPips = 0;
                MasterModel.AccountModel.CurrentLoss        = 0;
                TradesManager.GetAccount().Balance = TradesManager.GetAccount().Equity = 50000;
            }
            SaveTradingSettings(tmOriginal);
            var tms = GetTradingMacros().Where(t => t.IsActive).ToList();

            ReplayArguments.SetTradingMacros(tms);
            ReplayArguments.GetOriginalBalance = new Func <double>(() => MasterModel.AccountModel.OriginalBalance);
            foreach (var tm in tms)
            {
                if (IsInVirtualTrading)
                {
                    if (tm.Strategy == Strategies.None)
                    {
                        tm.Strategy = Strategies.UniversalA;
                    }
                    TradesManager.ClosePair(tm.Pair);
                    tm.ResetSessionId(ReplayArguments.SuperSessionId);
                    if (testParameter != null && tm == tmOriginal)
                    {
                        testParameter.ForEach(tp => {
                            try {
                                tm.LoadSetting(tp);
                            } catch (SetLotSizeException) {
                            } catch (Exception exc) {
                                if (!(exc.InnerException is SetLotSizeException))
                                {
                                    var e2 = new Exception("Property:" + new { tp.Key, tp.Value }, exc);
                                    LogWww(e2);
                                    throw e2;
                                }
                            }
                        });
                    }
                }
                if (!string.IsNullOrWhiteSpace(ReplayArguments.PrevSessionUid))
                {
                    TradingMacro.SessionId = Guid.Parse(ReplayArguments.PrevSessionUid);
                }
                var tmToRun = tm;
                tmToRun.ReplayCancelationToken = (_replayTaskCancellationToken = new CancellationTokenSource()).Token;
                var task = Task.Factory.StartNew(() => tmToRun.Replay(ReplayArguments), tmToRun.ReplayCancelationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);

                task.ContinueWith(t => {
                    RxApp.MainThreadScheduler.Schedule(() => _replayTasks.Remove(t));
                    if (tm == tmOriginal)
                    {
                        continueWith(t);
                    }
                });
                _replayTasks.Add(task);
                ReplayArguments.IsWww = false;
            }
        }
Example #7
0
        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);
        }