Skip to content

Commit

Permalink
Position cash (#504)
Browse files Browse the repository at this point in the history
* Allocate func implementation

* Merge origin/master

* Add Position.cashBalance and Lineage.transferReference
  • Loading branch information
hugohills-regnosys authored Sep 26, 2019
1 parent 870292b commit 64ac8e3
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,22 @@ protected PortfolioStateBuilder doEvaluate(Portfolio input) {
Collectors.reducing(BigDecimal.ZERO, this::getAggregationQuantity,
BigDecimal::add)));

// Build position -> aggregated cash balance map
Map<Position, BigDecimal> positionCashBalance = filteredExecution.stream()
.collect(Collectors.groupingBy(
e -> toPosition(e, date),
Collectors.reducing(BigDecimal.ZERO, this::getAggregationSettlementAmount,
BigDecimal::add)));

// Update Position with aggregated quantity
Set<Position> aggregatedPositions = positionQuantity.keySet().stream()
.map(p -> p.toBuilder()
.setQuantityBuilder(Quantity.builder().setAmount(positionQuantity.get(p)))
.build())
.collect(Collectors.toSet());
.map(p -> p.toBuilder()
.setQuantityBuilder(Quantity.builder().setAmount(positionQuantity.get(p)))
.setCashBalanceBuilder(Money.builder().setAmount(positionCashBalance.get(p))) // TODO add currency
.build())
.collect(Collectors.toSet());



PortfolioStateBuilder portfolioStateBuilder = PortfolioState.builder();
aggregatedPositions.forEach(portfolioStateBuilder::addPositions);
Expand Down Expand Up @@ -221,9 +231,21 @@ private PositionStatusEnum toPositionStatus(Execution execution, LocalDate date)
*/
private BigDecimal getAggregationQuantity(Execution e) {
PartyRoleEnum buyOrSell = getExecutingEntityBuyOrSell(e);
BigDecimal quantity = e.getQuantity().getAmount();
return buyOrSell == PartyRoleEnum.SELLER ?
quantity.negate() : // if selling, reduce position
quantity; // if buying, increase position
}

/**
* @return execution cash balance, as negative for buy, and positive for sell
*/
private BigDecimal getAggregationSettlementAmount(Execution e) {
PartyRoleEnum buyOrSell = getExecutingEntityBuyOrSell(e);
BigDecimal settlementAmount = e.getSettlementTerms().getSettlementAmount().getAmount();
return buyOrSell == PartyRoleEnum.SELLER ?
e.getQuantity().getAmount().negate() : // if selling, reduce position
e.getQuantity().getAmount(); // if buying, increase position
settlementAmount : // if selling, increase cash
settlementAmount.negate(); // if buying, reduce cash
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/rosetta/model-cdm-event.rosetta
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ class Lineage <"A class to provide lineage information across lifecycle events t
[synonym Rosetta_Workbench value optionPayoutReference meta href]
equityPayoutReference EquityPayout (0..*) reference <"The reference to the instantiation of a EquityPayout object. An expected typical usage is to provide lineage for the payment of, say, an equity dividend. The definition associated to the Lineage class provides more details with respect to those referencing approaches, their expected usage and available implementation.">;
[synonym Rosetta_Workbench value equityPayoutReference meta href]
transferReference TransferPrimitive (0..*) reference <"The reference to the instantiation of a TransferPrimitive object.">;
[synonym Rosetta_Workbench value transferReference meta href]
legalAgreement LegalAgreement (0..*) reference <"The reference to the instantiation of a Legal Agreement object. The definition associated to the Lineage class provides more details with respect to those referencing approaches, their expected usage and available implementation.">;
portfolioStateReference PortfolioState (0..*) reference <"The refence to the previous state of a Portfolio, in a chain of Events leading up to a build of that Portfolio as the holding of Product(s) in specific Quantity(ies). As part of the PortfolioState object, a pointer to the previous PortfolioState is provided through a Lineage object, together with pointer(s) to the Event or set of Events leading up to the current (new) state.">;
}
Expand Down
1 change: 1 addition & 0 deletions src/main/rosetta/model-cdm-product.rosetta
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ class Position <"A Position describes how much of a given Product is being held
{
product Product (1..1) <"The product underlying the position, which can either be a contractual product or securities.">;
quantity Quantity (1..1) <"The quantity of the product, which can be a negative number in case of a short position.">;
cashBalance Money (0..1) <"The aggregate cost of proceeds">
positionStatus PositionStatusEnum (1..1) <"Qualifier for the state of the Position, to distinguish if just executed, formed, already settled, closed etc.">;
contractReference Contract (0..1) reference <"Reference to the Contract, in case product is contractual and the contract has been formed">;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,22 @@ void shouldEvaluateTotalPositionForDate() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(91000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-8648032500.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.SETTLED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(138000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-13123950000.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));

Position p3 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.EXECUTED);
assertNotNull(p3);
assertEquals(BigDecimal.valueOf(-21000000), p3.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(1997001750.0).setScale(2), p3.getCashBalance().getAmount().setScale(2));

