public void InvalidDateIsIgnored()
        {
            var logger     = new LoggerStub();
            var repo       = new CandleHistoryRepositoryStub();
            var controller = new CandleGenerationController(repo, logger, "test component", env);

            DateTime unspecified = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
            DateTime local       = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Local);

            controller.HandleQuote(new Quote()
            {
                AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = unspecified
            }).Wait();
            controller.HandleQuote(new Quote()
            {
                AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = local
            }).Wait();
            controller.HandleQuote(new Quote()
            {
                AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = DateTime.MinValue
            }).Wait();
            controller.HandleQuote(new Quote()
            {
                AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = DateTime.MaxValue
            }).Wait();
            Assert.Equal(0, repo.Stored.Count);
        }
 public QueueMonitor(ILog logger, CandleGenerationController controller, int warningSize, string componentName)
     : base(componentName, (int)TimeSpan.FromMinutes(1).TotalMilliseconds, logger)
 {
     this.componentName = componentName;
     this.logger        = logger;
     this.controller    = controller;
     this.warningSize   = warningSize;
 }
        public void NullIsIgnored()
        {
            var logger     = new LoggerStub();
            var repo       = new CandleHistoryRepositoryStub();
            var controller = new CandleGenerationController(repo, logger, "test component", env);

            controller.HandleQuote(null).Wait();
            Assert.Equal(0, repo.Stored.Count);
        }
コード例 #4
0
        public void ConfigureServices(ContainerBuilder builder, ILog log)
        {
            var mq = settings.FeedCandlesHistoryWriterBroker.RabbitMq;
            RabbitMqSubscriberSettings subscriberSettings = new RabbitMqSubscriberSettings()
            {
                ConnectionString = $"amqp://{mq.Username}:{mq.Password}@{mq.Host}:{mq.Port}",
                QueueName        = mq.QuoteFeed + ".candleshistorywriter",
                ExchangeName     = mq.QuoteFeed,
                IsDurable        = true
            };

            var dictRepo = new AssetPairsRepository(new AzureTableStorage <AssetPairEntity>(
                                                        settings.FeedCandlesHistoryWriterBroker.ConnectionStrings.DictsConnectionString,
                                                        settings.FeedCandlesHistoryWriterBroker.DictionaryTableName,
                                                        log));

            var env        = new Environment(dictRepo, log, ApplicationName);
            var subscriber = new RabbitMqSubscriber <Quote>(subscriberSettings);

            this.controller = new CandleGenerationController(log, ApplicationName, env);
            this.monitor    = new QueueMonitor(log, this.controller, settings.FeedCandlesHistoryWriterBroker.QueueWarningSize, ApplicationName);
            this.broker     = new Broker(subscriber, log, this.controller, ApplicationName);

            builder.Register(c => new CandleHistoryRepositoryResolver((asset, tableName) => {
                string connString;
                if (!settings.CandleHistoryAssetConnections.TryGetValue(asset, out connString) ||
                    string.IsNullOrEmpty(connString))
                {
                    throw new AppSettingException(string.Format("Connection string for asset pair '{0}' is not specified.", asset));
                }

                var storage = new AzureTableStorage <CandleTableEntity>(connString, tableName, log);
                // Preload table info
                var res = storage.GetDataAsync(asset, "1900-01-01").Result;
                return(storage);
            })).As <ICandleHistoryRepository>();

            builder.RegisterInstance(subscriber)
            .As <IStartable>()
            .As <IStopable>();

            builder.RegisterInstance(this.controller)
            .As <IStartable>()
            .As <IStopable>();

            builder.RegisterInstance(this.monitor)
            .As <IStartable>()
            .As <IStopable>();

            builder.RegisterInstance(this.broker)
            .As <IStartable>()
            .As <IStopable>()
            .As <IPersistent>();
        }
コード例 #5
0
        public void NoExceptionExpectedOnMultithread()
        {
            var logger      = new LoggerStub();
            var candlesRepo = new CandleHistoryRepositoryStub();
            var env         = new EnvironmentStub(new List <AssetPair>()
            {
                new AssetPair()
                {
                    Id = "btcusd", Accuracy = 5
                }
            });
            var controller = new CandleGenerationController(candlesRepo, logger, "test component", env);

            // Cancel after 1 sec
            CancellationTokenSource tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2));
            CancellationToken       token       = tokenSource.Token;

            int consumeCalledTimes = 0;
            int tickCalledTimes    = 0;

            // Call Consume and Tick methods at the same time repeatedly and check that there was no exception.
            Task producing = Task.Run(async() =>
            {
                while (!token.IsCancellationRequested)
                {
                    await controller.HandleQuote(new Quote()
                    {
                        AssetPair = "btcusd",
                        IsBuy     = true,
                        Price     = 100,
                        Timestamp = DateTime.UtcNow
                    });
                    await Task.Delay(50);
                    Interlocked.Increment(ref consumeCalledTimes);
                }
            }, token);

            Task timer = Task.Run(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    controller.Tick();
                    Interlocked.Increment(ref tickCalledTimes);
                }
            }, token);

            Task.WaitAll(producing, timer);

            Assert.True(consumeCalledTimes > 0);
            Assert.True(tickCalledTimes > 0);
            Assert.True(candlesRepo.Stored.Count > 0);
        }
        public void EmptyAssetIsIgnored()
        {
            var logger     = new LoggerStub();
            var repo       = new CandleHistoryRepositoryStub();
            var controller = new CandleGenerationController(repo, logger, "test component", env);

            controller.HandleQuote(new Quote()
            {
                AssetPair = null, IsBuy = true, Price = 1, Timestamp = Utils.ParseUtc("2017-01-01 10:10:10Z")
            }).Wait();
            controller.HandleQuote(new Quote()
            {
                AssetPair = "", IsBuy = true, Price = 1, Timestamp = Utils.ParseUtc("2017-01-01 10:10:10Z")
            }).Wait();

            Assert.Equal(0, repo.Stored.Count);
        }
コード例 #7
0
        public Broker(
            RabbitMqSubscriber <Quote> subscriber,
            ILog logger,
            CandleGenerationController controller,
            string componentName)
            : base(componentName, (int)TimeSpan.FromMinutes(1).TotalMilliseconds, logger)
        {
            this.componentName = componentName;
            this.logger        = logger;
            this.controller    = controller;
            this.subscriber    = subscriber;

            // Using default message reader strategy
            subscriber
            .SetMessageDeserializer(new MessageDeserializer())
            .Subscribe(HandleMessage)
            .SetLogger(logger);
        }
コード例 #8
0
        private static void ProcessAllQuotes(IEnumerable <Quote> quotes, ICandleHistoryRepository repo, LoggerStub logger)
        {
            var env = new EnvironmentStub(new List <AssetPair>()
            {
                new AssetPair()
                {
                    Id = "btcusd", Accuracy = 3
                },
                //new AssetPair() { Id = "btcrub", Accuracy = 3 }
            });
            var controller = new CandleGenerationController(repo, logger, "test component", env);

            var tasks = new List <Task>();

            foreach (var quote in quotes)
            {
                var task = controller.HandleQuote(quote);
                tasks.Add(task);
            }
            Task.WaitAll(tasks.ToArray());

            // ... signal controller to process quotes
            controller.Tick();

            int counter = 0;

            while (counter < 5)
            {
                Task.Delay(1000).Wait(); // Wait while produce task is finished.
                if (controller.QueueLength == 0)
                {
                    break;
                }
                counter++;
            }
            Assert.Equal(0, controller.QueueLength);
        }
        public void ControllerHandlesRepositoryExceptions()
        {
            const string asset1 = "btcusd";
            DateTime     dt     = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var          logger = new LoggerStub();

            ClearTable(asset1, new string[] { "sec", "minute", "min30", "hour", "day", "week", "month" });
            var repo = new CandleHistoryRepositoryResolver((string asset, string tableName) =>
            {
                return(CreateStorage <CandleTableEntity>(asset, tableName, logger, 2, clear: false));
            });

            // 2. Process incoming quotes
            //
            var env = new EnvironmentStub(new List <AssetPair>()
            {
                new AssetPair()
                {
                    Id = asset1, Accuracy = 3
                }
            });
            var controller = new CandleGenerationController(repo, logger, "test component", env);

            for (int i = 0; i < 5; i++)
            {
                var tasks = new List <Task>();

                // pass a quote and signal controller to process quotes
                var q = new Quote()
                {
                    AssetPair = asset1, IsBuy = true, Price = i + 1, Timestamp = dt.AddMinutes(i)
                };
                var task = controller.HandleQuote(q);
                tasks.Add(task);

                Task.WaitAll(tasks.ToArray());

                // ... signal controller to process quotes
                controller.Tick();

                int counter = 0;
                while (counter < 60)
                {
                    Task.Delay(1000).Wait(); // Wait while produce task is finished.
                    if (controller.QueueLength == 0)
                    {
                        break;
                    }
                    counter++;
                }
            }

            Assert.Equal(0, controller.QueueLength);

            controller.Stop();
            // ... check for errors
            //Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count());

            var logs = logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info);

            // 3. Read candles with repository and check count of generated candles
            //
            IEnumerable <IFeedCandle> candles = repo.GetCandlesAsync(asset1, TimeInterval.Minute, PriceType.Bid, dt.AddDays(-1), dt.AddDays(1)).Result;

            Assert.Equal(5, candles.Count());

            candles = repo.GetCandlesAsync(asset1, TimeInterval.Sec, PriceType.Bid, dt.AddDays(-1), dt.AddDays(1)).Result;
            Assert.Equal(5, candles.Count());
        }