Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use chrono::prelude::*;
- struct Arguments {
- // milli-dollars ( $15 = 15000)
- starting_value: i64,
- // milli-dollars
- contrib: i64,
- // percentage in milli-percent ( 13% = 13_000, 100% = 100_000 )
- apr: i64,
- // deci-cents and milli-percent gives us a maximum balance near 922 billion dollars before we overflow
- contrib_years: usize,
- }
- struct Transaction {
- amount: i64,
- time: DateTime<Utc>,
- memo: String,
- }
- struct Account {
- transactions: Vec<Transaction>,
- }
- impl Account {
- fn get_balance_at(&self, time: &DateTime<Utc>) -> i64 {
- // TODO - walk through transactions and update running balance until we get to a date that is greater than the passed in time
- let mut running_balance = 0;
- for mut i in 0..self.transactions.len() {
- let transaction = self.transactions.get(i).unwrap();
- if transaction.time <= *time {
- running_balance += transaction.amount;
- } else {
- i = self.transactions.len();
- }
- }
- running_balance
- }
- }
- fn main() {
- let args = Arguments {
- starting_value: 16_000_000,
- contrib: 1_200_000,
- apr: 5_000,
- contrib_years: 20,
- };
- let mut account: Account = Account {
- transactions: Vec::new(),
- };
- let months = args.contrib_years * 12;
- let mpr = args.apr / 12;
- // println!("Final monthly milli percentage is {}", mpr);
- let mut date = Utc.ymd(2019, 3, 1).and_hms(0, 0, 0);
- let mut balance: i64 = args.starting_value;
- for i in 1..=months {
- date = next_month_truncate(&date);
- // println!("{}",&date.to_rfc2822());
- // apply last months percentage first
- let interest = (balance * mpr) / 100_000;
- // add this months contribution
- let new = balance + interest + args.contrib;
- //println!("{}. Increase by {} and contribute {} makes about {}.", i, interest as f64 / 1000f64, args.contrib as f64 / 1000f64, new as f64 / 1000f64);
- balance = new;
- account.transactions.push(Transaction {
- amount: interest,
- time: date,
- memo: "Simulated interest calculation".to_string(),
- });
- account.transactions.push(Transaction {
- amount: args.contrib,
- time: date,
- memo: "Simulated contribution".to_string(),
- });
- if i % 12 == 0 {
- println!("Year {} : {}", i / 12, &format_milli_dollars(balance));
- }
- }
- println!("Max balance is {}", &format_milli_dollars(balance));
- let query_date = Utc.ymd(2021, 6, 8).and_hms(0, 0, 0);
- println!(
- "Balance at {} is {}",
- &query_date.to_rfc2822(),
- &format_milli_dollars(account.get_balance_at(&query_date))
- );
- // start burn down
- }
- fn format_milli_dollars(dollars: i64) -> String {
- format!("${}.{}", dollars / 1000, (dollars % 1000) / 10)
- }
- fn next_month_truncate(date_time: &DateTime<Utc>) -> DateTime<Utc> {
- let date = date_time.date();
- let time = date_time.time();
- // December to month '0' first
- let n_month = (date.month() % 12) + 1;
- let n_year = if date.month() == 12 {
- date.year() + 1
- } else {
- date.year()
- };
- let n_month_next = (n_month % 12) + 1;
- let n_year_next = if n_month == 12 { n_year + 1 } else { n_year };
- // check length of the next month
- let max_day: u32 = Utc
- .ymd(n_year_next, n_month_next, 1)
- .signed_duration_since(Utc.ymd(n_year, n_month, 1))
- .num_days() as u32;
- let n_day = if date.day() > max_day {
- max_day
- } else {
- date.day()
- };
- Utc.ymd(n_year, n_month, n_day).and_time(time).unwrap()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement