Exemple #1
0
        public override List <string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            if (/*formulaResolver == null || */ packer == null)
            {
                return(null);
            }
            curTime = quotes[0].timeClose;

            // обновить табличку цен
            for (var i = 0; i < names.Length; i++)
            {
                if (lastBids.ContainsKey(names[i]))
                {
                    lastBids[names[i]] = quotes[i].close;
                }
                else
                {
                    lastBids.Add(names[i], quotes[i].close);
                }
            }

            CandleDataBidAsk curQuote = null;

            for (var i = 0; i < names.Length; i++)
            {
                if (names[i] == ticker)
                {
                    curQuote = quotes[i];
                    break;
                }
            }

            // нет торгуемой котировки?
            if (curQuote == null)
            {
                return(null);
            }

            // обновить свечки
            var candle = packer.UpdateCandle(curQuote);

            if (candle == null)
            {
                return(null);
            }

            // закрылась полная свеча, проводим вычисления
            candles.Add(candle);

            // обновить очереди (для индекса, переменные вида usdjpy#15)
            if (lastBidLists.Count > 0)
            {
                foreach (var listTicker in lastBidLists)
                {
                    double price;
                    if (!lastBids.TryGetValue(listTicker.Key, out price))
                    {
                        price = 0;
                    }
                    listTicker.Value.Add(price);
                }
            }

            // посчитать индексы
            foreach (var ind in IndexList)
            {
                ind.CalculateValue(tickerNames, candles, lastBidLists, /*curTime*/ candle.timeOpen, randomGener);
            }

            // если это период "разгона" конвейера
            if (isHistoryStartOff)
            {
                return(null);
            }

            // если "наращиваем" вход - ищем последнюю сделку и входим в ее направлении,
            // если закрытие "лучше"
            List <MarketOrder> orders;

            GetMarketOrders(out orders, true);
            var hints = new List <string>();
            // следует "нарастить" объем
            var shouldEnterByChain = false;
            var lastOrderSide      = 0;

            if (EnterChain == EnterChainCondition.НаЗакрытииЛучше &&
                orders.Count > 0 && orders.Count < CountTrades)
            {
                var lastOrder = orders[orders.IndexOfMin(o => - o.TimeEnter.Ticks)];
                lastOrderSide      = lastOrder.Side;
                shouldEnterByChain = lastOrderSide > 0
                                      ? (candle.close < lastOrder.PriceEnter)
                                      : (candle.close > lastOrder.PriceEnter);
            }

            // получить торговый сигнал
            string comment, expertComment;
            var    dealSign = GetSignalSide(hints, curQuote.GetCloseQuote(), out comment, out expertComment);

            // сигнала нет
            if (dealSign == 0)
            {
                // ... но есть условие - "нарастить объем"
                if (shouldEnterByChain)
                {
                    MakeOrder("", "повторный вход", lastOrderSide, curQuote.GetCloseQuote(), hints);
                }
                return(hints);
            }

            // от одной проекции не может быть открыто более 1 ордера
            // описание проекции сохраняем в спец. коменте
            // закрыть противонаправленные сделки
            var hasSameOrder    = false;
            var hasSameDealType = false;

            foreach (var oldOrder in orders)
            {
                if (oldOrder.Side == dealSign)
                {
                    hasSameDealType = true;
                }
                if (oldOrder.Side == dealSign &&
                    oldOrder.ExpertComment == expertComment)
                {
                    hasSameOrder = true;
                    continue;
                }

                // закрыть ордер другого знака
                if (oldOrder.Side == dealSign)
                {
                    continue;
                }
                var rst = CloseMarketOrder(oldOrder.ID);
                if (rst != RequestStatus.OK)
                {
                    hints.Add("Невозможно закрыть противоположный ордер " + oldOrder.ID);
                }
            }

            if (EnterChain == EnterChainCondition.НаНовойПроекции)
            {
                if (hasSameOrder)
                {
                    return(hints);
                }
                MakeOrder(expertComment, comment, dealSign, curQuote.GetCloseQuote(), hints);
                return(hints);
            }

            if (EnterChain == EnterChainCondition.НаЗакрытииЛучше)
            {
                if (shouldEnterByChain || !hasSameDealType)
                {
                    MakeOrder(expertComment, comment, dealSign, curQuote.GetCloseQuote(), hints);
                }
                return(hints);
            }

            return(hints);
        }
        public override List <string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            CandleDataBidAsk quote = null;

            for (var i = 0; i < names.Length; i++)
            {
                if (names[i] == ticker)
                {
                    quote = quotes[i];
                    break;
                }
            }
            var events = new List <string>();

            if (quote == null)
            {
                return(events);
            }
            // сопроводить сделки, коли треба...

            var candle = packer.UpdateCandle(quote);

            if (candle == null)
            {
                return(events);
            }
            candles.Add(candle);

            // получить уровни ЗигЗага
            var pivots = ZigZag.GetPivots(candles, ZigZagPeriodPercent, ZigZagSourceType);

            if (pivots.Count < 3)
            {
                return(events);
            }
            // проверить последнюю вершину ЗЗ - отстоит ли она от предпоследней на ZigZagPeriodPercent
            //var lastValid = Math.Abs(100*(pivots[pivots.Count - 1].b - pivots[pivots.Count - 2].b)/
            //                         pivots[pivots.Count - 2].b)
            //                >= ZigZagPeriodPercent;
            //if (!lastValid && pivots.Count == 3) return events;
            //var screenPointB = lastValid ? pivots[pivots.Count - 1] : pivots[pivots.Count - 2];
            //var screenPointA = lastValid ? pivots[pivots.Count - 2] : pivots[pivots.Count - 3];

            var ptB = pivots[pivots.Count - 2];
            var ptA = pivots[pivots.Count - 3];


            // отметить вершину ЗЗ
            if (ShowFiboTurnBars && (markedZigZagPivots.Count == 0 ||
                                     markedZigZagPivots[markedZigZagPivots.Count - 1] < ptA.a))
            {
                markedZigZagPivots.Add(ptA.a);
                events.Add(new RobotHint(ticker, Graphics[0].b.ToString(), "З.З", "З.З", "z", ptA.b)
                {
                    ColorFill     = Color.Olive,
                    Time          = candles[ptA.a].timeOpen,
                    RobotHintType = RobotHint.HintType.Коментарий
                }.ToString());
            }

            // соблюдаются ли условия входа в рынок?
            // - уровень Фибо пройден N-м баром Фибо
            // - с клоза того бара рынок вырос (для продаж)
            var fiboLevel = ptA.b + (ptA.b - ptB.b) * fiboLevels[0];
            //var potentialDealSide = screenPointA.b > screenPointB.b ? -1 : 1;
            var   fiboBreachIndex = -1;
            float fiboBreachPrice = 0;

            foreach (var fiboMember in fiboBars)
            {
                var index = fiboMember + ptB.a - 1;
                if (index >= candles.Count)
                {
                    break;
                }
                // свеча закрылась дальше расширения Фибо?
                var close       = candles[index].close;
                var fiboReached = ptA.b > ptB.b ? close > fiboLevel : close < fiboLevel;
                if (!fiboReached)
                {
                    continue;
                }
                fiboBreachIndex = index;
                fiboBreachPrice = close;
                break;
            }

            // считаем, сколько потенциально могло быть совершено входов
            // с момента пробития Фибо
            if (fiboBreachIndex > 0)
            {
                var countDeals = 1;
                // потенциальные сделки
                for (var i = fiboBreachIndex + 1; i < candles.Count - 1; i++)
                {
                    if ((candles[i].close > fiboBreachPrice && ptA.b > ptB.b) ||
                        (candles[i].close < fiboBreachPrice && ptA.b < ptB.b))
                    {
                        fiboBreachPrice = candles[i].close;
                        countDeals++;
                    }
                }
                var isEnterBetter = (candle.close > fiboBreachPrice && ptA.b > ptB.b) ||
                                    (candle.close < fiboBreachPrice && ptA.b < ptB.b);

                if ((isEnterBetter || fiboBreachIndex == candles.Count - 1) &&
                    countDeals <= maxDealsInSeries)
                {// войти в рынок, закрыв противонаправленные сделки
                    var dealSide = ptA.b > ptB.b ? -1 : 1;

                    List <MarketOrder> orders;
                    robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
                    if (orders.Count > 0)
                    {
                        orders = orders.Where(o => o.Magic == Magic && o.Side != dealSide).ToList();
                    }
                    foreach (var order in orders)
                    {
                        robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                                                      robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                    }

                    // открыть сделку
                    OpenDeal(quote.GetCloseQuote(), dealSide);
                    events.Add(new RobotHint(ticker, Graphics[0].b.ToString(),
                                             "Вход", "Вход по З.З", "e", dealSide < 0 ? quote.close : quote.closeAsk)
                    {
                        ColorFill     = dealSide > 0 ? Color.Green : Color.Red,
                        Time          = quote.timeClose,
                        RobotHintType = dealSide > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа
                    }.ToString());
                }
            }

            return(events);
        }