Skip to content

Commit

Permalink
Interest calculation in treasury based on Annual rate (#2822)
Browse files Browse the repository at this point in the history
* refactor: interest caluculation in treasure is based on APR

closes #2812

* refactor: interest calculation treat interest as an annual rate

update typescript declarations, which caused some renamings

* test: add tests showing plausible interest rates
  • Loading branch information
Chris-Hibbert authored Apr 6, 2021
1 parent 768ef03 commit 267a85d
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 44 deletions.
22 changes: 17 additions & 5 deletions packages/treasury/src/interest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@
import '@agoric/zoe/exported';
import '@agoric/zoe/src/contracts/callSpread/types';
import './types';
import { multiplyBy } from '@agoric/zoe/src/contractSupport/ratio';
import { multiplyBy, makeRatio } from '@agoric/zoe/src/contractSupport/ratio';
import { amountMath } from '@agoric/ertp';

function makeResult(latestInterestUpdate, interest, newDebt) {
return { latestInterestUpdate, interest, newDebt };
}

export const SECONDS_PER_YEAR = 60n * 60n * 24n * 365n;

/** @type {MakeInterestCalculator} */
export function makeInterestCalculator(
brand,
rate,
annualRate,
chargingPeriod,
recordingPeriod,
) {
const numeratorValue = BigInt(annualRate.numerator.value);
const denominatorValue = BigInt(annualRate.denominator.value);
const ratePerChargingPeriod = makeRatio(
chargingPeriod * numeratorValue,
annualRate.numerator.brand,
SECONDS_PER_YEAR * denominatorValue,
);
// Calculate new debt for charging periods up to the present.
/** @type {Calculate} */
function calculate(debtStatus, currentTime) {
const { currentDebt, latestInterestUpdate } = debtStatus;
const { newDebt, latestInterestUpdate } = debtStatus;
let newRecent = latestInterestUpdate;
let growingInterest = amountMath.makeEmpty(brand);
let growingDebt = currentDebt;
let growingDebt = newDebt;
while (newRecent + chargingPeriod <= currentTime) {
newRecent += chargingPeriod;
const newInterest = multiplyBy(growingDebt, rate);
const newInterest = multiplyBy(growingDebt, ratePerChargingPeriod);
growingInterest = amountMath.add(growingInterest, newInterest);
growingDebt = amountMath.add(growingDebt, newInterest, brand);
}
Expand All @@ -34,6 +45,7 @@ export function makeInterestCalculator(
// charging periods have elapsed that don't constitute whole reporting
// periods, the time is not updated past them and interest is not accumulated
// for them.
/** @type {Calculate} */
function calculateReportingPeriod(debtStatus, currentTime) {
const { latestInterestUpdate } = debtStatus;
const overshoot = (currentTime - latestInterestUpdate) % recordingPeriod;
Expand Down
12 changes: 6 additions & 6 deletions packages/treasury/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* @property {Ratio} liquidationMargin margin below which collateral will be
* liquidated to satisfy the debt.
* @property {Ratio} initialPrice price ratio of collateral to RUN
* @property {Ratio} interestRate interest rate charged on loans
* @property {Ratio} interestRate - annual interest rate charged on loans
* @property {Ratio} loanFee The fee (in BasisPoints) charged when opening
* or increasing a loan.
*/
Expand All @@ -36,7 +36,7 @@

/**
* @typedef {Object} UIState
* @property {Ratio} interestRate
* @property {Ratio} interestRate Annual interest rate charge
* @property {Ratio} liquidationRatio
* @property {Amount} locked Amount of Collateral locked
* @property {Amount} debt Amount of Loan (including accrued interest)
Expand All @@ -58,7 +58,7 @@
* @property {() => Ratio} getLoanFee
* @property {() => Promise<PriceQuote>} getCollateralQuote
* @property {() => Ratio} getInitialMargin
* @property {() => Ratio} getInterestRate
* @property {() => Ratio} getInterestRate - The annual interest rate on a loan
* @property {StageReward} stageReward
*/

Expand Down Expand Up @@ -143,7 +143,7 @@

/**
* @typedef {Object} DebtStatus
* @property {Timestamp} updateTime
* @property {Timestamp} latestInterestUpdate
* @property {Amount} interest
* @property {Amount} newDebt
*/
Expand All @@ -156,7 +156,7 @@
*/

/**
* @typedef {Object} Calculator
* @typedef {Object} CalculatorKit
* @property {Calculate} calculate calculate new debt for charging periods up to
* the present.
* @property {Calculate} calculateReportingPeriod calculate new debt for
Expand All @@ -171,5 +171,5 @@
* @param {Ratio} rate
* @param {RelativeTime} chargingPeriod
* @param {RelativeTime} recordingPeriod
* @returns {Calculator}
* @returns {CalculatorKit}
*/
6 changes: 5 additions & 1 deletion packages/treasury/src/vault.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,11 @@ export function makeVaultKit(

function accrueInterestAndAddToPool(currentTime) {
const interestKit = interestCalculator.calculateReportingPeriod(
{ latestInterestUpdate, currentDebt: runDebt },
{
latestInterestUpdate,
newDebt: runDebt,
interest: amountMath.makeEmpty(runBrand),
},
currentTime,
);

Expand Down
Loading

0 comments on commit 267a85d

Please sign in to comment.