Forked from johnshearing/4th Week HW Bank Loan In Haskell Using Compound Interest Formula
Created
June 23, 2022 08:13
-
-
Save marco-martins/b3929808000c19dc4b5396c6c4f2d153 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module Example where | |
import Language.Marlowe.Extended | |
-- Simulates an auto loan for a used car with compound interest. Native token represents title for the car. | |
-- Input loan amount. We imagine the car costs 5000 ADA | |
loan_amount_in_ADA = 5000 :: Double | |
-- Input number of payments. We imagine 36 monthly payments. | |
number_of_payments = 36 :: Integer | |
-- Input interest rate in percent per year. This goes to the bank. | |
-- We imagine 8% interest | |
interest_in_percent_per_year = 8 :: Double | |
-- Input the number of payments per year. | |
-- The formula compounds the interest every payment period. | |
-- Monthly in this case but you can set it to whatever you want using the periods_per_year field. | |
-- We imagine monthly payments. | |
periods_per_year = 12 :: Integer | |
{- | |
Code generation based on Haskell example by a_juggler which is linked below. | |
https://gist.github.com/ajuggler/c9b2617295112cb2f4839f4cda4a6b58 | |
Thank you @a_juggler for providing this example of foldr and replicate. | |
@IndyCoin did the code generation using a different method as seen below: | |
https://gist.github.com/CardanoDVPR/0a3bc218d0ab98564d723cc4e40dfebc | |
Lars has provided a nice example of code generation found at the link below and is discussed in the Lesson 4 at 30 minutes into the video: | |
https://github.com/input-output-hk/marlowe-pioneer-program/blob/lecture05/code/src/lecture04/multi-pay.hs | |
From lesson 5, the ACTUS demo app has no trouble with interest payments. | |
http://demo.actusfrf.org/form/PAM | |
That was the inspiration for working with compound interest for this homework assignment. | |
The bank earns ADA from interest on the car loan. | |
Native token (serves as title for the car) is automatically transfered to borrower if all payments are made on time. | |
Thanks to support from Hernan Rajchert (our own @Sherman in the Marlowe discord) for the help on stackexchange. | |
https://cardano.stackexchange.com/questions/8459/nft-support-for-marlowe | |
-} | |
-- Imagining a car loan smart contract in Marlowe for 5000 ADA as per the example found at the following link. | |
-- https://www.double-entry-bookkeeping.com/periodic-payment/auto-loan-payment/ | |
-- payment_amount_in_ADA = PV x i / (1 - 1 / (1 + i)^n) | |
-- PV = Value of the auto loan 5,000 | |
-- n = number of months = 3 x 12 = 36 | |
-- i = nominal rate = 8%/12 per month | |
-- payment_amount_in_ADA = 5000 x (8%/12) / (1 - 1 / (1 + 8%/12)^36) | |
-- payment_amount_in_ADA = 156.68 | |
interest_in_decimal_per_period = interest_in_percent_per_year / 100 / (fromIntegral periods_per_year) | |
--payment_amount_in_ADA = PV x i / (1 - 1 / (1 + i) ^ n) | |
--payment_amount_in_ADA = 5000 x (.08/12) / (1 - 1 / (1 + .08/12) ^ 36) = 156.68 | |
payment_amount_in_ADA = loan_amount_in_ADA * interest_in_decimal_per_period / (1 - 1 / (1 + interest_in_decimal_per_period) ^ number_of_payments) :: Double | |
-- Specify function to convert ADA to Lovelace | |
convert_ADA_To_Lovelace x = x * 1000000 | |
loan_amount_in_lovelace_as_type_double = convert_ADA_To_Lovelace loan_amount_in_ADA | |
loan_amount_in_lovelace = floor loan_amount_in_lovelace_as_type_double :: Integer | |
payment_amount_in_lovelace_as_type_double = convert_ADA_To_Lovelace payment_amount_in_ADA | |
payment_amount_in_lovelace = floor payment_amount_in_lovelace_as_type_double :: Integer | |
main :: IO () | |
main = printJSON $ contract loan_amount_in_lovelace payment_amount_in_lovelace number_of_payments (TimeParam "Deadline Bank Deposit") (TimeParam "Payment Deadline") | |
contract :: Integer -> Integer -> Integer -> Timeout -> Timeout -> Contract | |
contract loan_amount_in_lovelace payment_amount_in_lovelace number_of_payments deadlineBankDeposit paymentDeadline = | |
When | |
[Case | |
(Deposit | |
(Role "Bank") | |
(Role "Bank") | |
(Token "e0d123" "Car Title") | |
(Constant 1) | |
) | |
(deposits number_of_payments)] | |
(TimeParam "deadlineBankDeposit") | |
Close | |
where | |
deposit :: Action | |
deposit = | |
Deposit | |
(Role "Bank") | |
(Role "Borrower") | |
(Token "" "") | |
(Constant payment_amount_in_lovelace) | |
deposits :: Integer -> Contract | |
deposits m = foldr addContract payClient $ replicate (fromIntegral m) True | |
where | |
addContract :: Bool -> Contract -> Contract | |
addContract x y = case x of | |
True -> (When [Case deposit y] paymentDeadline Close) | |
False -> Close | |
payClient :: Contract | |
payClient = (Pay | |
(Role "Bank") | |
(Account (Role "Borrower")) | |
(Token "e0d123" "Car Title") | |
(Constant 1) | |
Close | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment