コード例 #1
0
        public bool Step(out string[] names, out CandleDataBidAsk[] currentQuotes)
        {
            var lstNames = new List<string>();
            var lstQuotes = new List<CandleDataBidAsk>();
            var nextTimes = new List<DateTime>();

            foreach (var pair in quotes)
            {
                var symbol = pair.Key;
                var quotesList = pair.Value;
                var index = currentIndex[symbol];
                if (index < 0) continue;

                var quote = quotesList[index];
                if (quote.timeClose == timeNow)
                {
                    lstQuotes.Add(quote);
                    lstNames.Add(pair.Key);
                    index++;
                    if (index >= quotesList.Count) index = -1;
                    currentIndex[symbol] = index;
                }

                if (index >= 0) nextTimes.Add(quotesList[index].timeClose);
            }
            if (nextTimes.Count > 0)
                timeNow = nextTimes.Min();
            names = lstNames.ToArray();
            currentQuotes = lstQuotes.ToArray();

            return names.Length > 0;
        }
コード例 #2
0
        public CandleDataBidAsk[] MakeCandles(QuoteData[] quotes, ref string[] names)
        {
            var candles = new CandleDataBidAsk[quotes.Length];

            List <int> indexesLacked = null;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePackerBidAsk packer;
                if (!packers.TryGetValue(names[i], out packer))
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgPackerForTickerMissed,
                                                          1000 * 60 * 5, "CandlePackerPool - не найден пакер для тикера {0}, всего {1} пакеров",
                                                          names[i], packers.Count);

                    if (indexesLacked == null)
                    {
                        indexesLacked = new List <int> {
                            i
                        }
                    }
                    ;
                    else
                    {
                        indexesLacked.Add(i);
                    }

                    continue;
                }
                var candle = packer.UpdateCandle(quotes[i]);
                candles[i] = candle;
            }

            if (indexesLacked != null)
            {
                if (indexesLacked.Count == quotes.Length)
                {
                    names = new string[0];
                    return(new CandleDataBidAsk[0]);
                }
                names   = names.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
                candles = candles.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
            }

            return(candles);
        }
コード例 #3
0
        public CandleDataBidAsk[] MakeCandles(QuoteData[] quotes, ref string[] names)
        {
            var candles = new CandleDataBidAsk[quotes.Length];

            List<int> indexesLacked = null;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePackerBidAsk packer;
                if (!packers.TryGetValue(names[i], out packer))
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgPackerForTickerMissed,
                        1000 * 60 * 5, "CandlePackerPool - не найден пакер для тикера {0}, всего {1} пакеров",
                        names[i], packers.Count);

                    if (indexesLacked == null)
                        indexesLacked = new List<int> {i};
                    else
                        indexesLacked.Add(i);

                    continue;
                }
                var candle = packer.UpdateCandle(quotes[i]);
                candles[i] = candle;
            }

            if (indexesLacked != null)
            {
                if (indexesLacked.Count == quotes.Length)
                {
                    names = new string[0];
                    return new CandleDataBidAsk[0];
                }
                names = names.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
                candles = candles.Where((n, i) => !indexesLacked.Contains(i)).ToArray();
            }

            return candles;
        }
コード例 #4
0
        public void MakeCandles(List<Cortege2<string, QuoteData>> quotes,
            out string[] names, out CandleDataBidAsk[] candles)
        {
            var namesList = new List<string>();
            var candlesList = new List<CandleDataBidAsk>();

            foreach (var quote in quotes)
            {
                CandlePackerBidAsk packer;
                if (!packers.TryGetValue(quote.a, out packer))
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgPackerForTickerMissed,
                        1000 * 60 * 5, "CandlePackerPool - не найден пакер для тикера {0}, всего {1} пакеров",
                        quote.a, packers.Count);
                    continue;
                }
                var candle = packer.UpdateCandle(quote.b);
                namesList.Add(quote.a);
                candlesList.Add(candle);
            }

            names = namesList.ToArray();
            candles = candlesList.ToArray();
        }
コード例 #5
0
        public void UpdateVolatility(CandleDataBidAsk candle)
        {
            var x = candle.close;
            if (prevValue == null)
            {
                prevValue = x;
                return;
            }
            var delta = x - prevValue.Value;
            var delta2 = delta * delta;
            prevValue = x;
            sum += delta2;

            items.Add(delta2);
            if (items.Count > maxLength)
            {
                sum -= items[0];
                items.RemoveAt(0);
                volatility = Math.Sqrt(sum / maxLength);
            }
        }
コード例 #6
0
 public void UpdateVolatility(CandleDataBidAsk candle)
 {
     deltas.Add(candle.close - candle.open);
     if (deltas.Count > maxSize)
         deltas.RemoveAt(0);
 }
コード例 #7
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var events = new List<string>();
            #region получить candle из quote
            if (string.IsNullOrEmpty(ticker)) return events;
            var tickerIndex = -1;
            for (var i = 0; i < names.Length; i++)
                if (names[i] == ticker)
                {
                    tickerIndex = i;
                    break;
                }
            if (tickerIndex < 0) return events;
            var quote = quotes[tickerIndex];

            var candle = packer.UpdateCandle(quote);
            if (candle == null) return events;
            #endregion

            extremumRangeQueue.Add(candle);
            if (extremumRangeQueue.Length != extremumRangeQueue.MaxQueueLength)
                return events;

            //  Если очередь заполнена полностью, значит можно проверять её среднее значение на локальный экстремум
            CheckExtremum(extremumRangeQueue);

            //  Все ли 4 экстремума сейчас имеются для анализа
            if (extremumQueue.Length != extremumQueue.MaxQueueLength)
                return events;

            var extrArray = extremumQueue.ToArray();
            //  Теперь можно проверить - чередуются ли экстремумы.
            var boofSign = !extrArray[0].b;
            foreach (var extremum in extrArray)
            {
                if (extremum.b == boofSign)
                    return events; // Это значит что два максимума или два минимума идут друг за другом
                boofSign = !boofSign;
            }

            //  Экстремумы чередуются друг за другом.
            //  Теперь проверяем, больше ли по модулю "а", чем "b", "с" и "d" и close.
            var priceA = extrArray[0].a;
            var currentSide = extrArray[0].b ? 1 : -1;

            for (var i = 1; i < extrArray.Length; i++)
            {
                if (currentSide != Math.Sign(priceA - extrArray[i].a))
                    return events;
            }
            if (currentSide != Math.Sign(priceA - candle.close))
                return events;

            // соотнесение "плеч"
            var ab = Math.Abs(extrArray[0].a - extrArray[1].a);
            var bc = Math.Abs(extrArray[1].a - extrArray[2].a);
            var cd = Math.Abs(extrArray[2].a - extrArray[3].a);
            var dClose = Math.Abs(extrArray[3].a - candle.close);

            var bcCd = cd == 0 ? float.MaxValue : bc / cd;
            if (bcCd < MinShoulder || bcCd > MaxShoulder)
                return events;
            if (ab <= bc || ab <= cd || ab <= dClose)
                return events;

            //  Первый экстремум является большим по модулю, чем остальные - можно совершать сделку
            if (!isHistoryStartOff) // линии скользящих средних пересеклись причём не на истории. Значит пора торговать!!!
            {
                // коментарий
                var extrNames = new [] {"A", "B", "C", "D"};
                var nameIndex = 0;
                // ReSharper disable LoopCanBeConvertedToQuery
                foreach (var extr in extrArray)
                // ReSharper restore LoopCanBeConvertedToQuery
                {
                    events.Add(new RobotHint(ticker,
                            Graphics[0].b.ToString(),
                            extrNames[nameIndex],
                            extrNames[nameIndex],
                            extrNames[nameIndex++], extr.a)
                            {
                                Time = extr.c,
                                RobotHintType = RobotHint.HintType.Линия //extr.b ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа
                            }.ToString());
                }

                // закрыть противонаправленные, если автозакрытие включено пользователем
                if (CloseDeal)
                {
                    List<MarketOrder> orders;
                    robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
                    foreach (
                        var order in
                            orders.Where(o => o.Side != currentSide && o.Magic == Magic && o.Symbol == ticker).ToList())
                        robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                                                      robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                }

                OpenDeal(candle.close, currentSide);

            }
            return events;
        }
コード例 #8
0
 private void MakeTrade(string name, CandleDataBidAsk quote)
 {
     var option = new Option
     {
         Symbol = name,
         TimeEnter = quote.timeClose,
         ExpirationMinutes = rand.Next(minStrikeMinutes, maxStrikeMinutes),
         OptionType = rand.Next(100) < 50 ? OptionType.Call : OptionType.Put,
         Volume = rand.Next(minVolume, maxVolume),
     };
     option.PriceEnter = (decimal)(option.OptionType == OptionType.Call
         ? quote.closeAsk
         : quote.close);
     var deltaStrikeAbs = DalSpot.Instance.GetAbsValue(name, (decimal) rand.Next(minPoints, maxPoints));
     var deltaSide = option.OptionType == OptionType.Call ? 1 : -1;
     option.PriceStrike = option.PriceEnter + deltaSide * deltaStrikeAbs;
     CalculatePremium(option);
     if (option.Premium == 0)
         return;
     activeOptions.Add(option);
 }
コード例 #9
0
        private void OpenOrder(int dealSign, string symbol, CandleDataBidAsk lastCandle)
        {
            var volume = CalculateVolume(symbol, base.Leverage);
            if (volume == 0)
            {
                events.Add(string.Format("{0} {1} отменена - объем равен 0", dealSign > 0 ? "покупка" : "продажа", symbol));
                return;
            }

            var enterPrice = dealSign > 0 ? lastCandle.closeAsk : lastCandle.close;
            var point = pointCost[symbol];
            var stopLoss = enterPrice - dealSign * (float)point * StopLossPoints;
            var takeProfit = enterPrice + dealSign * (float)point * TakeProfitPoints;
            var order = new MarketOrder
            {
                AccountID = robotContext.AccountInfo.ID,
                Magic = Magic,
                Symbol = symbol,
                Volume = volume,
                Side = dealSign,
                StopLoss = stopLoss,
                TakeProfit = takeProfit,
                // [A] не забывай уникальный комент
                ExpertComment = "Bollinger"
            };
            var status = NewOrder(order,
                OrderType.Market,
                0, 0);
            if (status != RequestStatus.OK)
                events.Add(string.Format("Ошибка добавления ордера {0} {1}: {2}",
                    dealSign > 0 ? "BUY" : "SELL", symbol, status));
        }
コード例 #10
0
ファイル: BaseRobot.cs プロジェクト: johnmensen/TradeSharp
 /// <summary>
 /// Вызывается с приходом новой котировки
 /// </summary>
 public abstract List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff);
コード例 #11
0
ファイル: NuBaseRobot.cs プロジェクト: johnmensen/TradeSharp
 public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
 {
     throw new NotImplementedException();
 }
コード例 #12
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            events = new List<string>();
            if (packers == null) return events;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePacker packer;
                if (!packers.TryGetValue(names[i], out packer))
                    continue;
                var candle = packer.UpdateCandle(quotes[i]);
                if (candle == null) continue;
                var candlesList = lastCandles[names[i]];
                candlesList.Add(candle);
                if (candlesList.Count > patternLength)
                    candlesList.RemoveAt(0);
                if (candlesList.Count < patternLength) continue;
                if (isHistoryStartOff) continue;

                List<PendingOrder> orders;
                GetPendingOrders(out orders);
                orders = orders.Where(o => o.Symbol == names[i]).ToList();

                PlaceNewOrder(candlesList, names[i], orders);
                CheckOrders(candlesList, names[i]);
            }

            return events;
        }
コード例 #13
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var events = new List<string>();
            if (tickers.Length == 0 || isHistoryStartOff) return events;

            if (lastTrade == null)
            {
                lastTrade = new ThreadSafeTimeStamp();
                lastTrade.Touch();
            }

            // секунд с последнего трейда...
            var timeSince = (DateTime.Now - lastTrade.GetLastHit()).TotalSeconds;
            if (timeSince < tradeIntervalSec) return events;

            lastTrade.Touch();

            // затребовать все сделки со своим magic
            List<MarketOrder> orders;
            GetMarketOrders(out orders, true);
            var sides = tickers.ToDictionary(t => t, t => 1);
            if (orders != null)
                foreach (var order in orders)
                {
                    if (sides.ContainsKey(order.Symbol))
                        sides[order.Symbol] = -order.Side;
                    // закрыть старую сделку
                    CloseMarketOrder(order.ID);
                }

            // открыть новые сделки
            foreach (var tickerSide in sides)
            {
                var newOrd = new MarketOrder
                    {
                        Symbol = tickerSide.Key,
                        Side = tickerSide.Value,
                        AccountID = robotContext.AccountInfo.ID,
                        Magic = Magic,
                        Volume = FixedVolume,
                        ExpertComment = "SimpleTradeMachine"
                    };
                var rst = robotContext.SendNewOrderRequest(protectedContext.MakeProtectedContext(),
                                                 RequestUniqueId.Next(), newOrd, OrderType.Market, 0, 0);
            }

            return events;
        }
コード例 #14
0
ファイル: Mt4Robot.cs プロジェクト: johnmensen/TradeSharp
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            if (isHistoryStartOff) return new List<string>();
            if (!string.IsNullOrEmpty(errorMessage))
            {
                var evts = new List<string> { errorMessage };
                errorMessage = string.Empty;
                return evts;
            }

            var evsList = spamMessage.GetMessages().Select(m => m.b).ToList();
            if (TradeSharpAccount > 0)
            {
                var account = robotContext.AccountInfo;
                if (account != null && account.ID != TradeSharpAccount)
                {
                    spamMessage.PutMessage(SpamMessage.MessageCategory.AccountMismatch,
                        "Открыт счет #" + account.ID + ", ожидается счет #" + TradeSharpAccount);
                    return evsList;
                }
            }

            if (!initMessageWasSent)
            {
                // сообщить - привет, я торговый робот, делаю то-то и то-то
                initMessageWasSent = true;
                evsList.Add(string.Format("MT4 робот, слушает порт {0}, отправляет на порт {1}",
                    portOwn, portMt4));
            }

            // проверить время с последней проверки ордеров
            var lastTime = timeSinceUpdate.GetLastHit();
            var nowTime = DateTime.Now;
            var milsPassed = (nowTime - lastTime).TotalMilliseconds;
            if (milsPassed < MilsBetweenChecks) return evsList;
            timeSinceUpdate.Touch();

            // транслировать сделки в МТ4
            if (Mode == RobotMode.УправлятьМТ4)
            {
                List<MarketOrder> orders;
                // проверить имеющиеся ордера
                GetMarketOrders(out orders, false);
                TranslateOrdersToMt4(orders);
                return evsList;
            }

            // копировать сделки из МТ4
            if (Mode == RobotMode.КопироватьОрдераМТ4)
            {
                CopyOrdersFromMt4(evsList);
                return evsList;
            }

            return evsList;
        }
コード例 #15
0
 public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
 {
     var evtList = new List<string>();
     var deltaMils = lastCheckTime.HasValue
                         ? (DateTime.Now - lastCheckTime.Value).TotalMilliseconds
                         : int.MaxValue;
     if (deltaMils >= IntervalCheckMils)
     {
         lastState = CheckDeposit();
         lastCheckTime = DateTime.Now;
     }
     if (lastState == StateCode.OK) return evtList;
     // осуществить стопаут?
     var countStopout = new Cortege2<int, int>(0, 0);
     if (lastState == StateCode.Stopout) countStopout = PerformStopout();
     // разослать сообщение
     PerformDelivery(countStopout);
     if (countStopout.a > 0)
     {
         Logger.InfoFormat("DrawDownStopoutChecker: закрыто {0} сделок из {1}",
             countStopout.a, countStopout.a + countStopout.b);
     }
     return evtList;
 }
コード例 #16
0
ファイル: RobotContext.cs プロジェクト: johnmensen/TradeSharp
 public void OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryTakeOff)
 {
     var realOrModelTime = quotes[0].timeClose;
     foreach (var robot in listRobots)
     {
         var robotMessages = robot.OnQuotesReceived(names, quotes, isHistoryTakeOff);
         if (robotMessages != null && robotMessages.Count > 0 && onRobotMessage != null)
             onRobotMessage(robot, realOrModelTime, robotMessages);
     }
 }
コード例 #17
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var events = new List<string>();
            if (isHistoryStartOff) return events;

            // сформировать свечи
            for (var i = 0; i < names.Length; i++)
            {
                CandlePacker packer;
                var ticker = names[i];
                if (!packers.TryGetValue(ticker, out packer)) continue;
                var candle = packer.UpdateCandle(quotes[i]);
                if (candle == null) continue;

                // проверить условия для входа в рынок
                string comment;
                var side = CheckTradeCondition(candle, ticker, out comment);
                if (side == 0) continue;

                // закрыть сделки противоположного знака
                if (CloseOpposite)
                {
                    List<MarketOrder> orders;
                    GetMarketOrders(out orders, true);
                    foreach (var order in orders.Where(o => o.Symbol == ticker && o.Side != side))
                        CloseMarketOrder(order.ID);
                }

                // создать ордер
                OpenDeal(quotes[i].close, side, ticker, comment);
            }
            return events;
        }
コード例 #18
0
ファイル: FarmAccount.cs プロジェクト: johnmensen/TradeSharp
 /// <summary>
 /// дать роботам котировки в работу
 /// </summary>
 public void OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryQuotes)
 {
     if (context == null) return;
     try
     {
         context.OnQuotesReceived(names, quotes, isHistoryQuotes);
     }
     catch (Exception ex)
     {
         logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgQuoteRecvError,
             1000 * 60 * 5, "Ошибка в OnQuotesReceived (счет {0}): {1}",
                 AccountId, ex);
     }
 }
コード例 #19
0
        private void OpenOrder(int dealSign, string symbol, CandleDataBidAsk lastCandle)
        {
            var volume = CalculateVolume(symbol, base.Leverage);
            if (volume == 0)
            {
                events.Add(string.Format("{0} {1} отменена - объем равен 0 (L:{2:f3}, #{3})",
                    dealSign > 0 ? "покупка" : "продажа", symbol, base.Leverage, robotContext.AccountInfo.ID));
                return;
            }

            var enterPrice = dealSign > 0 ? lastCandle.closeAsk : lastCandle.close;
            var stopLoss = enterPrice - dealSign * DalSpot.Instance.GetAbsValue(symbol, (float)StopLossPoints);
            var takeProfit = enterPrice + dealSign * DalSpot.Instance.GetAbsValue(symbol, (float)TakeProfitPoints);

            var order = new MarketOrder
            {
                Symbol = symbol,                            // Инструмент по которому совершается сделка
                Volume = volume,                            // Объём средств, на который совершается сделка
                Side = dealSign,                            // Устанавливаем тип сделки - покупка или продажа
                StopLoss = stopLoss,                        // Устанавливаем величину Stop loss для открываемой сделки
                TakeProfit = takeProfit,                    // Устанавливаем величину Take profit для открываемой сделки
                ExpertComment = "RsiDiverRobot"             // Комментарий по сделке, оставленный роботом
            };
            var status = NewOrder(order,
                OrderType.Market, // исполнение по рыночной цене - можно везде выбирать такой вариант
                0, 0); // последние 2 параметра для OrderType.Market не имеют значения
            if (status != RequestStatus.OK)
                events.Add(string.Format("Ошибка добавления ордера ({0}): {1} (#{2} bal: {3})",
                    order, status,
                    robotContext.AccountInfo.ID,
                    robotContext.AccountInfo.Balance.ToStringUniformMoneyFormat(true)));
        }
コード例 #20
0
ファイル: StopRobot.cs プロジェクト: johnmensen/TradeSharp
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var events = new List<string>();
            if (string.IsNullOrEmpty(ticker)) return events;

            CandleDataBidAsk quote = null;
            for (var i = 0; i < names.Length; i++)
            {
                if (names[i] != ticker) continue;
                quote = quotes[i];
                break;
            }

            if (quote == null) return events;

            // обновить свечку
            var candle = packer.UpdateCandle(quote);
            if (candle == null) return events;

            // получить ордера
            List<MarketOrder> orders;
            GetMarketOrders(out orders, false);
            orders = orders.Where(o => o.Symbol == ticker).ToList();
            if (orders.Count == 0 || isHistoryStartOff) return events;

            // проверить стоп по уровням и по индивидуальным настрофкам сделок
            if (checkIndividualStop)
                DoCheckIndividualStop(candle, orders, events);

            // проверить стоп по заданному уровню
            if (StopLevel != 0)
                DoCheckCommonStop(candle, orders, events);

            return events;
        }
コード例 #21
0
ファイル: RobotMA.cs プロジェクト: johnmensen/TradeSharp
        /// <summary>
        /// Этот метод вызывается каждый раз при новых данных котировки. Метод реализует основную логику торговли робота. 
        /// Здесь принимается решение о открытии нового ордера и закрытии открытых сделок
        /// Совершение сделок будет поисходить на закрытии свечи. При закрытии свечки метод  UpdateCandle объекта packer вернёт эту свечу, иначе Null.
        /// В случае если свеча закрылась, тогда методом CalculateMA расчитываем значение скользящей средней для текущей котировки.
        /// Если быстрая и медленная скользящие седние пересекаются, а так же если текущая котировка не является "исторической", тогда можно
        /// принимать решение об открытии новой сделки.
        /// </summary>
        /// <param name="quotes"></param>
        /// <param name="isHistoryStartOff">Флаг, показывающий, является текущая котировка взятой из истории, или это значение катировки на текущий момент на рынке</param>
        /// <param name="names"></param>
        public override List<string> OnQuotesReceived(string[] names, 
            CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            events = lastMessages.ToList();
            lastMessages.Clear();

            #region Получение текущей свечи
            // Массивы "names" и "quotes" всегда содержат одинаковое количество элементов (по одному). Фактически это пары ключ/значение

            if (string.IsNullOrEmpty(ticker))
            {
                Logger.ErrorFormat("Название текущего инструмента (ticker) для робота {0} задано не корректно", TypeName);
                return events;
            }
            var tickerIndex = -1;
            for (var i = 0; i < names.Length; i++)
                if (names[i] == ticker)
                {
                    tickerIndex = i;
                    break;
                }
            if (tickerIndex < 0)
            {
                //Logger.InfoFormat("Не удалось получить котировку для робота {0}", TypeName);
                return events;
            }

            //Выбираем из всего массива текущих катировкок, катировку для того инструмента, которым торгует робот
            var quote = quotes[tickerIndex];

            var candle = packer.UpdateCandle(quote);
            #endregion

            // Если свеча закрылась, тогда candle != null  (сделки соверши)
            if (candle == null) return events;

            queueSlow.Add(candle.close);
            queueFast.Add(candle.close);
            if (queueSlow.Length < queueSlow.MaxQueueLength) return events;
            CandlesAnalysisAndTrade(candle, isHistoryStartOff);
            return events;
        }
コード例 #22
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var hints = new List<RobotHint>();
            if (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)
            {
                // закрылась полная свеча, проводим вычисления
                candles.Add(candle);
                countCandles++;
            }

            List<MarketOrder> orders = null;
            if (ProtectPosType != ProtectType.НеЗащищать)
            {
                GetMarketOrders(out orders);
                if (orders.Count > 0)
                {
                    if (unconditionalProtectPips > 0)
                        CheckUnconditionalProtect(orders, curQuote.GetCloseQuote(), hints);
                    // проверить множество индексов на нескольких ТФ - условия защиты
                    CheckProtectTrigger(orders, curQuote.GetCloseQuote(), hints, isHistoryStartOff, candle);
                    // проверить собственно защиту
                    CheckProtect(orders, curQuote.GetCloseQuote(), hints);
                }
            }
            if (CalcDealChainStat)
            {
                if (orders == null) GetMarketOrders(out orders);
                UpdateChainStatistics(orders);
            }

            if (candle != null)
            {
                // закрылась полная свеча, проводим вычисления
                // обновить очереди (для индекса, переменные вида 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 DiversToEnter)
                    ind.CalculateValue(tickerNames, candles, lastBidLists, curTime, randomGener);

                // индексы для фильтров
                foreach (var filter in filters)
                    filter.indexCalculator.CalculateValue(tickerNames, candles, lastBidLists,
                        curTime, randomGener);

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

                // получить суммарный знак диверов на текущей свече
                var divergenceSign = 0;
                var commentBuilder = new StringBuilder();
                foreach (var ind in DiversToEnter)
                {
                    string commentOnDivergence;
                    var indiDiverSign = ind.GetDivergenceSign(candles, out commentOnDivergence);
                    divergenceSign += indiDiverSign;
                    if (!string.IsNullOrEmpty(commentOnDivergence))
                        commentBuilder.AppendLine(commentOnDivergence);
                }
                divergenceSign = Math.Sign(divergenceSign);

                // есть дивер?
                if (divergenceSign != 0)
                    TryEnterTheMarket(divergenceSign, curQuote.GetCloseQuote(), hints, commentBuilder.ToString());
            }

            var retHint = hints.Select(hint => hint.ToString()).ToList();
            return retHint.Count > 0 ? retHint : null;
        }
コード例 #23
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]] = (double)quotes[i].close;
                else
                    lastBids.Add(names[i], (double)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);

            var hints = new List<RobotHint>();
            if (candle != null)
            {
                // закрылась полная свеча, проводим вычисления
                candles.Add(candle);

                countCandles++;
                // обновить очереди (для индекса, переменные вида 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, randomGener);

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

                var hintText = new StringBuilder();
                List<MarketOrder> orders;

                #region ТОРГОВЫЙ МОДУЛЬ

                #region проверяем необходимость добавок к открытым позициям

                // проверяем состояние робота, если у нас нет позиций и робот торгует, возвращаем в исходное состояние
                GetMarketOrders(out orders);
                if (orders.Count == 0 && stopsOnPositions == StopPositionsState.ЗащитаУстановлена)
                {
                    RobotTradeState = TradeState.ПоискТочекВхода;
                    TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции закрылись");
                    TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState);
                    stopsOnPositions = StopPositionsState.Незащищены;
                }
                var addPosFlag = 0;
                if (RobotTradeState == TradeState.НаращиваниеПокупок || RobotTradeState == TradeState.НаращиваниеПродаж)
                {
                    var side = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 :
                                RobotTradeState == TradeState.НаращиваниеПродаж ? -1 : 0;
                    if (AddPositionRules == AddPositionRule.НаБареЛучшейЦены)
                    {
                        //GetMarketOrders(out orders);
                        if (orders.Count == 0)
                        {
                            addPosFlag = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 : -1;
                        }
                        else
                        {
                            var averagePrice = GetAveragePrice(orders, side, curQuote.close, ProtectType.ПоЛучшейПозиции);
                            if (side == 1 && curQuote.close < averagePrice) addPosFlag = 1;
                            if (side == -1 && curQuote.close > averagePrice) addPosFlag = -1;

                            // проверяю достижение актуального фибоуровня
                            if (ActualFiboLevel != null)
                            {
                                // если условие выполнилось, то мы не достигли уровня для открытия позиций
                                if ((addPosFlag == 1 && ActualFiboLevel < curQuote.close) ||
                                    (addPosFlag == -1 && ActualFiboLevel > curQuote.close))
                                    addPosFlag = 0;
                            }
                        }
                    }
                }

                if (addPosFlag != 0)
                {
                    GetMarketOrders(out orders);
                    var ordersCount = orders.Count;
                    // проверяем можно ли еще открыть позиции
                    if (ordersCount < CountTrades)
                    {

                        // открыть позу в направлении знака дивера
                        robotContext.SendNewOrderRequest(
                            protectedContext.MakeProtectedContext(),
                            RequestUniqueId.Next(),
                            new MarketOrder
                                {
                                    AccountID = robotContext.AccountInfo.ID,
                                    Magic = Magic,
                                    Symbol = ticker,
                                    Volume = GetTradeLot(),
                                    Side = addPosFlag,
                                    ExpertComment = "Atracotes MTS"
                                },
                            OrderType.Market, 0, 0);

                        if (ordersCount > 0)
                        {
                            hintText.AppendLine(string.Format("Добавка к {0}, текущая цена {1}",
                                                              addPosFlag == 1 ? "покупкам" : "продажам", curQuote.close));
                        }
                        else
                        {
                            hintText.AppendLine(string.Format("{0}, текущая цена {1}", addPosFlag == 1 ? "покупка" : "продажа",
                                                curQuote.close));
                        }
                        TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText);
                        hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), hintText.ToString(),
                            addPosFlag > 0 ? "BUY" : "SELL", "e", curQuote.close)
                        {
                            Time = curQuote.timeClose,
                            ColorFill = addPosFlag > 0 ? Color.Green : Color.Red,
                            ColorLine = Color.Black,
                            RobotHintType = addPosFlag > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа
                        });
                        stopsOnPositions = StopPositionsState.Незащищены;
                        if (ordersCount + 1 == CountTrades)
                        {
                            RobotTradeState = TradeState.НабранПолныйОбъем;
                            TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState);
                        }
                    }
                }
                #endregion

                #region считаем зигзагу и уровни расширений

                var quotesList = candles.ToList();
                var pivots = ZigZag.GetPivots(quotesList, ThresholdPercent, ZigZagSourceType);
                if (pivots.Count > 1)
                {
                    // появились точки, рассчитываем уровни
                    // проверяем процентный порог перешагнули или нет

                    for (var i = pivots.Count; i > 1; i--)
                    {
                        var index0 = i - 1;
                        var index1 = i - 2;
                        var percent = Math.Abs(pivots[index0].b - pivots[index1].b) / pivots[index1].b * 100;
                        if (percent > ThresholdPercent)
                        {
                            // процентный порог пройден, вычисляем уровни
                            // теперь вычисляем уровни расширений
                            var sign = pivots[index0].b > pivots[index1].b ? -1 : 1;
                            var delta = Math.Abs(pivots[index0].b - pivots[index1].b);

                            // очищаем все предыдущие уровни расширений как устаревшие
                            // extLevels.Clear();

                            foreach (var level in fiboLevels)
                            {
                                var lev = new ExtensionsLevel
                                {
                                    startIndex = countCandles > CandlesInIndexHistory ? countCandles - CandlesInIndexHistory + pivots[index0].a : pivots[index0].a,
                                    length = BarsCount,
                                    price = pivots[index0].b + delta * sign * (1 + level),
                                    delta = DalSpot.Instance.GetAbsValue(ticker, DeltaLevel),
                                    goalFrom = -sign
                                };
                                extLevels.Add(lev);
                            }
                            break;
                        }
                    }
                }
                #endregion

                #region ищем дивергенции на индексах и курсе валютной пары
                var divergenceSign = 0;

                foreach (var ind in IndexList)
                {
                    var commentOnDivergence = string.Empty;

                    var indiDiverSign = ind.GetDivergenceSign(candles, out commentOnDivergence);
                    if (indiDiverSign != 0)
                    {
                        if (hintText.Length != 0)
                            hintText.AppendLine();
                        hintText.AppendLine("Дивергенция на индексе №" + indexList.IndexOf(ind));
                        hintText.AppendLine(commentOnDivergence);
                        hintText.AppendLine("Переменные:");
                        // ReSharper disable PossibleNullReferenceException)
                        foreach (var pair in ind.indexCalculator.varValues)
                        // ReSharper restore PossibleNullReferenceException
                        {
                            hintText.AppendLine(string.Format("{1}{0}{2:f4}", (char)9, pair.Key, pair.Value));
                        }

                        //hints.Add(new RobotHint(hintText.ToString(),
                        //indiDiverSign > 0 ? "BUY" : "SELL", "e", curQuote.Bid)
                        //{
                        //    Time = candle.timeOpen,
                        //    ColorFill = indiDiverSign > 0 ? Color.Green : Color.Red,
                        //    ColorLine = Color.Black
                        //});

                    }

                    divergenceSign += indiDiverSign;

                }
                #endregion

                // теперь получен список дивергенций и уровни расширения.

                #region удаляем старые уровни
                for (var i = 0; i < extLevels.Count; i++)
                {
                    // проверка актуальности уровня по свечам
                    if (countCandles - 1 <= extLevels[i].startIndex + extLevels[i].length) continue;
                    // уровень устарел, прошли максимальную длину свечей
                    extLevels.RemoveAt(i);
                    i--;
                }
                #endregion

                // проверяем достижение уровней расширения текущей ценой и если есть - входим в рынок
                divergenceSign = Math.Sign(divergenceSign);

                if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign != 0)
                {
                    GetMarketOrders(out orders);
                    stopsOnPositions = ProtectPositions(orders, -divergenceSign, curQuote.close);
                    if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена)
                    {
                        TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены ны дивергенции");
                        hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                            "Защита позиций на дивергенции", "PROTECT", -divergenceSign > 0 ? "PB" : "PS", curQuote.close)
                        {
                            Time = curQuote.timeClose,
                            ColorFill = Color.Blue,
                            ColorLine = Color.Black,
                            RobotHintType = RobotHint.HintType.Поджатие
                        });
                    }
                }

                if (true || RobotTradeState == TradeState.НетПозиций || RobotTradeState == TradeState.ПоискТочекВхода || RobotTradeState == TradeState.НабранПолныйОбъем)
                {
                    foreach (var level in extLevels)
                    {
                        // проверяем попадание цены на уровень
                        //var prevCandle = candles.GetItemByIndex(candles.Count() - 2, true);
                        if ((level.goalFrom == -1 && candles[candles.Count - 1].close >= (level.price - level.delta)) ||
                            (level.goalFrom == 1 && candles[candles.Count - 1].close <= (level.price + level.delta)))
                        {
                            GetMarketOrders(out orders);
                            if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign == 0)
                            {
                                // надо поджать позиции
                                stopsOnPositions = ProtectPositions(orders, -level.goalFrom, curQuote.close);
                                if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена)
                                {
                                    TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены по достижению уровня расширения");
                                    hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                                        "Защита позиций по достижению уровня расширения",
                                        "PROTECT", -level.goalFrom > 0 ? "PB" : "PS", curQuote.close)
                                    {
                                        Time = curQuote.timeClose,
                                        ColorFill = Color.Blue,
                                        ColorLine = Color.Black,
                                        RobotHintType = RobotHint.HintType.Поджатие
                                    });
                                }
                                break;
                            }

                            if (divergenceSign == 0) continue;

                            var ordersCount = orders.Count;
                            // цена поднялась до целевого уровня
                            var level1 = level;
                            var ordersToClose = orders.FindAll(o => o.Side != divergenceSign);

                            foreach (var order in ordersToClose)
                            {
                                robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                                    robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                                ordersCount--;
                            }
                            // закрыли ордера и теперь начинаем открывать позиции в обратную сторону

                            // проверяем можно ли еще открыть позиции
                            if (ordersCount >= CountTrades) break;

                            // не добавляем позиции по новому диверу
                            if (RobotTradeState == TradeState.НаращиваниеПокупок && divergenceSign == 1 ||
                                RobotTradeState == TradeState.НаращиваниеПродаж && divergenceSign == -1) break;

                            // открыть позу в направлении знака дивера
                            robotContext.SendNewOrderRequest(
                            protectedContext.MakeProtectedContext(),
                            RequestUniqueId.Next(),
                            new MarketOrder
                            {
                                AccountID = robotContext.AccountInfo.ID,
                                Magic = Magic,
                                Symbol = ticker,
                                Volume = GetTradeLot(),
                                Side = divergenceSign,
                                ExpertComment = "Atracotes MTS"
                            },
                            OrderType.Market, 0, 0);

                            hintText.AppendLine(string.Format("Пересечение уровня {0} {1}, текущая цена {2}",
                                                              level1.price,
                                                              level1.goalFrom == -1 ? "снизу" : "сверху", curQuote.close));

                            TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText + ", " + (divergenceSign > 0 ? "покупка" : "продажа"));
                            hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                                hintText.ToString(), divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.close)
                            {
                                Time = curQuote.timeClose,
                                ColorFill = divergenceSign > 0 ? Color.Green : Color.Red,
                                ColorLine = Color.Black,
                                RobotHintType = divergenceSign > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа
                            });

                            RobotTradeState = divergenceSign == 1
                                                  ? TradeState.НаращиваниеПокупок

                                                  : TradeState.НаращиваниеПродаж;
                            TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState);
                            stopsOnPositions = StopPositionsState.Незащищены;
                            break;
                        }
                    }
                }

                #endregion
            }

            var retHint = hints.Select(hint => hint.ToString()).ToList();
            return retHint.Count > 0 ? retHint : null;
        }
コード例 #24
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            events = lastMessages.ToList();
            lastMessages.Clear();

            if (packers == null)
                return events;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePacker packer;
                if (!packers.TryGetValue(names[i], out packer))
                    continue;

                var candle = packer.UpdateCandle(quotes[i]);
                if (candle == null)
                    continue;

                var enterSign = CheckEnterCondition(names[i], candle.close);

                if (enterSign == 0)
                    continue;

                if (isHistoryStartOff) continue;

                if (CloseOpposite)
                    CloseCounterOrders(enterSign, names[i]);

                OpenOrder(enterSign, names[i], quotes[i]);
            }

            return events;
        }
コード例 #25
0
ファイル: NewsRobot.cs プロジェクト: johnmensen/TradeSharp
 public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
 {
     if (isProcessing)
         return new List<string>();
     try
     {
         isProcessing = true;
         return ProcessQuotes(names, quotes, isHistoryStartOff);
     }
     finally
     {
         isProcessing = false;
     }
 }
コード例 #26
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            events = new List<string>();
            if (packers == null) return events;

            for (var i = 0; i < quotes.Length; i++)
            {
                CandlePacker packer;
                if (!packers.TryGetValue(names[i], out packer))
                    continue;

                var candle = packer.UpdateCandle(quotes[i]);
                if (candle == null)
                    continue;

                var enterSign = CheckEnterCondition(names[i], candle);

                if (isHistoryStartOff || enterSign == 0) continue;

                // если есть открытые сделки против текущего направления - закрыть их
                if (CloseOpposite)
                    CloseCounterOrders(enterSign, names[i]);

                // открыть сделку
                OpenOrder(enterSign, names[i], quotes[i]);
            }

            return events;
        }
コード例 #27
0
ファイル: NewsRobot.cs プロジェクト: johnmensen/TradeSharp
        private List<string> ProcessQuotes(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var result = new List<string>();

            // дописываем лог
            foreach (var m in pendingLogMessages.Where(e => !logMessages.Contains(e)))
            {
                logMessages.Add(m);
                result.Add(MakeLog(m));
            }

            // проверяем инициализацию
            var message = "не инициализирован, остановлен";
            if (newsSettings == null || currencySettings == null)
            {
                if (!logMessages.Contains(message))
                {
                    logMessages.Add(message);
                    result.Add(MakeLog(message));
                }
                return result;
            }

            // all ok inform
            // информируем о начале работы
            message = "запущен";
            if (!logMessages.Contains(message))
            {
                logMessages.Add(message);
                result.Add(MakeLog(message));
            }

            // saving to cache
            // сохраняем кэш котировок
            for (var i = 0; i < names.Length; i++)
            {
                var name = names[i];
                if(!quoteStorage.ContainsKey(name))
                    quoteStorage.Add(name, new List<QuoteData>());
                quoteStorage[name].Add(quotes[i].GetCloseQuote());
            }

            // if this call is used for caching quotes - exiting
            // если мы в режиме наполнения кэша - выходим
            if (isHistoryStartOff)
                return result;

            // detemining model time
            // определение модельного времени
            if (quotes.Length == 0)
                return result;
            var now = quotes[0].timeClose;

            // update orders' SL & TP
            // обновляем сделки
            List<MarketOrder> orders;
            robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
            result.AddRange(UpdateOrders(now, orders));

            // working with news
            // make GrabNews calls unfrequent
            // сокращаем частоту вызовов GrabNews
            if ((now - lastGrabNewsCall.GetLastHit()).TotalSeconds < PauseForNewsReadingSeconds)
                return result;
            var grab = true; // in present - grab each PauseForNewsReadingSeconds
            if (now.Date < DateTime.Today) // working in the past (testing)
                if (now.Date == lastGrabNewsCall.GetLastHit().Date) // grabbing only once in day
                    grab = false;
            // grabbing
            // извлечение с Alpari
            if (grab)
            {
                List<string> parseErrors;
                var news = GrabNews(new DateTime(now.Year, now.Month, now.Day), out parseErrors);
                foreach (var m in parseErrors.Where(e => !logMessages.Contains(e)))
                {
                    logMessages.Add(m);
                    result.Add(MakeLog(m));
                }
                if (news.Count == 0)
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error,
                                                          LogMsgNoNewsParsed, 1000 * 60 * 5, "Прочитано 0 новостей");
                else
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info,
                                                          LogMsgNewsParsed, 1000 * 60 * 5, "Прочитано {0} новостей",
                                                          news.Count);
                freshNews.AddRange(news);
                lastGrabNewsCall.SetTime(now);
            }
            // processing
            // обработка новостей (внешний цикл)
            foreach (var curNews in freshNews)
            {
                var currentNews = curNews;

                // сверяем время
                if (oldNews.Contains(currentNews)) // news already processed
                    continue;
                // news obsolete
                // новость устарела
                if ((now - currentNews.Time - new TimeSpan(0, NewsProcessingDelayMinutes, 0)).TotalMinutes > NewsObsolescenceTimeMinutes)
                {
                    oldNews.Add(currentNews);
                    continue;
                }
                // news in future; skip processing
                // придержим новость на будущее
                if (currentNews.Time + new TimeSpan(0, NewsProcessingDelayMinutes, 0) > now)
                    continue;

                var timeNear = currentNews.Time.AddMinutes(TimeNearMinutes);
                var timeFar = currentNews.Time.AddMinutes(-TimeFarMinutes);

                result.Add(MakeLog("обрабатывается " + currentNews));
                var chatMessage = "\n"; // здесь формируется сообщение в чат
                chatMessage += string.Format("Обрабатывается новость: [{0}] {1}\nВремя: {2}, прогноз: {3}, фактическое: {4}\n",
                                  currentNews.CountryCode, currentNews.Title, currentNews.Time,
                                  currentNews.ProjectedValue, currentNews.Value);

                // calc weights
                // вычисляем веса, определяем знак
                int valueWeight;
                if(currentNews.ProjectedValue > currentNews.Value)
                    valueWeight = -1;
                else if((currentNews.ProjectedValue < currentNews.Value))
                    valueWeight = 1;
                else
                    valueWeight = 0;
                var delta = currentNews.ProjectedValue == 0
                                ? 100
                                : (int)Math.Abs((currentNews.Value - currentNews.ProjectedValue) / currentNews.ProjectedValue * 100);
                var newsWeight = GetWeight(currentNews.CountryCode, currentNews.Title, delta);
                // 4 debug
                /*if (newsWeight == 0)
                {
                    message = string.Format("Valuable news not processed: [{0}] {1}", currentNews.CountryCode,
                                                currentNews.Title);
                    if (!logMessages.Contains(message))
                    {
                        logMessages.Add(message);
                        result.AddRange(MakeLog(message));
                    }
                }*/
                var sign = valueWeight * newsWeight;
                if(sign == 0)
                {
                    oldNews.Add(currentNews);
                    chatMessage += "Результат: нет входа в рынок\n";
                    chatMessage += "Причина: " +
                                   (newsWeight == 0
                                        ? "вес новости равен 0\n"
                                        : "отклонение экономического показателя равно 0\n");
                    if (SendMessageInRoom != null)
                        SendMessageInRoom(chatMessage, chatRoom);
                    continue;
                }

                // gathering tickers for affected currecncies
                // определяем затронутые новостью валютные пары и их знак новостного сигнала
                var tickersAndSigns = new List<Cortege2<string, int>>();
                var currencies = currencySettings.Where(c => c.CountryCode == currentNews.CountryCode).Select(c => c.CurrencyCode);
                foreach (var currency in currencies)
                {
                    var cur = currency;
                    var tickersWithBaseCur = Graphics.Where(g => g.a.StartsWith(cur)).Select(g => g.a);
                    tickersAndSigns.AddRange(tickersWithBaseCur.Select(t => new Cortege2<string, int>(t, sign)).ToList());
                    var tickersWithQuoteCur = Graphics.Where(g => g.a.EndsWith(cur)).Select(g => g.a);
                    tickersAndSigns.AddRange(
                        tickersWithQuoteCur.Select(t => new Cortege2<string, int>(t, -sign)).ToList());
                }

                // processing tickers
                // работаем с выбранными валютными парами (внутренний цикл)
                foreach (var tickerAndSign in tickersAndSigns)
                {
                    var ticker = tickerAndSign.a;
                    var curSign = tickerAndSign.b;

                    // определение действующей на этот момент котировки
                    var data = GetDataFromStorage(ticker, currentNews.Time, currentNews.Time.AddMinutes(5));
                    if(data.Count == 0)
                    {
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: нет котировки для " + ticker + " в диапазоне от " +
                                       currentNews.Time + " до " + currentNews.Time.AddMinutes(5) + "\n";
                        if (SendMessageInRoom != null)
                            SendMessageInRoom(chatMessage, chatRoom);
                        continue;
                    }

                    // опорное значение для определения трендов и величины сделки - цена спроса
                    var value = data[0].bid;

                    // определение тренда
                    int signNear = 0, signFar = 0;
                    data = GetDataFromStorage(ticker, timeNear, timeNear.AddMinutes(5));
                    if (data.Count == 0)
                    {
                        // 4 debug
                        var hint = new RobotHint(ticker, "", "insufficient data for near-trend",
                                                    curSign > 0 ? "BUY no near-data" : "SELL no near-data", "e", value)
                                        {Time = now, ColorFill = Color.Red};
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: недостаточно данных для определения тренда после выхода новости\n";
                        if (SendMessageInRoom != null)
                            SendMessageInRoom(chatMessage, chatRoom);
                        continue;
                    }
                    var valueNear = data[0].bid;
                    if (value > valueNear)
                        signNear = 1;
                    else if (value < valueNear)
                        signNear = -1;
                    data = GetDataFromStorage(ticker, timeFar, timeFar.AddMinutes(5));
                    if (data.Count == 0)
                    {
                        // 4 debug
                        var hint = new RobotHint(ticker, "", "insufficient data for far-trend",
                                                    curSign > 0 ? "BUY no far-data" : "SELL no far-data", "e", value)
                                        {Time = now, ColorFill = Color.Red};
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: недостаточно данных для определения тренда до выхода новости\n";
                        if (SendMessageInRoom != null)
                            SendMessageInRoom(chatMessage, chatRoom);
                        continue;
                    }
                    var valueFar = data[0].bid;
                    if (value > valueFar)
                        signFar = 1;
                    else if (value < valueFar)
                        signFar = -1;

                    // определяем необходимость входа в рынок
                    var values = new Dictionary<string, double>();
                    values.Add("tn", curSign);
                    values.Add("tba", signFar);
                    values.Add("tcb", signNear);
                    double formulaResult;
                    var resultFlag = expressionResolver.Calculate(values, out formulaResult);
                    if (!resultFlag)
                    {
                        result.Add(MakeLog("Ошибка в расчете по формуле для входа в рынок"));
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: ошибка в расчете по формуле для входа в рынок\n";
                        if(SendMessageInRoom != null)
                            SendMessageInRoom(chatMessage, chatRoom);
                        continue;
                    }

                    // вход в рынок
                    var tradeSign = 0;
                    switch (EnterSign)
                    {
                        case EnterSignEnum.Tn:
                            tradeSign = curSign;
                            break;
                        case EnterSignEnum.NotTn:
                            tradeSign = -curSign;
                            break;
                        case EnterSignEnum.Tba:
                            tradeSign = signFar;
                            break;
                        case EnterSignEnum.NotTba:
                            tradeSign = -signFar;
                            break;
                        case EnterSignEnum.Tcb:
                            tradeSign = signNear;
                            break;
                        case EnterSignEnum.NotTcb:
                            tradeSign = -signNear;
                            break;
                    }
                    if (formulaResult != 0)
                    {
                        // если получен сигнал на покупку - купить, закрыв продажи
                        // наоборот, если получен сигнал на продажу - продать, закрыв покупки
                        robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
                        var ordersToClose = orders.Where(o => o.Symbol == ticker && o.Side != tradeSign).ToList();
                        foreach (var order in ordersToClose)
                        {
                            robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                                robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                        }
                        // создаем ордер
                        var decreaseSl = DalSpot.Instance.GetAbsValue(ticker, (float)InitialSlPoints);
                        var slValue = value - tradeSign * decreaseSl;
                        var decreaseTp = DalSpot.Instance.GetAbsValue(ticker, (float)InitialTpPoints);
                        var tpValue = value + tradeSign * decreaseTp;
                        var newOrder = new MarketOrder
                            {
                                AccountID = robotContext.AccountInfo.ID,
                                Magic = Magic,
                                Symbol = ticker,
                                Volume = Volume,
                                Side = tradeSign,
                                StopLoss = slValue,
                                TakeProfit = tpValue,
                                ExpertComment = currentNews.Title
                            };

                        var status = robotContext.SendNewOrderRequest(protectedContext.MakeProtectedContext(),
                                                            RequestUniqueId.Next(),
                                                            newOrder,
                                                            OrderType.Market, (decimal)value, 0);
                        if (status != RequestStatus.OK)
                        {
                            var hint = new RobotHint(ticker, "",
                                                     "SendNewOrderRequest error: " +
                                                     EnumFriendlyName<RequestStatus>.GetString(status) + " news: " +
                                                     currentNews,
                                                     tradeSign > 0 ? "BUY error" : "SELL error", "e", value)
                                {
                                    Time = now,
                                    ColorFill = Color.Red
                                };
                            result.Add(hint.ToString());
                        }
                        else
                        {
                            var hint = new RobotHint(ticker, "", "SendNewOrderRequest Ok, news: " + currentNews,
                                                        tradeSign > 0 ? "BUY" : "SELL", "i", value) { Time = now, ColorFill = Color.Red };
                            result.Add(MakeLog("вход в рынок по новости " + currentNews));
                            result.Add(hint.ToString());
                            chatMessage += "Результат: вход в рынок: " + (tradeSign > 0 ? "покупка " : "продажа ") + ticker + "\n";
                        }
                    }
                    else
                    {
                        var hint = new RobotHint(ticker, "", "Market condition fulfill failed, news: " + currentNews,
                                                    tradeSign > 0 ? "BUY no condition" : "SELL no condition", "e", value)
                                        {
                                            Time = now, RobotHintType = RobotHint.HintType.Стоп
                                        };
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: не выполнено условие входа\n";
                    }
                    if (SendMessageInRoom != null)
                        SendMessageInRoom(chatMessage, chatRoom);
                }
                oldNews.Add(currentNews);
            }
            return result;
        }
