Esempio n. 1
0
        private void ProcessCandle(Candle candle)
        {
            try
            {
                //Добавляем новую свечку для расчетов в индикаторы
                //Добавляем до проверки актуальности данных, так как возможна предзагрузка исторических данных
                var shortSma = _shortSma.Add(candle.ClosePrice);
                var longSma  = _longSma.Add(candle.ClosePrice);

                //Проверка актуальности данных
                if (!GetRealTimeData())
                {
                    return;
                }

                //Если индикаторы не сформированы, то ничего не делаем
                if (!_shortSma.IsFormed || !_longSma.IsFormed)
                {
                    return;
                }

                //Рассчитываем положение скользящих стредних друг относительно друга
                var stateSma = shortSma - longSma;

                //Текущая позиция по выбранному коннектору и инструменту
                var position = GetTradeInfo().Position;

                //Если короткая SMA больше или равна длинной SMA
                //и предыдущее положение было обратным, то короткая пересекла длинную SMA - Покупаем!
                if (stateSma >= 0 && _lastSma < 0 && position <= 0)
                {
                    var limitOrder = new Order
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Buy,
                        Volume    = position < 0 ? -position : _volume, //Закрываем полностью позицию или открываем новую
                        Price     = candle.ClosePrice
                    };

                    //Подписываемся на событие изменения заявки
                    limitOrder.OrderChanged += order =>
                    {
                        //Текущая позиция по выбранному коннектору и инструменту
                        var pos = GetTradeInfo().Position;

                        //Если заявка исполнилась, то защищаем ее алгоритмической стоп заявкой
                        if (order.State == OrderState.Filled && pos != 0)
                        {
                            var stopOrderId = _algoStopOrders.Create(order, order.Price - _stopOrderOffset, order.Price - _stopOrderOffset - _offset, _isTrailing);
                            MessageToLog($"Algo stop order ID{stopOrderId} - stop price {order.Price - _stopOrderOffset}, order price {order.Price - _stopOrderOffset - _offset}");
                        }

                        //Обрабатываем алгоритмические заявки
                        CheckAlgoOrders(order, pos);
                    };

                    //Создаем защитную алгоритмическую заявку на снятие лимитной заявки по таймеру
                    var cancelOrderId = _algoCancelOrdersByTimer.Create(limitOrder);
                    MessageToLog($"Algo cancel by timer ID{cancelOrderId} - waiting time {_algoCancelOrdersByTimer.Timer.TotalSeconds} sec");

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

                //Если короткая SMA меньше или равна длинной SMA
                //и предыдущее положение было обратным, то длинная пересекла короткую SMA - Продаем!
                if (stateSma <= 0 && _lastSma > 0 && position >= 0)
                {
                    var limitOrder = new Order()
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Sell,
                        Volume    = position < 0 ? -position : _volume,
                        Price     = candle.ClosePrice
                    };

                    //Подписываемся на событие изменения заявки
                    limitOrder.OrderChanged += order =>
                    {
                        //Текущая позиция по выбранному коннектору и инструменту
                        var pos = GetTradeInfo().Position;

                        //Если заявка исполнилась, то защищаем ее алгоритмической стоп заявкой
                        if (order.State == OrderState.Filled && pos != 0)
                        {
                            var stopOrderId = _algoStopOrders.Create(order, order.Price + _stopOrderOffset, order.Price + _stopOrderOffset + _offset, _isTrailing);
                            MessageToLog($"Algo stop order ID{stopOrderId} - stop price {order.Price + _stopOrderOffset}, order price {order.Price + _stopOrderOffset + _offset}");
                        }

                        //Обрабатываем алгоритмические заявки
                        CheckAlgoOrders(order, pos);
                    };

                    //Создаем защитную алгоритмическую заявку на снятие лимитной заявки по таймеру
                    var cancelOrderId = _algoCancelOrdersByTimer.Create(limitOrder);
                    MessageToLog($"Algo cancel by timer ID{cancelOrderId} - waiting time {_algoCancelOrdersByTimer.Timer.TotalSeconds} sec");

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

                //Запоминаем текущее положение SMA относительно друг друга
                _lastSma = stateSma;
            }
            catch (Exception ex)
            {
                ExceptionMessage(ex, "ProcessCandle");
            }
        }
Esempio n. 2
0
        public void ProcessCandle(Candle candle)
        {
            try
            {
                //Добавляем новую свечку для расчетов в индикаторы
                //Добавляем до проверки актуальности данных, так как возможна предзагрузка исторических данных
                var upperChannelOne = _upperChannelOne.Add(candle);
                var lowerChannelOne = _lowerChannelOne.Add(candle);
                var upperChannelTwo = _upperChannelTwo.Add(candle);
                var lowerChannelTwo = _lowerChannelTwo.Add(candle);
                var adxLookBack     = _adxLookBack.Add(candle);
                var adxThreshold    = _adxThreshold.Add(candle);
                var atr             = _atr.Add(candle);

                //Проверка актуальности данных
                if (!GetRealTimeData())
                {
                    return;
                }

                //Если индикаторы еще не сформировались, то ждем пока сформируются
                if (!_upperChannelOne.IsFormed || !_lowerChannelOne.IsFormed || !_upperChannelTwo.IsFormed || !_lowerChannelTwo.IsFormed ||
                    !_adxLookBack.IsFormed || !_adxThreshold.IsFormed || !_atr.IsFormed)
                {
                    return;
                }

                //Фильтр. Торгуем только если ADX_Look_Back > ADX_Threshold.
                if (adxLookBack <= adxThreshold)
                {
                    return;
                }

                //Текущая позиция по выбранному коннектору и инструменту
                var position = GetTradeInfo().Position;

                //Берем цену последней сделки как цену для заявки
                var price = HistoricalDataType == HistoricalDataType.Candles ? GetLastCandle().ClosePrice : GetLastTick().Price;

                //Входим в позицию. Покупаем, когда цена касается канала UpperChannelOne.
                if (candle.HighPrice >= upperChannelOne && position == 0)
                {
                    var order = new Order
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Buy,
                        Volume    = _volume,
                        Price     = price + _offset
                    };

                    //Подписываемся на событие изменения заявки
                    order.OrderChanged += newOrder =>
                    {
                        //Текущая позиция по выбранному коннектору и инструменту
                        var pos = GetTradeInfo().Position;

                        //Если заявка исполнилась и мы вошли в позицию, то защищаем ее алгоритмической стоп заявкой
                        if (newOrder.State == OrderState.Filled && pos != 0)
                        {
                            var stopPrice   = newOrder.Price - atr * _atrStop;
                            var stopOrderId = _algoStopOrders.Create(order, stopPrice, stopPrice - _offset, false);
                            MessageToLog($"Created algorithmic stop order ID{stopOrderId} - stop price {stopPrice}, order price {stopPrice - _offset}");
                        }
                    };

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

                //Входим в позицию. Продаем, когда цена касается канала LowerChannelOne.
                else if (candle.LowPrice <= lowerChannelOne && position == 0)
                {
                    var order = new Order
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Sell,
                        Volume    = _volume,
                        Price     = price - _offset
                    };

                    //Подписываемся на событие изменения заявки
                    order.OrderChanged += newOrder =>
                    {
                        //Текущая позиция по выбранному коннектору и инструменту
                        var pos = GetTradeInfo().Position;

                        //Если заявка исполнилась и мы вошли в позицию, то защищаем ее Стоп-лимит заявкой
                        if (newOrder.State == OrderState.Filled && pos != 0)
                        {
                            var stopPrice   = newOrder.Price + atr * _atrStop;
                            var stopOrderId = _algoStopOrders.Create(order, stopPrice, stopPrice + _offset, false);
                            MessageToLog($"Create algorithmic stop order ID{stopOrderId} - stop price {stopPrice}, order price {stopPrice + _offset}");
                        }
                    };

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

                //Закрываем позиции. Продаем, когда цена касается канала LowerChannelTwo.
                else if (candle.LowPrice <= lowerChannelTwo && position > 0)
                {
                    var limitOrder = new Order
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Sell,
                        Volume    = Math.Abs(position),
                        Price     = price - _offset
                    };

                    //Снимаем все лимитные заявки
                    CancelOrders();
                    //Снимаем все алгоритмические стоп заявки
                    _algoStopOrders.CancelAllOrders();

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

                //Закрываем позиции. Покупаем, когда цена касается канала UpperChannelTwo.
                else if (candle.HighPrice >= upperChannelTwo && position < 0)
                {
                    var limitOrder = new Order
                    {
                        Type      = OrderType.Limit,
                        Direction = Direction.Buy,
                        Volume    = Math.Abs(position),
                        Price     = price + _offset
                    };

                    //Снимаем все лимитные заявки
                    CancelOrders();
                    //Снимаем все алгоритмические стоп заявки
                    _algoStopOrders.CancelAllOrders();

                    //Отправляем лимитную заявку на регистрацию
                    RegisterOrder(limitOrder);
                }
            }
            catch (Exception ex)
            {
                ExceptionMessage(ex, "ProcessCandle");
            }
        }