예제 #1
0
        private void AssignLeaveRulesAndStart()
        {
            if (_leaveStrategy == null)
            {
                throw new NullReferenceException("leaveStrategy");
            }

            _leaveStrategy.WhenNewMyTrade()
            .Do(mt =>
            {
                var sign = 1;

                if (_leaveStrategy.QuotingSide == Sides.Sell)
                {
                    sign = -1;
                }

                PositionAndMoneySyncIncrementation(mt.Trade.Volume * sign, mt.Trade.Volume * mt.Trade.Price * sign * -1);

                _enterStrategy.SafeStop();
            })
            .Until(() => !_isLeaverActivated)
            .Apply(this);

            _leaveStrategy.PrimaryStrategyStopped += () =>
            {
                ChildStrategies.Remove(_leaveStrategy);

                _isLeaverActivated = false;
            };

            MarkStrategyLikeChild(_leaveStrategy);
            ChildStrategies.Add(_leaveStrategy);
        }
예제 #2
0
        private void OnChildStrategiesAdded(Strategy strategy)
        {
            var rule = strategy
                       .WhenStopped()
                       .Do(s =>
            {
                if (FinishMode == BasketStrategyFinishModes.First)
                {
                    if (FirstFinishStrategy == null)
                    {
                        FirstFinishStrategy = s;
                        Stop();
                    }
                }
                else
                {
                    if (ChildStrategies.All(child => child.ProcessState != ProcessStates.Started))
                    {
                        Stop();
                    }
                }
            })
                       .Once()
                       .Apply(this);

            rule.UpdateName(rule.Name + " (BasketStrategy.OnChildStrategiesAdded)");
        }
예제 #3
0
        private void OnNewOrderTrades(IEnumerable <MyTrade> trades)
        {
            // для каждой сделки добавляем защитную пару стратегии

            /*
             * var protectiveStrategies = trades.Select(t =>
             * {
             *      // выставляет стоп-лосс в deflevel пунктов
             *      var stopLoss = new StopLossStrategy(t, deflevel);
             *      stopLoss.IsTrailing = true;
             *      return stopLoss;
             * });
             *
             * //ChildStrategies.AddRange(protectiveStrategies);
             * foreach (var st in protectiveStrategies)
             *      ChildStrategies.Add(st);
             * */

            StopLossStrategy stopLoss = new StopLossStrategy(trades.ToArray <MyTrade>()[0], 40);

            stopLoss.IsTrailing = true;
            stopLoss.WhenError().Do(() => { this.AddInfoLog("ololo"); });
            stopLoss.WhenNewMyTrades().Do(() => { this.AddInfoLog("ololo111"); });
            ChildStrategies.Add(stopLoss);
        }
예제 #4
0
            public EquityStrategy(IEnumerable <Order> orders, IDictionary <Security, decimal> openedPositions)
            {
                _orders = orders.GroupBy(o => o.Time).ToDictionary(g => g.Key, g => g.ToArray());

                _childStrategies = orders.ToDictionary(GetKey, o => new Strategy
                {
                    Portfolio = o.Portfolio,
                    Security  = o.Security,
                    Position  = openedPositions.TryGetValue2(o.Security) ?? 0,
                });

                ChildStrategies.AddRange(_childStrategies.Values);
            }
예제 #5
0
        protected override void OnStarted()
        {
            DoStrategyPreparation(new Security[] { Security }, new Security[] { Security }, new Portfolio[] { Portfolio });

            if (_spread <= 0)
            {
                throw new ArgumentException("Spread cannot be below zero: " + _spread);
            }
            if (_lot <= 0)
            {
                throw new ArgumentException("Lot cannot be below zero: " + _lot);
            }
            if (Security.PriceStep == null)
            {
                throw new ArgumentException("Cannot read security price set, probably data still loading... :" + Security.PriceStep);
            }
            if (LimitedFuturesValueAbs < 0)
            {
                throw new ArgumentException("limitation of futures positions is established by value >=0 : " + LimitedFuturesValueAbs);
            }

            if (_sideForEnterToPosition == Sides.Sell)
            {
                LimitedFuturesValueAbs = LimitedFuturesValueAbs != 0 ? LimitedFuturesValueAbs * -1 : decimal.MinValue;
            }
            else
            {
                LimitedFuturesValueAbs = LimitedFuturesValueAbs != 0 ? LimitedFuturesValueAbs : decimal.MaxValue;
            }

            md = GetMarketDepth(Security);
            TimingController.SetTimingMethod(SpreadingProcess);

            Security.WhenMarketDepthChanged(Connector)
            .Do(() =>
            {
                TimingController.TimingMethodHappened();
                SpreadingProcess();
            })
            .Apply(this);

            this.WhenStopping()
            .Do(() =>
            {
                ChildStrategies.Clear();
            })
            .Once()
            .Apply(this);

            base.OnStarted();
        }
예제 #6
0
        public virtual void PrimaryStopping()
        {
            TimingController.StopTimingControl();

            var totalChildCount = ChildStrategies.Count;

            try
            {
                if (ChildStrategies?.Count > 0)
                {
                    ChildStrategies.ForEach(ps =>
                    {
                        Task.Run(() =>
                        {
                            var curStrategy = ps as PrimaryStrategy;

                            if (curStrategy == null)
                            {
                                return;
                            }

                            curStrategy.PrimaryStrategyStopped += () => _closedChildCounter++;

                            curStrategy.CancelActiveOrders();//TODO ещё одна попытка решить проблему залипающих ордеров в терминале после остановки стратегии

                            curStrategy.PrimaryStopping();
                        });
                    });
                }

                while (totalChildCount != _closedChildCounter)
                {
                    /*NOP*/
                }

                Stop();
                _closedChildCounter = 0;
            }
            catch (Exception e1)
            {
                this.AddErrorLog(e1);
            }
        }
예제 #7
0
        private void ProcessCandle(Candle candle)
        {
            // если наша стратегия в процессе остановки
            if (ProcessState == ProcessStates.Stopping)
            {
                // отменяем активные заявки
                CancelActiveOrders();
                return;
            }

            // добавляем новую свечу
            LongSma.Process(candle);
            ShortSma.Process(candle);

            // вычисляем новое положение относительно друг друга
            var isShortLessThenLong = ShortSma.GetCurrentValue() < LongSma.GetCurrentValue();

            // если произошло пересечение
            if (_isShortLessThenLong != isShortLessThenLong)
            {
                // если короткая меньше чем длинная, то продажа, иначе, покупка.
                var direction = isShortLessThenLong ? Sides.Sell : Sides.Buy;

                // вычисляем размер для открытия или переворота позы
                var volume = Position == 0 ? Volume : Position.Abs() * 2;

                // регистрируем заявку (обычным способом - лимитированной заявкой)
                //RegisterOrder(this.CreateOrder(direction, (decimal)Security.GetCurrentPrice(direction), volume));

                // переворачиваем позицию через котирование
                var strategy = new MarketQuotingStrategy(direction, volume);
                ChildStrategies.Add(strategy);

                // запоминаем текущее положение относительно друг друга
                _isShortLessThenLong = isShortLessThenLong;
            }
        }
        private void DoHedge(decimal currentDelta, decimal deltaStep)
        {
            QuoterStrategy mqs = null;

            var hedgeSize = (currentDelta / deltaStep).PrepareSizeToTrade();

            if (currentDelta > 0)
            {
                hedgeSize = hedgeSize.ShrinkSizeToTrade(Sides.Sell, _futuresPosition,
                                                        MinFuturesPositionVal);

                if (hedgeSize <= 0)
                {
                    return;
                }

                mqs = new MarketQuoterStrategy(Sides.Sell, hedgeSize, Security.GetMarketPrice(Sides.Sell));
                _futuresPosition -= hedgeSize;
            }

            if (currentDelta < 0)
            {
                hedgeSize = hedgeSize.ShrinkSizeToTrade(Sides.Buy, _futuresPosition,
                                                        MaxFuturesPositionVal);

                if (hedgeSize <= 0)
                {
                    return;
                }

                mqs = new MarketQuoterStrategy(Sides.Buy, hedgeSize, Security.GetMarketPrice(Sides.Buy));
                _futuresPosition += hedgeSize;
            }

            MarkStrategyLikeChild(mqs);
            ChildStrategies.Add(mqs);
        }