コード例 #28
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;
        }
コード例 #29
0
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var messages = new List<string>();

            var nowTime = quotes[0].timeClose;
            var minutesFromLastDeal = timeOfLastDeal.HasValue
                ? (nowTime - timeOfLastDeal.Value).TotalMinutes
                : int.MaxValue;

            for (var i = 0; i < names.Length; i++)
            {
                if (!tickers.Contains(names[i])) continue;
                tickerVolatility[names[i]].UpdateVolatility(quotes[i]);
            }

            if (minutesFromLastDeal >= intervalBetweenTradesMinutes)
            {
                for (var i = 0; i < names.Length; i++)
                {
                    if (!tickers.Contains(names[i])) continue;
                    MakeTrade(names[i], quotes[i]);
                }

                timeOfLastDeal = nowTime;
            }

            CheckOptions(names, quotes);

            return messages;
        }
コード例 #30
0
ファイル: RandomRobot.cs プロジェクト: johnmensen/TradeSharp
        public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            if (packers.Count == 0) return new List<string>();
            if (isHistoryStartOff) return new List<string>();
            var time = quotes[0].timeClose;

            // подготовить события входа
            for (var i = 0; i < names.Length; i++)
            {
                var ticker = names[i];
                foreach (var packer in packers)
                {
                    if (packer.Key.a != ticker) continue;
                    var candle = packer.Value.UpdateCandle(quotes[i]);
                    if (candle == null) continue;

                    // закрыть сделку / сделки?
                    if (CheckDice(probClose))
                        TryCloseDeal(ticker);

                    // войти в рынок или закрыть сделку или забить?
                    if (!CheckDice(probTrade)) continue;

                    // в рабочий час...?
                    var isWorkingHour = workHours.Any(hr => hr.a >= time.Hour && hr.b <= time.Hour);
                    if (!isWorkingHour && !CheckDice(probNonWorkTrade)) continue;

                    List<MarketOrder> orders;
                    GetMarketOrders(out orders, true);
                    orders = orders.Where(o => o.Symbol == ticker).ToList();

                    // повторный вход?
                    if (orders.Count > 0)
                        if (!CheckDice(probSecondOrder)) continue;

                    var side = CheckDice(50) ? 1 : -1;
                    // противоположный вход?
                    if (orders.Count > 0 && orders[orders.Count - 1].Side != side)
                        if (!CheckDice(probOpposOrder)) continue;

                    // время входа
                    var timeEnter = time;
                    if (!CheckDice(probStrictOnCandleCloseOrder))
                    {
                        var deltaMinutes = rnd.Next((int) (packer.Key.b.Intervals.Sum()/1.5));
                        timeEnter = timeEnter.AddMinutes(deltaMinutes);
                    }

                    plannedOrders.Add(new Cortege3<string, int, DateTime>(ticker, side, timeEnter));
                }
            }

            // если есть события для входа - войти в рынок
            for (var i = 0; i < plannedOrders.Count; i++)
            {
                if (time > plannedOrders[i].c) continue;
                OpenOrder(plannedOrders[i]);
                plannedOrders.RemoveAt(i);
                i--;
            }

            return null;
        }
コード例 #31
0
        private void CheckOptions(string[] names, CandleDataBidAsk[] quotes)
        {
            var nowTime = quotes.Max(q => q.timeClose);

            for (var i = 0; i < activeOptions.Count; i++)
            {
                var option = activeOptions[i];
                // опцион проэкспарился
                if (option.ExpireTime < nowTime)
                {
                    activeOptions.RemoveAt(i);
                    i--;
                    histOptions.Add(option);
                    continue;
                }

                // опцион сработал
                var nameIndex = names.IndexOf(option.Symbol);
                if (nameIndex < 0) continue;
                var quote = quotes[nameIndex];

                if ((option.OptionType == OptionType.Call && quote.high >= (float) option.PriceStrike) ||
                    (option.OptionType == OptionType.Put && quote.low <= (float) option.PriceStrike))
                {
                    option.Profit =
                        option.Volume * (option.PriceStrike - option.PriceEnter) * (int) option.OptionType;
                    activeOptions.RemoveAt(i);
                    i--;
                    histOptions.Add(option);
                }
            }
        }