Position p4 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.SETTLED);
assertNotNull(p4);
assertEquals(BigDecimal.valueOf(410000000), p4.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-38982750000.0).setScale(2), p4.getCashBalance().getAmount().setScale(2));
}

@Test
Expand All @@ -77,18 +81,22 @@ void shouldEvaluateDailyPositionForDate() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(80000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-7602400000.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.SETTLED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(-2000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(190100000.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));

Position p3 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.EXECUTED);
assertNotNull(p3);
assertEquals(BigDecimal.valueOf(-7500000), p3.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(713212500.0).setScale(2), p3.getCashBalance().getAmount().setScale(2));

Position p4 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.SETTLED);
assertNotNull(p4);
assertEquals(BigDecimal.valueOf(35000000), p4.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-3325875000.0).setScale(2), p4.getCashBalance().getAmount().setScale(2));
}

@Test
Expand All @@ -109,10 +117,13 @@ void shouldEvaluateTotalPositionForDateAndPositionStatus() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(91000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-8648032500.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.EXECUTED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(-21000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(1997001750.00).setScale(2), p2.getCashBalance().getAmount().setScale(2));

}

@Test
Expand All @@ -133,10 +144,12 @@ void shouldEvaluateDailyPositionForDateAndPositionStatus() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(80000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-7602400000.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.EXECUTED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(-7500000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(713212500.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));
}

@Test
Expand All @@ -157,10 +170,12 @@ void shouldEvaluateTotalPositionForDateAndProduct() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(91000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-8648032500.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.SETTLED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(138000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-13123950000.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));
}

@Test
Expand All @@ -181,10 +196,12 @@ void shouldEvaluateDailyPositionForDateAndProduct() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(80000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-7602400000.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.SETTLED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(-2000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(190100000.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));
}

private Product getProduct(String productId, ProductIdSourceEnum source) {
Expand Down Expand Up @@ -214,18 +231,22 @@ void shouldEvaluateTotalPositionForParty() {
Position p1 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.EXECUTED);
assertNotNull(p1);
assertEquals(BigDecimal.valueOf(80000000), p1.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-7602400000.0).setScale(2), p1.getCashBalance().getAmount().setScale(2));

Position p2 = getPosition(portfolioState, CUSIP_US1234567891, PositionStatusEnum.SETTLED);
assertNotNull(p2);
assertEquals(BigDecimal.valueOf(140000000), p2.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-13314050000.0).setScale(2), p2.getCashBalance().getAmount().setScale(2));

Position p3 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.EXECUTED);
assertNotNull(p3);
assertEquals(BigDecimal.valueOf(-13500000), p3.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(1283789250.0).setScale(2), p3.getCashBalance().getAmount().setScale(2));

Position p4 = getPosition(portfolioState, CUSIP_DH9105730505, PositionStatusEnum.SETTLED);
assertNotNull(p4);
assertEquals(BigDecimal.valueOf(125000000), p4.getQuantity().getAmount());
assertEquals(BigDecimal.valueOf(-11883125000.0).setScale(2), p4.getCashBalance().getAmount().setScale(2));
}

private Position getPosition(PortfolioState portfolioState, String productId, PositionStatusEnum positionStatus) {
Expand Down

0 comments on commit 64ac8e3

Please sign in to comment.