Skip to content
This repository has been archived by the owner on Mar 12, 2020. It is now read-only.

Commit

Permalink
Fix schedule calculation for RPL roles in ANNEngine (#12)
Browse files Browse the repository at this point in the history
* Fix schedule calculation for RPL roles in ANNEngine

* Format code and generate new artifacts
  • Loading branch information
nbundi authored and jo-es committed Sep 26, 2019
1 parent ed98c08 commit d97df65
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 25 deletions.
170 changes: 170 additions & 0 deletions actus-resources/tests/actus-tests-ANN.json
Original file line number Diff line number Diff line change
Expand Up @@ -9999,5 +9999,175 @@
"nominalAccrued": 0
}
]
},
"20031": {
"identifier": "20031",
"terms": {
"contractType": "ANN",
"contractID": "20031",
"contractRole": "RPL",
"contractDealDate": "2012-12-28T00:00:00",
"initialExchangeDate": "2013-01-01T00:00:00",
"statusDate": "2012-12-30T00:00:00",
"notionalPrincipal": 5000,
"cycleAnchorDateOfPrincipalRedemption": "2013-02-01T00:00:00",
"nextPrincipalRedemptionPayment": 700,
"dayCountConvention": "A/365",
"nominalInterestRate": 0.08,
"currency": "USD",
"cycleOfPrincipalRedemption": "1M+",
"maturityDate": "2013-09-01T00:00:00",
"rateMultiplier": 1,
"rateSpread": 0,
"fixingDays": "0D",
"premiumDiscountAtIED": 0,
"interestCalculationBase": "NT"
},
"results": [
{
"eventDate": "2012-12-31T00:00",
"eventType": "AD",
"eventValue": 0,
"nominalValue": 0,
"nominalRate": 0,
"nominalAccrued": 0
},
{
"eventDate": "2013-01-01T00:00",
"eventType": "IED",
"eventValue": 5000,
"nominalValue": -5000,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-02-01T00:00",
"eventType": "PR",
"eventValue": -666.027397260274,
"nominalValue": -4333.97260273973,
"nominalRate": 0.08,
"nominalAccrued": -33.972602739726
},
{
"eventDate": "2013-02-01T00:00",
"eventType": "IP",
"eventValue": -33.972602739726,
"nominalValue": -4333.97260273973,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-03-01T00:00",
"eventType": "PR",
"eventValue": -673.402469506474,
"nominalValue": -3660.57013323325,
"nominalRate": 0.08,
"nominalAccrued": -26.597530493526
},
{
"eventDate": "2013-03-01T00:00",
"eventType": "IP",
"eventValue": -26.597530493526,
"nominalValue": -3660.57013323325,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-04-01T00:00",
"eventType": "PR",
"eventValue": -675.128181012552,
"nominalValue": -2985.4419522207,
"nominalRate": 0.08,
"nominalAccrued": -24.8718189874479
},
{
"eventDate": "2013-04-01T00:00",
"eventType": "IP",
"eventValue": -24.8718189874479,
"nominalValue": -2985.4419522207,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-05-01T00:00",
"eventType": "PR",
"eventValue": -680.369696752522,
"nominalValue": -2305.07225546818,
"nominalRate": 0.08,
"nominalAccrued": -19.6303032474786
},
{
"eventDate": "2013-05-01T00:00",
"eventType": "IP",
"eventValue": -19.6303032474786,
"nominalValue": -2305.07225546818,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-06-01T00:00",
"eventType": "PR",
"eventValue": -684.338139195723,
"nominalValue": -1620.73411627246,
"nominalRate": 0.08,
"nominalAccrued": -15.6618608042769
},
{
"eventDate": "2013-06-01T00:00",
"eventType": "IP",
"eventValue": -15.6618608042769,
"nominalValue": -1620.73411627246,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-07-01T00:00",
"eventType": "PR",
"eventValue": -689.343118139578,
"nominalValue": -931.390998132877,
"nominalRate": 0.08,
"nominalAccrued": -10.6568818604216
},
{
"eventDate": "2013-07-01T00:00",
"eventType": "IP",
"eventValue": -10.6568818604216,
"nominalValue": -931.390998132877,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-08-01T00:00",
"eventType": "PR",
"eventValue": -693.671644725015,
"nominalValue": -237.719353407862,
"nominalRate": 0.08,
"nominalAccrued": -6.32835527498503
},
{
"eventDate": "2013-08-01T00:00",
"eventType": "IP",
"eventValue": -6.32835527498503,
"nominalValue": -237.719353407862,
"nominalRate": 0.08,
"nominalAccrued": 0
},
{
"eventDate": "2013-09-01T00:00",
"eventType": "PR",
"eventValue": -237.719353407862,
"nominalValue": 0,
"nominalRate": 0.08,
"nominalAccrued": -1.61518903137397
},
{
"eventDate": "2013-09-01T00:00",
"eventType": "IP",
"eventValue": -1.61518903137397,
"nominalValue": 0,
"nominalRate": 0.08,
"nominalAccrued": 0
}
]
}
}
33 changes: 29 additions & 4 deletions artifacts/ANNEngine.json

Large diffs are not rendered by default.

29 changes: 27 additions & 2 deletions artifacts/Migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,31 @@
"name": "solc",
"version": "0.5.2+commit.1df8f40c.Emscripten.clang"
},
"networks": {},
"updatedAt": "2019-09-18T14:55:45.132Z"
"networks": {
"3": {
"events": {},
"links": {},
"address": "0x4882E748ca2dD3a57F0a32793b4830bF5dd3D1D6",
"transactionHash": "0x955514b96a25f6a7e206d8f79fbefbc2ce55a741cec288ec1babb995cfd9b9b9"
},
"4": {
"events": {},
"links": {},
"address": "0x4882E748ca2dD3a57F0a32793b4830bF5dd3D1D6",
"transactionHash": "0x955514b96a25f6a7e206d8f79fbefbc2ce55a741cec288ec1babb995cfd9b9b9"
},
"5": {
"events": {},
"links": {},
"address": "0x29cfee2ccB305118b639E2683aea57E7a4dcc272",
"transactionHash": "0x9d64aae4592878a18c81d8ac83019fd1d476f33eb4c5421d3d2c8d5872bbbcec"
},
"42": {
"events": {},
"links": {},
"address": "0x29cfee2ccB305118b639E2683aea57E7a4dcc272",
"transactionHash": "0x9d64aae4592878a18c81d8ac83019fd1d476f33eb4c5421d3d2c8d5872bbbcec"
}
},
"updatedAt": "2019-09-18T15:07:27.132Z"
}
29 changes: 27 additions & 2 deletions artifacts/PAMEngine.json
Original file line number Diff line number Diff line change
Expand Up @@ -1601,6 +1601,31 @@
"name": "solc",
"version": "0.5.2+commit.1df8f40c.Emscripten.clang"
},
"networks": {},
"updatedAt": "2019-09-18T14:55:45.104Z"
"networks": {
"3": {
"events": {},
"links": {},
"address": "0xBDB1624D894A62b4fB3B3D9bE20b1F69Ba969cD4",
"transactionHash": "0x05f3309e8fdbf0c96e7ddee04867be8893ff72e1fa86218fcc3dd944bba0519f"
},
"4": {
"events": {},
"links": {},
"address": "0xBDB1624D894A62b4fB3B3D9bE20b1F69Ba969cD4",
"transactionHash": "0x05f3309e8fdbf0c96e7ddee04867be8893ff72e1fa86218fcc3dd944bba0519f"
},
"5": {
"events": {},
"links": {},
"address": "0xAd135adab829EEdc52a1c5c24741F4196f2D71A0",
"transactionHash": "0x0e36b693e37aa4199c32d69641b59422c99af809e5f99d040bfc9faf148e17c3"
},
"42": {
"events": {},
"links": {},
"address": "0xAd135adab829EEdc52a1c5c24741F4196f2D71A0",
"transactionHash": "0x0e36b693e37aa4199c32d69641b59422c99af809e5f99d040bfc9faf148e17c3"
}
},
"updatedAt": "2019-09-18T15:07:27.071Z"
}
29 changes: 27 additions & 2 deletions artifacts/SignedMath.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,31 @@
"name": "solc",
"version": "0.5.2+commit.1df8f40c.Emscripten.clang"
},
"networks": {},
"updatedAt": "2019-09-18T14:55:45.070Z"
"networks": {
"3": {
"events": {},
"links": {},
"address": "0x27bd9D7c156AF2BC60e0B2b458D716e080066697",
"transactionHash": "0x9bf5f53b39b70953da5c986a4daf4434501b5b2b74e7c969803bd20f29c6d07b"
},
"4": {
"events": {},
"links": {},
"address": "0x27bd9D7c156AF2BC60e0B2b458D716e080066697",
"transactionHash": "0x9bf5f53b39b70953da5c986a4daf4434501b5b2b74e7c969803bd20f29c6d07b"
},
"5": {
"events": {},
"links": {},
"address": "0xE9692a8E5eAaE6a01A82BB734A42cBA0A9b0541a",
"transactionHash": "0xb814c15efe2014325f67d4edb6f9d16948f009d019eb8160e6f562feeb890769"
},
"42": {
"events": {},
"links": {},
"address": "0xE9692a8E5eAaE6a01A82BB734A42cBA0A9b0541a",
"transactionHash": "0xb814c15efe2014325f67d4edb6f9d16948f009d019eb8160e6f562feeb890769"
}
},
"updatedAt": "2019-09-18T15:07:27.124Z"
}
37 changes: 22 additions & 15 deletions contracts/Engines/ANNEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,9 @@ contract ANNEngine is Core, IEngine {
contractState.interestScalingMultiplier = int256(1 * 10 ** PRECISION);
contractState.contractRoleSign = contractTerms.contractRole;
contractState.lastEventTime = contractTerms.statusDate;
contractState.nominalValue = contractTerms.notionalPrincipal;
contractState.nominalValue = roleSign(contractTerms.contractRole) * contractTerms.notionalPrincipal;
contractState.nominalRate = contractTerms.nominalInterestRate;
contractState.nominalAccrued = contractTerms.accruedInterest;
contractState.nominalAccrued = roleSign(contractTerms.contractRole) * contractTerms.accruedInterest;
contractState.feeAccrued = contractTerms.feeAccrued;
// annuity calculator to be implemented
contractState.nextPrincipalRedemptionPayment = roleSign(contractTerms.contractRole) * contractTerms.nextPrincipalRedemptionPayment;
Expand Down Expand Up @@ -524,7 +524,10 @@ contract ANNEngine is Core, IEngine {
);
contractState.nominalAccrued = contractState.nominalAccrued.add(contractState.nominalRate.floatMult(contractState.nominalValue).floatMult(contractState.timeFromLastEvent));
contractState.feeAccrued = contractState.feeAccrued.add(contractTerms.feeRate.floatMult(contractState.nominalValue).floatMult(contractState.timeFromLastEvent));
contractState.nominalValue = contractState.nominalValue - contractState.nominalValue.min(contractState.nextPrincipalRedemptionPayment - contractState.nominalAccrued);
contractState.nominalValue = contractState.nominalValue -
roleSign(contractTerms.contractRole) * (
roleSign(contractTerms.contractRole) * contractState.nominalValue).min(
roleSign(contractTerms.contractRole) * (contractState.nextPrincipalRedemptionPayment - contractState.nominalAccrued));
contractState.lastEventTime = timestamp;
return contractState;
}
Expand Down Expand Up @@ -739,20 +742,24 @@ contract ANNEngine is Core, IEngine {
if (eventType == EventType.PR) {
return (
performanceIndicator(contractState.contractStatus)
* contractState.nominalScalingMultiplier
* (contractState.nominalScalingMultiplier * roleSign(contractTerms.contractRole))
.floatMult(
contractState.nominalValue.min(
contractState.nextPrincipalRedemptionPayment
- contractState.nominalAccrued
- yearFraction(
shiftCalcTime(contractState.lastEventTime, contractTerms.businessDayConvention, contractTerms.calendar),
shiftCalcTime(timestamp, contractTerms.businessDayConvention, contractTerms.calendar),
contractTerms.dayCountConvention,
contractTerms.maturityDate
(roleSign(contractTerms.contractRole) * contractState.nominalValue)
.min(
roleSign(contractTerms.contractRole)
* (
contractState.nextPrincipalRedemptionPayment
- contractState.nominalAccrued
- yearFraction(
shiftCalcTime(contractState.lastEventTime, contractTerms.businessDayConvention, contractTerms.calendar),
shiftCalcTime(timestamp, contractTerms.businessDayConvention, contractTerms.calendar),
contractTerms.dayCountConvention,
contractTerms.maturityDate
)
.floatMult(contractState.nominalRate)
.floatMult(contractState.nominalValue)
)
)
.floatMult(contractState.nominalRate)
.floatMult(contractState.nominalValue)
)
)
);
}
Expand Down
7 changes: 7 additions & 0 deletions test/Engines/ANN/TestANNSchedules.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,11 @@ contract('ANNEngine', () => {
compareTestResults(evaluatedSchedule, testDetails['results']);
});
*/

it('should yield the expected evaluated contract schedule for test ANN20031', async () => {
const testDetails = this.testCases['20031'];
const evaluatedSchedule = await evaluateEventSchedule(testDetails['terms']);

compareTestResults(evaluatedSchedule, testDetails['results']);
});
});

0 comments on commit d97df65

Please sign in to comment.