aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs49
1 files changed, 29 insertions, 20 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6d95ff4..1637be7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,7 +5,7 @@ use std::ops::AddAssign;
use serde::Deserialize;
use serde::Serialize;
-#[derive(Clone, Copy, Serialize)]
+#[derive(Clone, Copy, Serialize, Default)]
pub struct Capital {
principal: f64,
interest: f64,
@@ -30,7 +30,8 @@ pub struct Simulation {
st: SimState,
updates: SimUpdates,
history: Vec<Quota>,
- topay: Capital,
+ payed_noupdates: Capital,
+ payed_noprepays: Capital,
payed: Capital,
payed_amortized: f64,
}
@@ -53,14 +54,12 @@ impl Simulation {
Simulation {
st,
- topay: Capital {
+ payed_noupdates: Capital {
principal,
interest: topay_total - principal,
},
- payed: Capital {
- principal: 0.,
- interest: 0.,
- },
+ payed_noprepays: Capital::default(),
+ payed: Capital::default(),
payed_amortized: 0.,
history: vec![],
updates: SimUpdates::default(),
@@ -70,25 +69,35 @@ impl Simulation {
pub fn run(&mut self, updates: SimUpdates) {
self.updates = updates;
let mut st = self.st.clone();
+ // Fist simulation: no prepayments
+ while st.pending_quotas > 0 && st.principal > 0. {
+ let quota = st.step();
+ self.payed_noprepays += quota.payed;
+ self.apply_updates(&mut st, false);
+ }
+ // Second simulation, the good one
+ let mut st = self.st.clone();
while st.pending_quotas > 0 && st.principal > 0. {
let quota = st.step();
self.payed += quota.payed;
self.history.push(quota);
- self.apply_updates(&mut st);
+ self.apply_updates(&mut st, true);
}
}
- fn apply_updates(&mut self, st: &mut SimState) {
+ fn apply_updates(&mut self, st: &mut SimState, apply_prepays: bool) {
for update in self.updates.get(st.period) {
match update {
SimUpdate::Amortize(mut principal) => {
- if principal > st.principal {
- principal = st.principal;
- };
- st.principal -= principal;
- st.calculate_monthly();
- self.payed.principal += principal;
- self.payed_amortized += principal;
+ if apply_prepays {
+ if principal > st.principal {
+ principal = st.principal;
+ };
+ st.principal -= principal;
+ st.calculate_monthly();
+ self.payed.principal += principal;
+ self.payed_amortized += principal;
+ }
}
SimUpdate::SetI1(i1) => {
st.i12 = i1 / 12.0;
@@ -123,13 +132,13 @@ impl Simulation {
println!("\n\n# A PRIORI\n");
println!(
"== Total a pagar: {:.2} ({:.2} cap + {:.2} int)",
- self.topay.total(),
- self.topay.principal,
- self.topay.interest
+ self.payed_noupdates.total(),
+ self.payed_noupdates.principal,
+ self.payed_noupdates.interest
);
println!(
"== Los intereses suponen un {:.2}% del total",
- 100. * self.topay.interest / self.topay.total()
+ 100. * self.payed_noupdates.interest / self.payed_noupdates.total()
);
println!("\n\n# RESULTADO FINAL\n");