/** * Gets the FX rate for the specified currency pair. * <p> * The rate returned is the rate from the base currency to the counter currency * as defined by this formula: {@code (1 * baseCurrency = fxRate * counterCurrency)}. * * @param currencyPair the ordered currency pair defining the rate required * @return the FX rate for the currency pair * @throws RuntimeException if no FX rate could be found */ public default double fxRate(CurrencyPair currencyPair) { return fxRate(currencyPair.getBase(), currencyPair.getCounter()); }
/** * Gets the FX rate for the specified currency pair on the valuation date. * <p> * The rate returned is the rate from the base currency to the counter currency * as defined by this formula: {@code (1 * baseCurrency = fxRate * counterCurrency)}. * * @param currencyPair the ordered currency pair defining the rate required * @return the current FX rate for the currency pair * @throws IllegalArgumentException if the rate is not available */ @Override public default double fxRate(CurrencyPair currencyPair) { return fxRate(currencyPair.getBase(), currencyPair.getCounter()); }
@ImmutableValidator private void validate() { if (pair.getBase().equals(pair.getCounter()) && rate != 1d) { throw new IllegalArgumentException("Conversion rate between identical currencies must be one"); } }
/** * Obtains an instance from the observation, reference currency and sensitivity value. * <p> * The sensitivity currency is defaulted to be the counter currency of queried currency pair. * * @param observation the rate observation, including the fixing date * @param referenceCurrency the reference currency * @param sensitivity the value of the sensitivity * @return the point sensitivity object */ public static FxIndexSensitivity of(FxIndexObservation observation, Currency referenceCurrency, double sensitivity) { CurrencyPair obsPair = observation.getCurrencyPair(); boolean inverse = referenceCurrency.equals(obsPair.getCounter()); CurrencyPair queriedPair = inverse ? obsPair.inverse() : obsPair; Currency sensiCurrency = queriedPair.getCounter(); return new FxIndexSensitivity(observation, referenceCurrency, sensiCurrency, sensitivity); }
/** * Gets the currency counter to the reference currency. * <p> * The currency pair contains two currencies. One is the reference currency. * This method returns the other. * * @return the counter currency */ public Currency getReferenceCounterCurrency() { boolean inverse = referenceCurrency.equals(currencyPair.getBase()); return inverse ? currencyPair.getCounter() : currencyPair.getBase(); }
/** * Adds a new rate for a currency pair to the builder. See * {@link #addRate(Currency, Currency, double)} for full * explanation. * * @param currencyPair the currency pair to be added * @param rate the FX rate between the base currency of the pair and the * counter currency. The rate indicates the value of one unit of the base * currency in terms of the counter currency. * @return the builder updated with the new rate */ public FxMatrixBuilder addRate(CurrencyPair currencyPair, double rate) { ArgChecker.notNull(currencyPair, "currencyPair"); return addRate(currencyPair.getBase(), currencyPair.getCounter(), rate); }
@ImmutableValidator private void validate() { if (pair.getBase().equals(pair.getCounter()) && !rates.stream().allMatch(v -> v == 1d)) { throw new IllegalArgumentException("Conversion rate between identical currencies must be one"); } }
@Override public FxForwardRates fxForwardRates(CurrencyPair currencyPair) { DiscountFactors base = discountFactors(currencyPair.getBase()); DiscountFactors counter = discountFactors(currencyPair.getCounter()); return DiscountFxForwardRates.of(currencyPair, fxRateProvider, base, counter); };
private static FxRate computeCross(FxRate fx1, FxRate fx2, CurrencyPair crossPairAC) { // aim is to convert AAA/BBB and BBB/CCC to AAA/CCC Currency currA = crossPairAC.getBase(); Currency currC = crossPairAC.getCounter(); // given the conventional cross rate pair, order the two rates to match boolean crossBaseCurrencyInFx1 = fx1.pair.contains(currA); FxRate fxABorBA = crossBaseCurrencyInFx1 ? fx1 : fx2; FxRate fxBCorCB = crossBaseCurrencyInFx1 ? fx2 : fx1; // extract the rates, taking the inverse if the pair is in the inverse order double rateAB = fxABorBA.getPair().getBase().equals(currA) ? fxABorBA.rate : 1d / fxABorBA.rate; double rateBC = fxBCorCB.getPair().getCounter().equals(currC) ? fxBCorCB.rate : 1d / fxBCorCB.rate; return FxRate.of(crossPairAC, rateAB * rateBC); }
public void test_of_CurrencyCurrency() { CurrencyPair test = CurrencyPair.of(GBP, USD); assertEquals(test.getBase(), GBP); assertEquals(test.getCounter(), USD); assertEquals(test.isIdentity(), false); assertEquals(test.toSet(), ImmutableSet.of(GBP, USD)); assertEquals(test.toString(), "GBP/USD"); }
public void test_of_CurrencyCurrency_same() { CurrencyPair test = CurrencyPair.of(USD, USD); assertEquals(test.getBase(), USD); assertEquals(test.getCounter(), USD); assertEquals(test.isIdentity(), true); assertEquals(test.toString(), "USD/USD"); }
@Override public double rateFxSpotSensitivity(Currency baseCurrency, LocalDate referenceDate) { ArgChecker.isTrue( currencyPair.contains(baseCurrency), "Currency {} invalid for CurrencyPair {}", baseCurrency, currencyPair); boolean inverse = baseCurrency.equals(currencyPair.getCounter()); double dfCcyBaseAtMaturity = baseCurrencyDiscountFactors.discountFactor(referenceDate); double dfCcyCounterAtMaturity = counterCurrencyDiscountFactors.discountFactor(referenceDate); double forwardRateDelta = dfCcyBaseAtMaturity / dfCcyCounterAtMaturity; return inverse ? 1d / forwardRateDelta : forwardRateDelta; }
/** * Gets the non-deliverable currency. * <p> * Returns the currency that is not the settlement currency. * * @return the currency that is not to be settled */ public Currency getNonDeliverableCurrency() { Currency base = agreedFxRate.getPair().getBase(); return base.equals(getSettlementCurrency()) ? agreedFxRate.getPair().getCounter() : base; }
public void test_of_CurrencyCurrency_reverseStandardOrder() { CurrencyPair test = CurrencyPair.of(USD, GBP); assertEquals(test.getBase(), USD); assertEquals(test.getCounter(), GBP); assertEquals(test.isIdentity(), false); assertEquals(test.toSet(), ImmutableSet.of(GBP, USD)); assertEquals(test.toString(), "USD/GBP"); }
@Override public double rate(Currency baseCurrency, LocalDate referenceDate) { ArgChecker.isTrue( currencyPair.contains(baseCurrency), "Currency {} invalid for CurrencyPair {}", baseCurrency, currencyPair); boolean inverse = baseCurrency.equals(currencyPair.getCounter()); double dfCcyBaseAtMaturity = baseCurrencyDiscountFactors.discountFactor(referenceDate); double dfCcyCounterAtMaturity = counterCurrencyDiscountFactors.discountFactor(referenceDate); double forwardRate = fxRateProvider.fxRate(currencyPair) * (dfCcyBaseAtMaturity / dfCcyCounterAtMaturity); return inverse ? 1d / forwardRate : forwardRate; }
private FxRateScenarioArray computeCross(FxRateScenarioArray other, CurrencyPair crossPairAC) { // aim is to convert AAA/BBB and BBB/CCC to AAA/CCC Currency currA = crossPairAC.getBase(); Currency currC = crossPairAC.getCounter(); // given the conventional cross rate pair, order the two rates to match boolean crossBaseCurrencyInFx1 = pair.contains(currA); FxRateScenarioArray fxABorBA = crossBaseCurrencyInFx1 ? this : other; FxRateScenarioArray fxBCorCB = crossBaseCurrencyInFx1 ? other : this; // extract the rates, taking the inverse if the pair is in the inverse order DoubleArray ratesAB = fxABorBA.getPair().getBase().equals(currA) ? fxABorBA.rates : fxABorBA.rates.map(v -> 1 / v); DoubleArray ratesBC = fxBCorCB.getPair().getCounter().equals(currC) ? fxBCorCB.rates : fxBCorCB.rates.map(v -> 1 / v); return FxRateScenarioArray.of(crossPairAC, ratesAB.multipliedBy(ratesBC)); }
/** * Gets the payment currency. * <p> * This returns the currency that the payment is made in. * ISDA refers to this as the <i>variable currency</i>. * * @return the payment currency */ @Override public Currency getCurrency() { FxIndex index = observation.getIndex(); Currency indexBase = index.getCurrencyPair().getBase(); Currency indexCounter = index.getCurrencyPair().getCounter(); return (getReferenceCurrency().equals(indexBase) ? indexCounter : indexBase); }
/** * Gets the non-deliverable currency. * <p> * Returns the currency that is not the settlement currency. * * @return the currency that is not to be settled */ public Currency getNonDeliverableCurrency() { FxIndex index = getIndex(); return index.getCurrencyPair().getBase().equals(getSettlementCurrency()) ? index.getCurrencyPair().getCounter() : index.getCurrencyPair().getBase(); }
@Override public double rate(FxIndexObservation observation, Currency baseCurrency) { ArgChecker.isTrue( index.getCurrencyPair().contains(baseCurrency), "Currency {} invalid for FxIndex {}", baseCurrency, index); LocalDate fixingDate = observation.getFixingDate(); double fxIndexRate = !fixingDate.isAfter(getValuationDate()) ? historicRate(observation) : forwardRate(observation); boolean inverse = baseCurrency.equals(index.getCurrencyPair().getCounter()); return (inverse ? 1d / fxIndexRate : fxIndexRate); }
private static FxSingle create( CurrencyAmount amount, FxRate fxRate, LocalDate paymentDate, BusinessDayAdjustment paymentDateAdjustment) { ArgChecker.notNull(amount, "amount"); ArgChecker.notNull(fxRate, "fxRate"); ArgChecker.notNull(paymentDate, "paymentDate"); CurrencyPair pair = fxRate.getPair(); if (!pair.contains(amount.getCurrency())) { throw new IllegalArgumentException(Messages.format( "FxRate '{}' and CurrencyAmount '{}' must have a currency in common", fxRate, amount)); } Currency currency2 = pair.getBase().equals(amount.getCurrency()) ? pair.getCounter() : pair.getBase(); CurrencyAmount amountCurrency2 = amount.convertedTo(currency2, fxRate).negated(); return create(amount, amountCurrency2, paymentDate, paymentDateAdjustment); }