All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdm.event.common.functions.Create_OnDemandInterestPaymentPrimitiveInstruction Maven / Gradle / Ivy

There is a newer version: 6.0.0-dev.89
Show newest version
package cdm.event.common.functions;

import cdm.base.math.NonNegativeQuantitySchedule;
import cdm.base.math.UnitType;
import cdm.base.math.metafields.ReferenceWithMetaNonNegativeQuantitySchedule;
import cdm.base.staticdata.party.PayerReceiver;
import cdm.event.common.PrimitiveInstruction;
import cdm.event.common.PrimitiveInstruction.PrimitiveInstructionBuilder;
import cdm.event.common.Trade;
import cdm.event.common.TradeState;
import cdm.observable.asset.Money;
import cdm.product.asset.InterestRatePayout;
import cdm.product.common.settlement.Cashflow;
import cdm.product.common.settlement.CashflowType;
import cdm.product.common.settlement.ResolvablePriceQuantity;
import cdm.product.common.settlement.ScheduledTransferEnum;
import cdm.product.common.settlement.SettlementDate;
import cdm.product.template.EconomicTerms;
import cdm.product.template.NonTransferableProduct;
import cdm.product.template.Payout;
import com.google.inject.ImplementedBy;
import com.rosetta.model.lib.expression.CardinalityOperator;
import com.rosetta.model.lib.functions.ConditionValidator;
import com.rosetta.model.lib.functions.ModelObjectValidator;
import com.rosetta.model.lib.functions.RosettaFunction;
import com.rosetta.model.lib.mapper.MapperS;
import com.rosetta.model.metafields.FieldWithMetaString;
import java.math.BigDecimal;
import java.util.Optional;
import javax.inject.Inject;

import static com.rosetta.model.lib.expression.ExpressionOperators.*;

@ImplementedBy(Create_OnDemandInterestPaymentPrimitiveInstruction.Create_OnDemandInterestPaymentPrimitiveInstructionDefault.class)
public abstract class Create_OnDemandInterestPaymentPrimitiveInstruction implements RosettaFunction {
	
	@Inject protected ConditionValidator conditionValidator;
	
	@Inject protected ModelObjectValidator objectValidator;
	
	// RosettaFunction dependencies
	//
	@Inject protected Create_Cashflow create_Cashflow;
	@Inject protected Create_CashflowTermsChangeInstruction create_CashflowTermsChangeInstruction;

	/**
	* @param tradeState The original trade to be modified.
	* @param interestAmount 
	* @param settlementDate 
	* @return instruction Result is a Terms Change Instruction.
	*/
	public PrimitiveInstruction evaluate(TradeState tradeState, Money interestAmount, SettlementDate settlementDate) {
		// pre-conditions
		conditionValidator.validate(() -> exists(interestRatePayout(tradeState, interestAmount, settlementDate)),
			"Only a contractual product with a single interest rate payout can have an on-demand interest payment.");
		
		conditionValidator.validate(() -> areEqual(MapperS.of(interestAmount).map("getUnit", money -> money.getUnit()).map("getCurrency", unitType -> unitType.getCurrency()).map("Type coercion", fieldWithMetaString0 -> fieldWithMetaString0 == null ? null : fieldWithMetaString0.getValue()), interestRatePayout(tradeState, interestAmount, settlementDate).map("getPriceQuantity", _interestRatePayout -> _interestRatePayout.getPriceQuantity()).map("getQuantitySchedule", resolvablePriceQuantity -> resolvablePriceQuantity.getQuantitySchedule()).map("Type coercion", referenceWithMetaNonNegativeQuantitySchedule -> referenceWithMetaNonNegativeQuantitySchedule == null ? null : referenceWithMetaNonNegativeQuantitySchedule.getValue()).map("getUnit", nonNegativeQuantitySchedule -> nonNegativeQuantitySchedule.getUnit()).map("getCurrency", unitType -> unitType.getCurrency()).map("Type coercion", fieldWithMetaString1 -> fieldWithMetaString1 == null ? null : fieldWithMetaString1.getValue()), CardinalityOperator.All),
			"The currency of the interest amount must match the currency of the original interest rate payout.");
		
		PrimitiveInstruction.PrimitiveInstructionBuilder instructionBuilder = doEvaluate(tradeState, interestAmount, settlementDate);
		
		final PrimitiveInstruction instruction;
		if (instructionBuilder == null) {
			instruction = null;
		} else {
			instruction = instructionBuilder.build();
			objectValidator.validate(PrimitiveInstruction.class, instruction);
		}
		
		return instruction;
	}

