Skip to content

Commit 5835dff

Browse files
Tapanitoximinez
authored andcommitted
refactor: Rename raw state to theoretical state (#6187)
1 parent 33027ef commit 5835dff

File tree

3 files changed

+84
-71
lines changed

3 files changed

+84
-71
lines changed

src/test/app/Loan_test.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ class Loan_test : public beast::unit_test::suite
914914
state.principalOutstanding,
915915
state.managementFeeOutstanding);
916916
{
917-
auto const raw = computeRawLoanState(
917+
auto const raw = computeTheoreticalLoanState(
918918
state.periodicPayment,
919919
periodicRate,
920920
state.paymentRemaining,
@@ -967,7 +967,7 @@ class Loan_test : public beast::unit_test::suite
967967
Number totalFeesPaid = 0;
968968
std::size_t totalPaymentsMade = 0;
969969

970-
ripple::LoanState currentTrueState = computeRawLoanState(
970+
ripple::LoanState currentTrueState = computeTheoreticalLoanState(
971971
state.periodicPayment,
972972
periodicRate,
973973
state.paymentRemaining,
@@ -1022,7 +1022,7 @@ class Loan_test : public beast::unit_test::suite
10221022
paymentComponents.trackedInterestPart() +
10231023
paymentComponents.trackedManagementFeeDelta);
10241024

1025-
ripple::LoanState const nextTrueState = computeRawLoanState(
1025+
ripple::LoanState const nextTrueState = computeTheoreticalLoanState(
10261026
state.periodicPayment,
10271027
periodicRate,
10281028
state.paymentRemaining - 1,
@@ -2673,7 +2673,7 @@ class Loan_test : public beast::unit_test::suite
26732673
Number::upward));
26742674

26752675
{
2676-
auto const raw = computeRawLoanState(
2676+
auto const raw = computeTheoreticalLoanState(
26772677
state.periodicPayment,
26782678
periodicRate,
26792679
state.paymentRemaining,
@@ -2716,11 +2716,12 @@ class Loan_test : public beast::unit_test::suite
27162716
Number totalInterestPaid = 0;
27172717
std::size_t totalPaymentsMade = 0;
27182718

2719-
ripple::LoanState currentTrueState = computeRawLoanState(
2720-
state.periodicPayment,
2721-
periodicRate,
2722-
state.paymentRemaining,
2723-
broker.params.managementFeeRate);
2719+
ripple::LoanState currentTrueState =
2720+
computeTheoreticalLoanState(
2721+
state.periodicPayment,
2722+
periodicRate,
2723+
state.paymentRemaining,
2724+
broker.params.managementFeeRate);
27242725

27252726
while (state.paymentRemaining > 0)
27262727
{
@@ -2741,11 +2742,12 @@ class Loan_test : public beast::unit_test::suite
27412742
paymentComponents.trackedValueDelta <=
27422743
roundedPeriodicPayment);
27432744

2744-
ripple::LoanState const nextTrueState = computeRawLoanState(
2745-
state.periodicPayment,
2746-
periodicRate,
2747-
state.paymentRemaining - 1,
2748-
broker.params.managementFeeRate);
2745+
ripple::LoanState const nextTrueState =
2746+
computeTheoreticalLoanState(
2747+
state.periodicPayment,
2748+
periodicRate,
2749+
state.paymentRemaining - 1,
2750+
broker.params.managementFeeRate);
27492751
detail::LoanStateDeltas const deltas =
27502752
currentTrueState - nextTrueState;
27512753

@@ -5919,7 +5921,7 @@ class Loan_test : public beast::unit_test::suite
59195921

59205922
auto const periodicRate =
59215923
loanPeriodicRate(interestRateValue, state.paymentInterval);
5922-
auto const rawLoanState = computeRawLoanState(
5924+
auto const rawLoanState = computeTheoreticalLoanState(
59235925
state.periodicPayment,
59245926
periodicRate,
59255927
state.paymentRemaining,

src/xrpld/app/misc/LendingHelpers.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ struct LoanPaymentParts
8686

8787
/** This structure captures the parts of a loan state.
8888
*
89-
* Whether the values are raw (unrounded) or rounded will depend on how it was
90-
* computed.
89+
* Whether the values are theoretical (unrounded) or rounded will depend on how
90+
* it was computed.
9191
*
9292
* Many of the fields can be derived from each other, but they're all provided
9393
* here to reduce code duplication and possible mistakes.
@@ -190,7 +190,7 @@ checkLoanGuards(
190190
beast::Journal j);
191191

192192
LoanState
193-
computeRawLoanState(
193+
computeTheoreticalLoanState(
194194
Number const& periodicPayment,
195195
Number const& periodicRate,
196196
std::uint32_t const paymentRemaining,
@@ -217,7 +217,7 @@ computeManagementFee(
217217

218218
Number
219219
computeFullPaymentInterest(
220-
Number const& rawPrincipalOutstanding,
220+
Number const& theoreticalPrincipalOutstanding,
221221
Number const& periodicRate,
222222
NetClock::time_point parentCloseTime,
223223
std::uint32_t paymentInterval,

src/xrpld/app/misc/detail/LendingHelpers.cpp

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -395,27 +395,28 @@ tryOverpayment(
395395
beast::Journal j)
396396
{
397397
// Calculate what the loan state SHOULD be theoretically (at full precision)
398-
auto const raw = computeRawLoanState(
398+
auto const theoreticalState = computeTheoreticalLoanState(
399399
periodicPayment, periodicRate, paymentRemaining, managementFeeRate);
400400

401401
// Calculate the accumulated rounding errors. These need to be preserved
402402
// across the re-amortization to maintain consistency with the loan's
403403
// payment history. Without preserving these errors, the loan could end
404404
// up with a different total value than what the borrower has actually paid.
405-
auto const errors = roundedOldState - raw;
405+
auto const errors = roundedOldState - theoreticalState;
406406

407-
// Compute the new principal by applying the overpayment to the raw
408-
// (theoretical) principal. Use max with 0 to ensure we never go negative.
409-
auto const newRawPrincipal = std::max(
410-
raw.principalOutstanding - overpaymentComponents.trackedPrincipalDelta,
407+
// Compute the new principal by applying the overpayment to the theoretical
408+
// principal. Use max with 0 to ensure we never go negative.
409+
auto const newTheoreticalPrincipal = std::max(
410+
theoreticalState.principalOutstanding -
411+
overpaymentComponents.trackedPrincipalDelta,
411412
Number{0});
412413

413414
// Compute new loan properties based on the reduced principal. This
414415
// recalculates the periodic payment, total value, and management fees
415416
// for the remaining payment schedule.
416417
auto newLoanProperties = computeLoanProperties(
417418
asset,
418-
newRawPrincipal,
419+
newTheoreticalPrincipal,
419420
periodicRate,
420421
paymentRemaining,
421422
managementFeeRate,
@@ -429,35 +430,41 @@ tryOverpayment(
429430
<< newLoanProperties.firstPaymentPrincipal;
430431

431432
// Calculate what the new loan state should be with the new periodic payment
432-
auto const newRaw = computeRawLoanState(
433-
newLoanProperties.periodicPayment,
434-
periodicRate,
435-
paymentRemaining,
436-
managementFeeRate) +
433+
// including rounding errors
434+
auto const newTheoreticalState = computeTheoreticalLoanState(
435+
newLoanProperties.periodicPayment,
436+
periodicRate,
437+
paymentRemaining,
438+
managementFeeRate) +
437439
errors;
438440

439-
JLOG(j.debug()) << "new raw value: " << newRaw.valueOutstanding
440-
<< ", principal: " << newRaw.principalOutstanding
441-
<< ", interest gross: " << newRaw.interestOutstanding();
442-
// Update the loan state variables with the new values PLUS the preserved
443-
// rounding errors. This ensures the loan's tracked state remains
444-
// consistent with its payment history.
441+
JLOG(j.debug()) << "new theoretical value: "
442+
<< newTheoreticalState.valueOutstanding << ", principal: "
443+
<< newTheoreticalState.principalOutstanding
444+
<< ", interest gross: "
445+
<< newTheoreticalState.interestOutstanding();
445446

447+
// Update the loan state variables with the new values that include the
448+
// preserved rounding errors. This ensures the loan's tracked state remains
449+
// consistent with its payment history.
446450
auto const principalOutstanding = std::clamp(
447451
roundToAsset(
448-
asset, newRaw.principalOutstanding, loanScale, Number::upward),
452+
asset,
453+
newTheoreticalState.principalOutstanding,
454+
loanScale,
455+
Number::upward),
449456
numZero,
450457
roundedOldState.principalOutstanding);
451458
auto const totalValueOutstanding = std::clamp(
452459
roundToAsset(
453460
asset,
454-
principalOutstanding + newRaw.interestOutstanding(),
461+
principalOutstanding + newTheoreticalState.interestOutstanding(),
455462
loanScale,
456463
Number::upward),
457464
numZero,
458465
roundedOldState.valueOutstanding);
459466
auto const managementFeeOutstanding = std::clamp(
460-
roundToAsset(asset, newRaw.managementFeeDue, loanScale),
467+
roundToAsset(asset, newTheoreticalState.managementFeeDue, loanScale),
461468
numZero,
462469
roundedOldState.managementFeeDue);
463470

@@ -829,15 +836,16 @@ computeFullPayment(
829836
}
830837

831838
// Calculate the theoretical principal based on the payment schedule.
832-
// This raw (unrounded) value is used to compute interest and penalties
833-
// accurately.
834-
Number const rawPrincipalOutstanding = loanPrincipalFromPeriodicPayment(
835-
periodicPayment, periodicRate, paymentRemaining);
839+
// This theoretical (unrounded) value is used to compute interest and
840+
// penalties accurately.
841+
Number const theoreticalPrincipalOutstanding =
842+
loanPrincipalFromPeriodicPayment(
843+
periodicPayment, periodicRate, paymentRemaining);
836844

837845
// Full payment interest includes both accrued interest (time since last
838846
// payment) and prepayment penalty (for closing early).
839847
auto const fullPaymentInterest = computeFullPaymentInterest(
840-
rawPrincipalOutstanding,
848+
theoreticalPrincipalOutstanding,
841849
periodicRate,
842850
view.parentCloseTime(),
843851
paymentInterval,
@@ -897,7 +905,8 @@ computeFullPayment(
897905
JLOG(j.trace()) << "computeFullPayment result: periodicPayment: "
898906
<< periodicPayment << ", periodicRate: " << periodicRate
899907
<< ", paymentRemaining: " << paymentRemaining
900-
<< ", rawPrincipalOutstanding: " << rawPrincipalOutstanding
908+
<< ", theoreticalPrincipalOutstanding: "
909+
<< theoreticalPrincipalOutstanding
901910
<< ", fullPaymentInterest: " << fullPaymentInterest
902911
<< ", roundedFullInterest: " << roundedFullInterest
903912
<< ", roundedFullManagementFee: "
@@ -977,7 +986,7 @@ computePaymentComponents(
977986

978987
// Calculate what the loan state SHOULD be after this payment (the target).
979988
// This is computed at full precision using the theoretical amortization.
980-
LoanState const trueTarget = computeRawLoanState(
989+
LoanState const trueTarget = computeTheoreticalLoanState(
981990
periodicPayment, periodicRate, paymentRemaining - 1, managementFeeRate);
982991

983992
// Round the target to the loan's scale to match how actual loan values
@@ -1348,7 +1357,7 @@ checkLoanGuards(
13481357
*/
13491358
Number
13501359
computeFullPaymentInterest(
1351-
Number const& rawPrincipalOutstanding,
1360+
Number const& theoreticalPrincipalOutstanding,
13521361
Number const& periodicRate,
13531362
NetClock::time_point parentCloseTime,
13541363
std::uint32_t paymentInterval,
@@ -1357,7 +1366,7 @@ computeFullPaymentInterest(
13571366
TenthBips32 closeInterestRate)
13581367
{
13591368
auto const accruedInterest = detail::loanAccruedInterest(
1360-
rawPrincipalOutstanding,
1369+
theoreticalPrincipalOutstanding,
13611370
periodicRate,
13621371
parentCloseTime,
13631372
startDate,
@@ -1371,7 +1380,7 @@ computeFullPaymentInterest(
13711380
// Equation (28) from XLS-66 spec, Section A-2 Equation Glossary
13721381
auto const prepaymentPenalty = closeInterestRate == beast::zero
13731382
? Number{}
1374-
: tenthBipsOfValue(rawPrincipalOutstanding, closeInterestRate);
1383+
: tenthBipsOfValue(theoreticalPrincipalOutstanding, closeInterestRate);
13751384

13761385
XRPL_ASSERT(
13771386
prepaymentPenalty >= 0,
@@ -1388,11 +1397,11 @@ computeFullPaymentInterest(
13881397
* This function computes what the loan's outstanding balances should be based
13891398
* on the periodic payment amount and number of payments remaining,
13901399
* without considering any rounding that may have been applied to the actual
1391-
* Loan object's state. This "raw" (unrounded) state is used as a target for
1392-
* computing payment components and validating that the loan's tracked state
1400+
* Loan object's state. This "theoretical" (unrounded) state is used as a target
1401+
* for computing payment components and validating that the loan's tracked state
13931402
* hasn't drifted too far from the theoretical values.
13941403
*
1395-
* The raw state serves several purposes:
1404+
* The theoretical state serves several purposes:
13961405
* 1. Computing the expected payment breakdown (principal, interest, fees)
13971406
* 2. Detecting and correcting rounding errors that accumulate over time
13981407
* 3. Validating that overpayments are calculated correctly
@@ -1402,7 +1411,7 @@ computeFullPaymentInterest(
14021411
* representing a completely paid-off loan.
14031412
*/
14041413
LoanState
1405-
computeRawLoanState(
1414+
computeTheoreticalLoanState(
14061415
Number const& periodicPayment,
14071416
Number const& periodicRate,
14081417
std::uint32_t const paymentRemaining,
@@ -1418,40 +1427,42 @@ computeRawLoanState(
14181427
}
14191428

14201429
// Equation (30) from XLS-66 spec, Section A-2 Equation Glossary
1421-
Number const rawTotalValueOutstanding = periodicPayment * paymentRemaining;
1430+
Number const totalValueOutstanding = periodicPayment * paymentRemaining;
14221431

1423-
Number const rawPrincipalOutstanding =
1432+
Number const principalOutstanding =
14241433
detail::loanPrincipalFromPeriodicPayment(
14251434
periodicPayment, periodicRate, paymentRemaining);
14261435

14271436
// Equation (31) from XLS-66 spec, Section A-2 Equation Glossary
1428-
Number const rawInterestOutstandingGross =
1429-
rawTotalValueOutstanding - rawPrincipalOutstanding;
1437+
Number const interestOutstandingGross =
1438+
totalValueOutstanding - principalOutstanding;
14301439

14311440
// Equation (32) from XLS-66 spec, Section A-2 Equation Glossary
1432-
Number const rawManagementFeeOutstanding =
1433-
tenthBipsOfValue(rawInterestOutstandingGross, managementFeeRate);
1441+
Number const managementFeeOutstanding =
1442+
tenthBipsOfValue(interestOutstandingGross, managementFeeRate);
14341443

14351444
// Equation (33) from XLS-66 spec, Section A-2 Equation Glossary
1436-
Number const rawInterestOutstandingNet =
1437-
rawInterestOutstandingGross - rawManagementFeeOutstanding;
1445+
Number const interestOutstandingNet =
1446+
interestOutstandingGross - managementFeeOutstanding;
14381447

14391448
return LoanState{
1440-
.valueOutstanding = rawTotalValueOutstanding,
1441-
.principalOutstanding = rawPrincipalOutstanding,
1442-
.interestDue = rawInterestOutstandingNet,
1443-
.managementFeeDue = rawManagementFeeOutstanding};
1449+
.valueOutstanding = totalValueOutstanding,
1450+
.principalOutstanding = principalOutstanding,
1451+
.interestDue = interestOutstandingNet,
1452+
.managementFeeDue = managementFeeOutstanding,
1453+
};
14441454
};
14451455

14461456
/* Constructs a LoanState from rounded Loan ledger object values.
14471457
*
14481458
* This function creates a LoanState structure from the three tracked values
1449-
* stored in a Loan ledger object. Unlike calculateRawLoanState(), which
1459+
* stored in a Loan ledger object. Unlike calculateTheoreticalLoanState(), which
14501460
* computes theoretical unrounded values, this function works with values
14511461
* that have already been rounded to the loan's scale.
14521462
*
1453-
* The key difference from calculateRawLoanState():
1454-
* - calculateRawLoanState: Computes theoretical values at full precision
1463+
* The key difference from calculateTheoreticalLoanState():
1464+
* - calculateTheoreticalLoanState: Computes theoretical values at full
1465+
* precision
14551466
* - constructRoundedLoanState: Builds state from actual rounded ledger values
14561467
*
14571468
* The interestDue field is derived from the other three values rather than
@@ -1592,13 +1603,13 @@ computeLoanProperties(
15921603
auto const firstPaymentPrincipal = [&]() {
15931604
// Compute the parts for the first payment. Ensure that the
15941605
// principal payment will actually change the principal.
1595-
auto const startingState = computeRawLoanState(
1606+
auto const startingState = computeTheoreticalLoanState(
15961607
periodicPayment,
15971608
periodicRate,
15981609
paymentsRemaining,
15991610
managementFeeRate);
16001611

1601-
auto const firstPaymentState = computeRawLoanState(
1612+
auto const firstPaymentState = computeTheoreticalLoanState(
16021613
periodicPayment,
16031614
periodicRate,
16041615
paymentsRemaining - 1,

0 commit comments

Comments
 (0)