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

cdm.event.common.functions.Create_QuantityChange 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.QuantityChangeDirectionEnum;
import cdm.base.math.metafields.FieldWithMetaNonNegativeQuantitySchedule;
import cdm.base.staticdata.identifier.Identifier;
import cdm.base.staticdata.party.AncillaryParty;
import cdm.base.staticdata.party.Counterparty;
import cdm.event.common.QuantityChangeInstruction;
import cdm.event.common.Trade;
import cdm.event.common.TradeState;
import cdm.event.common.TradeState.TradeStateBuilder;
import cdm.event.position.PositionStatusEnum;
import cdm.observable.asset.PriceSchedule;
import cdm.observable.asset.PriceTypeEnum;
import cdm.observable.asset.metafields.FieldWithMetaPriceSchedule;
import cdm.product.common.NotionalAdjustmentEnum;
import cdm.product.common.settlement.PriceQuantity;
import cdm.product.common.settlement.functions.UpdateAmountForEachMatchingQuantity;
import cdm.product.template.Product;
import cdm.product.template.TradableProduct;
import cdm.product.template.TradeLot;
import cdm.product.template.functions.AddTradeLot;
import cdm.product.template.functions.FilterTradeLot;
import cdm.product.template.functions.MergeTradeLot;
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.Mapper;
import com.rosetta.model.lib.mapper.MapperC;
import com.rosetta.model.lib.mapper.MapperS;
import com.rosetta.model.lib.mapper.MapperUtils;
import java.math.BigDecimal;
import java.util.Optional;
import javax.inject.Inject;

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

@ImplementedBy(Create_QuantityChange.Create_QuantityChangeDefault.class)
public abstract class Create_QuantityChange implements RosettaFunction {
	
	@Inject protected ConditionValidator conditionValidator;
	
	@Inject protected ModelObjectValidator objectValidator;
	
	// RosettaFunction dependencies
	//
	@Inject protected AddTradeLot addTradeLot;
	@Inject protected FilterTradeLot filterTradeLot;
	@Inject protected MergeTradeLot mergeTradeLot;
	@Inject protected UpdateAmountForEachMatchingQuantity updateAmountForEachMatchingQuantity;

	/**
	* @param instruction 
	* @param tradeState 
	* @return quantityChange 
	*/
	public TradeState evaluate(QuantityChangeInstruction instruction, TradeState tradeState) {
		// pre-conditions
		conditionValidator.validate(() -> 
			MapperUtils.toComparisonResult(MapperUtils.runSingle(() -> {
				if (areEqual(MapperS.of(instruction).map("getDirection", quantityChangeInstruction -> quantityChangeInstruction.getDirection()), MapperS.of(QuantityChangeDirectionEnum.DECREASE), CardinalityOperator.All).and(exists(MapperS.of(instruction).mapC("getChange", quantityChangeInstruction -> quantityChangeInstruction.getChange()).mapC("getPrice", priceQuantity -> priceQuantity.getPrice()).map("getValue", _f->_f.getValue()))).getOrDefault(false)) {
					return areEqual(MapperS.of(instruction).mapC("getChange", quantityChangeInstruction -> quantityChangeInstruction.getChange()).mapC("getPrice", priceQuantity -> priceQuantity.getPrice()).map("getValue", _f->_f.getValue()).map("getPriceType", priceSchedule -> priceSchedule.getPriceType()), MapperS.of(PriceTypeEnum.CASH_PRICE), CardinalityOperator.All);
				}
				else {
					return null;
				}
			})), 
				"Only termination where the termination price is specified as a cash price is supported for now.");
		
		TradeState.TradeStateBuilder quantityChangeBuilder = doEvaluate(instruction, tradeState);
		
		final TradeState quantityChange;
		if (quantityChangeBuilder == null) {
			quantityChange = null;
		} else {
			quantityChange = quantityChangeBuilder.build();
			objectValidator.validate(TradeState.class, quantityChange);
		}
		
		return quantityChange;
	}

	protected abstract TradeState.TradeStateBuilder doEvaluate(QuantityChangeInstruction instruction, TradeState tradeState);

	protected abstract Mapper tradableProduct(QuantityChangeInstruction instruction, TradeState tradeState);

	protected abstract Mapper tradeLot(QuantityChangeInstruction instruction, TradeState tradeState);

	protected abstract Mapper newPriceQuantity(QuantityChangeInstruction instruction, TradeState tradeState);

	protected abstract Mapper newTradeLots(QuantityChangeInstruction instruction, TradeState tradeState);

	public static class Create_QuantityChangeDefault extends Create_QuantityChange {
		@Override
		protected TradeState.TradeStateBuilder doEvaluate(QuantityChangeInstruction instruction, TradeState tradeState) {
			TradeState.TradeStateBuilder quantityChange = TradeState.builder();
			return assignOutput(quantityChange, instruction, tradeState);
		}
		
