@@ -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 */
13491358Number
13501359computeFullPaymentInterest (
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 */
14041413LoanState
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