	protected abstract PrimitiveInstruction.PrimitiveInstructionBuilder doEvaluate(TradeState tradeState, Money interestAmount, SettlementDate settlementDate);

	protected abstract MapperS interestRatePayout(TradeState tradeState, Money interestAmount, SettlementDate settlementDate);

	protected abstract MapperS cashflow(TradeState tradeState, Money interestAmount, SettlementDate settlementDate);

	public static class Create_OnDemandInterestPaymentPrimitiveInstructionDefault extends Create_OnDemandInterestPaymentPrimitiveInstruction {
		@Override
		protected PrimitiveInstruction.PrimitiveInstructionBuilder doEvaluate(TradeState tradeState, Money interestAmount, SettlementDate settlementDate) {
			PrimitiveInstruction.PrimitiveInstructionBuilder instruction = PrimitiveInstruction.builder();
			return assignOutput(instruction, tradeState, interestAmount, settlementDate);
		}
		
		protected PrimitiveInstruction.PrimitiveInstructionBuilder assignOutput(PrimitiveInstruction.PrimitiveInstructionBuilder instruction, TradeState tradeState, Money interestAmount, SettlementDate settlementDate) {
			instruction = toBuilder(PrimitiveInstruction.builder()
				.setTermsChange(create_CashflowTermsChangeInstruction.evaluate(MapperS.of(tradeState).map("getTrade", _tradeState -> _tradeState.getTrade()).map("getProduct", trade -> trade.getProduct()).get(), cashflow(tradeState, interestAmount, settlementDate).get()))
				.build());
			
			return Optional.ofNullable(instruction)
				.map(o -> o.prune())
				.orElse(null);
		}
		
		@Override
		protected MapperS interestRatePayout(TradeState tradeState, Money interestAmount, SettlementDate settlementDate) {
			return MapperS.of(MapperS.of(tradeState).map("getTrade", _tradeState -> _tradeState.getTrade()).map("getProduct", trade -> trade.getProduct()).map("getEconomicTerms", nonTransferableProduct -> nonTransferableProduct.getEconomicTerms()).mapC("getPayout", economicTerms -> economicTerms.getPayout()).map("getInterestRatePayout", payout -> payout.getInterestRatePayout()).get());
		}
		
		@Override
		protected MapperS cashflow(TradeState tradeState, Money interestAmount, SettlementDate settlementDate) {
			final FieldWithMetaString fieldWithMetaString = interestRatePayout(tradeState, interestAmount, settlementDate).map("getPriceQuantity", _interestRatePayout -> _interestRatePayout.getPriceQuantity()).map("getQuantitySchedule", resolvablePriceQuantity -> resolvablePriceQuantity.getQuantitySchedule()).map("Type coercion", referenceWithMetaNonNegativeQuantitySchedule -> referenceWithMetaNonNegativeQuantitySchedule == null ? null : referenceWithMetaNonNegativeQuantitySchedule.getValue()).map("getUnit", nonNegativeQuantitySchedule -> nonNegativeQuantitySchedule.getUnit()).map("getCurrency", unitType -> unitType.getCurrency()).get();
			return MapperS.of(create_Cashflow.evaluate(MapperS.of(interestAmount).map("getValue", money -> money.getValue()).get(), (fieldWithMetaString == null ? null : fieldWithMetaString.getValue()), settlementDate, interestRatePayout(tradeState, interestAmount, settlementDate).map("getPayerReceiver", _interestRatePayout -> _interestRatePayout.getPayerReceiver()).get(), CashflowType.builder()
				.setCashflowType(ScheduledTransferEnum.NET_INTEREST)
				.build(), null));
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy