investments 2.16.2

Helps you with managing your investments
Documentation
use crate::core::GenericResult;
use crate::currency::Cash;
use crate::currency::converter::CurrencyConverter;
use crate::types::Decimal;
use crate::util;

pub fn convert_price(
    price: Cash, quantity: Decimal, currency: &str, converter: &CurrencyConverter,
) -> GenericResult<Cash> {
    let volume = price * quantity;

    let volume_precision = util::decimal_precision(volume.amount) + 2;
    let converted_volume = util::round(
        converter.real_time_convert_to(volume, currency)?,
        volume_precision);

    Ok(calculate_price(quantity, Cash::new(currency, converted_volume)).map_err(|e| format!(
        "Unable to convert {} x {} price to {}: {}",
        quantity, price, currency, e
    ))?)
}

pub fn calculate_price(quantity: Decimal, volume: Cash) -> GenericResult<Cash> {
    let volume_precision = util::decimal_precision(volume.amount);

    let mut price = volume.amount / quantity;
    let mut price_precision = volume_precision;

    loop {
        let round_price = util::round(price, price_precision);

        if util::round(round_price * quantity, volume_precision) == volume.amount {
            price = round_price.normalize();
            break;
        }

        if price_precision >= 20 {
            return Err!(
                "Unable to calculate {} / {} price with a reasonable precision",
                volume, quantity);
        }
        price_precision += 1;
    }

    Ok(Cash::new(volume.currency, price))
}