public async Task Calculate_should_return_zero_if_portfolio_is_null() { IEnumerable <Quote> quotes = new Quote[0]; // ReSharper disable once ConvertToLocalFunction QuoteLoaderDelegate quoteLoader = symbols => Task.FromResult(quotes); (await PortfolioValueCalculator.Calculate(null, quoteLoader)).Should().Be(0); }
public async Task Calculate_should_be_OK_if_there_are_more_quotes_than_assets() { IEnumerable <Quote> quotes = new[] { new Quote(new Symbol("MSFT"), 100), new Quote(new Symbol("AAPL"), 200) }; // ReSharper disable once ConvertToLocalFunction QuoteLoaderDelegate quoteLoader = symbols => Task.FromResult(quotes); var portfolio = new Portfolio(); portfolio.AddAsset(new Asset(new Symbol("MSFT"), 10)); (await PortfolioValueCalculator.Calculate(portfolio, quoteLoader)).Should().Be(1000); }
public async Task Calculate_should_set_total_value() { // ReSharper disable once ConvertToLocalFunction QuoteLoaderDelegate quoteLoaderPrice100 = symbols => Task.FromResult(symbols.Select(symbol => new Quote(symbol, 100))); var portfolioWithValue = new PortfolioWithValue(quoteLoaderPrice100); await portfolioWithValue.Load(); portfolioWithValue.AddAsset(new Asset(new Symbol("MSFT"), 10)); portfolioWithValue.AddAsset(new Asset(new Symbol("AAPL"), 10)); #pragma warning disable 4014 portfolioWithValue.Calculate(); #pragma warning restore 4014 portfolioWithValue.TotalValue.Should().Be(2000); }
public async Task Adding_an_asset_should_change_the_portfolio_assets_and_fire_property_changed_event() { // ReSharper disable once ConvertToLocalFunction QuoteLoaderDelegate quoteLoaderPrice100 = symbols => Task.FromResult(symbols.Select(symbol => new Quote(symbol, 100))); var viewModel = new MainViewModel(new PortfolioWithValue(quoteLoaderPrice100)); await viewModel.Load(); using (IMonitor <MainViewModel> viewModelMonitored = viewModel.Monitor()) { viewModel.NewAssetSymbol = "MSFT"; viewModel.NewAssetAmount = 100; await viewModel.AddAsset(); viewModelMonitored.Should().RaisePropertyChangeFor(vm => vm.PortfolioDescription); viewModel.Portfolio.Assets.Should().BeEquivalentTo(new Asset(new Symbol("MSFT"), 100)); viewModelMonitored.Should().RaisePropertyChangeFor(vm => vm.PortfolioValueDescription); viewModel.TotalValue.Should().Be(10000); } }
public static async Task <decimal> Calculate([CanBeNull] Portfolio portfolio, [NotNull] QuoteLoaderDelegate quoteLoader) { decimal totalValue = 0; if (portfolio != null) { IEnumerable <Symbol> symbols = portfolio.Assets.Select(asset => asset.Symbol); // ReSharper disable once PossibleNullReferenceException IEnumerable <Quote> quotes = await quoteLoader(symbols); totalValue = portfolio.Assets .Join(quotes, asset => asset.Symbol, quote => quote.Symbol, (asset, quote) => quote != null ? asset.Amount * quote.Price : 0) .Sum(); } return(totalValue); }
public PortfolioWithValue([NotNull] QuoteLoaderDelegate quoteLoader) : this(new InMemoryPortfolioStore(), quoteLoader) { }
public PortfolioWithValue([NotNull] IPortfolioStore portfolioStore, [NotNull] QuoteLoaderDelegate quoteLoader) { _portfolioStore = portfolioStore; _quoteLoader = quoteLoader; }