//Test on Ticks private void ProcessCandleTicks(Candle candle) { try { _upperChannelOne.Add(candle); _lowerChannelOne.Add(candle); _upperChannelTwo.Add(candle); _lowerChannelTwo.Add(candle); _atr.Add(candle); } catch (Exception ex) { ExceptionMessage(ex, "ProcessCandleTicks"); } }
/// <summary> /// Обработчик появления новых данных /// Вычисляет среднюю за период /// Вычисляет отклонение источника от средней за период /// </summary> ///// <param name="item">Bar</param> //public override void OnEvent(long id) public void Do(long id) { ///вычисляем новые занчения ///Input double iHighest = Indicator.Highest_i(Input.Value.ToList <double>(), Period); //(Input.Value.ToList<double>(), Period, Highest.ToList<double>()); Highest.Add(iHighest); ///вызываем обработчики значений foreach (var handler in HandlersHighest) { handler.Invoke(Highest.Last()); } ///упаковка посчитанных значений ValueHighest.Add(new ValueDouble() { Id = id, //DateTime = item.DateTime, //TODO 4. сейчас отрисовывается по имени MaFast, надо переделать на стороне отрисовки Name = "Highest", Value = iHighest }); ///отправка посчитанных значений foreach (var handler in HandlersValueHighest) { handler.Invoke(ValueHighest.Last()); } }
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"); } }