public void When_StringWeightReporter_Given_Fundbot_Portfolio_Then_Report_Is_Written_To_String()
        {
            // setup
            var portfolio = TestDataGenerator.GenerateFundbotPortfolio();
            var categories = TestDataGenerator.GenerateFundbotCategories().ToList();
            var weights = TestDataGenerator.GenerateFundbotWeights(categories).ToList();

            _quoterMock.Setup(m => m.GetQuotes(It.IsAny<IEnumerable<Security>>())).Returns(new Dictionary<string, decimal>
            {
                {"XFN.TO", 29.97M},
                {"AGG", 1000.69M},
                {"XIU.TO", 21.1M},
                {"CPD.TO", 16.55M},
                {"EFA", 68.24M},
            });

            // execute
            StringWeightReporter reporter = new StringWeightReporter(_quoterMock.Object);
            var result = reporter.GetReport(portfolio, categories, weights);

            // validate
            Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.Not.Empty);

            const string expected = @"Portfolio: {0}

            Region
            USD: 57.2%
            CAD: 28.3%
            INTL: 14.5%

            Asset Class
            Bonds: 57.2%
            Equity: 25.3%
            Preferred: 17.5%

            Currency
            USD: 71.7%
            CAD: 28.3%
            ";
            Assert.That(result, Is.EqualTo(string.Format(expected, portfolio.Name)));
        }
        private static ErrorCode QuickQuestradeWeightReportOperation(string portfolioName)
        {
            var portfolio = new Portfolio
            {
                Name = portfolioName
            };
            var categoryRepository = new InMemoryCategoryRepository();
            var securityCategory = categoryRepository.GetCategory("Security");
            var currencyCategory = categoryRepository.GetCategory("Currency");
            using (var tokenManager = new QuestradeApiTokenManager(Configuration))
            {
                var api = new QuestradeService(tokenManager, new InMemorySecurityRepository(), categoryRepository);
                portfolio.Accounts = api.GetAccounts();
                var weights = new List<CategoryWeight>();

                foreach (var account in portfolio.Accounts)
                {
                    account.Positions = api.GetPositions(account);
                    foreach (var position in account.Positions)
                    {
                        weights.AddRange(api.GetWeights(securityCategory, position.Security));
                        weights.AddRange(api.GetWeights(currencyCategory, position.Security));
                    }
                }

                var reporter = new StringWeightReporter(api);
                var report = reporter.GetReport(portfolio, new[] {securityCategory, currencyCategory}, weights.Distinct());

                Console.Write(report);
            }

            return ErrorCode.NoError;
        }
        private static ErrorCode QuickFundbotWeightReportOperation(string portfolioName)
        {
            var dataDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(Configuration.DataDirectoryPath));

            if (!Directory.Exists(dataDir))
            {
                Console.Error.WriteLine("Data directory at {0} does not exist.", dataDir);
                return ErrorCode.DirectoryMissing;
            }

            var fundbotBuysFile = Path.Combine(dataDir, "buys.csv");
            if (!File.Exists(fundbotBuysFile))
            {
                Console.Error.WriteLine("Fundbot file at {0} does not exist.", fundbotBuysFile);
                return ErrorCode.FileMissing;
            }

            var fundbotCategoriesFile = Path.Combine(dataDir, "categories.csv");
            if (!File.Exists(fundbotCategoriesFile))
            {
                Console.Error.WriteLine("Fundbot file at {0} does not exist.", fundbotCategoriesFile);
                return ErrorCode.FileMissing;
            }

            var factory = new DataImporterFactory();
            var transactionReader = factory.GetFundbotTransactions(fundbotBuysFile);
            var transactions = transactionReader.GetTransactions();

            var account = new Account
            {
                Name = portfolioName
            };
            var portfolio = new Portfolio
            {
                Name = portfolioName,
                Accounts = new List<Account> { account }
            };
            account.Portfolio = portfolio;

            foreach (var transaction in transactions)
            {
                transaction.Account = account;
            }

            var portfolioService = new PortfolioService(portfolio);
            portfolioService.UpdateWith(transactions);

            var categoryReader = factory.GetFundbotCategories(fundbotCategoriesFile);
            IEnumerable<Category> categories;
            IEnumerable<CategoryWeight> weights;
            categoryReader.GetCategoriesAndWeights(out categories, out weights);

            var quoter = new YahooStockService(new YahooServiceFactory());
            StringWeightReporter reporter = new StringWeightReporter(quoter);
            var report = reporter.GetReport(portfolio, categories, weights);

            Console.Write(report);

            return ErrorCode.NoError;
        }