예제 #9
0
        private void ProcessCandle(Candle candle)
        {
            // если наша стратегия в процессе остановки
            if (ProcessState == ProcessStates.Stopping)
            {
                // отменяем активные заявки
                CancelActiveOrders();
                return;
            }

            this.AddInfoLog(LocalizedStrings.Str2177Params.Put(candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume));

            // добавляем новую свечу
            var longValue  = LongATR.Process(candle);
            var shortValue = ShortATR.Process(candle);

            if (Position < 0)
            {
                if (maxPrice > candle.ClosePrice)
                {
                    maxPrice = candle.ClosePrice;
                }
            }
            // вычисляем новое положение относительно друг друга
            // var isShortLessThenLong = ShortSma.GetCurrentValue() < LongSma.GetCurrentValue();
            if (-maxPrice + candle.ClosePrice > protectLevel && needProtect)
            {
                var price = Security.GetMarketPrice(Connector, Sides.Buy);

                // регистрируем псевдо-маркетную заявку - лимитная заявка с ценой гарантирующей немедленное исполнение.
                if (price != null)
                {
                    RegisterOrder(this.CreateOrder(Sides.Buy, price.Value, Volume));
                    needProtect = false;
                }
            }
            // если индикаторы заполнились
            if (LongATR.Container.Count >= LongATR.Length)
            {
                if (LongATR.GetCurrentValue <int>() > ShortATR.GetCurrentValue <int>() && Position == 0)
                {
                    // если короткая меньше чем длинная, то продажа, иначе, покупка.
                    var direction = Sides.Sell;

                    // вычисляем размер для открытия или переворота позы
                    var volume = Volume;

                    if (!SafeGetConnector().RegisteredMarketDepths.Contains(Security))
                    {
                        var price = Security.GetMarketPrice(Connector, direction);

                        // регистрируем псевдо-маркетную заявку - лимитная заявка с ценой гарантирующей немедленное исполнение.
                        if (price != null)
                        {
                            RegisterOrder(this.CreateOrder(direction, price.Value, volume));
                            needProtect  = true;
                            protectLevel = LongATR.GetCurrentValue <int>() * 3;
                        }
                    }
                    else
                    {
                        // переворачиваем позицию через котирование
                        var strategy = new MarketQuotingStrategy(direction, volume)
                        {
                            WaitAllTrades = true,
                        };
                        ChildStrategies.Add(strategy);
                    }
                }
            }


            _myTrades.Clear();

            var dict = new Dictionary <IChartElement, object>
            {
                { _candlesElem, candle },
            };

            _chart.Draw(candle.OpenTime, dict);
        }
예제 #10
0
        private void ProcessCandle(Candle candle)
        {
            // если наша стратегия в процессе остановки
            if (ProcessState == ProcessStates.Stopping)
            {
                // отменяем активные заявки
                CancelActiveOrders();
                return;
            }

            this.AddInfoLog(LocalizedStrings.Str2177Params.Put(candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume));

            // добавляем новую свечу
            var longValue  = LongSma.Process(candle);
            var shortValue = ShortSma.Process(candle);

            // вычисляем новое положение относительно друг друга
            var isShortLessThenLong = ShortSma.GetCurrentValue() < LongSma.GetCurrentValue();

            // если произошло пересечение
            if (_isShortLessThenLong != isShortLessThenLong)
            {
                // если короткая меньше чем длинная, то продажа, иначе, покупка.
                var direction = isShortLessThenLong ? Sides.Sell : Sides.Buy;

                // вычисляем размер для открытия или переворота позы
                var volume = Position == 0 ? Volume : Position.Abs().Min(Volume) * 2;

                if (!SafeGetConnector().RegisteredMarketDepths.Contains(Security))
                {
                    var price = Security.GetMarketPrice(Connector, direction);

                    // регистрируем псевдо-маркетную заявку - лимитная заявка с ценой гарантирующей немедленное исполнение.
                    if (price != null)
                    {
                        RegisterOrder(this.CreateOrder(direction, price.Value, volume));
                    }
                }
                else
                {
                    // переворачиваем позицию через котирование
                    var strategy = new MarketQuotingStrategy(direction, volume)
                    {
                        WaitAllTrades = true,
                    };
                    ChildStrategies.Add(strategy);
                }

                // запоминаем текущее положение относительно друг друга
                _isShortLessThenLong = isShortLessThenLong;
            }

            var trade = _myTrades.FirstOrDefault();

            _myTrades.Clear();

            var dict = new Dictionary <IChartElement, object>
            {
                { _candlesElem, candle },
                { _shortElem, shortValue },
                { _longElem, longValue },
                { _tradesElem, trade }
            };

            _chart.Draw(candle.OpenTime, dict);
        }
예제 #11
0
        protected override void OnStarted()
        {
            if (SecurityWithSignalToClose == null)
            {
                DoStrategyPreparation(new Security[] { }, new Security[] { Security }, new Portfolio[] { Portfolio });
            }
            else
            {
                DoStrategyPreparation(new Security[] { }, new Security[] { Security, SecurityWithSignalToClose }, new Portfolio[] { Portfolio });
            }


            if (Volume <= 0 || _priceToClose <= 0)
            {
                throw new ArgumentException(
                          $"Volume: {Volume} or price to close: {_priceToClose} cannot be below zero");
            }
            ;

            this.WhenPositionChanged()
            .Do(() =>
            {
                if (Math.Abs(Position) >= Volume)
                {
                    PrimaryStopping();
                }
            })
            .Apply(this);

            //не проверяем время, т.к. правило выполняется Once()
            TimingController.SetTimingUnnecessary();

            if (SecurityWithSignalToClose == null)
            {
                var md = GetMarketDepth(Security);

                Security.WhenMarketDepthChanged(Connector)
                .Do(() =>
                {
                    var mqs = new MarketQuoterStrategy(_strategyOrderSide, Volume, _priceToClose);

                    mqs.WhenStopped()
                    .Do(this.Stop)
                    .Once()
                    .Apply(this);

                    MarkStrategyLikeChild(mqs);
                    ChildStrategies.Add(mqs);
                })
                .Once()
                .Apply(this);
            }
            else
            {
                PrimaryStrategy mqs = null;

                var md = GetMarketDepth(SecurityWithSignalToClose);

                var mqsStartRule = SecurityWithSignalToClose
                                   .WhenMarketDepthChanged(Connector)
                                   .Do(() =>
                {
                    if (!IsTradingTime())
                    {
                        return;
                    }

                    //котировки специально развернуты неверно - как только была сделка на графике (ударили в аск или налили в бид) - закрываемся
                    if (_securityDesirableDirection == PriceDirection.Up && md.BestAsk.Price >= _priceToClose ||
                        _securityDesirableDirection == PriceDirection.Down && md.BestBid.Price <= _priceToClose)
                    {
                        // пока делаем по любой цене, как только сработает условие
                        mqs = new MarketQuoterStrategy(_strategyOrderSide, Volume, Security.GetMarketPrice(_strategyOrderSide));

                        mqs.WhenStopped()
                        .Do(this.Stop)
                        .Once()
                        .Apply(this);

                        MarkStrategyLikeChild(mqs);
                        ChildStrategies.Add(mqs);
                    }
                })
                                   .Until(() => mqs != null)
                                   .Apply(this);

                this.WhenStopping()
                .Do(() => { /*NOP*/ })
                .Apply(this)
                .Exclusive(mqsStartRule);
            }

            base.OnStarted();
        }
예제 #12
0
        private void AssignEnterRulesAndStart()
        {
            if (_enterStrategy == null)
            {
                throw new NullReferenceException("strategy, when was trying to assign enter rules");
            }

            Security.WhenMarketDepthChanged(Connector)
            .Do(md =>
            {
                if (_lastQuoterPrice == 0)
                {
                    return;
                }

                if (md.BestBid == null || md.BestAsk == null)
                {
                    return;
                }

                var bestQuote = md.GetSuitableBestLimitQuote(_enterStrategy.QuotingSide);

                if (_enterStrategy.QuotePriceShift != 0)
                {
                    if (_lastQuoterPrice != bestQuote.Price ||
                        md.BestPair.SpreadPrice != null && md.BestPair.SpreadPrice.Value <= _spread)
                    {
                        _lastQuoterPrice = 0;

                        _enterStrategy.SafeStop();
                    }
                }

                if (_enterStrategy.QuotePriceShift == 0 && CheckIfSpreadChangedOrItsParts(md.BestPair))
                {
                    _enterStrategy.SafeStop();
                }
            })
            .Until(() => !_isEnterActivated)
            .Apply(this);

            _enterStrategy.WhenOrderRegistered()
            .Do(o =>
            {
                _lastQuoterPrice = o.Price;
            })
            .Until(() => !_isEnterActivated)
            .Apply(this);

            _enterStrategy.WhenNewMyTrade()
            .Do(mt =>
            {
                var sign = 1;

                if (_enterStrategy.QuotingSide == Sides.Sell)
                {
                    sign = -1;
                }

                PositionAndMoneySyncIncrementation(mt.Trade.Volume * sign, mt.Trade.Volume * mt.Trade.Price * sign * -1);

                _leaveStrategy.SafeStop();
            })
            .Until(() => !_isEnterActivated)
            .Apply(this);

            _enterStrategy.PrimaryStrategyStopped += () =>
            {
                ChildStrategies.Remove(_enterStrategy);

                _isEnterActivated = false;
            };


            MarkStrategyLikeChild(_enterStrategy);
            ChildStrategies.Add(_enterStrategy);
        }