		protected TradeState.TradeStateBuilder assignOutput(TradeState.TradeStateBuilder quantityChange, QuantityChangeInstruction instruction, TradeState tradeState) {
			quantityChange = toBuilder(MapperS.of(tradeState).get());
			
			quantityChange
				.getOrCreateTrade()
				.setTradableProduct(MapperS.of(TradableProduct.builder()
					.setProduct(MapperS.of(tradableProduct(instruction, tradeState).get()).map("getProduct", _tradableProduct -> _tradableProduct.getProduct()).get())
					.setTradeLot(MapperC.of(newTradeLots(instruction, tradeState).getMulti()).getMulti())
					.setCounterparty(MapperS.of(tradableProduct(instruction, tradeState).get()).mapC("getCounterparty", _tradableProduct -> _tradableProduct.getCounterparty()).getMulti())
					.setAncillaryParty(MapperS.of(tradableProduct(instruction, tradeState).get()).mapC("getAncillaryParty", _tradableProduct -> _tradableProduct.getAncillaryParty()).getMulti())
					.setAdjustment(MapperS.of(tradableProduct(instruction, tradeState).get()).map("getAdjustment", _tradableProduct -> _tradableProduct.getAdjustment()).get())
					.build())
				.get());
			
			quantityChange
				.getOrCreateState()
				.setPositionState(MapperUtils.runSingle(() -> {
					if (areEqual(MapperC.of(newTradeLots(instruction, tradeState).getMulti()).mapC("getPriceQuantity", _tradeLot -> _tradeLot.getPriceQuantity()).mapC("getQuantity", priceQuantity -> priceQuantity.getQuantity()).map("getValue", _f->_f.getValue()).map("getValue", measureBase -> measureBase.getValue()), MapperS.of(Integer.valueOf(0)), CardinalityOperator.All).getOrDefault(false)) {
						return MapperS.of(PositionStatusEnum.CLOSED);
					}
					else {
						return null;
					}
				}).get());
			
			return Optional.ofNullable(quantityChange)
				.map(o -> o.prune())
				.orElse(null);
		}
		
		@Override
		protected Mapper tradableProduct(QuantityChangeInstruction instruction, TradeState tradeState) {
			return MapperS.of(tradeState).map("getTrade", _tradeState -> _tradeState.getTrade()).map("getTradableProduct", trade -> trade.getTradableProduct());
		}
		
		@Override
		protected Mapper tradeLot(QuantityChangeInstruction instruction, TradeState tradeState) {
			return MapperUtils.runSinglePolymorphic(() -> {
				if (notEqual(MapperS.of(instruction).map("getDirection", quantityChangeInstruction -> quantityChangeInstruction.getDirection()), MapperS.of(QuantityChangeDirectionEnum.INCREASE), CardinalityOperator.Any).getOrDefault(false)) {
					return MapperUtils.runSinglePolymorphic(() -> {
						if (exists(MapperS.of(instruction).mapC("getLotIdentifier", quantityChangeInstruction -> quantityChangeInstruction.getLotIdentifier())).getOrDefault(false)) {
							return MapperS.of(MapperC.of(filterTradeLot.evaluate(MapperS.of(tradableProduct(instruction, tradeState).get()).mapC("getTradeLot", _tradableProduct -> _tradableProduct.getTradeLot()).getMulti(), MapperS.of(instruction).mapC("getLotIdentifier", quantityChangeInstruction -> quantityChangeInstruction.getLotIdentifier()).getMulti())).get());
						}
						else {
							return MapperS.of(MapperS.of(tradableProduct(instruction, tradeState).get()).mapC("getTradeLot", _tradableProduct -> _tradableProduct.getTradeLot()).get());
						}
					});
				}
				else {
					return null;
				}
			});
		}
		
		@Override
		protected Mapper newPriceQuantity(QuantityChangeInstruction instruction, TradeState tradeState) {
			return MapperUtils.runMultiPolymorphic(() -> {
				if (areEqual(MapperS.of(instruction).map("getDirection", quantityChangeInstruction -> quantityChangeInstruction.getDirection()), MapperS.of(QuantityChangeDirectionEnum.INCREASE), CardinalityOperator.All).getOrDefault(false)) {
					return MapperS.of(instruction).mapC("getChange", quantityChangeInstruction -> quantityChangeInstruction.getChange());
				}
				else {
					return MapperC.of(updateAmountForEachMatchingQuantity.evaluate(MapperS.of(tradeLot(instruction, tradeState).get()).mapC("getPriceQuantity", _tradeLot -> _tradeLot.getPriceQuantity()).getMulti(), MapperS.of(instruction).mapC("getChange", quantityChangeInstruction -> quantityChangeInstruction.getChange()).getMulti(), MapperS.of(instruction).map("getDirection", quantityChangeInstruction -> quantityChangeInstruction.getDirection()).get()));
				}
			});
		}
		
		@Override
		protected Mapper newTradeLots(QuantityChangeInstruction instruction, TradeState tradeState) {
			return MapperUtils.runMultiPolymorphic(() -> {
				if (areEqual(MapperS.of(instruction).map("getDirection", quantityChangeInstruction -> quantityChangeInstruction.getDirection()), MapperS.of(QuantityChangeDirectionEnum.INCREASE), CardinalityOperator.All).getOrDefault(false)) {
					return MapperS.of(addTradeLot.evaluate(MapperS.of(tradableProduct(instruction, tradeState).get()).get(), MapperS.of(TradeLot.builder()
						.setLotIdentifier(MapperS.of(instruction).mapC("getLotIdentifier", quantityChangeInstruction -> quantityChangeInstruction.getLotIdentifier()).getMulti())
						.setPriceQuantity(MapperC.of(newPriceQuantity(instruction, tradeState).getMulti()).getMulti())
						.build())
					.get())).mapC("getTradeLot", _tradableProduct -> _tradableProduct.getTradeLot());
				}
				else {
					return MapperC.of(mergeTradeLot.evaluate(MapperS.of(tradableProduct(instruction, tradeState).get()).mapC("getTradeLot", _tradableProduct -> _tradableProduct.getTradeLot()).getMulti(), MapperS.of(TradeLot.builder()
						.setLotIdentifier(MapperS.of(instruction).mapC("getLotIdentifier", quantityChangeInstruction -> quantityChangeInstruction.getLotIdentifier()).getMulti())
						.setPriceQuantity(MapperC.of(newPriceQuantity(instruction, tradeState).getMulti()).getMulti())
						.build())
					.get()));
				}
			});
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy