private async void ConvertButton_Click(object sender, RoutedEventArgs e)
 {
     _model.IsEnabled = false;
     try
     {
         _model.Output = await _currencyConverterService.Convert(_model.Input);
     }
     catch (ClientException cex)
     {
         MessageBox.Show(cex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
     }
     finally
     {
         _model.IsEnabled = true;
     }
 }
        async public Task <Result> ChangeCurrencyAsync(long userId, decimal amount, int from, int to)
        {
            if (amount <= 0)
            {
                return(AccountRepositoryErrorResultCreator.MoneyLessOrEqualZero(amount));
            }

            if (!_currencyCodesResolver.IsExists(to))
            {
                return(AccountRepositoryErrorResultCreator.CurrencyNotExists(to));
            }

            if (!_currencyCodesResolver.IsExists(from))
            {
                return(AccountRepositoryErrorResultCreator.CurrencyNotExists(from));
            }

            if (from == to)
            {
                return(AccountRepositoryErrorResultCreator.CurrenciesAreSame(from));
            }

            Result <decimal> convertionResult = _currencyConverterService.Convert(amount, from, to);

            if (!convertionResult.IsSuccess)
            {
                return(Result <Dictionary <int, decimal> > .CreateError(convertionResult.ErrorMessage));
            }

            if (convertionResult.Data <= 0)
            {
                return(AccountRepositoryErrorResultCreator.CreateConvertationError(convertionResult.Data));
            }

            using (_dbManager.OpenConnection())
            {
                return(await _dbManager.AccountRepository.ChangeCurrencyAsync(userId, from, amount, to, convertionResult.Data));
            }
        }
        /// <summary>
        /// Take realised profits and then for any remaining amount use virtual profits
        /// </summary>
        public async Task <RevenueMoney> CalculateRevenueOfPosition(
            IList <Order> activeFulfilledTradeOrders,
            DateTime universeDateTime,
            ISystemProcessOperationRunRuleContext ctx,
            IMarketDataCacheStrategy cacheStrategy)
        {
            if (activeFulfilledTradeOrders == null ||
                !activeFulfilledTradeOrders.Any())
            {
                Logger.LogInformation($"RevenueCurrencyConvertingCalculator CalculateRevenueOfPosition had a null or empty active fulfilled trade orders. Returning.");
                return(null);
            }

            var realisedRevenue = await CalculateRealisedRevenue(activeFulfilledTradeOrders, _targetCurrency, universeDateTime, ctx);

            var totalPurchaseVolume = CalculateTotalPurchaseVolume(activeFulfilledTradeOrders);
            var totalSaleVolume     = CalculateTotalSalesVolume(activeFulfilledTradeOrders);

            var sizeOfVirtualPosition = totalPurchaseVolume - totalSaleVolume;

            if (sizeOfVirtualPosition <= 0)
            {
                Logger.LogInformation($"RevenueCurrencyConvertingCalculator CalculateRevenueOfPosition had no virtual position. Total purchase volume of {totalPurchaseVolume} and total sale volume of {totalSaleVolume}. Returning the realised revenue only.");
                // fully traded out position; return its value
                return(new RevenueMoney(false, realisedRevenue, HighProfitComponents.Realised));
            }

            // has a virtual position; calculate its value
            var security = activeFulfilledTradeOrders.FirstOrDefault()?.Instrument;

            if (security == null)
            {
                Logger.LogInformation($"RevenueCurrencyConvertingCalculator CalculateRevenueOfPosition had no virtual position. Total purchase volume of {totalPurchaseVolume} and total sale volume of {totalSaleVolume}. Could not find a security so just returning the realised revenue.");

                return(new RevenueMoney(false, realisedRevenue, HighProfitComponents.Realised));
            }

            var marketDataRequest =
                MarketDataRequest(
                    activeFulfilledTradeOrders.FirstOrDefault()?.Market?.MarketIdentifierCode,
                    security.Identifiers,
                    universeDateTime,
                    ctx,
                    cacheStrategy.DataSource);

            if (marketDataRequest == null)
            {
                Logger.LogInformation($"RevenueCurrencyConvertingCalculator CalculateRevenueOfPosition had no virtual position. Total purchase volume of {totalPurchaseVolume} and total sale volume of {totalSaleVolume}. Returning the realised revenue only.");

                return(new RevenueMoney(false, null, HighProfitComponents.Realised));
            }

            var marketResponse = cacheStrategy.Query(marketDataRequest);

            if (marketResponse.HadMissingData())
            {
                Logger.LogInformation($"Revenue currency converting calculator calculating for inferred virtual profits due to missing market data");

                return(new RevenueMoney(true, null, HighProfitComponents.Virtual));
            }

            var virtualRevenue           = (marketResponse.PriceOrClose()?.Value ?? 0) * sizeOfVirtualPosition;
            var money                    = new Money(virtualRevenue, marketResponse.PriceOrClose()?.Currency.Code ?? string.Empty);
            var convertedVirtualRevenues = await _currencyConverterService.Convert(new[] { money }, _targetCurrency, universeDateTime, ctx);

            if (realisedRevenue == null &&
                convertedVirtualRevenues == null)
            {
                Logger.LogInformation($"Revenue currency converting calculator could not calculate converted virtual revenues, returning null.");
                return(null);
            }

            if (realisedRevenue == null)
            {
                Logger.LogInformation($"Revenue currency converting calculator could not calculate realised revenues, returning unrealised revenues.");
                return(new RevenueMoney(false, convertedVirtualRevenues, HighProfitComponents.Virtual));
            }

            if (convertedVirtualRevenues == null)
            {
                Logger.LogInformation($"Revenue currency converting calculator could not calculate virtual revenues. Returning realised revenues.");
                return(new RevenueMoney(false, realisedRevenue, HighProfitComponents.Realised));
            }

            if (!realisedRevenue.Value.DenominatedInCommonCurrency(convertedVirtualRevenues.Value))
            {
                var convertedMoney =
                    await this._currencyConverterService.Convert(
                        new[] { convertedVirtualRevenues.Value },
                        realisedRevenue.Value.Currency,
                        universeDateTime,
                        ctx);

                if (convertedMoney == null)
                {
                    this.Logger.LogError($"CalculateRevenueOfPosition at {universeDateTime} was unable to convert ({convertedVirtualRevenues.Value.Currency}) {convertedVirtualRevenues.Value.Value} to the realised revenue currency of {realisedRevenue.Value.Currency} due to missing currency conversion data.");

                    return(new RevenueMoney(true, realisedRevenue, HighProfitComponents.Realised));
                }

                convertedVirtualRevenues = convertedMoney.Value;
            }

            var totalMoneys = realisedRevenue + convertedVirtualRevenues;

            var component =
                realisedRevenue.HasValue && realisedRevenue.Value.Value > 0
                ? HighProfitComponents.Hybrid
                : HighProfitComponents.Virtual;

            return(new RevenueMoney(false, totalMoneys, component));
        }