예제 #13
0
        protected void ProcessFinCandle(Candle candle)
        {
            if (ProcessState == ProcessStates.Stopping)
            {
                // отменяем активные заявки
                CancelActiveOrders();
                return;
            }

            //this.AddInfoLog("Новая свеча {0}: {1};{2};{3};{4}; объем {5}".Put(candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume));

            // добавляем новую свечку
            LongATR.Process(candle);
            ShortATR.Process(candle);
            PLB.Process(candle);
            int tt = PLB.GetCurrentValue <int>();

            if ((double)candle.ClosePrice < buyprice - deflevel && buyprice > 0)
            {
            }
            //+! костыльная проверка что индикатор заполнен.
            // нужно всегда заполнять перед торговлей
            if (LongATR.Container.Count >= LongATR.Length)
            {
                if (LongATR.GetCurrentValue <int>() > ShortATR.GetCurrentValue <int>() && this.Position == 0)
                {
                    var direction = OrderDirections.Buy;
                    buyprice = (double)candle.ClosePrice;
                    //спизжено из стоп лос стретеджи
                    //var longPos = this.BuyAtMarket();

                    //// регистрируем правило, отслеживающее появление новых сделок по заявке
                    //longPos
                    //    .WhenNewTrades()
                    //    .Do(OnNewOrderTrades)
                    //    .Apply(this);

                    //// отправляем заявку на регистрацию
                    //RegisterOrder(longPos);

                    double dl = 2.5 * ShortATR.GetCurrentValue <int>();
                    deflevel = (int)(dl + 0.5);
                    Order longPos;
                    if (!((EmulationTrader)Trader).MarketEmulator.Settings.UseMarketDepth)
                    {
                        // регистрируем псевдо-маркетную заявку - лимитная заявка с ценой гарантирующей немедленное исполнение.
                        longPos = this.CreateOrder(direction, Security.GetMarketPrice(direction), Volume);
                        RegisterOrder(longPos);
                    }
                    else
                    {
                        // переворачиваем позицию через котирование
                        var strategy = new MarketQuotingStrategy(direction, Volume)
                        {
                            WaitAllTrades = true,
                        };
                        ChildStrategies.Add(strategy);
                    }

                    // если произошло пересечение
                    //if (_isShortLessThenLong != isShortLessThenLong)
                    //{
                    //     если короткая меньше чем длинная, то продажа, иначе, покупка.
                    //    var direction = isShortLessThenLong ? OrderDirections.Sell : OrderDirections.Buy;

                    //    if (!((EmulationTrader)Trader).MarketEmulator.Settings.UseMarketDepth)
                    //    {
                    //         регистрируем псевдо-маркетную заявку - лимитная заявка с ценой гарантирующей немедленное исполнение.
                    //        RegisterOrder(this.CreateOrder(direction, Security.GetMarketPrice(direction), Volume));
                    //    }
                    //    else
                    //    {
                    //         переворачиваем позицию через котирование
                    //        var strategy = new MarketQuotingStrategy(direction, Volume)
                    //        {
                    //            WaitAllTrades = true,
                    //        };
                    //        ChildStrategies.Add(strategy);
                    //    }

                    //     запоминаем текущее положение относительно друг друга
                    //    _isShortLessThenLong = isShortLessThenLong;
                    //}

                    //+! щас будет костыльный параметр 2.5 на ATR  в стопах
                }
            }
        }