You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2026/03/20 12:16:25 UTC

(fineract) branch develop updated: FINERACT-2455: Add projected amortization schedule

This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new c26fc075a1 FINERACT-2455: Add projected amortization schedule
c26fc075a1 is described below

commit c26fc075a122e6ebe55d618a5fe2afdee39e926c
Author: Oleksii Novikov <al...@onix-systems.com>
AuthorDate: Fri Feb 27 13:34:36 2026 +0200

    FINERACT-2455: Add projected amortization schedule
---
 .../src/docs/en/chapters/features/index.adoc       |    1 +
 .../working-capital-amortization-schedule.adoc     |  201 ++
 .../WorkingCapitalAmortizationScheduleStepDef.java |  203 ++
 .../WorkingCapitalAmortizationSchedule.feature     |  216 ++
 .../api/InternalWorkingCapitalLoanApiResource.java |   80 +
 ...CapitalLoanAmortizationScheduleApiResource.java |   68 +
 ...ultProjectedAmortizationScheduleCalculator.java |   57 +
 .../ProjectedAmortizationScheduleCalculator.java   |   73 +
 .../calc/ProjectedAmortizationScheduleModel.java   |  430 ++++
 .../workingcapitalloan/calc/ProjectedPayment.java  |   80 +
 .../workingcapitalloan/calc/TvmFunctions.java      |  157 ++
 .../data/ProjectedAmortizationScheduleData.java    |   43 +
 ...ojectedAmortizationScheduleGenerateRequest.java |   39 +
 .../ProjectedAmortizationSchedulePaymentData.java  |   48 +
 .../domain/ProjectedAmortizationLoanModel.java     |   57 +
 ...ectedAmortizationScheduleNotFoundException.java |   29 +
 .../ProjectedAmortizationScheduleMapper.java       |   77 +
 .../ProjectedAmortizationLoanModelRepository.java  |   31 +
 ...ctedAmortizationScheduleModelParserService.java |   33 +
 ...tizationScheduleModelParserServiceGsonImpl.java |   87 +
 ...ectedAmortizationScheduleRepositoryWrapper.java |   34 +
 ...dAmortizationScheduleRepositoryWrapperImpl.java |   66 +
 ...CapitalLoanAmortizationScheduleReadService.java |   26 +
 ...talLoanAmortizationScheduleReadServiceImpl.java |   58 +
 ...apitalLoanAmortizationScheduleWriteService.java |   26 +
 ...alLoanAmortizationScheduleWriteServiceImpl.java |   65 +
 .../workingcapitalloan/module-changelog-master.xml |    1 +
 .../parts/0009_wc_loan_amortization_model.xml      |   81 +
 ...rojectedAmortizationScheduleCalculatorTest.java | 2316 ++++++++++++++++++++
 29 files changed, 4683 insertions(+)

diff --git a/fineract-doc/src/docs/en/chapters/features/index.adoc b/fineract-doc/src/docs/en/chapters/features/index.adoc
index 5c386f1e1e..c7a212145d 100644
--- a/fineract-doc/src/docs/en/chapters/features/index.adoc
+++ b/fineract-doc/src/docs/en/chapters/features/index.adoc
@@ -16,3 +16,4 @@ include::re-amortization.adoc[leveloffset=+1]
 include::re-ageing.adoc[leveloffset=+1]
 include::delayed-schedule-captures.adoc[leveloffset=+1]
 include::loan-origination-details.adoc[leveloffset=+1]
+include::working-capital-amortization-schedule.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/features/working-capital-amortization-schedule.adoc b/fineract-doc/src/docs/en/chapters/features/working-capital-amortization-schedule.adoc
new file mode 100644
index 0000000000..a0d7ab5ff6
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/features/working-capital-amortization-schedule.adoc
@@ -0,0 +1,201 @@
+= Working Capital Loan — Projected Amortization Schedule
+
+== Overview
+
+Dynamically updated amortization schedule for Working Capital (WC) Loans — zero-interest, discount/fee-based products with flexible, sales-based repayments. Uses EIR methodology for income recognition, deferral, and NPV calculation.
+
+Each payment period is exactly *one day*: period `N` date = `expectedDisbursementDate + N days`.
+
+== Lifecycle
+
+[cols="1,3",options="header"]
+|===
+| Stage | Behavior
+
+| *Create* | `generateModel()` — initial schedule from application parameters.
+| *Disburse* | `addDisbursement()` — recalculates with actual disbursement amounts/date, preserves applied payments.
+| *Repayment* | `applyPayment()` — records payment, full schedule rebuild.
+|===
+
+== Input Parameters
+
+[cols="2,1,4",options="header"]
+|===
+| Parameter | Type | Description
+
+| `originationFeeAmount` | Money | Upfront discount/fee. Amortized over lifecycle.
+| `netDisbursementAmount` | Money | Principal disbursed. Must be positive.
+| `totalPaymentValue` | Money | Merchant's TPV.
+| `periodPaymentRate` | BigDecimal | Rate applied to TPV (e.g., 0.18 = 18%).
+| `npvDayCount` | Integer | Day-count convention (e.g., 360). Must be positive.
+| `expectedDisbursementDate` | Date | Loan start date.
+|===
+
+== Formulas
+
+----
+expectedPaymentAmount = (TPV × periodPaymentRate) / npvDayCount
+loanTerm             = roundUp((netDisbursement + originationFee) / expectedPayment)
+EIR                  = RATE(loanTerm, -expectedPayment, netDisbursement)   // Newton-Raphson, tol=1E-10, max 100 iter
+paymentsLeft         = max(0, paymentNo - appliedPaymentCount)
+discountFactor       = 1 / (1 + EIR) ^ paymentsLeft                       // model wrapper: returns 1.0 if ≤ 0
+npvSource            = actualPayment (if applied) or forecastPayment (if not)
+npvValue             = max(0, npvSource × discountFactor)   // row 0: -netDisbursementAmount (unclamped)
+----
+
+== Schedule Fields
+
+[cols="2,4",options="header"]
+|===
+| Field | Formula / Description
+
+| `paymentNo` | 1-based. Row 0 = disbursement.
+| `paymentDate` | `expectedDisbursementDate + paymentNo` days.
+| `count` | `loanTerm + appliedPaymentCount - paymentNo`. Can be negative for tail periods.
+| `paymentsLeft` | `max(0, paymentNo - appliedPaymentCount)`. Zero for row 0.
+| `expectedPaymentAmount` | Constant. Row 0: `-netDisbursementAmount`. Tail: null.
+| `forecastPaymentAmount` | Expected payment reduced by excess (backward from last period), clamped to zero. Row 0: null.
+| `discountFactor` | `1/(1+EIR)^paymentsLeft`. Row 0 and paid periods: 1.0.
+| `npvValue` | `max(0, npvSource × DF)`. Row 0: `-netDisbursementAmount`.
+| `balance` | `balance[i-1]×(1+EIR) - expectedPayment`. Row 0: `+netDisbursementAmount`. Tail: null.
+| `expectedAmortizationAmount` | `min(balance[i] + expectedPayment - balance[i-1], originationFee)`. Row 0 / tail: null.
+| `netAmortizationAmount` | Paid: `min(totalNetAmort - cumulativeActualAmort_before, originationFee)` where `cumulativeActualAmort_before` excludes the current period. Unpaid: 0. Row 0: null.
+| `actualPaymentAmount` | Actual cash paid. Null if no payment.
+| `actualAmortizationAmount` | Cursor-based: `actualPayment/expectedPayment` periods of expected amortization consumed. Null if no payment.
+| `incomeModification` | Paid: `actualAmort - expectedAmort`. Unpaid: `-expectedAmort`. Row 0 / tail: null.
+| `deferredBalance` | `originationFee - cumulativeActualAmort`. Row 0: `originationFee`. Tail: null.
+|===
+
+=== Disbursement Row (paymentNo = 0)
+
+[cols="1,2"]
+|===
+| `count` | `loanTerm + appliedPaymentCount`
+| `paymentsLeft` | 0
+| `expectedPaymentAmount` | `-netDisbursementAmount`
+| `forecastPaymentAmount` | null
+| `discountFactor` | 1.0
+| `npvValue` | `-netDisbursementAmount`
+| `balance` | `+netDisbursementAmount`
+| `deferredBalance` | `originationFeeAmount`
+| all other nullable fields | null
+|===
+
+=== Tail Periods
+
+Appended when shortfall remains after loanTerm. Each forecasts `min(remainingShortfall, expectedPayment)`. Structural fields (`paymentNo`, `paymentDate`, `count`, `paymentsLeft`) are always set. Among nullable fields, only `forecastPaymentAmount`, `discountFactor`, `npvValue`, `netAmortizationAmount` (zero) are populated; rest are null. Trailing rows with zero forecast are trimmed.
+
+== Calculation Algorithm
+
+. *Balances & expected amortizations*: `balance[i] = balance[i-1]×(1+EIR) - expectedPayment`. Expected amort capped at `originationFee`.
+. *Aggregate payments by date* (same-date payments summed). Payments must occupy consecutive day slots starting from day 1.
+. *Shortfall/excess analysis*: compare each applied payment to expected.
+. *Cursor-based actual amortization*: cursor advances by `actualPayment/expectedPayment` periods; interpolates partial periods.
+. *Excess distribution*: reduces forecast payments backward from last period.
+. *Tail periods*: appended for remaining shortfall.
+. *Total net amortization*: `-netDisbursement + Σ(npvSource[i] × DF[i]) + tailNpv`.
+. *Assemble rows*, trim trailing zero-forecast.
+
+== API Endpoints
+
+=== GET /v1/working-capital-loans/{loanId}/amortization-schedule
+
+Example Request:
+
+ GET /fineract-provider/api/v1/working-capital-loans/1/amortization-schedule
+
+Example Response (first 3 payments shown):
+
+[source,json]
+----
+{
+  "originationFeeAmount": 1000.00,
+  "netDisbursementAmount": 9000.00,
+  "totalPaymentValue": 100000.00,
+  "periodPaymentRate": 0.18,
+  "npvDayCount": 360,
+  "expectedDisbursementDate": "2019-01-01",
+  "expectedPaymentAmount": 50.00,
+  "loanTerm": 200,
+  "effectiveInterestRate": 0.0010678144878363462,
+  "payments": [
+    {
+      "paymentNo": 0,
+      "paymentDate": "2019-01-01",
+      "count": 200,
+      "paymentsLeft": 0,
+      "expectedPaymentAmount": -9000.00,
+      "forecastPaymentAmount": null,
+      "discountFactor": 1,
+      "npvValue": -9000.00,
+      "balance": 9000.00,
+      "expectedAmortizationAmount": null,
+      "netAmortizationAmount": null,
+      "actualPaymentAmount": null,
+      "actualAmortizationAmount": null,
+      "incomeModification": null,
+      "deferredBalance": 1000.00
+    },
+    {
+      "paymentNo": 1,
+      "paymentDate": "2019-01-02",
+      "count": 199,
+      "paymentsLeft": 1,
+      "expectedPaymentAmount": 50.00,
+      "forecastPaymentAmount": 50.00,
+      "discountFactor": 0.998933324523691,
+      "npvValue": 49.95,
+      "balance": 8959.61,
+      "expectedAmortizationAmount": 9.61,
+      "netAmortizationAmount": 0.00,
+      "actualPaymentAmount": null,
+      "actualAmortizationAmount": null,
+      "incomeModification": -9.61,
+      "deferredBalance": 1000.00
+    },
+    {
+      "paymentNo": 2,
+      "paymentDate": "2019-01-03",
+      "count": 198,
+      "paymentsLeft": 2,
+      "expectedPaymentAmount": 50.00,
+      "forecastPaymentAmount": 50.00,
+      "discountFactor": 0.9978677868439537,
+      "npvValue": 49.89,
+      "balance": 8919.18,
+      "expectedAmortizationAmount": 9.57,
+      "netAmortizationAmount": 0.00,
+      "actualPaymentAmount": null,
+      "actualAmortizationAmount": null,
+      "incomeModification": -9.57,
+      "deferredBalance": 1000.00
+    }
+  ]
+}
+----
+
+== Database
+
+.Table: `m_wc_loan_amortization_model`
+[cols="2,1,3",options="header"]
+|===
+| Column | Type | Description
+
+| `id` | BIGINT | PK, auto-increment.
+| `version` | INT | Optimistic lock.
+| `loan_id` | BIGINT | FK → `m_wc_loan`. Unique.
+| `json_model` | LONGTEXT (MySQL/MariaDB) / TEXT (PostgreSQL) | Serialized model (Gson). `@JsonExclude` on `MathContext`, `MonetaryCurrency`; restored via `forDeserialization()`.
+| `business_date` | DATE | Last generated/updated.
+| `last_modified_on_utc` | DATETIME(6) / TIMESTAMP WITH TIME ZONE | Audit. MySQL / PostgreSQL.
+| `json_model_version` | VARCHAR(10) | Currently `"1"`.
+|===
+
+=== Rebuild Flow
+
+Every state change triggers full rebuild: aggregate payments → build payment list (1 to loanTerm, actual or null) → balances → payment analysis → cursor amortizations → excess distribution → tail → net amortization → assemble rows → trim.
+
+== TVM Functions
+
+*RATE*: Newton-Raphson solving `pv×(1+r)^n + pmt×((1+r)^n−1)/r = 0`. Initial guess: `2×(pmt×n+pv)/(pv×n)`, fallback 0.01. Tolerance 1E-10, max 100 iterations.
+
+*Discount Factor*: `1/(1+eir)^days`. Returns 1.0 when days=0. Throws `IllegalArgumentException` for negative days. The model wraps this via `safeDiscountFactor()` which additionally returns 1.0 when the computed result is ≤ 0.
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalAmortizationScheduleStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalAmortizationScheduleStepDef.java
new file mode 100644
index 0000000000..b920f0e0e7
--- /dev/null
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalAmortizationScheduleStepDef.java
@@ -0,0 +1,203 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.test.stepdef.loan;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.cucumber.datatable.DataTable;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.client.feign.FineractFeignClient;
+import org.apache.fineract.client.feign.services.WorkingCapitalLoansApi;
+import org.apache.fineract.client.models.PostWorkingCapitalLoansResponse;
+import org.apache.fineract.client.models.ProjectedAmortizationScheduleData;
+import org.apache.fineract.client.models.ProjectedAmortizationScheduleGenerateRequest;
+import org.apache.fineract.client.models.ProjectedAmortizationSchedulePaymentData;
+import org.apache.fineract.test.stepdef.AbstractStepDef;
+import org.apache.fineract.test.support.TestContext;
+import org.apache.fineract.test.support.TestContextKey;
+import org.assertj.core.api.SoftAssertions;
+
+@Slf4j
+@RequiredArgsConstructor
+public class WorkingCapitalAmortizationScheduleStepDef extends AbstractStepDef {
+
+    private static final String WC_AMORT_SCHEDULE_KEY = "WC_AMORT_SCHEDULE_RESPONSE";
+
+    private final FineractFeignClient fineractFeignClient;
+
+    @When("Admin generates a projected amortization schedule with originationFeeAmount {double}, netDisbursementAmount {double}, totalPaymentValue {double}, periodPaymentRate {double}, npvDayCount {int}, expectedDisbursementDate {string}")
+    public void generateAmortizationSchedule(final double originationFeeAmount, final double netDisbursementAmount,
+            final double totalPaymentValue, final double periodPaymentRate, final int npvDayCount, final String expectedDisbursementDate) {
+        final Long loanId = extractLoanId();
+        final WorkingCapitalLoansApi api = fineractFeignClient.create(WorkingCapitalLoansApi.class);
+
+        final ProjectedAmortizationScheduleGenerateRequest request = new ProjectedAmortizationScheduleGenerateRequest();
+        request.setOriginationFeeAmount(BigDecimal.valueOf(originationFeeAmount));
+        request.setNetDisbursementAmount(BigDecimal.valueOf(netDisbursementAmount));
+        request.setTotalPaymentValue(BigDecimal.valueOf(totalPaymentValue));
+        request.setPeriodPaymentRate(BigDecimal.valueOf(periodPaymentRate));
+        request.setNpvDayCount(npvDayCount);
+        request.setExpectedDisbursementDate(LocalDate.parse(expectedDisbursementDate));
+
+        api.generateAmortizationSchedule(loanId, request);
+        log.info("Generated amortization schedule for loan {}", loanId);
+    }
+
+    @When("Admin retrieves the projected amortization schedule")
+    public void retrieveAmortizationSchedule() {
+        final Long loanId = extractLoanId();
+        final WorkingCapitalLoansApi api = fineractFeignClient.create(WorkingCapitalLoansApi.class);
+
+        final ProjectedAmortizationScheduleData response = api.retrieveAmortizationSchedule(loanId);
+        log.info("Retrieved amortization schedule for loan {}: netDisbursementAmount={}", loanId, response.getNetDisbursementAmount());
+        TestContext.INSTANCE.set(WC_AMORT_SCHEDULE_KEY, response);
+    }
+
+    @Then("The retrieved amortization schedule has the following summary fields:")
+    public void verifyRetrievedSummaryFields(final DataTable dataTable) {
+        verifySummaryFields(dataTable);
+    }
+
+    @Then("The retrieved amortization schedule has payments with the following details:")
+    public void verifyRetrievedPaymentDetails(final DataTable dataTable) {
+        verifyPaymentDetails(dataTable);
+    }
+
+    private void verifySummaryFields(final DataTable dataTable) {
+        final ProjectedAmortizationScheduleData response = TestContext.INSTANCE.get(WC_AMORT_SCHEDULE_KEY);
+        assertThat(response).as("Amortization schedule response").isNotNull();
+
+        final Map<String, String> expected = dataTable.asMaps().getFirst();
+        final SoftAssertions assertions = new SoftAssertions();
+
+        assertDecimal(assertions, "originationFeeAmount", response.getOriginationFeeAmount(), expected.get("originationFeeAmount"));
+        assertDecimal(assertions, "netDisbursementAmount", response.getNetDisbursementAmount(), expected.get("netDisbursementAmount"));
+        assertDecimal(assertions, "totalPaymentValue", response.getTotalPaymentValue(), expected.get("totalPaymentValue"));
+        assertDecimal(assertions, "periodPaymentRate", response.getPeriodPaymentRate(), expected.get("periodPaymentRate"));
+        assertInt(assertions, "npvDayCount", response.getNpvDayCount(), expected.get("npvDayCount"));
+        assertDecimal(assertions, "expectedPaymentAmount", response.getExpectedPaymentAmount(), expected.get("expectedPaymentAmount"));
+        assertInt(assertions, "loanTerm", response.getLoanTerm(), expected.get("loanTerm"));
+
+        assertions.assertAll();
+    }
+
+    private void verifyPaymentDetails(final DataTable dataTable) {
+        final ProjectedAmortizationScheduleData response = TestContext.INSTANCE.get(WC_AMORT_SCHEDULE_KEY);
+        assertThat(response).as("Amortization schedule response").isNotNull();
+
+        final List<ProjectedAmortizationSchedulePaymentData> actualPayments = response.getPayments();
+        assertThat(actualPayments).as("payments list").isNotNull();
+
+        final List<Map<String, String>> expectedRows = dataTable.asMaps();
+        assertThat(actualPayments).as("payment count").hasSameSizeAs(expectedRows);
+
+        final SoftAssertions assertions = new SoftAssertions();
+        for (int i = 0; i < expectedRows.size(); i++) {
+            final Map<String, String> expected = expectedRows.get(i);
+            final ProjectedAmortizationSchedulePaymentData actual = actualPayments.get(i);
+            final String p = "payment[" + i + "].";
+
+            assertInt(assertions, p + "paymentNo", actual.getPaymentNo(), expected.get("paymentNo"));
+            assertDate(assertions, p + "date", actual.getPaymentDate(), expected.get("date"));
+            assertLong(assertions, p + "paymentsLeft", actual.getPaymentsLeft(), expected.get("paymentsLeft"));
+            assertNullableDecimal(assertions, p + "expectedPaymentAmount", actual.getExpectedPaymentAmount(),
+                    expected.get("expectedPaymentAmount"));
+            assertNullableDecimal(assertions, p + "forecastPaymentAmount", actual.getForecastPaymentAmount(),
+                    expected.get("forecastPaymentAmount"));
+            assertOptionalDecimal(assertions, p + "discountFactor", actual.getDiscountFactor(), expected.get("discountFactor"));
+            assertNullableDecimal(assertions, p + "npvValue", actual.getNpvValue(), expected.get("npvValue"));
+            assertNullableDecimal(assertions, p + "balance", actual.getBalance(), expected.get("balance"));
+            assertNullableDecimal(assertions, p + "expectedAmortizationAmount", actual.getExpectedAmortizationAmount(),
+                    expected.get("expectedAmortizationAmount"));
+            assertNullableDecimal(assertions, p + "netAmortizationAmount", actual.getNetAmortizationAmount(),
+                    expected.get("netAmortizationAmount"));
+            assertNullableDecimal(assertions, p + "actualPaymentAmount", actual.getActualPaymentAmount(),
+                    expected.get("actualPaymentAmount"));
+            assertNullableDecimal(assertions, p + "actualAmortizationAmount", actual.getActualAmortizationAmount(),
+                    expected.get("actualAmortizationAmount"));
+            assertNullableDecimal(assertions, p + "incomeModification", actual.getIncomeModification(), expected.get("incomeModification"));
+            assertNullableDecimal(assertions, p + "deferredBalance", actual.getDeferredBalance(), expected.get("deferredBalance"));
+        }
+
+        assertions.assertAll();
+    }
+
+    private static void assertDecimal(final SoftAssertions assertions, final String field, final BigDecimal actual,
+            final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            return;
+        }
+        final BigDecimal expected = new BigDecimal(expectedStr);
+        assertions.assertThat(actual).as(field).isNotNull();
+        if (actual != null) {
+            assertions.assertThat(actual.compareTo(expected)).as("%s: expected=%s actual=%s", field, expected, actual).isEqualTo(0);
+        }
+    }
+
+    private static void assertNullableDecimal(final SoftAssertions assertions, final String field, final BigDecimal actual,
+            final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            assertions.assertThat(actual).as(field + " should be null").isNull();
+            return;
+        }
+        assertDecimal(assertions, field, actual, expectedStr);
+    }
+
+    private static void assertInt(final SoftAssertions assertions, final String field, final Integer actual, final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            return;
+        }
+        assertions.assertThat(actual).as(field).isEqualTo(Integer.parseInt(expectedStr));
+    }
+
+    private static void assertLong(final SoftAssertions assertions, final String field, final Long actual, final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            return;
+        }
+        assertions.assertThat(actual).as(field).isEqualTo(Long.parseLong(expectedStr));
+    }
+
+    private static void assertDate(final SoftAssertions assertions, final String field, final LocalDate actual, final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            return;
+        }
+        assertions.assertThat(actual).as(field).isEqualTo(LocalDate.parse(expectedStr));
+    }
+
+    private static void assertOptionalDecimal(final SoftAssertions assertions, final String field, final BigDecimal actual,
+            final String expectedStr) {
+        if (expectedStr == null || expectedStr.isBlank()) {
+            assertions.assertThat(actual).as(field + " should not be null").isNotNull();
+            return;
+        }
+        assertDecimal(assertions, field, actual, expectedStr);
+    }
+
+    private Long extractLoanId() {
+        final PostWorkingCapitalLoansResponse response = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
+        return response.getLoanId();
+    }
+}
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalAmortizationSchedule.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalAmortizationSchedule.feature
new file mode 100644
index 0000000000..48384646ab
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalAmortizationSchedule.feature
@@ -0,0 +1,216 @@
+Feature: WorkingCapitalAmortizationSchedule
+
+  Scenario: Generate and retrieve a projected amortization schedule with 200 payments
+    When Admin sets the business date to "01 January 2026"
+    And Admin creates a client with random data
+    And Admin creates a working capital loan with the following data:
+      | LoanProduct | submittedOnDate | expectedDisbursementDate | principalAmount | totalPayment | periodPaymentRate | discount |
+      | WCLP        | 01 January 2026 | 01 January 2026          | 100             | 100          | 1                 | 0        |
+    When Admin generates a projected amortization schedule with originationFeeAmount 1000.0, netDisbursementAmount 9000.0, totalPaymentValue 100000.0, periodPaymentRate 0.18, npvDayCount 360, expectedDisbursementDate "2019-01-01"
+    And Admin retrieves the projected amortization schedule
+    Then The retrieved amortization schedule has the following summary fields:
+      | originationFeeAmount | netDisbursementAmount | totalPaymentValue | periodPaymentRate | npvDayCount | expectedPaymentAmount | loanTerm |
+      | 1000.00        | 9000.00   | 100000.00         | 0.18              | 360         | 50.00                 | 200      |
+    And The retrieved amortization schedule has payments with the following details:
+      | paymentNo | date | paymentsLeft | expectedPaymentAmount | forecastPaymentAmount | discountFactor | npvValue | balance  | expectedAmortizationAmount | netAmortizationAmount | actualPaymentAmount | actualAmortizationAmount | incomeModification | deferredBalance |
+      | 0             | 2019-01-01      | 0        | -9000.00              |                       | 1              | -9000.00 | 9000.00  |                            |                       |                     |                          |                    | 1000.00         |
+      | 1             | 2019-01-02      | 1        | 50.00                 | 50.00                 |                | 49.95    | 8959.61  | 9.61                       | 0.00                  |                     |                          | -9.61              | 1000.00         |
+      | 2             | 2019-01-03      | 2        | 50.00                 | 50.00                 |                | 49.89    | 8919.18  | 9.57                       | 0.00                  |                     |                          | -9.57              | 1000.00         |
+      | 3             | 2019-01-04      | 3        | 50.00                 | 50.00                 |                | 49.84    | 8878.70  | 9.52                       | 0.00                  |                     |                          | -9.52              | 1000.00         |
+      | 4             | 2019-01-05      | 4        | 50.00                 | 50.00                 |                | 49.79    | 8838.18  | 9.48                       | 0.00                  |                     |                          | -9.48              | 1000.00         |
+      | 5             | 2019-01-06      | 5        | 50.00                 | 50.00                 |                | 49.73    | 8797.62  | 9.44                       | 0.00                  |                     |                          | -9.44              | 1000.00         |
+      | 6             | 2019-01-07      | 6        | 50.00                 | 50.00                 |                | 49.68    | 8757.01  | 9.39                       | 0.00                  |                     |                          | -9.39              | 1000.00         |
+      | 7             | 2019-01-08      | 7        | 50.00                 | 50.00                 |                | 49.63    | 8716.36  | 9.35                       | 0.00                  |                     |                          | -9.35              | 1000.00         |
+      | 8             | 2019-01-09      | 8        | 50.00                 | 50.00                 |                | 49.57    | 8675.67  | 9.31                       | 0.00                  |                     |                          | -9.31              | 1000.00         |
+      | 9             | 2019-01-10      | 9        | 50.00                 | 50.00                 |                | 49.52    | 8634.94  | 9.26                       | 0.00                  |                     |                          | -9.26              | 1000.00         |
+      | 10            | 2019-01-11      | 10       | 50.00                 | 50.00                 |                | 49.47    | 8594.16  | 9.22                       | 0.00                  |                     |                          | -9.22              | 1000.00         |
+      | 11            | 2019-01-12      | 11       | 50.00                 | 50.00                 |                | 49.42    | 8553.33  | 9.18                       | 0.00                  |                     |                          | -9.18              | 1000.00         |
+      | 12            | 2019-01-13      | 12       | 50.00                 | 50.00                 |                | 49.36    | 8512.47  | 9.13                       | 0.00                  |                     |                          | -9.13              | 1000.00         |
+      | 13            | 2019-01-14      | 13       | 50.00                 | 50.00                 |                | 49.31    | 8471.56  | 9.09                       | 0.00                  |                     |                          | -9.09              | 1000.00         |
+      | 14            | 2019-01-15      | 14       | 50.00                 | 50.00                 |                | 49.26    | 8430.60  | 9.05                       | 0.00                  |                     |                          | -9.05              | 1000.00         |
+      | 15            | 2019-01-16      | 15       | 50.00                 | 50.00                 |                | 49.21    | 8389.61  | 9.00                       | 0.00                  |                     |                          | -9.00              | 1000.00         |
+      | 16            | 2019-01-17      | 16       | 50.00                 | 50.00                 |                | 49.15    | 8348.56  | 8.96                       | 0.00                  |                     |                          | -8.96              | 1000.00         |
+      | 17            | 2019-01-18      | 17       | 50.00                 | 50.00                 |                | 49.10    | 8307.48  | 8.91                       | 0.00                  |                     |                          | -8.91              | 1000.00         |
+      | 18            | 2019-01-19      | 18       | 50.00                 | 50.00                 |                | 49.05    | 8266.35  | 8.87                       | 0.00                  |                     |                          | -8.87              | 1000.00         |
+      | 19            | 2019-01-20      | 19       | 50.00                 | 50.00                 |                | 49.00    | 8225.18  | 8.83                       | 0.00                  |                     |                          | -8.83              | 1000.00         |
+      | 20            | 2019-01-21      | 20       | 50.00                 | 50.00                 |                | 48.94    | 8183.96  | 8.78                       | 0.00                  |                     |                          | -8.78              | 1000.00         |
+      | 21            | 2019-01-22      | 21       | 50.00                 | 50.00                 |                | 48.89    | 8142.70  | 8.74                       | 0.00                  |                     |                          | -8.74              | 1000.00         |
+      | 22            | 2019-01-23      | 22       | 50.00                 | 50.00                 |                | 48.84    | 8101.39  | 8.69                       | 0.00                  |                     |                          | -8.69              | 1000.00         |
+      | 23            | 2019-01-24      | 23       | 50.00                 | 50.00                 |                | 48.79    | 8060.04  | 8.65                       | 0.00                  |                     |                          | -8.65              | 1000.00         |
+      | 24            | 2019-01-25      | 24       | 50.00                 | 50.00                 |                | 48.74    | 8018.65  | 8.61                       | 0.00                  |                     |                          | -8.61              | 1000.00         |
+      | 25            | 2019-01-26      | 25       | 50.00                 | 50.00                 |                | 48.68    | 7977.21  | 8.56                       | 0.00                  |                     |                          | -8.56              | 1000.00         |
+      | 26            | 2019-01-27      | 26       | 50.00                 | 50.00                 |                | 48.63    | 7935.73  | 8.52                       | 0.00                  |                     |                          | -8.52              | 1000.00         |
+      | 27            | 2019-01-28      | 27       | 50.00                 | 50.00                 |                | 48.58    | 7894.21  | 8.47                       | 0.00                  |                     |                          | -8.47              | 1000.00         |
+      | 28            | 2019-01-29      | 28       | 50.00                 | 50.00                 |                | 48.53    | 7852.63  | 8.43                       | 0.00                  |                     |                          | -8.43              | 1000.00         |
+      | 29            | 2019-01-30      | 29       | 50.00                 | 50.00                 |                | 48.48    | 7811.02  | 8.39                       | 0.00                  |                     |                          | -8.39              | 1000.00         |
+      | 30            | 2019-01-31      | 30       | 50.00                 | 50.00                 |                | 48.42    | 7769.36  | 8.34                       | 0.00                  |                     |                          | -8.34              | 1000.00         |
+      | 31            | 2019-02-01      | 31       | 50.00                 | 50.00                 |                | 48.37    | 7727.66  | 8.30                       | 0.00                  |                     |                          | -8.30              | 1000.00         |
+      | 32            | 2019-02-02      | 32       | 50.00                 | 50.00                 |                | 48.32    | 7685.91  | 8.25                       | 0.00                  |                     |                          | -8.25              | 1000.00         |
+      | 33            | 2019-02-03      | 33       | 50.00                 | 50.00                 |                | 48.27    | 7644.12  | 8.21                       | 0.00                  |                     |                          | -8.21              | 1000.00         |
+      | 34            | 2019-02-04      | 34       | 50.00                 | 50.00                 |                | 48.22    | 7602.28  | 8.16                       | 0.00                  |                     |                          | -8.16              | 1000.00         |
+      | 35            | 2019-02-05      | 35       | 50.00                 | 50.00                 |                | 48.17    | 7560.40  | 8.12                       | 0.00                  |                     |                          | -8.12              | 1000.00         |
+      | 36            | 2019-02-06      | 36       | 50.00                 | 50.00                 |                | 48.12    | 7518.47  | 8.07                       | 0.00                  |                     |                          | -8.07              | 1000.00         |
+      | 37            | 2019-02-07      | 37       | 50.00                 | 50.00                 |                | 48.06    | 7476.50  | 8.03                       | 0.00                  |                     |                          | -8.03              | 1000.00         |
+      | 38            | 2019-02-08      | 38       | 50.00                 | 50.00                 |                | 48.01    | 7434.48  | 7.98                       | 0.00                  |                     |                          | -7.98              | 1000.00         |
+      | 39            | 2019-02-09      | 39       | 50.00                 | 50.00                 |                | 47.96    | 7392.42  | 7.94                       | 0.00                  |                     |                          | -7.94              | 1000.00         |
+      | 40            | 2019-02-10      | 40       | 50.00                 | 50.00                 |                | 47.91    | 7350.31  | 7.89                       | 0.00                  |                     |                          | -7.89              | 1000.00         |
+      | 41            | 2019-02-11      | 41       | 50.00                 | 50.00                 |                | 47.86    | 7308.16  | 7.85                       | 0.00                  |                     |                          | -7.85              | 1000.00         |
+      | 42            | 2019-02-12      | 42       | 50.00                 | 50.00                 |                | 47.81    | 7265.97  | 7.80                       | 0.00                  |                     |                          | -7.80              | 1000.00         |
+      | 43            | 2019-02-13      | 43       | 50.00                 | 50.00                 |                | 47.76    | 7223.72  | 7.76                       | 0.00                  |                     |                          | -7.76              | 1000.00         |
+      | 44            | 2019-02-14      | 44       | 50.00                 | 50.00                 |                | 47.71    | 7181.44  | 7.71                       | 0.00                  |                     |                          | -7.71              | 1000.00         |
+      | 45            | 2019-02-15      | 45       | 50.00                 | 50.00                 |                | 47.66    | 7139.11  | 7.67                       | 0.00                  |                     |                          | -7.67              | 1000.00         |
+      | 46            | 2019-02-16      | 46       | 50.00                 | 50.00                 |                | 47.60    | 7096.73  | 7.62                       | 0.00                  |                     |                          | -7.62              | 1000.00         |
+      | 47            | 2019-02-17      | 47       | 50.00                 | 50.00                 |                | 47.55    | 7054.31  | 7.58                       | 0.00                  |                     |                          | -7.58              | 1000.00         |
+      | 48            | 2019-02-18      | 48       | 50.00                 | 50.00                 |                | 47.50    | 7011.84  | 7.53                       | 0.00                  |                     |                          | -7.53              | 1000.00         |
+      | 49            | 2019-02-19      | 49       | 50.00                 | 50.00                 |                | 47.45    | 6969.33  | 7.49                       | 0.00                  |                     |                          | -7.49              | 1000.00         |
+      | 50            | 2019-02-20      | 50       | 50.00                 | 50.00                 |                | 47.40    | 6926.77  | 7.44                       | 0.00                  |                     |                          | -7.44              | 1000.00         |
+      | 51            | 2019-02-21      | 51       | 50.00                 | 50.00                 |                | 47.35    | 6884.17  | 7.40                       | 0.00                  |                     |                          | -7.40              | 1000.00         |
+      | 52            | 2019-02-22      | 52       | 50.00                 | 50.00                 |                | 47.30    | 6841.52  | 7.35                       | 0.00                  |                     |                          | -7.35              | 1000.00         |
+      | 53            | 2019-02-23      | 53       | 50.00                 | 50.00                 |                | 47.25    | 6798.82  | 7.31                       | 0.00                  |                     |                          | -7.31              | 1000.00         |
+      | 54            | 2019-02-24      | 54       | 50.00                 | 50.00                 |                | 47.20    | 6756.08  | 7.26                       | 0.00                  |                     |                          | -7.26              | 1000.00         |
+      | 55            | 2019-02-25      | 55       | 50.00                 | 50.00                 |                | 47.15    | 6713.30  | 7.21                       | 0.00                  |                     |                          | -7.21              | 1000.00         |
+      | 56            | 2019-02-26      | 56       | 50.00                 | 50.00                 |                | 47.10    | 6670.47  | 7.17                       | 0.00                  |                     |                          | -7.17              | 1000.00         |
+      | 57            | 2019-02-27      | 57       | 50.00                 | 50.00                 |                | 47.05    | 6627.59  | 7.12                       | 0.00                  |                     |                          | -7.12              | 1000.00         |
+      | 58            | 2019-02-28      | 58       | 50.00                 | 50.00                 |                | 47.00    | 6584.67  | 7.08                       | 0.00                  |                     |                          | -7.08              | 1000.00         |
+      | 59            | 2019-03-01      | 59       | 50.00                 | 50.00                 |                | 46.95    | 6541.70  | 7.03                       | 0.00                  |                     |                          | -7.03              | 1000.00         |
+      | 60            | 2019-03-02      | 60       | 50.00                 | 50.00                 |                | 46.90    | 6498.68  | 6.99                       | 0.00                  |                     |                          | -6.99              | 1000.00         |
+      | 61            | 2019-03-03      | 61       | 50.00                 | 50.00                 |                | 46.85    | 6455.62  | 6.94                       | 0.00                  |                     |                          | -6.94              | 1000.00         |
+      | 62            | 2019-03-04      | 62       | 50.00                 | 50.00                 |                | 46.80    | 6412.51  | 6.89                       | 0.00                  |                     |                          | -6.89              | 1000.00         |
+      | 63            | 2019-03-05      | 63       | 50.00                 | 50.00                 |                | 46.75    | 6369.36  | 6.85                       | 0.00                  |                     |                          | -6.85              | 1000.00         |
+      | 64            | 2019-03-06      | 64       | 50.00                 | 50.00                 |                | 46.70    | 6326.16  | 6.80                       | 0.00                  |                     |                          | -6.80              | 1000.00         |
+      | 65            | 2019-03-07      | 65       | 50.00                 | 50.00                 |                | 46.65    | 6282.92  | 6.76                       | 0.00                  |                     |                          | -6.76              | 1000.00         |
+      | 66            | 2019-03-08      | 66       | 50.00                 | 50.00                 |                | 46.60    | 6239.63  | 6.71                       | 0.00                  |                     |                          | -6.71              | 1000.00         |
+      | 67            | 2019-03-09      | 67       | 50.00                 | 50.00                 |                | 46.55    | 6196.29  | 6.66                       | 0.00                  |                     |                          | -6.66              | 1000.00         |
+      | 68            | 2019-03-10      | 68       | 50.00                 | 50.00                 |                | 46.50    | 6152.91  | 6.62                       | 0.00                  |                     |                          | -6.62              | 1000.00         |
+      | 69            | 2019-03-11      | 69       | 50.00                 | 50.00                 |                | 46.45    | 6109.48  | 6.57                       | 0.00                  |                     |                          | -6.57              | 1000.00         |
+      | 70            | 2019-03-12      | 70       | 50.00                 | 50.00                 |                | 46.40    | 6066.00  | 6.52                       | 0.00                  |                     |                          | -6.52              | 1000.00         |
+      | 71            | 2019-03-13      | 71       | 50.00                 | 50.00                 |                | 46.35    | 6022.48  | 6.48                       | 0.00                  |                     |                          | -6.48              | 1000.00         |
+      | 72            | 2019-03-14      | 72       | 50.00                 | 50.00                 |                | 46.30    | 5978.91  | 6.43                       | 0.00                  |                     |                          | -6.43              | 1000.00         |
+      | 73            | 2019-03-15      | 73       | 50.00                 | 50.00                 |                | 46.25    | 5935.29  | 6.38                       | 0.00                  |                     |                          | -6.38              | 1000.00         |
+      | 74            | 2019-03-16      | 74       | 50.00                 | 50.00                 |                | 46.20    | 5891.63  | 6.34                       | 0.00                  |                     |                          | -6.34              | 1000.00         |
+      | 75            | 2019-03-17      | 75       | 50.00                 | 50.00                 |                | 46.15    | 5847.92  | 6.29                       | 0.00                  |                     |                          | -6.29              | 1000.00         |
+      | 76            | 2019-03-18      | 76       | 50.00                 | 50.00                 |                | 46.10    | 5804.17  | 6.24                       | 0.00                  |                     |                          | -6.24              | 1000.00         |
+      | 77            | 2019-03-19      | 77       | 50.00                 | 50.00                 |                | 46.06    | 5760.36  | 6.20                       | 0.00                  |                     |                          | -6.20              | 1000.00         |
+      | 78            | 2019-03-20      | 78       | 50.00                 | 50.00                 |                | 46.01    | 5716.52  | 6.15                       | 0.00                  |                     |                          | -6.15              | 1000.00         |
+      | 79            | 2019-03-21      | 79       | 50.00                 | 50.00                 |                | 45.96    | 5672.62  | 6.10                       | 0.00                  |                     |                          | -6.10              | 1000.00         |
+      | 80            | 2019-03-22      | 80       | 50.00                 | 50.00                 |                | 45.91    | 5628.68  | 6.06                       | 0.00                  |                     |                          | -6.06              | 1000.00         |
+      | 81            | 2019-03-23      | 81       | 50.00                 | 50.00                 |                | 45.86    | 5584.69  | 6.01                       | 0.00                  |                     |                          | -6.01              | 1000.00         |
+      | 82            | 2019-03-24      | 82       | 50.00                 | 50.00                 |                | 45.81    | 5540.65  | 5.96                       | 0.00                  |                     |                          | -5.96              | 1000.00         |
+      | 83            | 2019-03-25      | 83       | 50.00                 | 50.00                 |                | 45.76    | 5496.57  | 5.92                       | 0.00                  |                     |                          | -5.92              | 1000.00         |
+      | 84            | 2019-03-26      | 84       | 50.00                 | 50.00                 |                | 45.71    | 5452.44  | 5.87                       | 0.00                  |                     |                          | -5.87              | 1000.00         |
+      | 85            | 2019-03-27      | 85       | 50.00                 | 50.00                 |                | 45.66    | 5408.26  | 5.82                       | 0.00                  |                     |                          | -5.82              | 1000.00         |
+      | 86            | 2019-03-28      | 86       | 50.00                 | 50.00                 |                | 45.62    | 5364.03  | 5.78                       | 0.00                  |                     |                          | -5.78              | 1000.00         |
+      | 87            | 2019-03-29      | 87       | 50.00                 | 50.00                 |                | 45.57    | 5319.76  | 5.73                       | 0.00                  |                     |                          | -5.73              | 1000.00         |
+      | 88            | 2019-03-30      | 88       | 50.00                 | 50.00                 |                | 45.52    | 5275.44  | 5.68                       | 0.00                  |                     |                          | -5.68              | 1000.00         |
+      | 89            | 2019-03-31      | 89       | 50.00                 | 50.00                 |                | 45.47    | 5231.08  | 5.63                       | 0.00                  |                     |                          | -5.63              | 1000.00         |
+      | 90            | 2019-04-01      | 90       | 50.00                 | 50.00                 |                | 45.42    | 5186.66  | 5.59                       | 0.00                  |                     |                          | -5.59              | 1000.00         |
+      | 91            | 2019-04-02      | 91       | 50.00                 | 50.00                 |                | 45.37    | 5142.20  | 5.54                       | 0.00                  |                     |                          | -5.54              | 1000.00         |
+      | 92            | 2019-04-03      | 92       | 50.00                 | 50.00                 |                | 45.32    | 5097.69  | 5.49                       | 0.00                  |                     |                          | -5.49              | 1000.00         |
+      | 93            | 2019-04-04      | 93       | 50.00                 | 50.00                 |                | 45.28    | 5053.13  | 5.44                       | 0.00                  |                     |                          | -5.44              | 1000.00         |
+      | 94            | 2019-04-05      | 94       | 50.00                 | 50.00                 |                | 45.23    | 5008.53  | 5.40                       | 0.00                  |                     |                          | -5.40              | 1000.00         |
+      | 95            | 2019-04-06      | 95       | 50.00                 | 50.00                 |                | 45.18    | 4963.88  | 5.35                       | 0.00                  |                     |                          | -5.35              | 1000.00         |
+      | 96            | 2019-04-07      | 96       | 50.00                 | 50.00                 |                | 45.13    | 4919.18  | 5.30                       | 0.00                  |                     |                          | -5.30              | 1000.00         |
+      | 97            | 2019-04-08      | 97       | 50.00                 | 50.00                 |                | 45.08    | 4874.43  | 5.25                       | 0.00                  |                     |                          | -5.25              | 1000.00         |
+      | 98            | 2019-04-09      | 98       | 50.00                 | 50.00                 |                | 45.03    | 4829.64  | 5.20                       | 0.00                  |                     |                          | -5.20              | 1000.00         |
+      | 99            | 2019-04-10      | 99       | 50.00                 | 50.00                 |                | 44.99    | 4784.79  | 5.16                       | 0.00                  |                     |                          | -5.16              | 1000.00         |
+      | 100           | 2019-04-11      | 100      | 50.00                 | 50.00                 |                | 44.94    | 4739.90  | 5.11                       | 0.00                  |                     |                          | -5.11              | 1000.00         |
+      | 101           | 2019-04-12      | 101      | 50.00                 | 50.00                 |                | 44.89    | 4694.96  | 5.06                       | 0.00                  |                     |                          | -5.06              | 1000.00         |
+      | 102           | 2019-04-13      | 102      | 50.00                 | 50.00                 |                | 44.84    | 4649.98  | 5.01                       | 0.00                  |                     |                          | -5.01              | 1000.00         |
+      | 103           | 2019-04-14      | 103      | 50.00                 | 50.00                 |                | 44.80    | 4604.94  | 4.97                       | 0.00                  |                     |                          | -4.97              | 1000.00         |
+      | 104           | 2019-04-15      | 104      | 50.00                 | 50.00                 |                | 44.75    | 4559.86  | 4.92                       | 0.00                  |                     |                          | -4.92              | 1000.00         |
+      | 105           | 2019-04-16      | 105      | 50.00                 | 50.00                 |                | 44.70    | 4514.73  | 4.87                       | 0.00                  |                     |                          | -4.87              | 1000.00         |
+      | 106           | 2019-04-17      | 106      | 50.00                 | 50.00                 |                | 44.65    | 4469.55  | 4.82                       | 0.00                  |                     |                          | -4.82              | 1000.00         |
+      | 107           | 2019-04-18      | 107      | 50.00                 | 50.00                 |                | 44.60    | 4424.32  | 4.77                       | 0.00                  |                     |                          | -4.77              | 1000.00         |
+      | 108           | 2019-04-19      | 108      | 50.00                 | 50.00                 |                | 44.56    | 4379.05  | 4.72                       | 0.00                  |                     |                          | -4.72              | 1000.00         |
+      | 109           | 2019-04-20      | 109      | 50.00                 | 50.00                 |                | 44.51    | 4333.72  | 4.68                       | 0.00                  |                     |                          | -4.68              | 1000.00         |
+      | 110           | 2019-04-21      | 110      | 50.00                 | 50.00                 |                | 44.46    | 4288.35  | 4.63                       | 0.00                  |                     |                          | -4.63              | 1000.00         |
+      | 111           | 2019-04-22      | 111      | 50.00                 | 50.00                 |                | 44.41    | 4242.93  | 4.58                       | 0.00                  |                     |                          | -4.58              | 1000.00         |
+      | 112           | 2019-04-23      | 112      | 50.00                 | 50.00                 |                | 44.37    | 4197.46  | 4.53                       | 0.00                  |                     |                          | -4.53              | 1000.00         |
+      | 113           | 2019-04-24      | 113      | 50.00                 | 50.00                 |                | 44.32    | 4151.94  | 4.48                       | 0.00                  |                     |                          | -4.48              | 1000.00         |
+      | 114           | 2019-04-25      | 114      | 50.00                 | 50.00                 |                | 44.27    | 4106.38  | 4.43                       | 0.00                  |                     |                          | -4.43              | 1000.00         |
+      | 115           | 2019-04-26      | 115      | 50.00                 | 50.00                 |                | 44.22    | 4060.76  | 4.38                       | 0.00                  |                     |                          | -4.38              | 1000.00         |
+      | 116           | 2019-04-27      | 116      | 50.00                 | 50.00                 |                | 44.18    | 4015.10  | 4.34                       | 0.00                  |                     |                          | -4.34              | 1000.00         |
+      | 117           | 2019-04-28      | 117      | 50.00                 | 50.00                 |                | 44.13    | 3969.38  | 4.29                       | 0.00                  |                     |                          | -4.29              | 1000.00         |
+      | 118           | 2019-04-29      | 118      | 50.00                 | 50.00                 |                | 44.08    | 3923.62  | 4.24                       | 0.00                  |                     |                          | -4.24              | 1000.00         |
+      | 119           | 2019-04-30      | 119      | 50.00                 | 50.00                 |                | 44.04    | 3877.81  | 4.19                       | 0.00                  |                     |                          | -4.19              | 1000.00         |
+      | 120           | 2019-05-01      | 120      | 50.00                 | 50.00                 |                | 43.99    | 3831.95  | 4.14                       | 0.00                  |                     |                          | -4.14              | 1000.00         |
+      | 121           | 2019-05-02      | 121      | 50.00                 | 50.00                 |                | 43.94    | 3786.04  | 4.09                       | 0.00                  |                     |                          | -4.09              | 1000.00         |
+      | 122           | 2019-05-03      | 122      | 50.00                 | 50.00                 |                | 43.90    | 3740.09  | 4.04                       | 0.00                  |                     |                          | -4.04              | 1000.00         |
+      | 123           | 2019-05-04      | 123      | 50.00                 | 50.00                 |                | 43.85    | 3694.08  | 3.99                       | 0.00                  |                     |                          | -3.99              | 1000.00         |
+      | 124           | 2019-05-05      | 124      | 50.00                 | 50.00                 |                | 43.80    | 3648.03  | 3.94                       | 0.00                  |                     |                          | -3.94              | 1000.00         |
+      | 125           | 2019-05-06      | 125      | 50.00                 | 50.00                 |                | 43.76    | 3601.92  | 3.90                       | 0.00                  |                     |                          | -3.90              | 1000.00         |
+      | 126           | 2019-05-07      | 126      | 50.00                 | 50.00                 |                | 43.71    | 3555.77  | 3.85                       | 0.00                  |                     |                          | -3.85              | 1000.00         |
+      | 127           | 2019-05-08      | 127      | 50.00                 | 50.00                 |                | 43.66    | 3509.56  | 3.80                       | 0.00                  |                     |                          | -3.80              | 1000.00         |
+      | 128           | 2019-05-09      | 128      | 50.00                 | 50.00                 |                | 43.62    | 3463.31  | 3.75                       | 0.00                  |                     |                          | -3.75              | 1000.00         |
+      | 129           | 2019-05-10      | 129      | 50.00                 | 50.00                 |                | 43.57    | 3417.01  | 3.70                       | 0.00                  |                     |                          | -3.70              | 1000.00         |
+      | 130           | 2019-05-11      | 130      | 50.00                 | 50.00                 |                | 43.52    | 3370.66  | 3.65                       | 0.00                  |                     |                          | -3.65              | 1000.00         |
+      | 131           | 2019-05-12      | 131      | 50.00                 | 50.00                 |                | 43.48    | 3324.26  | 3.60                       | 0.00                  |                     |                          | -3.60              | 1000.00         |
+      | 132           | 2019-05-13      | 132      | 50.00                 | 50.00                 |                | 43.43    | 3277.81  | 3.55                       | 0.00                  |                     |                          | -3.55              | 1000.00         |
+      | 133           | 2019-05-14      | 133      | 50.00                 | 50.00                 |                | 43.38    | 3231.31  | 3.50                       | 0.00                  |                     |                          | -3.50              | 1000.00         |
+      | 134           | 2019-05-15      | 134      | 50.00                 | 50.00                 |                | 43.34    | 3184.76  | 3.45                       | 0.00                  |                     |                          | -3.45              | 1000.00         |
+      | 135           | 2019-05-16      | 135      | 50.00                 | 50.00                 |                | 43.29    | 3138.16  | 3.40                       | 0.00                  |                     |                          | -3.40              | 1000.00         |
+      | 136           | 2019-05-17      | 136      | 50.00                 | 50.00                 |                | 43.24    | 3091.51  | 3.35                       | 0.00                  |                     |                          | -3.35              | 1000.00         |
+      | 137           | 2019-05-18      | 137      | 50.00                 | 50.00                 |                | 43.20    | 3044.81  | 3.30                       | 0.00                  |                     |                          | -3.30              | 1000.00         |
+      | 138           | 2019-05-19      | 138      | 50.00                 | 50.00                 |                | 43.15    | 2998.06  | 3.25                       | 0.00                  |                     |                          | -3.25              | 1000.00         |
+      | 139           | 2019-05-20      | 139      | 50.00                 | 50.00                 |                | 43.11    | 2951.26  | 3.20                       | 0.00                  |                     |                          | -3.20              | 1000.00         |
+      | 140           | 2019-05-21      | 140      | 50.00                 | 50.00                 |                | 43.06    | 2904.42  | 3.15                       | 0.00                  |                     |                          | -3.15              | 1000.00         |
+      | 141           | 2019-05-22      | 141      | 50.00                 | 50.00                 |                | 43.01    | 2857.52  | 3.10                       | 0.00                  |                     |                          | -3.10              | 1000.00         |
+      | 142           | 2019-05-23      | 142      | 50.00                 | 50.00                 |                | 42.97    | 2810.57  | 3.05                       | 0.00                  |                     |                          | -3.05              | 1000.00         |
+      | 143           | 2019-05-24      | 143      | 50.00                 | 50.00                 |                | 42.92    | 2763.57  | 3.00                       | 0.00                  |                     |                          | -3.00              | 1000.00         |
+      | 144           | 2019-05-25      | 144      | 50.00                 | 50.00                 |                | 42.88    | 2716.52  | 2.95                       | 0.00                  |                     |                          | -2.95              | 1000.00         |
+      | 145           | 2019-05-26      | 145      | 50.00                 | 50.00                 |                | 42.83    | 2669.42  | 2.90                       | 0.00                  |                     |                          | -2.90              | 1000.00         |
+      | 146           | 2019-05-27      | 146      | 50.00                 | 50.00                 |                | 42.79    | 2622.27  | 2.85                       | 0.00                  |                     |                          | -2.85              | 1000.00         |
+      | 147           | 2019-05-28      | 147      | 50.00                 | 50.00                 |                | 42.74    | 2575.07  | 2.80                       | 0.00                  |                     |                          | -2.80              | 1000.00         |
+      | 148           | 2019-05-29      | 148      | 50.00                 | 50.00                 |                | 42.69    | 2527.82  | 2.75                       | 0.00                  |                     |                          | -2.75              | 1000.00         |
+      | 149           | 2019-05-30      | 149      | 50.00                 | 50.00                 |                | 42.65    | 2480.52  | 2.70                       | 0.00                  |                     |                          | -2.70              | 1000.00         |
+      | 150           | 2019-05-31      | 150      | 50.00                 | 50.00                 |                | 42.60    | 2433.17  | 2.65                       | 0.00                  |                     |                          | -2.65              | 1000.00         |
+      | 151           | 2019-06-01      | 151      | 50.00                 | 50.00                 |                | 42.56    | 2385.77  | 2.60                       | 0.00                  |                     |                          | -2.60              | 1000.00         |
+      | 152           | 2019-06-02      | 152      | 50.00                 | 50.00                 |                | 42.51    | 2338.31  | 2.55                       | 0.00                  |                     |                          | -2.55              | 1000.00         |
+      | 153           | 2019-06-03      | 153      | 50.00                 | 50.00                 |                | 42.47    | 2290.81  | 2.50                       | 0.00                  |                     |                          | -2.50              | 1000.00         |
+      | 154           | 2019-06-04      | 154      | 50.00                 | 50.00                 |                | 42.42    | 2243.26  | 2.45                       | 0.00                  |                     |                          | -2.45              | 1000.00         |
+      | 155           | 2019-06-05      | 155      | 50.00                 | 50.00                 |                | 42.38    | 2195.65  | 2.40                       | 0.00                  |                     |                          | -2.40              | 1000.00         |
+      | 156           | 2019-06-06      | 156      | 50.00                 | 50.00                 |                | 42.33    | 2148.00  | 2.34                       | 0.00                  |                     |                          | -2.34              | 1000.00         |
+      | 157           | 2019-06-07      | 157      | 50.00                 | 50.00                 |                | 42.29    | 2100.29  | 2.29                       | 0.00                  |                     |                          | -2.29              | 1000.00         |
+      | 158           | 2019-06-08      | 158      | 50.00                 | 50.00                 |                | 42.24    | 2052.53  | 2.24                       | 0.00                  |                     |                          | -2.24              | 1000.00         |
+      | 159           | 2019-06-09      | 159      | 50.00                 | 50.00                 |                | 42.20    | 2004.73  | 2.19                       | 0.00                  |                     |                          | -2.19              | 1000.00         |
+      | 160           | 2019-06-10      | 160      | 50.00                 | 50.00                 |                | 42.15    | 1956.87  | 2.14                       | 0.00                  |                     |                          | -2.14              | 1000.00         |
+      | 161           | 2019-06-11      | 161      | 50.00                 | 50.00                 |                | 42.11    | 1908.96  | 2.09                       | 0.00                  |                     |                          | -2.09              | 1000.00         |
+      | 162           | 2019-06-12      | 162      | 50.00                 | 50.00                 |                | 42.06    | 1860.99  | 2.04                       | 0.00                  |                     |                          | -2.04              | 1000.00         |
+      | 163           | 2019-06-13      | 163      | 50.00                 | 50.00                 |                | 42.02    | 1812.98  | 1.99                       | 0.00                  |                     |                          | -1.99              | 1000.00         |
+      | 164           | 2019-06-14      | 164      | 50.00                 | 50.00                 |                | 41.97    | 1764.92  | 1.94                       | 0.00                  |                     |                          | -1.94              | 1000.00         |
+      | 165           | 2019-06-15      | 165      | 50.00                 | 50.00                 |                | 41.93    | 1716.80  | 1.88                       | 0.00                  |                     |                          | -1.88              | 1000.00         |
+      | 166           | 2019-06-16      | 166      | 50.00                 | 50.00                 |                | 41.88    | 1668.64  | 1.83                       | 0.00                  |                     |                          | -1.83              | 1000.00         |
+      | 167           | 2019-06-17      | 167      | 50.00                 | 50.00                 |                | 41.84    | 1620.42  | 1.78                       | 0.00                  |                     |                          | -1.78              | 1000.00         |
+      | 168           | 2019-06-18      | 168      | 50.00                 | 50.00                 |                | 41.79    | 1572.15  | 1.73                       | 0.00                  |                     |                          | -1.73              | 1000.00         |
+      | 169           | 2019-06-19      | 169      | 50.00                 | 50.00                 |                | 41.75    | 1523.83  | 1.68                       | 0.00                  |                     |                          | -1.68              | 1000.00         |
+      | 170           | 2019-06-20      | 170      | 50.00                 | 50.00                 |                | 41.70    | 1475.45  | 1.63                       | 0.00                  |                     |                          | -1.63              | 1000.00         |
+      | 171           | 2019-06-21      | 171      | 50.00                 | 50.00                 |                | 41.66    | 1427.03  | 1.58                       | 0.00                  |                     |                          | -1.58              | 1000.00         |
+      | 172           | 2019-06-22      | 172      | 50.00                 | 50.00                 |                | 41.61    | 1378.55  | 1.52                       | 0.00                  |                     |                          | -1.52              | 1000.00         |
+      | 173           | 2019-06-23      | 173      | 50.00                 | 50.00                 |                | 41.57    | 1330.02  | 1.47                       | 0.00                  |                     |                          | -1.47              | 1000.00         |
+      | 174           | 2019-06-24      | 174      | 50.00                 | 50.00                 |                | 41.53    | 1281.45  | 1.42                       | 0.00                  |                     |                          | -1.42              | 1000.00         |
+      | 175           | 2019-06-25      | 175      | 50.00                 | 50.00                 |                | 41.48    | 1232.81  | 1.37                       | 0.00                  |                     |                          | -1.37              | 1000.00         |
+      | 176           | 2019-06-26      | 176      | 50.00                 | 50.00                 |                | 41.44    | 1184.13  | 1.32                       | 0.00                  |                     |                          | -1.32              | 1000.00         |
+      | 177           | 2019-06-27      | 177      | 50.00                 | 50.00                 |                | 41.39    | 1135.39  | 1.26                       | 0.00                  |                     |                          | -1.26              | 1000.00         |
+      | 178           | 2019-06-28      | 178      | 50.00                 | 50.00                 |                | 41.35    | 1086.61  | 1.21                       | 0.00                  |                     |                          | -1.21              | 1000.00         |
+      | 179           | 2019-06-29      | 179      | 50.00                 | 50.00                 |                | 41.31    | 1037.77  | 1.16                       | 0.00                  |                     |                          | -1.16              | 1000.00         |
+      | 180           | 2019-06-30      | 180      | 50.00                 | 50.00                 |                | 41.26    | 988.88   | 1.11                       | 0.00                  |                     |                          | -1.11              | 1000.00         |
+      | 181           | 2019-07-01      | 181      | 50.00                 | 50.00                 |                | 41.22    | 939.93   | 1.06                       | 0.00                  |                     |                          | -1.06              | 1000.00         |
+      | 182           | 2019-07-02      | 182      | 50.00                 | 50.00                 |                | 41.17    | 890.93   | 1.00                       | 0.00                  |                     |                          | -1.00              | 1000.00         |
+      | 183           | 2019-07-03      | 183      | 50.00                 | 50.00                 |                | 41.13    | 841.89   | 0.95                       | 0.00                  |                     |                          | -0.95              | 1000.00         |
+      | 184           | 2019-07-04      | 184      | 50.00                 | 50.00                 |                | 41.09    | 792.79   | 0.90                       | 0.00                  |                     |                          | -0.90              | 1000.00         |
+      | 185           | 2019-07-05      | 185      | 50.00                 | 50.00                 |                | 41.04    | 743.63   | 0.85                       | 0.00                  |                     |                          | -0.85              | 1000.00         |
+      | 186           | 2019-07-06      | 186      | 50.00                 | 50.00                 |                | 41.00    | 694.43   | 0.79                       | 0.00                  |                     |                          | -0.79              | 1000.00         |
+      | 187           | 2019-07-07      | 187      | 50.00                 | 50.00                 |                | 40.95    | 645.17   | 0.74                       | 0.00                  |                     |                          | -0.74              | 1000.00         |
+      | 188           | 2019-07-08      | 188      | 50.00                 | 50.00                 |                | 40.91    | 595.86   | 0.69                       | 0.00                  |                     |                          | -0.69              | 1000.00         |
+      | 189           | 2019-07-09      | 189      | 50.00                 | 50.00                 |                | 40.87    | 546.49   | 0.64                       | 0.00                  |                     |                          | -0.64              | 1000.00         |
+      | 190           | 2019-07-10      | 190      | 50.00                 | 50.00                 |                | 40.82    | 497.08   | 0.58                       | 0.00                  |                     |                          | -0.58              | 1000.00         |
+      | 191           | 2019-07-11      | 191      | 50.00                 | 50.00                 |                | 40.78    | 447.61   | 0.53                       | 0.00                  |                     |                          | -0.53              | 1000.00         |
+      | 192           | 2019-07-12      | 192      | 50.00                 | 50.00                 |                | 40.74    | 398.08   | 0.48                       | 0.00                  |                     |                          | -0.48              | 1000.00         |
+      | 193           | 2019-07-13      | 193      | 50.00                 | 50.00                 |                | 40.69    | 348.51   | 0.43                       | 0.00                  |                     |                          | -0.43              | 1000.00         |
+      | 194           | 2019-07-14      | 194      | 50.00                 | 50.00                 |                | 40.65    | 298.88   | 0.37                       | 0.00                  |                     |                          | -0.37              | 1000.00         |
+      | 195           | 2019-07-15      | 195      | 50.00                 | 50.00                 |                | 40.61    | 249.20   | 0.32                       | 0.00                  |                     |                          | -0.32              | 1000.00         |
+      | 196           | 2019-07-16      | 196      | 50.00                 | 50.00                 |                | 40.56    | 199.47   | 0.27                       | 0.00                  |                     |                          | -0.27              | 1000.00         |
+      | 197           | 2019-07-17      | 197      | 50.00                 | 50.00                 |                | 40.52    | 149.68   | 0.21                       | 0.00                  |                     |                          | -0.21              | 1000.00         |
+      | 198           | 2019-07-18      | 198      | 50.00                 | 50.00                 |                | 40.48    | 99.84    | 0.16                       | 0.00                  |                     |                          | -0.16              | 1000.00         |
+      | 199           | 2019-07-19      | 199      | 50.00                 | 50.00                 |                | 40.43    | 49.95    | 0.11                       | 0.00                  |                     |                          | -0.11              | 1000.00         |
+      | 200           | 2019-07-20      | 200      | 50.00                 | 50.00                 |                | 40.39    | 0.00     | 0.05                       | 0.00                  |                     |                          | -0.05              | 1000.00         |
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/InternalWorkingCapitalLoanApiResource.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/InternalWorkingCapitalLoanApiResource.java
new file mode 100644
index 0000000000..ce308c44bf
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/InternalWorkingCapitalLoanApiResource.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.api;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleGenerateRequest;
+import org.apache.fineract.portfolio.workingcapitalloan.service.WorkingCapitalLoanAmortizationScheduleWriteService;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@RequiredArgsConstructor
+@Profile(FineractProfiles.TEST)
+@Component
+@Path("v1/internal/working-capital-loans")
+@Tag(name = "Working Capital Loans", description = "Internal WCL testing API. This API should be disabled in production!")
+public class InternalWorkingCapitalLoanApiResource implements InitializingBean {
+
+    private final WorkingCapitalLoanAmortizationScheduleWriteService writeService;
+
+    @Override
+    @SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
+    public void afterPropertiesSet() throws Exception {
+        log.warn("------------------------------------------------------------");
+        log.warn("                                                            ");
+        log.warn("DO NOT USE THIS IN PRODUCTION!");
+        log.warn("Internal client services mode is enabled");
+        log.warn("DO NOT USE THIS IN PRODUCTION!");
+        log.warn("                                                            ");
+        log.warn("------------------------------------------------------------");
+    }
+
+    @POST
+    @Path("{loanId}/amortization-schedule")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Generate and save Projected Amortization Schedule (testing)", description = """
+            Generates a projected amortization schedule from the provided parameters \
+            and saves it for the given Working Capital Loan.
+
+            DO NOT USE THIS IN PRODUCTION! In the real flow, the schedule will be \
+            generated during loan approval/disbursement from the loan and product data.""")
+    @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK"),
+            @ApiResponse(responseCode = "404", description = "Working Capital Loan not found") })
+    public void generateAmortizationSchedule(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
+            final ProjectedAmortizationScheduleGenerateRequest request) {
+        writeService.generateAndSaveAmortizationSchedule(loanId, request);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanAmortizationScheduleApiResource.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanAmortizationScheduleApiResource.java
new file mode 100644
index 0000000000..cc91ad6395
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanAmortizationScheduleApiResource.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.api;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleData;
+import org.apache.fineract.portfolio.workingcapitalloan.service.WorkingCapitalLoanAmortizationScheduleReadService;
+import org.springframework.stereotype.Component;
+
+@Path("/v1/working-capital-loans")
+@Component
+@Tag(name = "Working Capital Loans", description = "Working Capital Loan operations including projected amortization schedule.")
+@RequiredArgsConstructor
+public class WorkingCapitalLoanAmortizationScheduleApiResource {
+
+    private final WorkingCapitalLoanAmortizationScheduleReadService readService;
+
+    @GET
+    @Path("{loanId}/amortization-schedule")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Retrieve Projected Amortization Schedule", description = """
+            Returns the projected amortization schedule for a Working Capital Loan.
+
+            The schedule contains per-payment details including expected and forecast payments, \
+            discount factors, NPV values, balances, expected and actual amortization amounts, \
+            income modifications, and deferred balance.
+
+            Example Request:
+
+            working-capital-loans/1/amortization-schedule""")
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ProjectedAmortizationScheduleData.class))),
+            @ApiResponse(responseCode = "404", description = "Working Capital Loan or schedule not found") })
+    public ProjectedAmortizationScheduleData retrieveAmortizationSchedule(
+            @PathParam("loanId") @Parameter(description = "loanId") final Long loanId) {
+        return readService.retrieveAmortizationSchedule(loanId);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/DefaultProjectedAmortizationScheduleCalculator.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/DefaultProjectedAmortizationScheduleCalculator.java
new file mode 100644
index 0000000000..c639f69760
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/DefaultProjectedAmortizationScheduleCalculator.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.time.LocalDate;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+
+/**
+ * Default implementation of {@link ProjectedAmortizationScheduleCalculator}. Delegates to
+ * {@link ProjectedAmortizationScheduleModel} methods.
+ */
+@Component
+public final class DefaultProjectedAmortizationScheduleCalculator implements ProjectedAmortizationScheduleCalculator {
+
+    @Override
+    @NonNull
+    public ProjectedAmortizationScheduleModel generateModel(@NonNull final BigDecimal originationFeeAmount,
+            @NonNull final BigDecimal netDisbursementAmount, @NonNull final BigDecimal totalPaymentValue,
+            @NonNull final BigDecimal periodPaymentRate, final int npvDayCount, @NonNull final LocalDate expectedDisbursementDate,
+            @NonNull final MathContext mc, @NonNull final MonetaryCurrency currency) {
+        return ProjectedAmortizationScheduleModel.generate(originationFeeAmount, netDisbursementAmount, totalPaymentValue,
+                periodPaymentRate, npvDayCount, expectedDisbursementDate, mc, currency);
+    }
+
+    @Override
+    @NonNull
+    public ProjectedAmortizationScheduleModel addDisbursement(@NonNull final ProjectedAmortizationScheduleModel model,
+            @NonNull final BigDecimal newDiscountAmount, @NonNull final BigDecimal newNetAmount, @NonNull final LocalDate newStartDate) {
+        return model.regenerate(newDiscountAmount, newNetAmount, newStartDate);
+    }
+
+    @Override
+    public void applyPayment(@NonNull final ProjectedAmortizationScheduleModel model, @NonNull final LocalDate paymentDate,
+            @NonNull final BigDecimal paymentAmount) {
+        model.applyPayment(paymentDate, paymentAmount);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculator.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculator.java
new file mode 100644
index 0000000000..f7e53452aa
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculator.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.time.LocalDate;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.springframework.lang.NonNull;
+
+/**
+ * Calculator service for Working Capital loan projected amortization schedule. Analogous to {@code EMICalculator} for
+ * progressive loans, but with a minimal API: generation, disbursement and payment.
+ */
+public interface ProjectedAmortizationScheduleCalculator {
+
+    /**
+     * Creates an initial projected amortization schedule model (at loan creation).
+     *
+     * @return model with no payments applied
+     */
+    @NonNull
+    ProjectedAmortizationScheduleModel generateModel(@NonNull BigDecimal originationFeeAmount, @NonNull BigDecimal netDisbursementAmount,
+            @NonNull BigDecimal totalPaymentValue, @NonNull BigDecimal periodPaymentRate, int npvDayCount,
+            @NonNull LocalDate expectedDisbursementDate, @NonNull MathContext mc, @NonNull MonetaryCurrency currency);
+
+    /**
+     * Recalculates the model with updated financial parameters (at approval or disbursement). Preserves already applied
+     * payments on the model.
+     *
+     * @param model
+     *            current model (may have payments)
+     * @param newDiscountAmount
+     *            approved or disbursed discount
+     * @param newNetAmount
+     *            approved or actual net amount
+     * @param newStartDate
+     *            actual start date
+     * @return new model with recalculated schedule
+     */
+    @NonNull
+    ProjectedAmortizationScheduleModel addDisbursement(@NonNull ProjectedAmortizationScheduleModel model,
+            @NonNull BigDecimal newDiscountAmount, @NonNull BigDecimal newNetAmount, @NonNull LocalDate newStartDate);
+
+    /**
+     * Applies a payment to the model. The model is mutated in place; callers can read the updated payment directly from
+     * the model.
+     *
+     * @param model
+     *            current model (mutated in place)
+     * @param paymentDate
+     *            the date when payment was made
+     * @param paymentAmount
+     *            actual payment amount
+     */
+    void applyPayment(@NonNull ProjectedAmortizationScheduleModel model, @NonNull LocalDate paymentDate, @NonNull BigDecimal paymentAmount);
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleModel.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleModel.java
new file mode 100644
index 0000000000..385f04ee1a
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleModel.java
@@ -0,0 +1,430 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.apache.fineract.infrastructure.core.serialization.gson.JsonExclude;
+import org.apache.fineract.infrastructure.core.service.MathUtil;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.Money;
+
+/**
+ * Projected Amortization Schedule model for Working Capital loans.
+ *
+ * <h3>Lifecycle</h3>
+ * <ol>
+ * <li>{@link #generate} — create initial schedule (at loan creation)</li>
+ * <li>{@link #regenerate} — recalculate with new amounts (at approval / disbursement)</li>
+ * <li>{@link #applyPayment} — record payments by date; schedule rebuilds after each</li>
+ * </ol>
+ */
+@Getter
+@Accessors(fluent = true)
+public final class ProjectedAmortizationScheduleModel {
+
+    private static final String MODEL_VERSION = "1";
+
+    private final Money originationFeeAmount;
+    private final Money netDisbursementAmount;
+    private final Money totalPaymentValue;
+    private final BigDecimal periodPaymentRate;
+    private final int npvDayCount;
+    private final LocalDate expectedDisbursementDate;
+
+    /** {@code (TPV × periodPaymentRate) / npvDayCount} — constant across payments. */
+    private final Money expectedPaymentAmount;
+
+    /** {@code roundUp((netDisbursementAmount + originationFeeAmount) / expectedPaymentAmount)} */
+    private final int loanTerm;
+
+    /** Periodic EIR from {@code RATE(loanTerm, -expectedPayment, netDisbursementAmount)}. */
+    private final BigDecimal effectiveInterestRate;
+
+    @JsonExclude
+    private final MathContext mc;
+
+    @JsonExclude
+    private final MonetaryCurrency currency;
+
+    @Getter(AccessLevel.NONE)
+    private final List<AppliedPayment> appliedPayments;
+
+    @Getter(AccessLevel.NONE)
+    private List<ProjectedPayment> payments;
+
+    private ProjectedAmortizationScheduleModel(final Money originationFeeAmount, final Money netDisbursementAmount,
+            final Money totalPaymentValue, final BigDecimal periodPaymentRate, final int npvDayCount,
+            final LocalDate expectedDisbursementDate, final Money expectedPaymentAmount, final int loanTerm,
+            final BigDecimal effectiveInterestRate, final MathContext mc, final MonetaryCurrency currency) {
+        this.originationFeeAmount = originationFeeAmount;
+        this.netDisbursementAmount = netDisbursementAmount;
+        this.totalPaymentValue = totalPaymentValue;
+        this.periodPaymentRate = periodPaymentRate;
+        this.npvDayCount = npvDayCount;
+        this.expectedDisbursementDate = expectedDisbursementDate;
+        this.expectedPaymentAmount = expectedPaymentAmount;
+        this.loanTerm = loanTerm;
+        this.effectiveInterestRate = effectiveInterestRate;
+        this.mc = mc;
+        this.currency = currency;
+        this.appliedPayments = new ArrayList<>();
+        rebuildPayments();
+    }
+
+    /**
+     * Creates a skeleton instance for Gson deserialization. Gson will overwrite final fields via reflection; payments
+     * are restored from JSON directly (no rebuild needed).
+     */
+    public static ProjectedAmortizationScheduleModel forDeserialization(final MathContext mc, final MonetaryCurrency currency) {
+        return new ProjectedAmortizationScheduleModel(mc, currency);
+    }
+
+    private ProjectedAmortizationScheduleModel(final MathContext mc, final MonetaryCurrency currency) {
+        this.originationFeeAmount = null;
+        this.netDisbursementAmount = null;
+        this.totalPaymentValue = null;
+        this.periodPaymentRate = null;
+        this.npvDayCount = 0;
+        this.expectedDisbursementDate = null;
+        this.expectedPaymentAmount = null;
+        this.loanTerm = 0;
+        this.effectiveInterestRate = null;
+        this.mc = mc;
+        this.currency = currency;
+        this.appliedPayments = new ArrayList<>();
+        this.payments = List.of();
+    }
+
+    public List<ProjectedPayment> payments() {
+        return payments;
+    }
+
+    public static ProjectedAmortizationScheduleModel generate(final BigDecimal originationFeeAmount, final BigDecimal netDisbursementAmount,
+            final BigDecimal totalPaymentValue, final BigDecimal periodPaymentRate, final int npvDayCount,
+            final LocalDate expectedDisbursementDate, final MathContext mc, final MonetaryCurrency currency) {
+
+        Objects.requireNonNull(originationFeeAmount, "originationFeeAmount");
+        Objects.requireNonNull(netDisbursementAmount, "netDisbursementAmount");
+        Objects.requireNonNull(totalPaymentValue, "totalPaymentValue");
+        Objects.requireNonNull(periodPaymentRate, "periodPaymentRate");
+        Objects.requireNonNull(expectedDisbursementDate, "expectedDisbursementDate");
+        Objects.requireNonNull(currency, "currency");
+        if (netDisbursementAmount.signum() <= 0) {
+            throw new IllegalArgumentException("netDisbursementAmount must be positive");
+        }
+        if (npvDayCount <= 0) {
+            throw new IllegalArgumentException("npvDayCount must be positive");
+        }
+
+        final BigDecimal expectedPayment = totalPaymentValue.multiply(periodPaymentRate, mc).divide(BigDecimal.valueOf(npvDayCount), mc);
+        if (expectedPayment.signum() <= 0) {
+            throw new IllegalArgumentException("expectedPaymentAmount must be positive (check totalPaymentValue and periodPaymentRate)");
+        }
+
+        final int term = netDisbursementAmount.add(originationFeeAmount, mc).divide(expectedPayment, mc).setScale(0, RoundingMode.UP)
+                .intValueExact();
+        if (term <= 0) {
+            throw new IllegalArgumentException("computed loan term must be positive, got: " + term);
+        }
+
+        final BigDecimal eir = TvmFunctions.rate(term, expectedPayment.negate(), netDisbursementAmount, mc);
+
+        return new ProjectedAmortizationScheduleModel(Money.of(currency, originationFeeAmount, mc),
+                Money.of(currency, netDisbursementAmount, mc), Money.of(currency, totalPaymentValue, mc), periodPaymentRate, npvDayCount,
+                expectedDisbursementDate, Money.of(currency, expectedPayment, mc), term, eir, mc, currency);
+    }
+
+    public void applyPayment(final LocalDate paymentDate, final BigDecimal amount) {
+        Objects.requireNonNull(paymentDate, "paymentDate");
+        Objects.requireNonNull(amount, "amount");
+        final int index = resolvePaymentIndex(paymentDate);
+        if (index < 0 || index >= loanTerm) {
+            throw new IllegalArgumentException("paymentDate " + paymentDate + " is outside the valid range ["
+                    + expectedDisbursementDate.plusDays(1) + " .. " + expectedDisbursementDate.plusDays(loanTerm) + "]");
+        }
+        appliedPayments.add(new AppliedPayment(paymentDate, amount));
+        rebuildPayments();
+    }
+
+    /** Creates a new model with updated parameters, preserving applied payments. */
+    public ProjectedAmortizationScheduleModel regenerate(final BigDecimal newDiscountAmount, final BigDecimal newNetAmount,
+            final LocalDate newStartDate) {
+        final ProjectedAmortizationScheduleModel newModel = generate(newDiscountAmount, newNetAmount, totalPaymentValue.getAmount(),
+                periodPaymentRate, npvDayCount, newStartDate, mc, currency);
+        newModel.appliedPayments.addAll(appliedPayments);
+        newModel.rebuildPayments();
+        return newModel;
+    }
+
+    private void rebuildPayments() {
+        final Map<LocalDate, BigDecimal> paymentsByDate = aggregatePaymentsByDate();
+        final List<BigDecimal> paymentList = buildPaymentList(paymentsByDate);
+        this.payments = List.copyOf(buildPayments(paymentList, paymentsByDate.size()));
+    }
+
+    private Map<LocalDate, BigDecimal> aggregatePaymentsByDate() {
+        final Map<LocalDate, BigDecimal> result = new HashMap<>();
+        for (final AppliedPayment payment : appliedPayments) {
+            result.merge(payment.date(), payment.amount(), BigDecimal::add);
+        }
+        return result;
+    }
+
+    private List<BigDecimal> buildPaymentList(final Map<LocalDate, BigDecimal> paymentsByDate) {
+        final List<BigDecimal> result = new ArrayList<>(loanTerm);
+        for (int i = 0; i < loanTerm; i++) {
+            final LocalDate paymentDate = expectedDisbursementDate.plusDays(i + 1);
+            result.add(paymentsByDate.get(paymentDate));
+        }
+        return result;
+    }
+
+    private int resolvePaymentIndex(final LocalDate date) {
+        return (int) ChronoUnit.DAYS.between(expectedDisbursementDate, date) - 1;
+    }
+
+    private List<ProjectedPayment> buildPayments(final List<BigDecimal> payments, final int appliedCount) {
+        final BalancesAndAmortizations ba = computeBalancesAndAmortizations();
+        final PaymentAnalysis pa = analyzePayments(payments, appliedCount);
+        final List<BigDecimal> actualAmortizations = computeActualAmortizations(ba.expectedAmortizations, payments, appliedCount);
+        final List<BigDecimal> runningExpected = computeRunningExpectedPayments(pa.excess);
+        final List<ProjectedPayment> tailPayments = new ArrayList<>();
+        final BigDecimal tailNpv = buildTailPeriodsAndComputeNpv(tailPayments, pa.shortfall, appliedCount);
+        final BigDecimal totalNetAmortization = computeTotalNetAmortization(payments, runningExpected, appliedCount, tailNpv);
+
+        final BigDecimal originationFee = originationFeeAmount.getAmount();
+        final BigDecimal safeExpectedPayment = MathUtil.negativeToZero(expectedPaymentAmount.getAmount());
+
+        final List<ProjectedPayment> result = new ArrayList<>(loanTerm + 2 + tailPayments.size());
+        result.add(createDisbursementPayment(appliedCount));
+
+        BigDecimal cumulativeActualAmort = BigDecimal.ZERO;
+        for (int i = 0; i < loanTerm; i++) {
+            final int periodNo = i + 1;
+            final boolean hasAppliedAmount = payments.get(i) != null;
+            final long count = (long) loanTerm + appliedCount - periodNo;
+            final long paymentsLeft = paymentsLeft(periodNo, appliedCount);
+            final BigDecimal safeDf = safeDiscountFactor(paymentsLeft);
+            final BigDecimal safeRunningExpected = MathUtil.negativeToZero(runningExpected.get(i));
+            final BigDecimal npvSource = hasAppliedAmount ? payments.get(i) : safeRunningExpected;
+            final BigDecimal npvValue = MathUtil.negativeToZero(npvSource.multiply(safeDf, mc));
+            final BigDecimal safeExpectedAmort = ba.expectedAmortizations.get(i).min(originationFee);
+
+            final BigDecimal netAmortization;
+            final BigDecimal actualAmortization;
+            final BigDecimal incomeModification;
+
+            if (hasAppliedAmount) {
+                actualAmortization = actualAmortizations.get(i);
+                netAmortization = totalNetAmortization.subtract(cumulativeActualAmort, mc).min(originationFee);
+                cumulativeActualAmort = cumulativeActualAmort.add(actualAmortization, mc).min(originationFee);
+                incomeModification = actualAmortization.subtract(safeExpectedAmort, mc);
+            } else {
+                netAmortization = BigDecimal.ZERO;
+                actualAmortization = null;
+                incomeModification = safeExpectedAmort.negate();
+            }
+
+            final BigDecimal deferredBalance = originationFee.subtract(cumulativeActualAmort, mc);
+            final BigDecimal balance = ba.balances.get(i);
+            result.add(new ProjectedPayment(periodNo, expectedDisbursementDate.plusDays(periodNo), count, paymentsLeft,
+                    money(safeExpectedPayment), money(safeRunningExpected), safeDf, money(npvValue), money(balance),
+                    money(safeExpectedAmort), money(netAmortization), hasAppliedAmount ? money(payments.get(i)) : null,
+                    actualAmortization != null ? money(actualAmortization) : null, money(incomeModification), money(deferredBalance)));
+        }
+
+        result.addAll(tailPayments);
+
+        while (result.size() > 1) {
+            final ProjectedPayment last = result.getLast();
+            if (last.forecastPaymentAmount() != null && last.forecastPaymentAmount().isZero()) {
+                result.removeLast();
+            } else {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    private ProjectedPayment createDisbursementPayment(final int appliedCount) {
+        final Money negDisbursement = netDisbursementAmount.negated(mc);
+        final long count = (long) loanTerm + appliedCount;
+        return new ProjectedPayment(0, expectedDisbursementDate, count, 0L, negDisbursement, null, BigDecimal.ONE, negDisbursement,
+                netDisbursementAmount, null, null, null, null, null, originationFeeAmount);
+    }
+
+    /**
+     * {@code balance[i] = balance[i-1]×(1+EIR) - expectedPayment}<br>
+     * {@code expectedAmort[i] = balance[i] + expectedPayment - balance[i-1]}
+     */
+    private BalancesAndAmortizations computeBalancesAndAmortizations() {
+        final BigDecimal onePlusRate = BigDecimal.ONE.add(effectiveInterestRate, mc);
+        final BigDecimal expectedPayment = expectedPaymentAmount.getAmount();
+        final List<BigDecimal> balances = new ArrayList<>(loanTerm);
+        final List<BigDecimal> expectedAmortizations = new ArrayList<>(loanTerm);
+        BigDecimal prevBalance = netDisbursementAmount.getAmount();
+        for (int i = 0; i < loanTerm; i++) {
+            final BigDecimal balance = prevBalance.multiply(onePlusRate, mc).subtract(expectedPayment, mc);
+            balances.add(balance);
+            expectedAmortizations.add(balance.add(expectedPayment, mc).subtract(prevBalance, mc));
+            prevBalance = balance;
+        }
+        return new BalancesAndAmortizations(balances, expectedAmortizations);
+    }
+
+    private PaymentAnalysis analyzePayments(final List<BigDecimal> payments, final int appliedCount) {
+        final BigDecimal expectedPayment = expectedPaymentAmount.getAmount();
+        BigDecimal shortfall = BigDecimal.ZERO;
+        BigDecimal excess = BigDecimal.ZERO;
+        for (int i = 0; i < appliedCount; i++) {
+            final BigDecimal diff = payments.get(i).subtract(expectedPayment, mc);
+            if (diff.signum() > 0) {
+                excess = excess.add(diff, mc);
+            } else if (diff.signum() < 0) {
+                shortfall = shortfall.add(diff.negate(), mc);
+            }
+        }
+        return new PaymentAnalysis(shortfall, excess);
+    }
+
+    /** Cursor-based: each payment consumes {@code actualPayment/expectedPayment} periods of expected amortization. */
+    private List<BigDecimal> computeActualAmortizations(final List<BigDecimal> expectedAmortizations, final List<BigDecimal> payments,
+            final int appliedCount) {
+        final BigDecimal expectedPayment = expectedPaymentAmount.getAmount();
+        final List<BigDecimal> result = new ArrayList<>(appliedCount);
+        BigDecimal cursor = BigDecimal.ZERO;
+        for (int i = 0; i < appliedCount; i++) {
+            final BigDecimal periodsConsumed = payments.get(i).divide(expectedPayment, mc);
+            result.add(consumeExpectedAmortization(expectedAmortizations, cursor, periodsConsumed));
+            cursor = cursor.add(periodsConsumed, mc);
+        }
+        return result;
+    }
+
+    private BigDecimal consumeExpectedAmortization(final List<BigDecimal> expectedAmortizations, final BigDecimal startPos,
+            final BigDecimal count) {
+        if (count.signum() <= 0) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal sum = BigDecimal.ZERO;
+        BigDecimal pos = startPos;
+        BigDecimal remaining = count;
+        while (remaining.signum() > 0 && pos.intValue() < expectedAmortizations.size()) {
+            final int periodIndex = pos.intValue();
+            final BigDecimal posInPeriod = pos.subtract(BigDecimal.valueOf(periodIndex), mc);
+            final BigDecimal availableInPeriod = BigDecimal.ONE.subtract(posInPeriod, mc);
+            final BigDecimal toConsume = remaining.min(availableInPeriod);
+            sum = sum.add(toConsume.multiply(expectedAmortizations.get(periodIndex), mc), mc);
+            pos = pos.add(toConsume, mc);
+            remaining = remaining.subtract(toConsume, mc);
+        }
+        return sum;
+    }
+
+    private List<BigDecimal> computeRunningExpectedPayments(final BigDecimal excess) {
+        final BigDecimal expectedPayment = expectedPaymentAmount.getAmount();
+        final List<BigDecimal> running = new ArrayList<>(loanTerm);
+        for (int i = 0; i < loanTerm; i++) {
+            running.add(expectedPayment);
+        }
+
+        BigDecimal remainingExcess = excess;
+        for (int i = loanTerm - 1; i >= 0 && remainingExcess.signum() > 0; i--) {
+            final BigDecimal reduction = remainingExcess.min(running.get(i));
+            running.set(i, running.get(i).subtract(reduction, mc));
+            remainingExcess = remainingExcess.subtract(reduction, mc);
+        }
+        return running;
+    }
+
+    private BigDecimal buildTailPeriodsAndComputeNpv(final List<ProjectedPayment> tailPayments, final BigDecimal shortfall,
+            final int appliedCount) {
+        final BigDecimal expectedPayment = expectedPaymentAmount.getAmount();
+        BigDecimal tailNpv = BigDecimal.ZERO;
+        BigDecimal remaining = shortfall;
+        int tailIndex = 0;
+        while (remaining.signum() > 0) {
+            final int periodNo = loanTerm + tailIndex + 1;
+            final long dl = paymentsLeft(periodNo, appliedCount);
+            final BigDecimal df = safeDiscountFactor(dl);
+            final BigDecimal forecast = remaining.min(expectedPayment);
+            final BigDecimal npv = MathUtil.negativeToZero(forecast.multiply(df, mc));
+
+            final long count = (long) loanTerm + appliedCount - periodNo;
+            tailNpv = tailNpv.add(npv, mc);
+            tailPayments.add(new ProjectedPayment(periodNo, expectedDisbursementDate.plusDays(periodNo), count, dl, null, money(forecast),
+                    df, money(npv), null, null, money(BigDecimal.ZERO), null, null, null, null));
+
+            remaining = remaining.subtract(forecast, mc);
+            tailIndex++;
+        }
+        return tailNpv;
+    }
+
+    /** {@code totalNetAmortization = -netDisbursementAmount + sum(npvSource × DF) + tailNpv} */
+    private BigDecimal computeTotalNetAmortization(final List<BigDecimal> payments, final List<BigDecimal> runningExpected,
+            final int appliedCount, final BigDecimal tailNpv) {
+        BigDecimal total = netDisbursementAmount.getAmount().negate();
+        for (int i = 0; i < loanTerm; i++) {
+            final BigDecimal npvSource = payments.get(i) != null ? payments.get(i) : runningExpected.get(i);
+            final BigDecimal df = safeDiscountFactor(paymentsLeft(i + 1, appliedCount));
+            total = total.add(npvSource.multiply(df, mc), mc);
+        }
+        return total.add(tailNpv, mc);
+    }
+
+    private BigDecimal safeDiscountFactor(final long paymentsLeft) {
+        final BigDecimal df = TvmFunctions.discountFactor(effectiveInterestRate, paymentsLeft, mc);
+        return df.signum() <= 0 ? BigDecimal.ONE : df;
+    }
+
+    private long paymentsLeft(final int periodNumber, final int appliedCount) {
+        return Math.max(0L, (long) periodNumber - appliedCount);
+    }
+
+    private Money money(final BigDecimal amount) {
+        return Money.of(currency, amount, mc);
+    }
+
+    private record BalancesAndAmortizations(List<BigDecimal> balances, List<BigDecimal> expectedAmortizations) {
+    }
+
+    private record PaymentAnalysis(BigDecimal shortfall, BigDecimal excess) {
+    }
+
+    public record AppliedPayment(LocalDate date, BigDecimal amount) {
+    }
+
+    public static String getModelVersion() {
+        return MODEL_VERSION;
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedPayment.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedPayment.java
new file mode 100644
index 0000000000..fe4f3def7c
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedPayment.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.apache.fineract.organisation.monetary.domain.Money;
+
+/**
+ * Single payment of a Working Capital loan's projected amortization schedule.
+ */
+@Getter
+@Accessors(fluent = true)
+@AllArgsConstructor
+public class ProjectedPayment {
+
+    /** 1-based payment number (0 = disbursement row). */
+    private final int paymentNo;
+
+    private final LocalDate date;
+
+    /** Remaining periods for calculation: {@code loanTerm + appliedPaymentCount - paymentNo}. */
+    private final long count;
+
+    /** Exponent for discount factor: {@code DF = 1/(1+EIR)^paymentsLeft}. Zero for paid periods. */
+    private final long paymentsLeft;
+
+    /** {@code (TPV × periodRate) / dayCount}; negated disbursement for row 0. */
+    private final Money expectedPaymentAmount;
+
+    /**
+     * Running expected payment: always the expected amount, adjusted for excess from the tail; {@code null} for row 0.
+     */
+    private final Money forecastPaymentAmount;
+
+    /** {@code 1 / (1 + EIR)^paymentsLeft} */
+    private final BigDecimal discountFactor;
+
+    /** {@code forecastPayment × discountFactor} */
+    private final Money npvValue;
+
+    /** {@code balance[i] = balance[i-1] × (1+EIR) - expectedPayment} */
+    private final Money balance;
+
+    /** {@code balance[i] + expectedPayment - balance[i-1]} (equivalent to {@code prevBalance × EIR}) */
+    private final Money expectedAmortizationAmount;
+
+    /** First paid: sum of all NPV values; subsequent: {@code netAmort[i-1] - actualAmort[i-1]}. */
+    private final Money netAmortizationAmount;
+
+    private final Money actualPaymentAmount;
+
+    /** Cursor-based consumption of expected amortization proportional to payment ratio. */
+    private final Money actualAmortizationAmount;
+
+    /** {@code actualAmortization - expectedAmortization} */
+    private final Money incomeModification;
+
+    /** {@code deferredBalance[i-1] - actualAmortization[i]} */
+    private final Money deferredBalance;
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/TvmFunctions.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/TvmFunctions.java
new file mode 100644
index 0000000000..34d8a0e18b
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/calc/TvmFunctions.java
@@ -0,0 +1,157 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * Time Value of Money (TVM) utility functions for working capital loan calculations.
+ *
+ * <ul>
+ * <li>{@link #rate} — periodic interest rate via Newton-Raphson (Excel RATE equivalent)</li>
+ * <li>{@link #discountFactor} — present value discount factor: {@code 1 / (1 + r)^days}</li>
+ * </ul>
+ */
+public final class TvmFunctions {
+
+    private static final int MAX_ITERATIONS = 100;
+    private static final BigDecimal TOLERANCE = new BigDecimal("1E-10");
+    private static final BigDecimal DEFAULT_GUESS = new BigDecimal("0.01");
+    private static final BigDecimal TWO = BigDecimal.valueOf(2);
+
+    private TvmFunctions() {}
+
+    /**
+     * Solves for the periodic interest rate in the present-value annuity equation. Equivalent to Excel
+     * {@code RATE(nper, pmt, pv)} with {@code fv=0, type=0}.
+     *
+     * <p>
+     * Finds {@code r} satisfying: {@code pv·(1+r)^n + pmt·((1+r)^n − 1)/r = 0}
+     *
+     * <p>
+     * Initial guess is derived via linear approximation: {@code r ≈ 2·(pmt·n + pv) / (pv·n)}
+     *
+     * @param nper
+     *            number of periods (must be positive)
+     * @param pmt
+     *            payment per period (negative = outgoing cash flow)
+     * @param pv
+     *            present value (positive = loan disbursement)
+     * @param mc
+     *            math context for precision
+     * @return the periodic interest rate
+     * @throws IllegalArgumentException
+     *             if nper &lt;= 0
+     * @throws IllegalStateException
+     *             if Newton-Raphson does not converge
+     */
+    public static BigDecimal rate(final int nper, final BigDecimal pmt, final BigDecimal pv, final MathContext mc) {
+        return rate(nper, pmt, pv, estimateInitialGuess(nper, pmt, pv, mc), mc);
+    }
+
+    /**
+     * Solves for the periodic interest rate with an explicit initial guess.
+     *
+     * @see #rate(int, BigDecimal, BigDecimal, MathContext)
+     */
+    public static BigDecimal rate(final int nper, final BigDecimal pmt, final BigDecimal pv, final BigDecimal guess, final MathContext mc) {
+        if (nper <= 0) {
+            throw new IllegalArgumentException("nper must be positive, got: " + nper);
+        }
+
+        final BigDecimal n = BigDecimal.valueOf(nper);
+
+        // Zero-rate case: pv + pmt·n ≈ 0
+        if (pv.add(pmt.multiply(n, mc), mc).abs().compareTo(TOLERANCE) < 0) {
+            return BigDecimal.ZERO;
+        }
+
+        BigDecimal r = guess;
+
+        for (int iter = 0; iter < MAX_ITERATIONS; iter++) {
+            if (r.signum() == 0) {
+                r = TOLERANCE; // nudge away from zero to avoid division by zero
+            }
+
+            final BigDecimal onePlusR = BigDecimal.ONE.add(r, mc);
+            final BigDecimal compound = onePlusR.pow(nper, mc); // (1+r)^n
+            final BigDecimal compoundMinusOne = compound.subtract(BigDecimal.ONE, mc); // (1+r)^n − 1
+
+            // f(r) = pv·(1+r)^n + pmt·((1+r)^n − 1) / r
+            final BigDecimal f = pv.multiply(compound, mc).add(pmt.multiply(compoundMinusOne, mc).divide(r, mc));
+
+            // f'(r) = pv·n·(1+r)^(n−1) + pmt·[n·(1+r)^(n−1)·r − ((1+r)^n−1)] / r²
+            final BigDecimal dCompound = n.multiply(onePlusR.pow(nper - 1, mc), mc); // n·(1+r)^(n−1)
+            final BigDecimal rSquared = r.multiply(r, mc);
+            final BigDecimal fPrime = pv.multiply(dCompound, mc)
+                    .add(pmt.multiply(dCompound.multiply(r, mc).subtract(compoundMinusOne, mc), mc).divide(rSquared, mc));
+
+            if (fPrime.signum() == 0) {
+                throw new IllegalStateException("RATE: zero derivative at iteration " + iter + ", r=" + r);
+            }
+
+            final BigDecimal correction = f.divide(fPrime, mc);
+            r = r.subtract(correction, mc);
+
+            if (correction.abs().compareTo(TOLERANCE) < 0) {
+                return r;
+            }
+        }
+
+        throw new IllegalStateException("RATE did not converge after " + MAX_ITERATIONS + " iterations");
+    }
+
+    /**
+     * Linear approximation for the initial Newton-Raphson guess: {@code r ≈ 2·(pmt·n + pv) / (pv·n)}. Falls back to
+     * {@value #DEFAULT_GUESS} if the estimate is non-positive.
+     */
+    private static BigDecimal estimateInitialGuess(final int nper, final BigDecimal pmt, final BigDecimal pv, final MathContext mc) {
+        final BigDecimal n = BigDecimal.valueOf(nper);
+        final BigDecimal pvTimesN = pv.multiply(n, mc);
+        if (pvTimesN.signum() == 0) {
+            return DEFAULT_GUESS;
+        }
+        final BigDecimal estimate = pmt.multiply(n, mc).add(pv, mc).multiply(TWO, mc).divide(pvTimesN, mc);
+        return estimate.signum() > 0 ? estimate : DEFAULT_GUESS;
+    }
+
+    /**
+     * Computes the discount factor: {@code 1 / (1 + eir)^days}.
+     *
+     * @param eir
+     *            effective interest rate per period
+     * @param days
+     *            number of periods to discount
+     * @param mc
+     *            math context for precision
+     * @return the discount factor (1.0 when days=0)
+     * @throws IllegalArgumentException
+     *             if days is negative or exceeds {@link Integer#MAX_VALUE}
+     */
+    public static BigDecimal discountFactor(final BigDecimal eir, final long days, final MathContext mc) {
+        if (days == 0) {
+            return BigDecimal.ONE;
+        }
+        if (days < 0 || days > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("days must be in [0, " + Integer.MAX_VALUE + "], got: " + days);
+        }
+        return BigDecimal.ONE.divide(BigDecimal.ONE.add(eir, mc).pow((int) days, mc), mc);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleData.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleData.java
new file mode 100644
index 0000000000..d5b34284f6
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleData.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+@AllArgsConstructor
+public class ProjectedAmortizationScheduleData {
+
+    private final BigDecimal originationFeeAmount;
+    private final BigDecimal netDisbursementAmount;
+    private final BigDecimal totalPaymentValue;
+    private final BigDecimal periodPaymentRate;
+    private final int npvDayCount;
+    private final LocalDate expectedDisbursementDate;
+    private final BigDecimal expectedPaymentAmount;
+    private final int loanTerm;
+    private final BigDecimal effectiveInterestRate;
+    private final List<ProjectedAmortizationSchedulePaymentData> payments;
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleGenerateRequest.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleGenerateRequest.java
new file mode 100644
index 0000000000..380f0f228d
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationScheduleGenerateRequest.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+public class ProjectedAmortizationScheduleGenerateRequest {
+
+    private BigDecimal originationFeeAmount;
+    private BigDecimal netDisbursementAmount;
+    private BigDecimal totalPaymentValue;
+    private BigDecimal periodPaymentRate;
+    private int npvDayCount;
+    private LocalDate expectedDisbursementDate;
+
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationSchedulePaymentData.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationSchedulePaymentData.java
new file mode 100644
index 0000000000..34bc396156
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/ProjectedAmortizationSchedulePaymentData.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+@AllArgsConstructor
+public class ProjectedAmortizationSchedulePaymentData {
+
+    private final int paymentNo;
+    private final LocalDate paymentDate;
+    private final long count;
+    private final long paymentsLeft;
+    private final BigDecimal expectedPaymentAmount;
+    private final BigDecimal forecastPaymentAmount;
+    private final BigDecimal discountFactor;
+    private final BigDecimal npvValue;
+    private final BigDecimal balance;
+    private final BigDecimal expectedAmortizationAmount;
+    private final BigDecimal netAmortizationAmount;
+    private final BigDecimal actualPaymentAmount;
+    private final BigDecimal actualAmortizationAmount;
+    private final BigDecimal incomeModification;
+    private final BigDecimal deferredBalance;
+
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/domain/ProjectedAmortizationLoanModel.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/domain/ProjectedAmortizationLoanModel.java
new file mode 100644
index 0000000000..4ea373f47f
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/domain/ProjectedAmortizationLoanModel.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.domain;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.Version;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+
+@Entity
+@Table(name = "m_wc_loan_amortization_model")
+@Getter
+@Setter
+public class ProjectedAmortizationLoanModel extends AbstractPersistableCustom<Long> {
+
+    @Version
+    int version;
+
+    @OneToOne
+    @JoinColumn(name = "loan_id", nullable = false)
+    private WorkingCapitalLoan loan;
+
+    @Column(name = "json_model", columnDefinition = "text", nullable = false)
+    private String jsonModel;
+
+    @Column(name = "business_date", nullable = false)
+    private LocalDate businessDate;
+
+    @Column(name = "last_modified_on_utc", nullable = false)
+    private OffsetDateTime lastModifiedDate;
+
+    @Column(name = "json_model_version", nullable = false)
+    private String jsonModelVersion;
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/exception/ProjectedAmortizationScheduleNotFoundException.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/exception/ProjectedAmortizationScheduleNotFoundException.java
new file mode 100644
index 0000000000..7742ce3da2
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/exception/ProjectedAmortizationScheduleNotFoundException.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+public class ProjectedAmortizationScheduleNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+    public ProjectedAmortizationScheduleNotFoundException(final Long loanId) {
+        super("error.msg.wc.loan.amortization.schedule.not.found",
+                "Projected amortization schedule for Working Capital Loan " + loanId + " does not exist", loanId);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/mapper/ProjectedAmortizationScheduleMapper.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/mapper/ProjectedAmortizationScheduleMapper.java
new file mode 100644
index 0000000000..9888c92290
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/mapper/ProjectedAmortizationScheduleMapper.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.mapper;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedPayment;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleData;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationSchedulePaymentData;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ProjectedAmortizationScheduleMapper {
+
+    private static final int DISPLAY_SCALE = 2;
+    private static final RoundingMode DISPLAY_ROUNDING = RoundingMode.HALF_UP;
+
+    public ProjectedAmortizationScheduleData toData(final ProjectedAmortizationScheduleModel model) {
+        final List<ProjectedAmortizationSchedulePaymentData> paymentDataList = model.payments().stream().map(this::toPaymentData).toList();
+
+        return ProjectedAmortizationScheduleData.builder() //
+                .originationFeeAmount(roundMoney(model.originationFeeAmount())) //
+                .netDisbursementAmount(roundMoney(model.netDisbursementAmount())) //
+                .totalPaymentValue(roundMoney(model.totalPaymentValue())) //
+                .periodPaymentRate(model.periodPaymentRate()) //
+                .npvDayCount(model.npvDayCount()) //
+                .expectedDisbursementDate(model.expectedDisbursementDate()) //
+                .expectedPaymentAmount(roundMoney(model.expectedPaymentAmount())) //
+                .loanTerm(model.loanTerm()) //
+                .effectiveInterestRate(model.effectiveInterestRate()) //
+                .payments(paymentDataList) //
+                .build();
+    }
+
+    private ProjectedAmortizationSchedulePaymentData toPaymentData(final ProjectedPayment payment) {
+        return ProjectedAmortizationSchedulePaymentData.builder() //
+                .paymentNo(payment.paymentNo()) //
+                .paymentDate(payment.date()) //
+                .count(payment.count()) //
+                .paymentsLeft(payment.paymentsLeft()) //
+                .expectedPaymentAmount(roundMoney(payment.expectedPaymentAmount())) //
+                .forecastPaymentAmount(roundMoney(payment.forecastPaymentAmount())) //
+                .discountFactor(payment.discountFactor()) //
+                .npvValue(roundMoney(payment.npvValue())) //
+                .balance(roundMoney(payment.balance())) //
+                .expectedAmortizationAmount(roundMoney(payment.expectedAmortizationAmount())) //
+                .netAmortizationAmount(roundMoney(payment.netAmortizationAmount())) //
+                .actualPaymentAmount(roundMoney(payment.actualPaymentAmount())) //
+                .actualAmortizationAmount(roundMoney(payment.actualAmortizationAmount())) //
+                .incomeModification(roundMoney(payment.incomeModification())) //
+                .deferredBalance(roundMoney(payment.deferredBalance())) //
+                .build();
+    }
+
+    private static BigDecimal roundMoney(final Money value) {
+        return value != null ? value.getAmount().setScale(DISPLAY_SCALE, DISPLAY_ROUNDING) : null;
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/ProjectedAmortizationLoanModelRepository.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/ProjectedAmortizationLoanModelRepository.java
new file mode 100644
index 0000000000..5177341e25
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/ProjectedAmortizationLoanModelRepository.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.repository;
+
+import java.util.Optional;
+import org.apache.fineract.portfolio.workingcapitalloan.domain.ProjectedAmortizationLoanModel;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ProjectedAmortizationLoanModelRepository
+        extends JpaSpecificationExecutor<ProjectedAmortizationLoanModel>, JpaRepository<ProjectedAmortizationLoanModel, Long> {
+
+    Optional<ProjectedAmortizationLoanModel> findByLoanId(Long loanId);
+
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserService.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserService.java
new file mode 100644
index 0000000000..62a1cfacd1
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserService.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import java.math.MathContext;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+public interface ProjectedAmortizationScheduleModelParserService {
+
+    String toJson(@NonNull ProjectedAmortizationScheduleModel model);
+
+    @Nullable
+    ProjectedAmortizationScheduleModel fromJson(@Nullable String json, @NonNull MathContext mc, @NonNull MonetaryCurrency currency);
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserServiceGsonImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserServiceGsonImpl.java
new file mode 100644
index 0000000000..3de2eced79
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleModelParserServiceGsonImpl.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.InstanceCreator;
+import com.google.gson.ToNumberPolicy;
+import java.math.MathContext;
+import java.time.LocalDate;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.serialization.gson.JsonExcludeAnnotationBasedExclusionStrategy;
+import org.apache.fineract.infrastructure.core.serialization.gson.LocalDateAdapter;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.organisation.monetary.serialization.MoneyDeserializer;
+import org.apache.fineract.organisation.monetary.serialization.MoneySerializer;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class ProjectedAmortizationScheduleModelParserServiceGsonImpl implements ProjectedAmortizationScheduleModelParserService {
+
+    private final Gson serializer = createSerializer();
+
+    private static Gson createSerializer() {
+        return new GsonBuilder() //
+                .registerTypeAdapter(LocalDate.class, new LocalDateAdapter().nullSafe()) //
+                .registerTypeAdapter(Money.class, new MoneySerializer()) //
+                .setNumberToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) //
+                .addSerializationExclusionStrategy(new JsonExcludeAnnotationBasedExclusionStrategy()) //
+                .addDeserializationExclusionStrategy(new JsonExcludeAnnotationBasedExclusionStrategy()) //
+                .create();
+    }
+
+    private static Gson createDeserializer(final MathContext mc, final MonetaryCurrency currency) {
+        return new GsonBuilder() //
+                .registerTypeAdapter(LocalDate.class, new LocalDateAdapter().nullSafe()) //
+                .registerTypeAdapter(Money.class, new MoneyDeserializer(mc, currency)) //
+                .setNumberToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) //
+                .registerTypeAdapter(ProjectedAmortizationScheduleModel.class,
+                        (InstanceCreator<ProjectedAmortizationScheduleModel>) type -> ProjectedAmortizationScheduleModel
+                                .forDeserialization(mc, currency)) //
+                .addSerializationExclusionStrategy(new JsonExcludeAnnotationBasedExclusionStrategy()) //
+                .addDeserializationExclusionStrategy(new JsonExcludeAnnotationBasedExclusionStrategy()) //
+                .create();
+    }
+
+    @Override
+    public String toJson(@NonNull final ProjectedAmortizationScheduleModel model) {
+        return serializer.toJson(model);
+    }
+
+    @Override
+    @Nullable
+    public ProjectedAmortizationScheduleModel fromJson(@Nullable final String json, @NonNull final MathContext mc,
+            @NonNull final MonetaryCurrency currency) {
+        if (json == null) {
+            return null;
+        }
+        try {
+            return createDeserializer(mc, currency).fromJson(json, ProjectedAmortizationScheduleModel.class);
+        } catch (Exception e) {
+            log.warn("Failed to parse ProjectedAmortizationScheduleModel JSON. Falling back to null.", e);
+            return null;
+        }
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapper.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapper.java
new file mode 100644
index 0000000000..98c6b95dd9
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapper.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import java.math.MathContext;
+import java.util.Optional;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoan;
+import org.springframework.lang.NonNull;
+
+public interface ProjectedAmortizationScheduleRepositoryWrapper {
+
+    Optional<ProjectedAmortizationScheduleModel> readModel(Long loanId, @NonNull MathContext mc, @NonNull MonetaryCurrency currency);
+
+    void writeModel(@NonNull WorkingCapitalLoan loan, @NonNull ProjectedAmortizationScheduleModel model);
+
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapperImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapperImpl.java
new file mode 100644
index 0000000000..b0448a73e7
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/ProjectedAmortizationScheduleRepositoryWrapperImpl.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import java.math.MathContext;
+import java.util.Optional;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.apache.fineract.portfolio.workingcapitalloan.domain.ProjectedAmortizationLoanModel;
+import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoan;
+import org.apache.fineract.portfolio.workingcapitalloan.repository.ProjectedAmortizationLoanModelRepository;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@RequiredArgsConstructor
+public class ProjectedAmortizationScheduleRepositoryWrapperImpl implements ProjectedAmortizationScheduleRepositoryWrapper {
+
+    private final ProjectedAmortizationLoanModelRepository repository;
+    private final ProjectedAmortizationScheduleModelParserService parserService;
+
+    @Override
+    public Optional<ProjectedAmortizationScheduleModel> readModel(final Long loanId, @NonNull final MathContext mc,
+            @NonNull final MonetaryCurrency currency) {
+        return repository.findByLoanId(loanId) //
+                .map(ProjectedAmortizationLoanModel::getJsonModel) //
+                .map(json -> parserService.fromJson(json, mc, currency));
+    }
+
+    @Override
+    @Transactional
+    public void writeModel(@NonNull final WorkingCapitalLoan loan, @NonNull final ProjectedAmortizationScheduleModel model) {
+        final String jsonModel = parserService.toJson(model);
+        final ProjectedAmortizationLoanModel entity = repository.findByLoanId(loan.getId()).orElseGet(() -> {
+            final ProjectedAmortizationLoanModel newEntity = new ProjectedAmortizationLoanModel();
+            newEntity.setLoan(loan);
+            return newEntity;
+        });
+        entity.setBusinessDate(ThreadLocalContextUtil.getBusinessDate());
+        entity.setLastModifiedDate(DateUtils.getAuditOffsetDateTime());
+        entity.setJsonModel(jsonModel);
+        entity.setJsonModelVersion(ProjectedAmortizationScheduleModel.getModelVersion());
+        repository.save(entity);
+    }
+
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadService.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadService.java
new file mode 100644
index 0000000000..137a1bd30f
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadService.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleData;
+
+public interface WorkingCapitalLoanAmortizationScheduleReadService {
+
+    ProjectedAmortizationScheduleData retrieveAmortizationSchedule(Long loanId);
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadServiceImpl.java
new file mode 100644
index 0000000000..b16d947236
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleReadServiceImpl.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import java.math.MathContext;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleData;
+import org.apache.fineract.portfolio.workingcapitalloan.exception.ProjectedAmortizationScheduleNotFoundException;
+import org.apache.fineract.portfolio.workingcapitalloan.exception.WorkingCapitalLoanNotFoundException;
+import org.apache.fineract.portfolio.workingcapitalloan.mapper.ProjectedAmortizationScheduleMapper;
+import org.apache.fineract.portfolio.workingcapitalloan.repository.WorkingCapitalLoanRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class WorkingCapitalLoanAmortizationScheduleReadServiceImpl implements WorkingCapitalLoanAmortizationScheduleReadService {
+
+    // TODO: currency should come from loan product once WCL lifecycle is implemented
+    private static final MonetaryCurrency DEFAULT_CURRENCY = new MonetaryCurrency("USD", 2, null);
+
+    private final WorkingCapitalLoanRepository loanRepository;
+    private final ProjectedAmortizationScheduleRepositoryWrapper scheduleRepositoryWrapper;
+    private final ProjectedAmortizationScheduleMapper mapper;
+
+    @Override
+    public ProjectedAmortizationScheduleData retrieveAmortizationSchedule(final Long loanId) {
+        if (!loanRepository.existsById(loanId)) {
+            throw new WorkingCapitalLoanNotFoundException(loanId);
+        }
+
+        final MathContext mc = MoneyHelper.getMathContext();
+        final ProjectedAmortizationScheduleModel model = scheduleRepositoryWrapper.readModel(loanId, mc, DEFAULT_CURRENCY)
+                .orElseThrow(() -> new ProjectedAmortizationScheduleNotFoundException(loanId));
+
+        return mapper.toData(model);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteService.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteService.java
new file mode 100644
index 0000000000..2f6958cbad
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteService.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleGenerateRequest;
+
+public interface WorkingCapitalLoanAmortizationScheduleWriteService {
+
+    void generateAndSaveAmortizationSchedule(Long loanId, ProjectedAmortizationScheduleGenerateRequest request);
+}
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteServiceImpl.java
new file mode 100644
index 0000000000..f8729c0b61
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanAmortizationScheduleWriteServiceImpl.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.service;
+
+import java.math.MathContext;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import org.apache.fineract.portfolio.workingcapitalloan.calc.ProjectedAmortizationScheduleModel;
+import org.apache.fineract.portfolio.workingcapitalloan.data.ProjectedAmortizationScheduleGenerateRequest;
+import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoan;
+import org.apache.fineract.portfolio.workingcapitalloan.exception.WorkingCapitalLoanNotFoundException;
+import org.apache.fineract.portfolio.workingcapitalloan.repository.WorkingCapitalLoanRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+// TODO: This is a temporary testing implementation. In the real flow, the amortization schedule
+// will be generated and saved as part of the loan lifecycle (approve/disburse) — not via a
+// standalone endpoint. The parameters will come from the loan entity + product, not from the
+// request body. Replace this once the full WCL lifecycle is implemented.
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class WorkingCapitalLoanAmortizationScheduleWriteServiceImpl implements WorkingCapitalLoanAmortizationScheduleWriteService {
+
+    // TODO: currency should come from loan product once WCL lifecycle is implemented
+    private static final MonetaryCurrency DEFAULT_CURRENCY = new MonetaryCurrency("USD", 2, null);
+
+    private final WorkingCapitalLoanRepository loanRepository;
+    private final ProjectedAmortizationScheduleRepositoryWrapper scheduleRepositoryWrapper;
+
+    @Override
+    public void generateAndSaveAmortizationSchedule(final Long loanId, final ProjectedAmortizationScheduleGenerateRequest request) {
+        final WorkingCapitalLoan loan = loanRepository.findById(loanId).orElseThrow(() -> new WorkingCapitalLoanNotFoundException(loanId));
+
+        final MathContext mc = MoneyHelper.getMathContext();
+
+        final ProjectedAmortizationScheduleModel model = ProjectedAmortizationScheduleModel.generate(//
+                request.getOriginationFeeAmount(), //
+                request.getNetDisbursementAmount(), //
+                request.getTotalPaymentValue(), //
+                request.getPeriodPaymentRate(), //
+                request.getNpvDayCount(), //
+                request.getExpectedDisbursementDate(), //
+                mc, DEFAULT_CURRENCY);
+
+        scheduleRepositoryWrapper.writeModel(loan, model);
+    }
+}
diff --git a/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/module-changelog-master.xml b/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/module-changelog-master.xml
index 47ef0f45d5..d49e648c1d 100644
--- a/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/module-changelog-master.xml
+++ b/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/module-changelog-master.xml
@@ -30,4 +30,5 @@
   <include relativeToChangelogFile="true" file="parts/0006_wc_loan_disbursement_details.xml"/>
   <include relativeToChangelogFile="true" file="parts/0007_drop_flat_percentage_amount.xml"/>
   <include relativeToChangelogFile="true" file="parts/0008_delinquency_for_working_capital_loans.xml"/>
+  <include relativeToChangelogFile="true" file="parts/0009_wc_loan_amortization_model.xml"/>
 </databaseChangeLog>
diff --git a/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/parts/0009_wc_loan_amortization_model.xml b/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/parts/0009_wc_loan_amortization_model.xml
new file mode 100644
index 0000000000..90f085f069
--- /dev/null
+++ b/fineract-working-capital-loan/src/main/resources/db/changelog/tenant/module/workingcapitalloan/parts/0009_wc_loan_amortization_model.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
+
+    <changeSet id="wcl-0008-1" author="fineract">
+        <preConditions onFail="MARK_RAN">
+            <not>
+                <tableExists tableName="m_wc_loan_amortization_model"/>
+            </not>
+        </preConditions>
+        <createTable tableName="m_wc_loan_amortization_model">
+            <column autoIncrement="true" name="id" type="BIGINT">
+                <constraints nullable="false" primaryKey="true"/>
+            </column>
+            <column name="version" type="INT">
+                <constraints nullable="false"/>
+            </column>
+            <column name="loan_id" type="BIGINT">
+                <constraints nullable="false"/>
+            </column>
+            <column name="json_model" type="CLOB">
+                <constraints nullable="false"/>
+            </column>
+            <column name="business_date" type="DATE">
+                <constraints nullable="false"/>
+            </column>
+            <column name="json_model_version" type="VARCHAR(10)">
+                <constraints nullable="false"/>
+            </column>
+        </createTable>
+    </changeSet>
+
+    <changeSet id="wcl-0008-2" author="fineract">
+        <addUniqueConstraint columnNames="loan_id" constraintName="uc_m_wc_loan_amort_model_loan"
+                             tableName="m_wc_loan_amortization_model"/>
+    </changeSet>
+
+    <changeSet id="wcl-0008-3" author="fineract">
+        <addForeignKeyConstraint baseColumnNames="loan_id" baseTableName="m_wc_loan_amortization_model"
+                                 constraintName="fk_m_wc_loan_amort_model_loan" referencedColumnNames="id"
+                                 referencedTableName="m_wc_loan"/>
+    </changeSet>
+
+    <changeSet author="fineract" id="wcl-0008-4-my" context="mysql">
+        <addColumn tableName="m_wc_loan_amortization_model">
+            <column name="last_modified_on_utc" type="DATETIME(6)">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+    </changeSet>
+
+    <changeSet author="fineract" id="wcl-0008-4-pg" context="postgresql">
+        <addColumn tableName="m_wc_loan_amortization_model">
+            <column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+    </changeSet>
+
+</databaseChangeLog>
diff --git a/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculatorTest.java b/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculatorTest.java
new file mode 100644
index 0000000000..e09a2cf63c
--- /dev/null
+++ b/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/calc/ProjectedAmortizationScheduleCalculatorTest.java
@@ -0,0 +1,2316 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.workingcapitalloan.calc;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.Money;
+import org.junit.jupiter.api.Test;
+
+class ProjectedAmortizationScheduleCalculatorTest {
+
+    private static final MathContext MC = MathContext.DECIMAL128;
+    private static final MonetaryCurrency CURRENCY = new MonetaryCurrency("USD", 2, null);
+
+    private static final BigDecimal ORIGINATION_FEE = new BigDecimal("1000");
+    private static final BigDecimal NET_DISBURSEMENT = new BigDecimal("9000");
+    private static final BigDecimal TPV = new BigDecimal("100000");
+    private static final BigDecimal RATE = new BigDecimal("0.18");
+    private static final int DAY_COUNT = 360;
+    private static final LocalDate EXPECTED_DISBURSEMENT_DATE = LocalDate.of(2019, 1, 1);
+    private static final int TERM = 200;
+
+    private final ProjectedAmortizationScheduleCalculator calculator = new DefaultProjectedAmortizationScheduleCalculator();
+
+    @Test
+    void testAddDisbursement_term10_originationFee50_netDisbursement450_then430() {
+        final BigDecimal originationFee = new BigDecimal("50");
+        final BigDecimal initialNetDisbursement = new BigDecimal("450");
+        final LocalDate initialDisbursementDate = LocalDate.of(2019, 1, 1);
+
+        final ProjectedAmortizationScheduleModel initial = calculator.generateModel(originationFee, initialNetDisbursement, TPV, RATE,
+                DAY_COUNT, initialDisbursementDate, MC, CURRENCY);
+        final ProjectedAmortizationScheduleModel model1 = calculator.addDisbursement(initial, originationFee, initialNetDisbursement,
+                initialDisbursementDate);
+
+        assertEquals(10, model1.loanTerm());
+        assertEquals(11, model1.payments().size());
+
+        checkInst(model1, 0, 0, LocalDate.of(2019, 1, 1), 10, 0, -450.00, null, null, 1.00000000, -450.00, 450.00, null, null, null, null,
+                50.00);
+        checkInst(model1, 1, 1, LocalDate.of(2019, 1, 2), 9, 1, 50.00, 50.00, null, 0.98074794, 49.04, 408.83, 8.83, 0.00, null, -8.83,
+                50.00);
+        checkInst(model1, 2, 2, LocalDate.of(2019, 1, 3), 8, 2, 50.00, 50.00, null, 0.96186652, 48.09, 366.86, 8.03, 0.00, null, -8.03,
+                50.00);
+        checkInst(model1, 3, 3, LocalDate.of(2019, 1, 4), 7, 3, 50.00, 50.00, null, 0.94334860, 47.17, 324.06, 7.20, 0.00, null, -7.20,
+                50.00);
+        checkInst(model1, 4, 4, LocalDate.of(2019, 1, 5), 6, 4, 50.00, 50.00, null, 0.92518720, 46.26, 280.42, 6.36, 0.00, null, -6.36,
+                50.00);
+        checkInst(model1, 5, 5, LocalDate.of(2019, 1, 6), 5, 5, 50.00, 50.00, null, 0.90737544, 45.37, 235.93, 5.50, 0.00, null, -5.50,
+                50.00);
+        checkInst(model1, 6, 6, LocalDate.of(2019, 1, 7), 4, 6, 50.00, 50.00, null, 0.88990659, 44.50, 190.56, 4.63, 0.00, null, -4.63,
+                50.00);
+        checkInst(model1, 7, 7, LocalDate.of(2019, 1, 8), 3, 7, 50.00, 50.00, null, 0.87277405, 43.64, 144.30, 3.74, 0.00, null, -3.74,
+                50.00);
+        checkInst(model1, 8, 8, LocalDate.of(2019, 1, 9), 2, 8, 50.00, 50.00, null, 0.85597135, 42.80, 97.13, 2.83, 0.00, null, -2.83,
+                50.00);
+        checkInst(model1, 9, 9, LocalDate.of(2019, 1, 10), 1, 9, 50.00, 50.00, null, 0.83949214, 41.97, 49.04, 1.91, 0.00, null, -1.91,
+                50.00);
+        checkInst(model1, 10, 10, LocalDate.of(2019, 1, 11), 0, 10, 50.00, 50.00, null, 0.82333018, 41.17, 0.00, 0.96, 0.00, null, -0.96,
+                50.00);
+
+        final BigDecimal newNetDisbursement = new BigDecimal("430");
+        final LocalDate newDisbursementDate = LocalDate.of(2019, 1, 5);
+
+        final ProjectedAmortizationScheduleModel model2 = calculator.addDisbursement(model1, originationFee, newNetDisbursement,
+                newDisbursementDate);
+
+        assertEquals(10, model2.loanTerm());
+        assertEquals(11, model2.payments().size());
+
+        checkInst(model2, 0, 0, LocalDate.of(2019, 1, 5), 10, 0, -430.00, null, null, 1.00000000, -430.00, 430.00, null, null, null, null,
+                50.00);
+        checkInst(model2, 1, 1, LocalDate.of(2019, 1, 6), 9, 1, 50.00, 50.00, null, 0.97237826, 48.62, 392.21, 12.21, 0.00, null, -12.21,
+                50.00);
+        checkInst(model2, 2, 2, LocalDate.of(2019, 1, 7), 8, 2, 50.00, 50.00, null, 0.94551948, 47.28, 353.36, 11.14, 0.00, null, -11.14,
+                50.00);
+        checkInst(model2, 3, 3, LocalDate.of(2019, 1, 8), 7, 3, 50.00, 50.00, null, 0.91940259, 45.97, 313.39, 10.04, 0.00, null, -10.04,
+                50.00);
+        checkInst(model2, 4, 4, LocalDate.of(2019, 1, 9), 6, 4, 50.00, 50.00, null, 0.89400709, 44.70, 272.30, 8.90, 0.00, null, -8.90,
+                50.00);
+        checkInst(model2, 5, 5, LocalDate.of(2019, 1, 10), 5, 5, 50.00, 50.00, null, 0.86931306, 43.47, 230.03, 7.73, 0.00, null, -7.73,
+                50.00);
+        checkInst(model2, 6, 6, LocalDate.of(2019, 1, 11), 4, 6, 50.00, 50.00, null, 0.84530113, 42.27, 186.57, 6.53, 0.00, null, -6.53,
+                50.00);
+        checkInst(model2, 7, 7, LocalDate.of(2019, 1, 12), 3, 7, 50.00, 50.00, null, 0.82195244, 41.10, 141.87, 5.30, 0.00, null, -5.30,
+                50.00);
+        checkInst(model2, 8, 8, LocalDate.of(2019, 1, 13), 2, 8, 50.00, 50.00, null, 0.79924869, 39.96, 95.89, 4.03, 0.00, null, -4.03,
+                50.00);
+        checkInst(model2, 9, 9, LocalDate.of(2019, 1, 14), 1, 9, 50.00, 50.00, null, 0.77717205, 38.86, 48.62, 2.72, 0.00, null, -2.72,
+                50.00);
+        checkInst(model2, 10, 10, LocalDate.of(2019, 1, 15), 0, 10, 50.00, 50.00, null, 0.75570520, 37.79, 0.00, 1.38, 0.00, null, -1.38,
+                50.00);
+    }
+
+    @Test
+    void testProjectedSchedule_term200_originationFee1000_netDisbursement9000() {
+        final ProjectedAmortizationScheduleModel model = generateModel();
+
+        assertEquals(TERM, model.loanTerm());
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 200, 0, -9000.00, null, null, 1.00000000, -9000.00, 9000.00, null, null, null,
+                null, 1000.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 199, 1, 50.00, 50.00, null, 0.99893332, 49.95, 8959.61, 9.61, 0.00, null, -9.61,
+                1000.00);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 198, 2, 50.00, 50.00, null, 0.99786779, 49.89, 8919.18, 9.57, 0.00, null, -9.57,
+                1000.00);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 197, 3, 50.00, 50.00, null, 0.99680339, 49.84, 8878.70, 9.52, 0.00, null, -9.52,
+                1000.00);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 196, 4, 50.00, 50.00, null, 0.99574012, 49.79, 8838.18, 9.48, 0.00, null, -9.48,
+                1000.00);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 195, 5, 50.00, 50.00, null, 0.99467799, 49.73, 8797.62, 9.44, 0.00, null, -9.44,
+                1000.00);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 194, 6, 50.00, 50.00, null, 0.99361699, 49.68, 8757.01, 9.39, 0.00, null, -9.39,
+                1000.00);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 193, 7, 50.00, 50.00, null, 0.99255712, 49.63, 8716.36, 9.35, 0.00, null, -9.35,
+                1000.00);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 192, 8, 50.00, 50.00, null, 0.99149839, 49.57, 8675.67, 9.31, 0.00, null, -9.31,
+                1000.00);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 191, 9, 50.00, 50.00, null, 0.99044078, 49.52, 8634.94, 9.26, 0.00, null, -9.26,
+                1000.00);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 190, 10, 50.00, 50.00, null, 0.98938430, 49.47, 8594.16, 9.22, 0.00, null,
+                -9.22, 1000.00);
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 189, 11, 50.00, 50.00, null, 0.98832895, 49.42, 8553.33, 9.18, 0.00, null,
+                -9.18, 1000.00);
+        checkInst(model, 12, 12, LocalDate.of(2019, 1, 13), 188, 12, 50.00, 50.00, null, 0.98727472, 49.36, 8512.47, 9.13, 0.00, null,
+                -9.13, 1000.00);
+        checkInst(model, 13, 13, LocalDate.of(2019, 1, 14), 187, 13, 50.00, 50.00, null, 0.98622162, 49.31, 8471.56, 9.09, 0.00, null,
+                -9.09, 1000.00);
+        checkInst(model, 14, 14, LocalDate.of(2019, 1, 15), 186, 14, 50.00, 50.00, null, 0.98516964, 49.26, 8430.60, 9.05, 0.00, null,
+                -9.05, 1000.00);
+        checkInst(model, 15, 15, LocalDate.of(2019, 1, 16), 185, 15, 50.00, 50.00, null, 0.98411879, 49.21, 8389.61, 9.00, 0.00, null,
+                -9.00, 1000.00);
+        checkInst(model, 16, 16, LocalDate.of(2019, 1, 17), 184, 16, 50.00, 50.00, null, 0.98306905, 49.15, 8348.56, 8.96, 0.00, null,
+                -8.96, 1000.00);
+        checkInst(model, 17, 17, LocalDate.of(2019, 1, 18), 183, 17, 50.00, 50.00, null, 0.98202044, 49.10, 8307.48, 8.91, 0.00, null,
+                -8.91, 1000.00);
+        checkInst(model, 18, 18, LocalDate.of(2019, 1, 19), 182, 18, 50.00, 50.00, null, 0.98097294, 49.05, 8266.35, 8.87, 0.00, null,
+                -8.87, 1000.00);
+        checkInst(model, 19, 19, LocalDate.of(2019, 1, 20), 181, 19, 50.00, 50.00, null, 0.97992656, 49.00, 8225.18, 8.83, 0.00, null,
+                -8.83, 1000.00);
+        checkInst(model, 20, 20, LocalDate.of(2019, 1, 21), 180, 20, 50.00, 50.00, null, 0.97888129, 48.94, 8183.96, 8.78, 0.00, null,
+                -8.78, 1000.00);
+        checkInst(model, 21, 21, LocalDate.of(2019, 1, 22), 179, 21, 50.00, 50.00, null, 0.97783715, 48.89, 8142.70, 8.74, 0.00, null,
+                -8.74, 1000.00);
+        checkInst(model, 22, 22, LocalDate.of(2019, 1, 23), 178, 22, 50.00, 50.00, null, 0.97679411, 48.84, 8101.39, 8.69, 0.00, null,
+                -8.69, 1000.00);
+        checkInst(model, 23, 23, LocalDate.of(2019, 1, 24), 177, 23, 50.00, 50.00, null, 0.97575219, 48.79, 8060.04, 8.65, 0.00, null,
+                -8.65, 1000.00);
+        checkInst(model, 24, 24, LocalDate.of(2019, 1, 25), 176, 24, 50.00, 50.00, null, 0.97471138, 48.74, 8018.65, 8.61, 0.00, null,
+                -8.61, 1000.00);
+        checkInst(model, 25, 25, LocalDate.of(2019, 1, 26), 175, 25, 50.00, 50.00, null, 0.97367168, 48.68, 7977.21, 8.56, 0.00, null,
+                -8.56, 1000.00);
+        checkInst(model, 26, 26, LocalDate.of(2019, 1, 27), 174, 26, 50.00, 50.00, null, 0.97263309, 48.63, 7935.73, 8.52, 0.00, null,
+                -8.52, 1000.00);
+        checkInst(model, 27, 27, LocalDate.of(2019, 1, 28), 173, 27, 50.00, 50.00, null, 0.97159560, 48.58, 7894.21, 8.47, 0.00, null,
+                -8.47, 1000.00);
+        checkInst(model, 28, 28, LocalDate.of(2019, 1, 29), 172, 28, 50.00, 50.00, null, 0.97055922, 48.53, 7852.63, 8.43, 0.00, null,
+                -8.43, 1000.00);
+        checkInst(model, 29, 29, LocalDate.of(2019, 1, 30), 171, 29, 50.00, 50.00, null, 0.96952395, 48.48, 7811.02, 8.39, 0.00, null,
+                -8.39, 1000.00);
+        checkInst(model, 30, 30, LocalDate.of(2019, 1, 31), 170, 30, 50.00, 50.00, null, 0.96848979, 48.42, 7769.36, 8.34, 0.00, null,
+                -8.34, 1000.00);
+        checkInst(model, 31, 31, LocalDate.of(2019, 2, 1), 169, 31, 50.00, 50.00, null, 0.96745672, 48.37, 7727.66, 8.30, 0.00, null, -8.30,
+                1000.00);
+        checkInst(model, 32, 32, LocalDate.of(2019, 2, 2), 168, 32, 50.00, 50.00, null, 0.96642476, 48.32, 7685.91, 8.25, 0.00, null, -8.25,
+                1000.00);
+        checkInst(model, 33, 33, LocalDate.of(2019, 2, 3), 167, 33, 50.00, 50.00, null, 0.96539390, 48.27, 7644.12, 8.21, 0.00, null, -8.21,
+                1000.00);
+        checkInst(model, 34, 34, LocalDate.of(2019, 2, 4), 166, 34, 50.00, 50.00, null, 0.96436413, 48.22, 7602.28, 8.16, 0.00, null, -8.16,
+                1000.00);
+        checkInst(model, 35, 35, LocalDate.of(2019, 2, 5), 165, 35, 50.00, 50.00, null, 0.96333547, 48.17, 7560.40, 8.12, 0.00, null, -8.12,
+                1000.00);
+        checkInst(model, 36, 36, LocalDate.of(2019, 2, 6), 164, 36, 50.00, 50.00, null, 0.96230790, 48.12, 7518.47, 8.07, 0.00, null, -8.07,
+                1000.00);
+        checkInst(model, 37, 37, LocalDate.of(2019, 2, 7), 163, 37, 50.00, 50.00, null, 0.96128143, 48.06, 7476.50, 8.03, 0.00, null, -8.03,
+                1000.00);
+        checkInst(model, 38, 38, LocalDate.of(2019, 2, 8), 162, 38, 50.00, 50.00, null, 0.96025606, 48.01, 7434.48, 7.98, 0.00, null, -7.98,
+                1000.00);
+        checkInst(model, 39, 39, LocalDate.of(2019, 2, 9), 161, 39, 50.00, 50.00, null, 0.95923178, 47.96, 7392.42, 7.94, 0.00, null, -7.94,
+                1000.00);
+        checkInst(model, 40, 40, LocalDate.of(2019, 2, 10), 160, 40, 50.00, 50.00, null, 0.95820859, 47.91, 7350.31, 7.89, 0.00, null,
+                -7.89, 1000.00);
+        checkInst(model, 41, 41, LocalDate.of(2019, 2, 11), 159, 41, 50.00, 50.00, null, 0.95718649, 47.86, 7308.16, 7.85, 0.00, null,
+                -7.85, 1000.00);
+        checkInst(model, 42, 42, LocalDate.of(2019, 2, 12), 158, 42, 50.00, 50.00, null, 0.95616548, 47.81, 7265.97, 7.80, 0.00, null,
+                -7.80, 1000.00);
+        checkInst(model, 43, 43, LocalDate.of(2019, 2, 13), 157, 43, 50.00, 50.00, null, 0.95514557, 47.76, 7223.72, 7.76, 0.00, null,
+                -7.76, 1000.00);
+        checkInst(model, 44, 44, LocalDate.of(2019, 2, 14), 156, 44, 50.00, 50.00, null, 0.95412674, 47.71, 7181.44, 7.71, 0.00, null,
+                -7.71, 1000.00);
+        checkInst(model, 45, 45, LocalDate.of(2019, 2, 15), 155, 45, 50.00, 50.00, null, 0.95310899, 47.66, 7139.11, 7.67, 0.00, null,
+                -7.67, 1000.00);
+        checkInst(model, 46, 46, LocalDate.of(2019, 2, 16), 154, 46, 50.00, 50.00, null, 0.95209233, 47.60, 7096.73, 7.62, 0.00, null,
+                -7.62, 1000.00);
+        checkInst(model, 47, 47, LocalDate.of(2019, 2, 17), 153, 47, 50.00, 50.00, null, 0.95107676, 47.55, 7054.31, 7.58, 0.00, null,
+                -7.58, 1000.00);
+        checkInst(model, 48, 48, LocalDate.of(2019, 2, 18), 152, 48, 50.00, 50.00, null, 0.95006227, 47.50, 7011.84, 7.53, 0.00, null,
+                -7.53, 1000.00);
+        checkInst(model, 49, 49, LocalDate.of(2019, 2, 19), 151, 49, 50.00, 50.00, null, 0.94904886, 47.45, 6969.33, 7.49, 0.00, null,
+                -7.49, 1000.00);
+        checkInst(model, 50, 50, LocalDate.of(2019, 2, 20), 150, 50, 50.00, 50.00, null, 0.94803653, 47.40, 6926.77, 7.44, 0.00, null,
+                -7.44, 1000.00);
+        checkInst(model, 51, 51, LocalDate.of(2019, 2, 21), 149, 51, 50.00, 50.00, null, 0.94702529, 47.35, 6884.17, 7.40, 0.00, null,
+                -7.40, 1000.00);
+        checkInst(model, 52, 52, LocalDate.of(2019, 2, 22), 148, 52, 50.00, 50.00, null, 0.94601512, 47.30, 6841.52, 7.35, 0.00, null,
+                -7.35, 1000.00);
+        checkInst(model, 53, 53, LocalDate.of(2019, 2, 23), 147, 53, 50.00, 50.00, null, 0.94500603, 47.25, 6798.82, 7.31, 0.00, null,
+                -7.31, 1000.00);
+        checkInst(model, 54, 54, LocalDate.of(2019, 2, 24), 146, 54, 50.00, 50.00, null, 0.94399801, 47.20, 6756.08, 7.26, 0.00, null,
+                -7.26, 1000.00);
+        checkInst(model, 55, 55, LocalDate.of(2019, 2, 25), 145, 55, 50.00, 50.00, null, 0.94299107, 47.15, 6713.30, 7.21, 0.00, null,
+                -7.21, 1000.00);
+        checkInst(model, 56, 56, LocalDate.of(2019, 2, 26), 144, 56, 50.00, 50.00, null, 0.94198521, 47.10, 6670.47, 7.17, 0.00, null,
+                -7.17, 1000.00);
+        checkInst(model, 57, 57, LocalDate.of(2019, 2, 27), 143, 57, 50.00, 50.00, null, 0.94098042, 47.05, 6627.59, 7.12, 0.00, null,
+                -7.12, 1000.00);
+        checkInst(model, 58, 58, LocalDate.of(2019, 2, 28), 142, 58, 50.00, 50.00, null, 0.93997669, 47.00, 6584.67, 7.08, 0.00, null,
+                -7.08, 1000.00);
+        checkInst(model, 59, 59, LocalDate.of(2019, 3, 1), 141, 59, 50.00, 50.00, null, 0.93897404, 46.95, 6541.70, 7.03, 0.00, null, -7.03,
+                1000.00);
+        checkInst(model, 60, 60, LocalDate.of(2019, 3, 2), 140, 60, 50.00, 50.00, null, 0.93797246, 46.90, 6498.68, 6.99, 0.00, null, -6.99,
+                1000.00);
+        checkInst(model, 61, 61, LocalDate.of(2019, 3, 3), 139, 61, 50.00, 50.00, null, 0.93697195, 46.85, 6455.62, 6.94, 0.00, null, -6.94,
+                1000.00);
+        checkInst(model, 62, 62, LocalDate.of(2019, 3, 4), 138, 62, 50.00, 50.00, null, 0.93597251, 46.80, 6412.51, 6.89, 0.00, null, -6.89,
+                1000.00);
+        checkInst(model, 63, 63, LocalDate.of(2019, 3, 5), 137, 63, 50.00, 50.00, null, 0.93497413, 46.75, 6369.36, 6.85, 0.00, null, -6.85,
+                1000.00);
+        checkInst(model, 64, 64, LocalDate.of(2019, 3, 6), 136, 64, 50.00, 50.00, null, 0.93397681, 46.70, 6326.16, 6.80, 0.00, null, -6.80,
+                1000.00);
+        checkInst(model, 65, 65, LocalDate.of(2019, 3, 7), 135, 65, 50.00, 50.00, null, 0.93298056, 46.65, 6282.92, 6.76, 0.00, null, -6.76,
+                1000.00);
+        checkInst(model, 66, 66, LocalDate.of(2019, 3, 8), 134, 66, 50.00, 50.00, null, 0.93198538, 46.60, 6239.63, 6.71, 0.00, null, -6.71,
+                1000.00);
+        checkInst(model, 67, 67, LocalDate.of(2019, 3, 9), 133, 67, 50.00, 50.00, null, 0.93099125, 46.55, 6196.29, 6.66, 0.00, null, -6.66,
+                1000.00);
+        checkInst(model, 68, 68, LocalDate.of(2019, 3, 10), 132, 68, 50.00, 50.00, null, 0.92999818, 46.50, 6152.91, 6.62, 0.00, null,
+                -6.62, 1000.00);
+        checkInst(model, 69, 69, LocalDate.of(2019, 3, 11), 131, 69, 50.00, 50.00, null, 0.92900618, 46.45, 6109.48, 6.57, 0.00, null,
+                -6.57, 1000.00);
+        checkInst(model, 70, 70, LocalDate.of(2019, 3, 12), 130, 70, 50.00, 50.00, null, 0.92801523, 46.40, 6066.00, 6.52, 0.00, null,
+                -6.52, 1000.00);
+        checkInst(model, 71, 71, LocalDate.of(2019, 3, 13), 129, 71, 50.00, 50.00, null, 0.92702534, 46.35, 6022.48, 6.48, 0.00, null,
+                -6.48, 1000.00);
+        checkInst(model, 72, 72, LocalDate.of(2019, 3, 14), 128, 72, 50.00, 50.00, null, 0.92603650, 46.30, 5978.91, 6.43, 0.00, null,
+                -6.43, 1000.00);
+        checkInst(model, 73, 73, LocalDate.of(2019, 3, 15), 127, 73, 50.00, 50.00, null, 0.92504872, 46.25, 5935.29, 6.38, 0.00, null,
+                -6.38, 1000.00);
+        checkInst(model, 74, 74, LocalDate.of(2019, 3, 16), 126, 74, 50.00, 50.00, null, 0.92406200, 46.20, 5891.63, 6.34, 0.00, null,
+                -6.34, 1000.00);
+        checkInst(model, 75, 75, LocalDate.of(2019, 3, 17), 125, 75, 50.00, 50.00, null, 0.92307632, 46.15, 5847.92, 6.29, 0.00, null,
+                -6.29, 1000.00);
+        checkInst(model, 76, 76, LocalDate.of(2019, 3, 18), 124, 76, 50.00, 50.00, null, 0.92209170, 46.10, 5804.17, 6.24, 0.00, null,
+                -6.24, 1000.00);
+        checkInst(model, 77, 77, LocalDate.of(2019, 3, 19), 123, 77, 50.00, 50.00, null, 0.92110813, 46.06, 5760.36, 6.20, 0.00, null,
+                -6.20, 1000.00);
+        checkInst(model, 78, 78, LocalDate.of(2019, 3, 20), 122, 78, 50.00, 50.00, null, 0.92012560, 46.01, 5716.52, 6.15, 0.00, null,
+                -6.15, 1000.00);
+        checkInst(model, 79, 79, LocalDate.of(2019, 3, 21), 121, 79, 50.00, 50.00, null, 0.91914413, 45.96, 5672.62, 6.10, 0.00, null,
+                -6.10, 1000.00);
+        checkInst(model, 80, 80, LocalDate.of(2019, 3, 22), 120, 80, 50.00, 50.00, null, 0.91816370, 45.91, 5628.68, 6.06, 0.00, null,
+                -6.06, 1000.00);
+        checkInst(model, 81, 81, LocalDate.of(2019, 3, 23), 119, 81, 50.00, 50.00, null, 0.91718432, 45.86, 5584.69, 6.01, 0.00, null,
+                -6.01, 1000.00);
+        checkInst(model, 82, 82, LocalDate.of(2019, 3, 24), 118, 82, 50.00, 50.00, null, 0.91620598, 45.81, 5540.65, 5.96, 0.00, null,
+                -5.96, 1000.00);
+        checkInst(model, 83, 83, LocalDate.of(2019, 3, 25), 117, 83, 50.00, 50.00, null, 0.91522868, 45.76, 5496.57, 5.92, 0.00, null,
+                -5.92, 1000.00);
+        checkInst(model, 84, 84, LocalDate.of(2019, 3, 26), 116, 84, 50.00, 50.00, null, 0.91425243, 45.71, 5452.44, 5.87, 0.00, null,
+                -5.87, 1000.00);
+        checkInst(model, 85, 85, LocalDate.of(2019, 3, 27), 115, 85, 50.00, 50.00, null, 0.91327722, 45.66, 5408.26, 5.82, 0.00, null,
+                -5.82, 1000.00);
+        checkInst(model, 86, 86, LocalDate.of(2019, 3, 28), 114, 86, 50.00, 50.00, null, 0.91230305, 45.62, 5364.03, 5.78, 0.00, null,
+                -5.78, 1000.00);
+        checkInst(model, 87, 87, LocalDate.of(2019, 3, 29), 113, 87, 50.00, 50.00, null, 0.91132992, 45.57, 5319.76, 5.73, 0.00, null,
+                -5.73, 1000.00);
+        checkInst(model, 88, 88, LocalDate.of(2019, 3, 30), 112, 88, 50.00, 50.00, null, 0.91035783, 45.52, 5275.44, 5.68, 0.00, null,
+                -5.68, 1000.00);
+        checkInst(model, 89, 89, LocalDate.of(2019, 3, 31), 111, 89, 50.00, 50.00, null, 0.90938677, 45.47, 5231.08, 5.63, 0.00, null,
+                -5.63, 1000.00);
+        checkInst(model, 90, 90, LocalDate.of(2019, 4, 1), 110, 90, 50.00, 50.00, null, 0.90841675, 45.42, 5186.66, 5.59, 0.00, null, -5.59,
+                1000.00);
+        checkInst(model, 91, 91, LocalDate.of(2019, 4, 2), 109, 91, 50.00, 50.00, null, 0.90744776, 45.37, 5142.20, 5.54, 0.00, null, -5.54,
+                1000.00);
+        checkInst(model, 92, 92, LocalDate.of(2019, 4, 3), 108, 92, 50.00, 50.00, null, 0.90647981, 45.32, 5097.69, 5.49, 0.00, null, -5.49,
+                1000.00);
+        checkInst(model, 93, 93, LocalDate.of(2019, 4, 4), 107, 93, 50.00, 50.00, null, 0.90551289, 45.28, 5053.13, 5.44, 0.00, null, -5.44,
+                1000.00);
+        checkInst(model, 94, 94, LocalDate.of(2019, 4, 5), 106, 94, 50.00, 50.00, null, 0.90454700, 45.23, 5008.53, 5.40, 0.00, null, -5.40,
+                1000.00);
+        checkInst(model, 95, 95, LocalDate.of(2019, 4, 6), 105, 95, 50.00, 50.00, null, 0.90358215, 45.18, 4963.88, 5.35, 0.00, null, -5.35,
+                1000.00);
+        checkInst(model, 96, 96, LocalDate.of(2019, 4, 7), 104, 96, 50.00, 50.00, null, 0.90261832, 45.13, 4919.18, 5.30, 0.00, null, -5.30,
+                1000.00);
+        checkInst(model, 97, 97, LocalDate.of(2019, 4, 8), 103, 97, 50.00, 50.00, null, 0.90165552, 45.08, 4874.43, 5.25, 0.00, null, -5.25,
+                1000.00);
+        checkInst(model, 98, 98, LocalDate.of(2019, 4, 9), 102, 98, 50.00, 50.00, null, 0.90069374, 45.03, 4829.64, 5.20, 0.00, null, -5.20,
+                1000.00);
+        checkInst(model, 99, 99, LocalDate.of(2019, 4, 10), 101, 99, 50.00, 50.00, null, 0.89973299, 44.99, 4784.79, 5.16, 0.00, null,
+                -5.16, 1000.00);
+        checkInst(model, 100, 100, LocalDate.of(2019, 4, 11), 100, 100, 50.00, 50.00, null, 0.89877327, 44.94, 4739.90, 5.11, 0.00, null,
+                -5.11, 1000.00);
+        checkInst(model, 101, 101, LocalDate.of(2019, 4, 12), 99, 101, 50.00, 50.00, null, 0.89781457, 44.89, 4694.96, 5.06, 0.00, null,
+                -5.06, 1000.00);
+        checkInst(model, 102, 102, LocalDate.of(2019, 4, 13), 98, 102, 50.00, 50.00, null, 0.89685689, 44.84, 4649.98, 5.01, 0.00, null,
+                -5.01, 1000.00);
+        checkInst(model, 103, 103, LocalDate.of(2019, 4, 14), 97, 103, 50.00, 50.00, null, 0.89590024, 44.80, 4604.94, 4.97, 0.00, null,
+                -4.97, 1000.00);
+        checkInst(model, 104, 104, LocalDate.of(2019, 4, 15), 96, 104, 50.00, 50.00, null, 0.89494460, 44.75, 4559.86, 4.92, 0.00, null,
+                -4.92, 1000.00);
+        checkInst(model, 105, 105, LocalDate.of(2019, 4, 16), 95, 105, 50.00, 50.00, null, 0.89398999, 44.70, 4514.73, 4.87, 0.00, null,
+                -4.87, 1000.00);
+        checkInst(model, 106, 106, LocalDate.of(2019, 4, 17), 94, 106, 50.00, 50.00, null, 0.89303639, 44.65, 4469.55, 4.82, 0.00, null,
+                -4.82, 1000.00);
+        checkInst(model, 107, 107, LocalDate.of(2019, 4, 18), 93, 107, 50.00, 50.00, null, 0.89208381, 44.60, 4424.32, 4.77, 0.00, null,
+                -4.77, 1000.00);
+        checkInst(model, 108, 108, LocalDate.of(2019, 4, 19), 92, 108, 50.00, 50.00, null, 0.89113225, 44.56, 4379.05, 4.72, 0.00, null,
+                -4.72, 1000.00);
+        checkInst(model, 109, 109, LocalDate.of(2019, 4, 20), 91, 109, 50.00, 50.00, null, 0.89018170, 44.51, 4333.72, 4.68, 0.00, null,
+                -4.68, 1000.00);
+        checkInst(model, 110, 110, LocalDate.of(2019, 4, 21), 90, 110, 50.00, 50.00, null, 0.88923216, 44.46, 4288.35, 4.63, 0.00, null,
+                -4.63, 1000.00);
+        checkInst(model, 111, 111, LocalDate.of(2019, 4, 22), 89, 111, 50.00, 50.00, null, 0.88828364, 44.41, 4242.93, 4.58, 0.00, null,
+                -4.58, 1000.00);
+        checkInst(model, 112, 112, LocalDate.of(2019, 4, 23), 88, 112, 50.00, 50.00, null, 0.88733613, 44.37, 4197.46, 4.53, 0.00, null,
+                -4.53, 1000.00);
+        checkInst(model, 113, 113, LocalDate.of(2019, 4, 24), 87, 113, 50.00, 50.00, null, 0.88638963, 44.32, 4151.94, 4.48, 0.00, null,
+                -4.48, 1000.00);
+        checkInst(model, 114, 114, LocalDate.of(2019, 4, 25), 86, 114, 50.00, 50.00, null, 0.88544414, 44.27, 4106.38, 4.43, 0.00, null,
+                -4.43, 1000.00);
+        checkInst(model, 115, 115, LocalDate.of(2019, 4, 26), 85, 115, 50.00, 50.00, null, 0.88449966, 44.22, 4060.76, 4.38, 0.00, null,
+                -4.38, 1000.00);
+        checkInst(model, 116, 116, LocalDate.of(2019, 4, 27), 84, 116, 50.00, 50.00, null, 0.88355619, 44.18, 4015.10, 4.34, 0.00, null,
+                -4.34, 1000.00);
+        checkInst(model, 117, 117, LocalDate.of(2019, 4, 28), 83, 117, 50.00, 50.00, null, 0.88261372, 44.13, 3969.38, 4.29, 0.00, null,
+                -4.29, 1000.00);
+        checkInst(model, 118, 118, LocalDate.of(2019, 4, 29), 82, 118, 50.00, 50.00, null, 0.88167226, 44.08, 3923.62, 4.24, 0.00, null,
+                -4.24, 1000.00);
+        checkInst(model, 119, 119, LocalDate.of(2019, 4, 30), 81, 119, 50.00, 50.00, null, 0.88073180, 44.04, 3877.81, 4.19, 0.00, null,
+                -4.19, 1000.00);
+        checkInst(model, 120, 120, LocalDate.of(2019, 5, 1), 80, 120, 50.00, 50.00, null, 0.87979234, 43.99, 3831.95, 4.14, 0.00, null,
+                -4.14, 1000.00);
+        checkInst(model, 121, 121, LocalDate.of(2019, 5, 2), 79, 121, 50.00, 50.00, null, 0.87885389, 43.94, 3786.04, 4.09, 0.00, null,
+                -4.09, 1000.00);
+        checkInst(model, 122, 122, LocalDate.of(2019, 5, 3), 78, 122, 50.00, 50.00, null, 0.87791644, 43.90, 3740.09, 4.04, 0.00, null,
+                -4.04, 1000.00);
+        checkInst(model, 123, 123, LocalDate.of(2019, 5, 4), 77, 123, 50.00, 50.00, null, 0.87697999, 43.85, 3694.08, 3.99, 0.00, null,
+                -3.99, 1000.00);
+        checkInst(model, 124, 124, LocalDate.of(2019, 5, 5), 76, 124, 50.00, 50.00, null, 0.87604453, 43.80, 3648.03, 3.94, 0.00, null,
+                -3.94, 1000.00);
+        checkInst(model, 125, 125, LocalDate.of(2019, 5, 6), 75, 125, 50.00, 50.00, null, 0.87511008, 43.76, 3601.92, 3.90, 0.00, null,
+                -3.90, 1000.00);
+        checkInst(model, 126, 126, LocalDate.of(2019, 5, 7), 74, 126, 50.00, 50.00, null, 0.87417662, 43.71, 3555.77, 3.85, 0.00, null,
+                -3.85, 1000.00);
+        checkInst(model, 127, 127, LocalDate.of(2019, 5, 8), 73, 127, 50.00, 50.00, null, 0.87324416, 43.66, 3509.56, 3.80, 0.00, null,
+                -3.80, 1000.00);
+        checkInst(model, 128, 128, LocalDate.of(2019, 5, 9), 72, 128, 50.00, 50.00, null, 0.87231269, 43.62, 3463.31, 3.75, 0.00, null,
+                -3.75, 1000.00);
+        checkInst(model, 129, 129, LocalDate.of(2019, 5, 10), 71, 129, 50.00, 50.00, null, 0.87138221, 43.57, 3417.01, 3.70, 0.00, null,
+                -3.70, 1000.00);
+        checkInst(model, 130, 130, LocalDate.of(2019, 5, 11), 70, 130, 50.00, 50.00, null, 0.87045273, 43.52, 3370.66, 3.65, 0.00, null,
+                -3.65, 1000.00);
+        checkInst(model, 131, 131, LocalDate.of(2019, 5, 12), 69, 131, 50.00, 50.00, null, 0.86952424, 43.48, 3324.26, 3.60, 0.00, null,
+                -3.60, 1000.00);
+        checkInst(model, 132, 132, LocalDate.of(2019, 5, 13), 68, 132, 50.00, 50.00, null, 0.86859674, 43.43, 3277.81, 3.55, 0.00, null,
+                -3.55, 1000.00);
+        checkInst(model, 133, 133, LocalDate.of(2019, 5, 14), 67, 133, 50.00, 50.00, null, 0.86767023, 43.38, 3231.31, 3.50, 0.00, null,
+                -3.50, 1000.00);
+        checkInst(model, 134, 134, LocalDate.of(2019, 5, 15), 66, 134, 50.00, 50.00, null, 0.86674471, 43.34, 3184.76, 3.45, 0.00, null,
+                -3.45, 1000.00);
+        checkInst(model, 135, 135, LocalDate.of(2019, 5, 16), 65, 135, 50.00, 50.00, null, 0.86582017, 43.29, 3138.16, 3.40, 0.00, null,
+                -3.40, 1000.00);
+        checkInst(model, 136, 136, LocalDate.of(2019, 5, 17), 64, 136, 50.00, 50.00, null, 0.86489662, 43.24, 3091.51, 3.35, 0.00, null,
+                -3.35, 1000.00);
+        checkInst(model, 137, 137, LocalDate.of(2019, 5, 18), 63, 137, 50.00, 50.00, null, 0.86397406, 43.20, 3044.81, 3.30, 0.00, null,
+                -3.30, 1000.00);
+        checkInst(model, 138, 138, LocalDate.of(2019, 5, 19), 62, 138, 50.00, 50.00, null, 0.86305248, 43.15, 2998.06, 3.25, 0.00, null,
+                -3.25, 1000.00);
+        checkInst(model, 139, 139, LocalDate.of(2019, 5, 20), 61, 139, 50.00, 50.00, null, 0.86213188, 43.11, 2951.26, 3.20, 0.00, null,
+                -3.20, 1000.00);
+        checkInst(model, 140, 140, LocalDate.of(2019, 5, 21), 60, 140, 50.00, 50.00, null, 0.86121227, 43.06, 2904.42, 3.15, 0.00, null,
+                -3.15, 1000.00);
+        checkInst(model, 141, 141, LocalDate.of(2019, 5, 22), 59, 141, 50.00, 50.00, null, 0.86029363, 43.01, 2857.52, 3.10, 0.00, null,
+                -3.10, 1000.00);
+        checkInst(model, 142, 142, LocalDate.of(2019, 5, 23), 58, 142, 50.00, 50.00, null, 0.85937598, 42.97, 2810.57, 3.05, 0.00, null,
+                -3.05, 1000.00);
+        checkInst(model, 143, 143, LocalDate.of(2019, 5, 24), 57, 143, 50.00, 50.00, null, 0.85845930, 42.92, 2763.57, 3.00, 0.00, null,
+                -3.00, 1000.00);
+        checkInst(model, 144, 144, LocalDate.of(2019, 5, 25), 56, 144, 50.00, 50.00, null, 0.85754361, 42.88, 2716.52, 2.95, 0.00, null,
+                -2.95, 1000.00);
+        checkInst(model, 145, 145, LocalDate.of(2019, 5, 26), 55, 145, 50.00, 50.00, null, 0.85662889, 42.83, 2669.42, 2.90, 0.00, null,
+                -2.90, 1000.00);
+        checkInst(model, 146, 146, LocalDate.of(2019, 5, 27), 54, 146, 50.00, 50.00, null, 0.85571514, 42.79, 2622.27, 2.85, 0.00, null,
+                -2.85, 1000.00);
+        checkInst(model, 147, 147, LocalDate.of(2019, 5, 28), 53, 147, 50.00, 50.00, null, 0.85480237, 42.74, 2575.07, 2.80, 0.00, null,
+                -2.80, 1000.00);
+        checkInst(model, 148, 148, LocalDate.of(2019, 5, 29), 52, 148, 50.00, 50.00, null, 0.85389057, 42.69, 2527.82, 2.75, 0.00, null,
+                -2.75, 1000.00);
+        checkInst(model, 149, 149, LocalDate.of(2019, 5, 30), 51, 149, 50.00, 50.00, null, 0.85297975, 42.65, 2480.52, 2.70, 0.00, null,
+                -2.70, 1000.00);
+        checkInst(model, 150, 150, LocalDate.of(2019, 5, 31), 50, 150, 50.00, 50.00, null, 0.85206990, 42.60, 2433.17, 2.65, 0.00, null,
+                -2.65, 1000.00);
+        checkInst(model, 151, 151, LocalDate.of(2019, 6, 1), 49, 151, 50.00, 50.00, null, 0.85116101, 42.56, 2385.77, 2.60, 0.00, null,
+                -2.60, 1000.00);
+        checkInst(model, 152, 152, LocalDate.of(2019, 6, 2), 48, 152, 50.00, 50.00, null, 0.85025310, 42.51, 2338.31, 2.55, 0.00, null,
+                -2.55, 1000.00);
+        checkInst(model, 153, 153, LocalDate.of(2019, 6, 3), 47, 153, 50.00, 50.00, null, 0.84934616, 42.47, 2290.81, 2.50, 0.00, null,
+                -2.50, 1000.00);
+        checkInst(model, 154, 154, LocalDate.of(2019, 6, 4), 46, 154, 50.00, 50.00, null, 0.84844018, 42.42, 2243.26, 2.45, 0.00, null,
+                -2.45, 1000.00);
+        checkInst(model, 155, 155, LocalDate.of(2019, 6, 5), 45, 155, 50.00, 50.00, null, 0.84753517, 42.38, 2195.65, 2.40, 0.00, null,
+                -2.40, 1000.00);
+        checkInst(model, 156, 156, LocalDate.of(2019, 6, 6), 44, 156, 50.00, 50.00, null, 0.84663113, 42.33, 2148.00, 2.34, 0.00, null,
+                -2.34, 1000.00);
+        checkInst(model, 157, 157, LocalDate.of(2019, 6, 7), 43, 157, 50.00, 50.00, null, 0.84572805, 42.29, 2100.29, 2.29, 0.00, null,
+                -2.29, 1000.00);
+        checkInst(model, 158, 158, LocalDate.of(2019, 6, 8), 42, 158, 50.00, 50.00, null, 0.84482593, 42.24, 2052.53, 2.24, 0.00, null,
+                -2.24, 1000.00);
+        checkInst(model, 159, 159, LocalDate.of(2019, 6, 9), 41, 159, 50.00, 50.00, null, 0.84392477, 42.20, 2004.73, 2.19, 0.00, null,
+                -2.19, 1000.00);
+        checkInst(model, 160, 160, LocalDate.of(2019, 6, 10), 40, 160, 50.00, 50.00, null, 0.84302458, 42.15, 1956.87, 2.14, 0.00, null,
+                -2.14, 1000.00);
+        checkInst(model, 161, 161, LocalDate.of(2019, 6, 11), 39, 161, 50.00, 50.00, null, 0.84212535, 42.11, 1908.96, 2.09, 0.00, null,
+                -2.09, 1000.00);
+        checkInst(model, 162, 162, LocalDate.of(2019, 6, 12), 38, 162, 50.00, 50.00, null, 0.84122707, 42.06, 1860.99, 2.04, 0.00, null,
+                -2.04, 1000.00);
+        checkInst(model, 163, 163, LocalDate.of(2019, 6, 13), 37, 163, 50.00, 50.00, null, 0.84032975, 42.02, 1812.98, 1.99, 0.00, null,
+                -1.99, 1000.00);
+        checkInst(model, 164, 164, LocalDate.of(2019, 6, 14), 36, 164, 50.00, 50.00, null, 0.83943340, 41.97, 1764.92, 1.94, 0.00, null,
+                -1.94, 1000.00);
+        checkInst(model, 165, 165, LocalDate.of(2019, 6, 15), 35, 165, 50.00, 50.00, null, 0.83853799, 41.93, 1716.80, 1.88, 0.00, null,
+                -1.88, 1000.00);
+        checkInst(model, 166, 166, LocalDate.of(2019, 6, 16), 34, 166, 50.00, 50.00, null, 0.83764354, 41.88, 1668.64, 1.83, 0.00, null,
+                -1.83, 1000.00);
+        checkInst(model, 167, 167, LocalDate.of(2019, 6, 17), 33, 167, 50.00, 50.00, null, 0.83675005, 41.84, 1620.42, 1.78, 0.00, null,
+                -1.78, 1000.00);
+        checkInst(model, 168, 168, LocalDate.of(2019, 6, 18), 32, 168, 50.00, 50.00, null, 0.83585751, 41.79, 1572.15, 1.73, 0.00, null,
+                -1.73, 1000.00);
+        checkInst(model, 169, 169, LocalDate.of(2019, 6, 19), 31, 169, 50.00, 50.00, null, 0.83496592, 41.75, 1523.83, 1.68, 0.00, null,
+                -1.68, 1000.00);
+        checkInst(model, 170, 170, LocalDate.of(2019, 6, 20), 30, 170, 50.00, 50.00, null, 0.83407528, 41.70, 1475.45, 1.63, 0.00, null,
+                -1.63, 1000.00);
+        checkInst(model, 171, 171, LocalDate.of(2019, 6, 21), 29, 171, 50.00, 50.00, null, 0.83318560, 41.66, 1427.03, 1.58, 0.00, null,
+                -1.58, 1000.00);
+        checkInst(model, 172, 172, LocalDate.of(2019, 6, 22), 28, 172, 50.00, 50.00, null, 0.83229686, 41.61, 1378.55, 1.52, 0.00, null,
+                -1.52, 1000.00);
+        checkInst(model, 173, 173, LocalDate.of(2019, 6, 23), 27, 173, 50.00, 50.00, null, 0.83140907, 41.57, 1330.02, 1.47, 0.00, null,
+                -1.47, 1000.00);
+        checkInst(model, 174, 174, LocalDate.of(2019, 6, 24), 26, 174, 50.00, 50.00, null, 0.83052222, 41.53, 1281.45, 1.42, 0.00, null,
+                -1.42, 1000.00);
+        checkInst(model, 175, 175, LocalDate.of(2019, 6, 25), 25, 175, 50.00, 50.00, null, 0.82963633, 41.48, 1232.81, 1.37, 0.00, null,
+                -1.37, 1000.00);
+        checkInst(model, 176, 176, LocalDate.of(2019, 6, 26), 24, 176, 50.00, 50.00, null, 0.82875137, 41.44, 1184.13, 1.32, 0.00, null,
+                -1.32, 1000.00);
+        checkInst(model, 177, 177, LocalDate.of(2019, 6, 27), 23, 177, 50.00, 50.00, null, 0.82786736, 41.39, 1135.39, 1.26, 0.00, null,
+                -1.26, 1000.00);
+        checkInst(model, 178, 178, LocalDate.of(2019, 6, 28), 22, 178, 50.00, 50.00, null, 0.82698430, 41.35, 1086.61, 1.21, 0.00, null,
+                -1.21, 1000.00);
+        checkInst(model, 179, 179, LocalDate.of(2019, 6, 29), 21, 179, 50.00, 50.00, null, 0.82610217, 41.31, 1037.77, 1.16, 0.00, null,
+                -1.16, 1000.00);
+        checkInst(model, 180, 180, LocalDate.of(2019, 6, 30), 20, 180, 50.00, 50.00, null, 0.82522099, 41.26, 988.88, 1.11, 0.00, null,
+                -1.11, 1000.00);
+        checkInst(model, 181, 181, LocalDate.of(2019, 7, 1), 19, 181, 50.00, 50.00, null, 0.82434075, 41.22, 939.93, 1.06, 0.00, null,
+                -1.06, 1000.00);
+        checkInst(model, 182, 182, LocalDate.of(2019, 7, 2), 18, 182, 50.00, 50.00, null, 0.82346144, 41.17, 890.93, 1.00, 0.00, null,
+                -1.00, 1000.00);
+        checkInst(model, 183, 183, LocalDate.of(2019, 7, 3), 17, 183, 50.00, 50.00, null, 0.82258308, 41.13, 841.89, 0.95, 0.00, null,
+                -0.95, 1000.00);
+        checkInst(model, 184, 184, LocalDate.of(2019, 7, 4), 16, 184, 50.00, 50.00, null, 0.82170565, 41.09, 792.79, 0.90, 0.00, null,
+                -0.90, 1000.00);
+        checkInst(model, 185, 185, LocalDate.of(2019, 7, 5), 15, 185, 50.00, 50.00, null, 0.82082916, 41.04, 743.63, 0.85, 0.00, null,
+                -0.85, 1000.00);
+        checkInst(model, 186, 186, LocalDate.of(2019, 7, 6), 14, 186, 50.00, 50.00, null, 0.81995360, 41.00, 694.43, 0.79, 0.00, null,
+                -0.79, 1000.00);
+        checkInst(model, 187, 187, LocalDate.of(2019, 7, 7), 13, 187, 50.00, 50.00, null, 0.81907897, 40.95, 645.17, 0.74, 0.00, null,
+                -0.74, 1000.00);
+        checkInst(model, 188, 188, LocalDate.of(2019, 7, 8), 12, 188, 50.00, 50.00, null, 0.81820528, 40.91, 595.86, 0.69, 0.00, null,
+                -0.69, 1000.00);
+        checkInst(model, 189, 189, LocalDate.of(2019, 7, 9), 11, 189, 50.00, 50.00, null, 0.81733252, 40.87, 546.49, 0.64, 0.00, null,
+                -0.64, 1000.00);
+        checkInst(model, 190, 190, LocalDate.of(2019, 7, 10), 10, 190, 50.00, 50.00, null, 0.81646069, 40.82, 497.08, 0.58, 0.00, null,
+                -0.58, 1000.00);
+        checkInst(model, 191, 191, LocalDate.of(2019, 7, 11), 9, 191, 50.00, 50.00, null, 0.81558979, 40.78, 447.61, 0.53, 0.00, null,
+                -0.53, 1000.00);
+        checkInst(model, 192, 192, LocalDate.of(2019, 7, 12), 8, 192, 50.00, 50.00, null, 0.81471983, 40.74, 398.08, 0.48, 0.00, null,
+                -0.48, 1000.00);
+        checkInst(model, 193, 193, LocalDate.of(2019, 7, 13), 7, 193, 50.00, 50.00, null, 0.81385078, 40.69, 348.51, 0.43, 0.00, null,
+                -0.43, 1000.00);
+        checkInst(model, 194, 194, LocalDate.of(2019, 7, 14), 6, 194, 50.00, 50.00, null, 0.81298267, 40.65, 298.88, 0.37, 0.00, null,
+                -0.37, 1000.00);
+        checkInst(model, 195, 195, LocalDate.of(2019, 7, 15), 5, 195, 50.00, 50.00, null, 0.81211548, 40.61, 249.20, 0.32, 0.00, null,
+                -0.32, 1000.00);
+        checkInst(model, 196, 196, LocalDate.of(2019, 7, 16), 4, 196, 50.00, 50.00, null, 0.81124922, 40.56, 199.47, 0.27, 0.00, null,
+                -0.27, 1000.00);
+        checkInst(model, 197, 197, LocalDate.of(2019, 7, 17), 3, 197, 50.00, 50.00, null, 0.81038388, 40.52, 149.68, 0.21, 0.00, null,
+                -0.21, 1000.00);
+        checkInst(model, 198, 198, LocalDate.of(2019, 7, 18), 2, 198, 50.00, 50.00, null, 0.80951946, 40.48, 99.84, 0.16, 0.00, null, -0.16,
+                1000.00);
+        checkInst(model, 199, 199, LocalDate.of(2019, 7, 19), 1, 199, 50.00, 50.00, null, 0.80865597, 40.43, 49.95, 0.11, 0.00, null, -0.11,
+                1000.00);
+        checkInst(model, 200, 200, LocalDate.of(2019, 7, 20), 0, 200, 50.00, 50.00, null, 0.80779339, 40.39, 0.00, 0.05, 0.00, null, -0.05,
+                1000.00);
+    }
+
+    @Test
+    void testOnTimePayment_term200_originationFee1000_netDisbursement9000_pay50_50() {
+        final ProjectedAmortizationScheduleModel model = generateModel();
+
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), new BigDecimal("50"));
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(2), new BigDecimal("50"));
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 202, 0, -9000.00, null, null, 1.00000000, -9000.00, 9000.00, null, null, null,
+                null, 1000.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 201, 0, 50.00, 50.00, 50.00, 1.00000000, 50.00, 8959.61, 9.61, 19.18, 9.61, 0.00,
+                990.39);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 200, 0, 50.00, 50.00, 50.00, 1.00000000, 50.00, 8919.18, 9.57, 9.57, 9.57, 0.00,
+                980.82);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 199, 1, 50.00, 50.00, null, 0.99893332, 49.95, 8878.70, 9.52, 0.00, null, -9.52,
+                980.82);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 198, 2, 50.00, 50.00, null, 0.99786779, 49.89, 8838.18, 9.48, 0.00, null, -9.48,
+                980.82);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 197, 3, 50.00, 50.00, null, 0.99680339, 49.84, 8797.62, 9.44, 0.00, null, -9.44,
+                980.82);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 196, 4, 50.00, 50.00, null, 0.99574012, 49.79, 8757.01, 9.39, 0.00, null, -9.39,
+                980.82);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 195, 5, 50.00, 50.00, null, 0.99467799, 49.73, 8716.36, 9.35, 0.00, null, -9.35,
+                980.82);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 194, 6, 50.00, 50.00, null, 0.99361699, 49.68, 8675.67, 9.31, 0.00, null, -9.31,
+                980.82);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 193, 7, 50.00, 50.00, null, 0.99255712, 49.63, 8634.94, 9.26, 0.00, null, -9.26,
+                980.82);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 192, 8, 50.00, 50.00, null, 0.99149839, 49.57, 8594.16, 9.22, 0.00, null, -9.22,
+                980.82);
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 191, 9, 50.00, 50.00, null, 0.99044078, 49.52, 8553.33, 9.18, 0.00, null, -9.18,
+                980.82);
+        checkInst(model, 12, 12, LocalDate.of(2019, 1, 13), 190, 10, 50.00, 50.00, null, 0.98938430, 49.47, 8512.47, 9.13, 0.00, null,
+                -9.13, 980.82);
+        checkInst(model, 13, 13, LocalDate.of(2019, 1, 14), 189, 11, 50.00, 50.00, null, 0.98832895, 49.42, 8471.56, 9.09, 0.00, null,
+                -9.09, 980.82);
+        checkInst(model, 14, 14, LocalDate.of(2019, 1, 15), 188, 12, 50.00, 50.00, null, 0.98727472, 49.36, 8430.60, 9.05, 0.00, null,
+                -9.05, 980.82);
+        checkInst(model, 15, 15, LocalDate.of(2019, 1, 16), 187, 13, 50.00, 50.00, null, 0.98622162, 49.31, 8389.61, 9.00, 0.00, null,
+                -9.00, 980.82);
+        checkInst(model, 16, 16, LocalDate.of(2019, 1, 17), 186, 14, 50.00, 50.00, null, 0.98516964, 49.26, 8348.56, 8.96, 0.00, null,
+                -8.96, 980.82);
+        checkInst(model, 17, 17, LocalDate.of(2019, 1, 18), 185, 15, 50.00, 50.00, null, 0.98411879, 49.21, 8307.48, 8.91, 0.00, null,
+                -8.91, 980.82);
+        checkInst(model, 18, 18, LocalDate.of(2019, 1, 19), 184, 16, 50.00, 50.00, null, 0.98306905, 49.15, 8266.35, 8.87, 0.00, null,
+                -8.87, 980.82);
+        checkInst(model, 19, 19, LocalDate.of(2019, 1, 20), 183, 17, 50.00, 50.00, null, 0.98202044, 49.10, 8225.18, 8.83, 0.00, null,
+                -8.83, 980.82);
+        checkInst(model, 20, 20, LocalDate.of(2019, 1, 21), 182, 18, 50.00, 50.00, null, 0.98097294, 49.05, 8183.96, 8.78, 0.00, null,
+                -8.78, 980.82);
+        checkInst(model, 21, 21, LocalDate.of(2019, 1, 22), 181, 19, 50.00, 50.00, null, 0.97992656, 49.00, 8142.70, 8.74, 0.00, null,
+                -8.74, 980.82);
+        checkInst(model, 22, 22, LocalDate.of(2019, 1, 23), 180, 20, 50.00, 50.00, null, 0.97888129, 48.94, 8101.39, 8.69, 0.00, null,
+                -8.69, 980.82);
+        checkInst(model, 23, 23, LocalDate.of(2019, 1, 24), 179, 21, 50.00, 50.00, null, 0.97783715, 48.89, 8060.04, 8.65, 0.00, null,
+                -8.65, 980.82);
+        checkInst(model, 24, 24, LocalDate.of(2019, 1, 25), 178, 22, 50.00, 50.00, null, 0.97679411, 48.84, 8018.65, 8.61, 0.00, null,
+                -8.61, 980.82);
+        checkInst(model, 25, 25, LocalDate.of(2019, 1, 26), 177, 23, 50.00, 50.00, null, 0.97575219, 48.79, 7977.21, 8.56, 0.00, null,
+                -8.56, 980.82);
+        checkInst(model, 26, 26, LocalDate.of(2019, 1, 27), 176, 24, 50.00, 50.00, null, 0.97471138, 48.74, 7935.73, 8.52, 0.00, null,
+                -8.52, 980.82);
+        checkInst(model, 27, 27, LocalDate.of(2019, 1, 28), 175, 25, 50.00, 50.00, null, 0.97367168, 48.68, 7894.21, 8.47, 0.00, null,
+                -8.47, 980.82);
+        checkInst(model, 28, 28, LocalDate.of(2019, 1, 29), 174, 26, 50.00, 50.00, null, 0.97263309, 48.63, 7852.63, 8.43, 0.00, null,
+                -8.43, 980.82);
+        checkInst(model, 29, 29, LocalDate.of(2019, 1, 30), 173, 27, 50.00, 50.00, null, 0.97159560, 48.58, 7811.02, 8.39, 0.00, null,
+                -8.39, 980.82);
+        checkInst(model, 30, 30, LocalDate.of(2019, 1, 31), 172, 28, 50.00, 50.00, null, 0.97055922, 48.53, 7769.36, 8.34, 0.00, null,
+                -8.34, 980.82);
+        checkInst(model, 31, 31, LocalDate.of(2019, 2, 1), 171, 29, 50.00, 50.00, null, 0.96952395, 48.48, 7727.66, 8.30, 0.00, null, -8.30,
+                980.82);
+        checkInst(model, 32, 32, LocalDate.of(2019, 2, 2), 170, 30, 50.00, 50.00, null, 0.96848979, 48.42, 7685.91, 8.25, 0.00, null, -8.25,
+                980.82);
+        checkInst(model, 33, 33, LocalDate.of(2019, 2, 3), 169, 31, 50.00, 50.00, null, 0.96745672, 48.37, 7644.12, 8.21, 0.00, null, -8.21,
+                980.82);
+        checkInst(model, 34, 34, LocalDate.of(2019, 2, 4), 168, 32, 50.00, 50.00, null, 0.96642476, 48.32, 7602.28, 8.16, 0.00, null, -8.16,
+                980.82);
+        checkInst(model, 35, 35, LocalDate.of(2019, 2, 5), 167, 33, 50.00, 50.00, null, 0.96539390, 48.27, 7560.40, 8.12, 0.00, null, -8.12,
+                980.82);
+        checkInst(model, 36, 36, LocalDate.of(2019, 2, 6), 166, 34, 50.00, 50.00, null, 0.96436413, 48.22, 7518.47, 8.07, 0.00, null, -8.07,
+                980.82);
+        checkInst(model, 37, 37, LocalDate.of(2019, 2, 7), 165, 35, 50.00, 50.00, null, 0.96333547, 48.17, 7476.50, 8.03, 0.00, null, -8.03,
+                980.82);
+        checkInst(model, 38, 38, LocalDate.of(2019, 2, 8), 164, 36, 50.00, 50.00, null, 0.96230790, 48.12, 7434.48, 7.98, 0.00, null, -7.98,
+                980.82);
+        checkInst(model, 39, 39, LocalDate.of(2019, 2, 9), 163, 37, 50.00, 50.00, null, 0.96128143, 48.06, 7392.42, 7.94, 0.00, null, -7.94,
+                980.82);
+        checkInst(model, 40, 40, LocalDate.of(2019, 2, 10), 162, 38, 50.00, 50.00, null, 0.96025606, 48.01, 7350.31, 7.89, 0.00, null,
+                -7.89, 980.82);
+        checkInst(model, 41, 41, LocalDate.of(2019, 2, 11), 161, 39, 50.00, 50.00, null, 0.95923178, 47.96, 7308.16, 7.85, 0.00, null,
+                -7.85, 980.82);
+        checkInst(model, 42, 42, LocalDate.of(2019, 2, 12), 160, 40, 50.00, 50.00, null, 0.95820859, 47.91, 7265.97, 7.80, 0.00, null,
+                -7.80, 980.82);
+        checkInst(model, 43, 43, LocalDate.of(2019, 2, 13), 159, 41, 50.00, 50.00, null, 0.95718649, 47.86, 7223.72, 7.76, 0.00, null,
+                -7.76, 980.82);
+        checkInst(model, 44, 44, LocalDate.of(2019, 2, 14), 158, 42, 50.00, 50.00, null, 0.95616548, 47.81, 7181.44, 7.71, 0.00, null,
+                -7.71, 980.82);
+        checkInst(model, 45, 45, LocalDate.of(2019, 2, 15), 157, 43, 50.00, 50.00, null, 0.95514557, 47.76, 7139.11, 7.67, 0.00, null,
+                -7.67, 980.82);
+        checkInst(model, 46, 46, LocalDate.of(2019, 2, 16), 156, 44, 50.00, 50.00, null, 0.95412674, 47.71, 7096.73, 7.62, 0.00, null,
+                -7.62, 980.82);
+        checkInst(model, 47, 47, LocalDate.of(2019, 2, 17), 155, 45, 50.00, 50.00, null, 0.95310899, 47.66, 7054.31, 7.58, 0.00, null,
+                -7.58, 980.82);
+        checkInst(model, 48, 48, LocalDate.of(2019, 2, 18), 154, 46, 50.00, 50.00, null, 0.95209233, 47.60, 7011.84, 7.53, 0.00, null,
+                -7.53, 980.82);
+        checkInst(model, 49, 49, LocalDate.of(2019, 2, 19), 153, 47, 50.00, 50.00, null, 0.95107676, 47.55, 6969.33, 7.49, 0.00, null,
+                -7.49, 980.82);
+        checkInst(model, 50, 50, LocalDate.of(2019, 2, 20), 152, 48, 50.00, 50.00, null, 0.95006227, 47.50, 6926.77, 7.44, 0.00, null,
+                -7.44, 980.82);
+        checkInst(model, 51, 51, LocalDate.of(2019, 2, 21), 151, 49, 50.00, 50.00, null, 0.94904886, 47.45, 6884.17, 7.40, 0.00, null,
+                -7.40, 980.82);
+        checkInst(model, 52, 52, LocalDate.of(2019, 2, 22), 150, 50, 50.00, 50.00, null, 0.94803653, 47.40, 6841.52, 7.35, 0.00, null,
+                -7.35, 980.82);
+        checkInst(model, 53, 53, LocalDate.of(2019, 2, 23), 149, 51, 50.00, 50.00, null, 0.94702529, 47.35, 6798.82, 7.31, 0.00, null,
+                -7.31, 980.82);
+        checkInst(model, 54, 54, LocalDate.of(2019, 2, 24), 148, 52, 50.00, 50.00, null, 0.94601512, 47.30, 6756.08, 7.26, 0.00, null,
+                -7.26, 980.82);
+        checkInst(model, 55, 55, LocalDate.of(2019, 2, 25), 147, 53, 50.00, 50.00, null, 0.94500603, 47.25, 6713.30, 7.21, 0.00, null,
+                -7.21, 980.82);
+        checkInst(model, 56, 56, LocalDate.of(2019, 2, 26), 146, 54, 50.00, 50.00, null, 0.94399801, 47.20, 6670.47, 7.17, 0.00, null,
+                -7.17, 980.82);
+        checkInst(model, 57, 57, LocalDate.of(2019, 2, 27), 145, 55, 50.00, 50.00, null, 0.94299107, 47.15, 6627.59, 7.12, 0.00, null,
+                -7.12, 980.82);
+        checkInst(model, 58, 58, LocalDate.of(2019, 2, 28), 144, 56, 50.00, 50.00, null, 0.94198521, 47.10, 6584.67, 7.08, 0.00, null,
+                -7.08, 980.82);
+        checkInst(model, 59, 59, LocalDate.of(2019, 3, 1), 143, 57, 50.00, 50.00, null, 0.94098042, 47.05, 6541.70, 7.03, 0.00, null, -7.03,
+                980.82);
+        checkInst(model, 60, 60, LocalDate.of(2019, 3, 2), 142, 58, 50.00, 50.00, null, 0.93997669, 47.00, 6498.68, 6.99, 0.00, null, -6.99,
+                980.82);
+        checkInst(model, 61, 61, LocalDate.of(2019, 3, 3), 141, 59, 50.00, 50.00, null, 0.93897404, 46.95, 6455.62, 6.94, 0.00, null, -6.94,
+                980.82);
+        checkInst(model, 62, 62, LocalDate.of(2019, 3, 4), 140, 60, 50.00, 50.00, null, 0.93797246, 46.90, 6412.51, 6.89, 0.00, null, -6.89,
+                980.82);
+        checkInst(model, 63, 63, LocalDate.of(2019, 3, 5), 139, 61, 50.00, 50.00, null, 0.93697195, 46.85, 6369.36, 6.85, 0.00, null, -6.85,
+                980.82);
+        checkInst(model, 64, 64, LocalDate.of(2019, 3, 6), 138, 62, 50.00, 50.00, null, 0.93597251, 46.80, 6326.16, 6.80, 0.00, null, -6.80,
+                980.82);
+        checkInst(model, 65, 65, LocalDate.of(2019, 3, 7), 137, 63, 50.00, 50.00, null, 0.93497413, 46.75, 6282.92, 6.76, 0.00, null, -6.76,
+                980.82);
+        checkInst(model, 66, 66, LocalDate.of(2019, 3, 8), 136, 64, 50.00, 50.00, null, 0.93397681, 46.70, 6239.63, 6.71, 0.00, null, -6.71,
+                980.82);
+        checkInst(model, 67, 67, LocalDate.of(2019, 3, 9), 135, 65, 50.00, 50.00, null, 0.93298056, 46.65, 6196.29, 6.66, 0.00, null, -6.66,
+                980.82);
+        checkInst(model, 68, 68, LocalDate.of(2019, 3, 10), 134, 66, 50.00, 50.00, null, 0.93198538, 46.60, 6152.91, 6.62, 0.00, null,
+                -6.62, 980.82);
+        checkInst(model, 69, 69, LocalDate.of(2019, 3, 11), 133, 67, 50.00, 50.00, null, 0.93099125, 46.55, 6109.48, 6.57, 0.00, null,
+                -6.57, 980.82);
+        checkInst(model, 70, 70, LocalDate.of(2019, 3, 12), 132, 68, 50.00, 50.00, null, 0.92999818, 46.50, 6066.00, 6.52, 0.00, null,
+                -6.52, 980.82);
+        checkInst(model, 71, 71, LocalDate.of(2019, 3, 13), 131, 69, 50.00, 50.00, null, 0.92900618, 46.45, 6022.48, 6.48, 0.00, null,
+                -6.48, 980.82);
+        checkInst(model, 72, 72, LocalDate.of(2019, 3, 14), 130, 70, 50.00, 50.00, null, 0.92801523, 46.40, 5978.91, 6.43, 0.00, null,
+                -6.43, 980.82);
+        checkInst(model, 73, 73, LocalDate.of(2019, 3, 15), 129, 71, 50.00, 50.00, null, 0.92702534, 46.35, 5935.29, 6.38, 0.00, null,
+                -6.38, 980.82);
+        checkInst(model, 74, 74, LocalDate.of(2019, 3, 16), 128, 72, 50.00, 50.00, null, 0.92603650, 46.30, 5891.63, 6.34, 0.00, null,
+                -6.34, 980.82);
+        checkInst(model, 75, 75, LocalDate.of(2019, 3, 17), 127, 73, 50.00, 50.00, null, 0.92504872, 46.25, 5847.92, 6.29, 0.00, null,
+                -6.29, 980.82);
+        checkInst(model, 76, 76, LocalDate.of(2019, 3, 18), 126, 74, 50.00, 50.00, null, 0.92406200, 46.20, 5804.17, 6.24, 0.00, null,
+                -6.24, 980.82);
+        checkInst(model, 77, 77, LocalDate.of(2019, 3, 19), 125, 75, 50.00, 50.00, null, 0.92307632, 46.15, 5760.36, 6.20, 0.00, null,
+                -6.20, 980.82);
+        checkInst(model, 78, 78, LocalDate.of(2019, 3, 20), 124, 76, 50.00, 50.00, null, 0.92209170, 46.10, 5716.52, 6.15, 0.00, null,
+                -6.15, 980.82);
+        checkInst(model, 79, 79, LocalDate.of(2019, 3, 21), 123, 77, 50.00, 50.00, null, 0.92110813, 46.06, 5672.62, 6.10, 0.00, null,
+                -6.10, 980.82);
+        checkInst(model, 80, 80, LocalDate.of(2019, 3, 22), 122, 78, 50.00, 50.00, null, 0.92012560, 46.01, 5628.68, 6.06, 0.00, null,
+                -6.06, 980.82);
+        checkInst(model, 81, 81, LocalDate.of(2019, 3, 23), 121, 79, 50.00, 50.00, null, 0.91914413, 45.96, 5584.69, 6.01, 0.00, null,
+                -6.01, 980.82);
+        checkInst(model, 82, 82, LocalDate.of(2019, 3, 24), 120, 80, 50.00, 50.00, null, 0.91816370, 45.91, 5540.65, 5.96, 0.00, null,
+                -5.96, 980.82);
+        checkInst(model, 83, 83, LocalDate.of(2019, 3, 25), 119, 81, 50.00, 50.00, null, 0.91718432, 45.86, 5496.57, 5.92, 0.00, null,
+                -5.92, 980.82);
+        checkInst(model, 84, 84, LocalDate.of(2019, 3, 26), 118, 82, 50.00, 50.00, null, 0.91620598, 45.81, 5452.44, 5.87, 0.00, null,
+                -5.87, 980.82);
+        checkInst(model, 85, 85, LocalDate.of(2019, 3, 27), 117, 83, 50.00, 50.00, null, 0.91522868, 45.76, 5408.26, 5.82, 0.00, null,
+                -5.82, 980.82);
+        checkInst(model, 86, 86, LocalDate.of(2019, 3, 28), 116, 84, 50.00, 50.00, null, 0.91425243, 45.71, 5364.03, 5.78, 0.00, null,
+                -5.78, 980.82);
+        checkInst(model, 87, 87, LocalDate.of(2019, 3, 29), 115, 85, 50.00, 50.00, null, 0.91327722, 45.66, 5319.76, 5.73, 0.00, null,
+                -5.73, 980.82);
+        checkInst(model, 88, 88, LocalDate.of(2019, 3, 30), 114, 86, 50.00, 50.00, null, 0.91230305, 45.62, 5275.44, 5.68, 0.00, null,
+                -5.68, 980.82);
+        checkInst(model, 89, 89, LocalDate.of(2019, 3, 31), 113, 87, 50.00, 50.00, null, 0.91132992, 45.57, 5231.08, 5.63, 0.00, null,
+                -5.63, 980.82);
+        checkInst(model, 90, 90, LocalDate.of(2019, 4, 1), 112, 88, 50.00, 50.00, null, 0.91035783, 45.52, 5186.66, 5.59, 0.00, null, -5.59,
+                980.82);
+        checkInst(model, 91, 91, LocalDate.of(2019, 4, 2), 111, 89, 50.00, 50.00, null, 0.90938677, 45.47, 5142.20, 5.54, 0.00, null, -5.54,
+                980.82);
+        checkInst(model, 92, 92, LocalDate.of(2019, 4, 3), 110, 90, 50.00, 50.00, null, 0.90841675, 45.42, 5097.69, 5.49, 0.00, null, -5.49,
+                980.82);
+        checkInst(model, 93, 93, LocalDate.of(2019, 4, 4), 109, 91, 50.00, 50.00, null, 0.90744776, 45.37, 5053.13, 5.44, 0.00, null, -5.44,
+                980.82);
+        checkInst(model, 94, 94, LocalDate.of(2019, 4, 5), 108, 92, 50.00, 50.00, null, 0.90647981, 45.32, 5008.53, 5.40, 0.00, null, -5.40,
+                980.82);
+        checkInst(model, 95, 95, LocalDate.of(2019, 4, 6), 107, 93, 50.00, 50.00, null, 0.90551289, 45.28, 4963.88, 5.35, 0.00, null, -5.35,
+                980.82);
+        checkInst(model, 96, 96, LocalDate.of(2019, 4, 7), 106, 94, 50.00, 50.00, null, 0.90454700, 45.23, 4919.18, 5.30, 0.00, null, -5.30,
+                980.82);
+        checkInst(model, 97, 97, LocalDate.of(2019, 4, 8), 105, 95, 50.00, 50.00, null, 0.90358215, 45.18, 4874.43, 5.25, 0.00, null, -5.25,
+                980.82);
+        checkInst(model, 98, 98, LocalDate.of(2019, 4, 9), 104, 96, 50.00, 50.00, null, 0.90261832, 45.13, 4829.64, 5.20, 0.00, null, -5.20,
+                980.82);
+        checkInst(model, 99, 99, LocalDate.of(2019, 4, 10), 103, 97, 50.00, 50.00, null, 0.90165552, 45.08, 4784.79, 5.16, 0.00, null,
+                -5.16, 980.82);
+        checkInst(model, 100, 100, LocalDate.of(2019, 4, 11), 102, 98, 50.00, 50.00, null, 0.90069374, 45.03, 4739.90, 5.11, 0.00, null,
+                -5.11, 980.82);
+        checkInst(model, 101, 101, LocalDate.of(2019, 4, 12), 101, 99, 50.00, 50.00, null, 0.89973299, 44.99, 4694.96, 5.06, 0.00, null,
+                -5.06, 980.82);
+        checkInst(model, 102, 102, LocalDate.of(2019, 4, 13), 100, 100, 50.00, 50.00, null, 0.89877327, 44.94, 4649.98, 5.01, 0.00, null,
+                -5.01, 980.82);
+        checkInst(model, 103, 103, LocalDate.of(2019, 4, 14), 99, 101, 50.00, 50.00, null, 0.89781457, 44.89, 4604.94, 4.97, 0.00, null,
+                -4.97, 980.82);
+        checkInst(model, 104, 104, LocalDate.of(2019, 4, 15), 98, 102, 50.00, 50.00, null, 0.89685689, 44.84, 4559.86, 4.92, 0.00, null,
+                -4.92, 980.82);
+        checkInst(model, 105, 105, LocalDate.of(2019, 4, 16), 97, 103, 50.00, 50.00, null, 0.89590024, 44.80, 4514.73, 4.87, 0.00, null,
+                -4.87, 980.82);
+        checkInst(model, 106, 106, LocalDate.of(2019, 4, 17), 96, 104, 50.00, 50.00, null, 0.89494460, 44.75, 4469.55, 4.82, 0.00, null,
+                -4.82, 980.82);
+        checkInst(model, 107, 107, LocalDate.of(2019, 4, 18), 95, 105, 50.00, 50.00, null, 0.89398999, 44.70, 4424.32, 4.77, 0.00, null,
+                -4.77, 980.82);
+        checkInst(model, 108, 108, LocalDate.of(2019, 4, 19), 94, 106, 50.00, 50.00, null, 0.89303639, 44.65, 4379.05, 4.72, 0.00, null,
+                -4.72, 980.82);
+        checkInst(model, 109, 109, LocalDate.of(2019, 4, 20), 93, 107, 50.00, 50.00, null, 0.89208381, 44.60, 4333.72, 4.68, 0.00, null,
+                -4.68, 980.82);
+        checkInst(model, 110, 110, LocalDate.of(2019, 4, 21), 92, 108, 50.00, 50.00, null, 0.89113225, 44.56, 4288.35, 4.63, 0.00, null,
+                -4.63, 980.82);
+        checkInst(model, 111, 111, LocalDate.of(2019, 4, 22), 91, 109, 50.00, 50.00, null, 0.89018170, 44.51, 4242.93, 4.58, 0.00, null,
+                -4.58, 980.82);
+        checkInst(model, 112, 112, LocalDate.of(2019, 4, 23), 90, 110, 50.00, 50.00, null, 0.88923216, 44.46, 4197.46, 4.53, 0.00, null,
+                -4.53, 980.82);
+        checkInst(model, 113, 113, LocalDate.of(2019, 4, 24), 89, 111, 50.00, 50.00, null, 0.88828364, 44.41, 4151.94, 4.48, 0.00, null,
+                -4.48, 980.82);
+        checkInst(model, 114, 114, LocalDate.of(2019, 4, 25), 88, 112, 50.00, 50.00, null, 0.88733613, 44.37, 4106.38, 4.43, 0.00, null,
+                -4.43, 980.82);
+        checkInst(model, 115, 115, LocalDate.of(2019, 4, 26), 87, 113, 50.00, 50.00, null, 0.88638963, 44.32, 4060.76, 4.38, 0.00, null,
+                -4.38, 980.82);
+        checkInst(model, 116, 116, LocalDate.of(2019, 4, 27), 86, 114, 50.00, 50.00, null, 0.88544414, 44.27, 4015.10, 4.34, 0.00, null,
+                -4.34, 980.82);
+        checkInst(model, 117, 117, LocalDate.of(2019, 4, 28), 85, 115, 50.00, 50.00, null, 0.88449966, 44.22, 3969.38, 4.29, 0.00, null,
+                -4.29, 980.82);
+        checkInst(model, 118, 118, LocalDate.of(2019, 4, 29), 84, 116, 50.00, 50.00, null, 0.88355619, 44.18, 3923.62, 4.24, 0.00, null,
+                -4.24, 980.82);
+        checkInst(model, 119, 119, LocalDate.of(2019, 4, 30), 83, 117, 50.00, 50.00, null, 0.88261372, 44.13, 3877.81, 4.19, 0.00, null,
+                -4.19, 980.82);
+        checkInst(model, 120, 120, LocalDate.of(2019, 5, 1), 82, 118, 50.00, 50.00, null, 0.88167226, 44.08, 3831.95, 4.14, 0.00, null,
+                -4.14, 980.82);
+        checkInst(model, 121, 121, LocalDate.of(2019, 5, 2), 81, 119, 50.00, 50.00, null, 0.88073180, 44.04, 3786.04, 4.09, 0.00, null,
+                -4.09, 980.82);
+        checkInst(model, 122, 122, LocalDate.of(2019, 5, 3), 80, 120, 50.00, 50.00, null, 0.87979234, 43.99, 3740.09, 4.04, 0.00, null,
+                -4.04, 980.82);
+        checkInst(model, 123, 123, LocalDate.of(2019, 5, 4), 79, 121, 50.00, 50.00, null, 0.87885389, 43.94, 3694.08, 3.99, 0.00, null,
+                -3.99, 980.82);
+        checkInst(model, 124, 124, LocalDate.of(2019, 5, 5), 78, 122, 50.00, 50.00, null, 0.87791644, 43.90, 3648.03, 3.94, 0.00, null,
+                -3.94, 980.82);
+        checkInst(model, 125, 125, LocalDate.of(2019, 5, 6), 77, 123, 50.00, 50.00, null, 0.87697999, 43.85, 3601.92, 3.90, 0.00, null,
+                -3.90, 980.82);
+        checkInst(model, 126, 126, LocalDate.of(2019, 5, 7), 76, 124, 50.00, 50.00, null, 0.87604453, 43.80, 3555.77, 3.85, 0.00, null,
+                -3.85, 980.82);
+        checkInst(model, 127, 127, LocalDate.of(2019, 5, 8), 75, 125, 50.00, 50.00, null, 0.87511008, 43.76, 3509.56, 3.80, 0.00, null,
+                -3.80, 980.82);
+        checkInst(model, 128, 128, LocalDate.of(2019, 5, 9), 74, 126, 50.00, 50.00, null, 0.87417662, 43.71, 3463.31, 3.75, 0.00, null,
+                -3.75, 980.82);
+        checkInst(model, 129, 129, LocalDate.of(2019, 5, 10), 73, 127, 50.00, 50.00, null, 0.87324416, 43.66, 3417.01, 3.70, 0.00, null,
+                -3.70, 980.82);
+        checkInst(model, 130, 130, LocalDate.of(2019, 5, 11), 72, 128, 50.00, 50.00, null, 0.87231269, 43.62, 3370.66, 3.65, 0.00, null,
+                -3.65, 980.82);
+        checkInst(model, 131, 131, LocalDate.of(2019, 5, 12), 71, 129, 50.00, 50.00, null, 0.87138221, 43.57, 3324.26, 3.60, 0.00, null,
+                -3.60, 980.82);
+        checkInst(model, 132, 132, LocalDate.of(2019, 5, 13), 70, 130, 50.00, 50.00, null, 0.87045273, 43.52, 3277.81, 3.55, 0.00, null,
+                -3.55, 980.82);
+        checkInst(model, 133, 133, LocalDate.of(2019, 5, 14), 69, 131, 50.00, 50.00, null, 0.86952424, 43.48, 3231.31, 3.50, 0.00, null,
+                -3.50, 980.82);
+        checkInst(model, 134, 134, LocalDate.of(2019, 5, 15), 68, 132, 50.00, 50.00, null, 0.86859674, 43.43, 3184.76, 3.45, 0.00, null,
+                -3.45, 980.82);
+        checkInst(model, 135, 135, LocalDate.of(2019, 5, 16), 67, 133, 50.00, 50.00, null, 0.86767023, 43.38, 3138.16, 3.40, 0.00, null,
+                -3.40, 980.82);
+        checkInst(model, 136, 136, LocalDate.of(2019, 5, 17), 66, 134, 50.00, 50.00, null, 0.86674471, 43.34, 3091.51, 3.35, 0.00, null,
+                -3.35, 980.82);
+        checkInst(model, 137, 137, LocalDate.of(2019, 5, 18), 65, 135, 50.00, 50.00, null, 0.86582017, 43.29, 3044.81, 3.30, 0.00, null,
+                -3.30, 980.82);
+        checkInst(model, 138, 138, LocalDate.of(2019, 5, 19), 64, 136, 50.00, 50.00, null, 0.86489662, 43.24, 2998.06, 3.25, 0.00, null,
+                -3.25, 980.82);
+        checkInst(model, 139, 139, LocalDate.of(2019, 5, 20), 63, 137, 50.00, 50.00, null, 0.86397406, 43.20, 2951.26, 3.20, 0.00, null,
+                -3.20, 980.82);
+        checkInst(model, 140, 140, LocalDate.of(2019, 5, 21), 62, 138, 50.00, 50.00, null, 0.86305248, 43.15, 2904.42, 3.15, 0.00, null,
+                -3.15, 980.82);
+        checkInst(model, 141, 141, LocalDate.of(2019, 5, 22), 61, 139, 50.00, 50.00, null, 0.86213188, 43.11, 2857.52, 3.10, 0.00, null,
+                -3.10, 980.82);
+        checkInst(model, 142, 142, LocalDate.of(2019, 5, 23), 60, 140, 50.00, 50.00, null, 0.86121227, 43.06, 2810.57, 3.05, 0.00, null,
+                -3.05, 980.82);
+        checkInst(model, 143, 143, LocalDate.of(2019, 5, 24), 59, 141, 50.00, 50.00, null, 0.86029363, 43.01, 2763.57, 3.00, 0.00, null,
+                -3.00, 980.82);
+        checkInst(model, 144, 144, LocalDate.of(2019, 5, 25), 58, 142, 50.00, 50.00, null, 0.85937598, 42.97, 2716.52, 2.95, 0.00, null,
+                -2.95, 980.82);
+        checkInst(model, 145, 145, LocalDate.of(2019, 5, 26), 57, 143, 50.00, 50.00, null, 0.85845930, 42.92, 2669.42, 2.90, 0.00, null,
+                -2.90, 980.82);
+        checkInst(model, 146, 146, LocalDate.of(2019, 5, 27), 56, 144, 50.00, 50.00, null, 0.85754361, 42.88, 2622.27, 2.85, 0.00, null,
+                -2.85, 980.82);
+        checkInst(model, 147, 147, LocalDate.of(2019, 5, 28), 55, 145, 50.00, 50.00, null, 0.85662889, 42.83, 2575.07, 2.80, 0.00, null,
+                -2.80, 980.82);
+        checkInst(model, 148, 148, LocalDate.of(2019, 5, 29), 54, 146, 50.00, 50.00, null, 0.85571514, 42.79, 2527.82, 2.75, 0.00, null,
+                -2.75, 980.82);
+        checkInst(model, 149, 149, LocalDate.of(2019, 5, 30), 53, 147, 50.00, 50.00, null, 0.85480237, 42.74, 2480.52, 2.70, 0.00, null,
+                -2.70, 980.82);
+        checkInst(model, 150, 150, LocalDate.of(2019, 5, 31), 52, 148, 50.00, 50.00, null, 0.85389057, 42.69, 2433.17, 2.65, 0.00, null,
+                -2.65, 980.82);
+        checkInst(model, 151, 151, LocalDate.of(2019, 6, 1), 51, 149, 50.00, 50.00, null, 0.85297975, 42.65, 2385.77, 2.60, 0.00, null,
+                -2.60, 980.82);
+        checkInst(model, 152, 152, LocalDate.of(2019, 6, 2), 50, 150, 50.00, 50.00, null, 0.85206990, 42.60, 2338.31, 2.55, 0.00, null,
+                -2.55, 980.82);
+        checkInst(model, 153, 153, LocalDate.of(2019, 6, 3), 49, 151, 50.00, 50.00, null, 0.85116101, 42.56, 2290.81, 2.50, 0.00, null,
+                -2.50, 980.82);
+        checkInst(model, 154, 154, LocalDate.of(2019, 6, 4), 48, 152, 50.00, 50.00, null, 0.85025310, 42.51, 2243.26, 2.45, 0.00, null,
+                -2.45, 980.82);
+        checkInst(model, 155, 155, LocalDate.of(2019, 6, 5), 47, 153, 50.00, 50.00, null, 0.84934616, 42.47, 2195.65, 2.40, 0.00, null,
+                -2.40, 980.82);
+        checkInst(model, 156, 156, LocalDate.of(2019, 6, 6), 46, 154, 50.00, 50.00, null, 0.84844018, 42.42, 2148.00, 2.34, 0.00, null,
+                -2.34, 980.82);
+        checkInst(model, 157, 157, LocalDate.of(2019, 6, 7), 45, 155, 50.00, 50.00, null, 0.84753517, 42.38, 2100.29, 2.29, 0.00, null,
+                -2.29, 980.82);
+        checkInst(model, 158, 158, LocalDate.of(2019, 6, 8), 44, 156, 50.00, 50.00, null, 0.84663113, 42.33, 2052.53, 2.24, 0.00, null,
+                -2.24, 980.82);
+        checkInst(model, 159, 159, LocalDate.of(2019, 6, 9), 43, 157, 50.00, 50.00, null, 0.84572805, 42.29, 2004.73, 2.19, 0.00, null,
+                -2.19, 980.82);
+        checkInst(model, 160, 160, LocalDate.of(2019, 6, 10), 42, 158, 50.00, 50.00, null, 0.84482593, 42.24, 1956.87, 2.14, 0.00, null,
+                -2.14, 980.82);
+        checkInst(model, 161, 161, LocalDate.of(2019, 6, 11), 41, 159, 50.00, 50.00, null, 0.84392477, 42.20, 1908.96, 2.09, 0.00, null,
+                -2.09, 980.82);
+        checkInst(model, 162, 162, LocalDate.of(2019, 6, 12), 40, 160, 50.00, 50.00, null, 0.84302458, 42.15, 1860.99, 2.04, 0.00, null,
+                -2.04, 980.82);
+        checkInst(model, 163, 163, LocalDate.of(2019, 6, 13), 39, 161, 50.00, 50.00, null, 0.84212535, 42.11, 1812.98, 1.99, 0.00, null,
+                -1.99, 980.82);
+        checkInst(model, 164, 164, LocalDate.of(2019, 6, 14), 38, 162, 50.00, 50.00, null, 0.84122707, 42.06, 1764.92, 1.94, 0.00, null,
+                -1.94, 980.82);
+        checkInst(model, 165, 165, LocalDate.of(2019, 6, 15), 37, 163, 50.00, 50.00, null, 0.84032975, 42.02, 1716.80, 1.88, 0.00, null,
+                -1.88, 980.82);
+        checkInst(model, 166, 166, LocalDate.of(2019, 6, 16), 36, 164, 50.00, 50.00, null, 0.83943340, 41.97, 1668.64, 1.83, 0.00, null,
+                -1.83, 980.82);
+        checkInst(model, 167, 167, LocalDate.of(2019, 6, 17), 35, 165, 50.00, 50.00, null, 0.83853799, 41.93, 1620.42, 1.78, 0.00, null,
+                -1.78, 980.82);
+        checkInst(model, 168, 168, LocalDate.of(2019, 6, 18), 34, 166, 50.00, 50.00, null, 0.83764354, 41.88, 1572.15, 1.73, 0.00, null,
+                -1.73, 980.82);
+        checkInst(model, 169, 169, LocalDate.of(2019, 6, 19), 33, 167, 50.00, 50.00, null, 0.83675005, 41.84, 1523.83, 1.68, 0.00, null,
+                -1.68, 980.82);
+        checkInst(model, 170, 170, LocalDate.of(2019, 6, 20), 32, 168, 50.00, 50.00, null, 0.83585751, 41.79, 1475.45, 1.63, 0.00, null,
+                -1.63, 980.82);
+        checkInst(model, 171, 171, LocalDate.of(2019, 6, 21), 31, 169, 50.00, 50.00, null, 0.83496592, 41.75, 1427.03, 1.58, 0.00, null,
+                -1.58, 980.82);
+        checkInst(model, 172, 172, LocalDate.of(2019, 6, 22), 30, 170, 50.00, 50.00, null, 0.83407528, 41.70, 1378.55, 1.52, 0.00, null,
+                -1.52, 980.82);
+        checkInst(model, 173, 173, LocalDate.of(2019, 6, 23), 29, 171, 50.00, 50.00, null, 0.83318560, 41.66, 1330.02, 1.47, 0.00, null,
+                -1.47, 980.82);
+        checkInst(model, 174, 174, LocalDate.of(2019, 6, 24), 28, 172, 50.00, 50.00, null, 0.83229686, 41.61, 1281.45, 1.42, 0.00, null,
+                -1.42, 980.82);
+        checkInst(model, 175, 175, LocalDate.of(2019, 6, 25), 27, 173, 50.00, 50.00, null, 0.83140907, 41.57, 1232.81, 1.37, 0.00, null,
+                -1.37, 980.82);
+        checkInst(model, 176, 176, LocalDate.of(2019, 6, 26), 26, 174, 50.00, 50.00, null, 0.83052222, 41.53, 1184.13, 1.32, 0.00, null,
+                -1.32, 980.82);
+        checkInst(model, 177, 177, LocalDate.of(2019, 6, 27), 25, 175, 50.00, 50.00, null, 0.82963633, 41.48, 1135.39, 1.26, 0.00, null,
+                -1.26, 980.82);
+        checkInst(model, 178, 178, LocalDate.of(2019, 6, 28), 24, 176, 50.00, 50.00, null, 0.82875137, 41.44, 1086.61, 1.21, 0.00, null,
+                -1.21, 980.82);
+        checkInst(model, 179, 179, LocalDate.of(2019, 6, 29), 23, 177, 50.00, 50.00, null, 0.82786736, 41.39, 1037.77, 1.16, 0.00, null,
+                -1.16, 980.82);
+        checkInst(model, 180, 180, LocalDate.of(2019, 6, 30), 22, 178, 50.00, 50.00, null, 0.82698430, 41.35, 988.88, 1.11, 0.00, null,
+                -1.11, 980.82);
+        checkInst(model, 181, 181, LocalDate.of(2019, 7, 1), 21, 179, 50.00, 50.00, null, 0.82610217, 41.31, 939.93, 1.06, 0.00, null,
+                -1.06, 980.82);
+        checkInst(model, 182, 182, LocalDate.of(2019, 7, 2), 20, 180, 50.00, 50.00, null, 0.82522099, 41.26, 890.93, 1.00, 0.00, null,
+                -1.00, 980.82);
+        checkInst(model, 183, 183, LocalDate.of(2019, 7, 3), 19, 181, 50.00, 50.00, null, 0.82434075, 41.22, 841.89, 0.95, 0.00, null,
+                -0.95, 980.82);
+        checkInst(model, 184, 184, LocalDate.of(2019, 7, 4), 18, 182, 50.00, 50.00, null, 0.82346144, 41.17, 792.79, 0.90, 0.00, null,
+                -0.90, 980.82);
+        checkInst(model, 185, 185, LocalDate.of(2019, 7, 5), 17, 183, 50.00, 50.00, null, 0.82258308, 41.13, 743.63, 0.85, 0.00, null,
+                -0.85, 980.82);
+        checkInst(model, 186, 186, LocalDate.of(2019, 7, 6), 16, 184, 50.00, 50.00, null, 0.82170565, 41.09, 694.43, 0.79, 0.00, null,
+                -0.79, 980.82);
+        checkInst(model, 187, 187, LocalDate.of(2019, 7, 7), 15, 185, 50.00, 50.00, null, 0.82082916, 41.04, 645.17, 0.74, 0.00, null,
+                -0.74, 980.82);
+        checkInst(model, 188, 188, LocalDate.of(2019, 7, 8), 14, 186, 50.00, 50.00, null, 0.81995360, 41.00, 595.86, 0.69, 0.00, null,
+                -0.69, 980.82);
+        checkInst(model, 189, 189, LocalDate.of(2019, 7, 9), 13, 187, 50.00, 50.00, null, 0.81907897, 40.95, 546.49, 0.64, 0.00, null,
+                -0.64, 980.82);
+        checkInst(model, 190, 190, LocalDate.of(2019, 7, 10), 12, 188, 50.00, 50.00, null, 0.81820528, 40.91, 497.08, 0.58, 0.00, null,
+                -0.58, 980.82);
+        checkInst(model, 191, 191, LocalDate.of(2019, 7, 11), 11, 189, 50.00, 50.00, null, 0.81733252, 40.87, 447.61, 0.53, 0.00, null,
+                -0.53, 980.82);
+        checkInst(model, 192, 192, LocalDate.of(2019, 7, 12), 10, 190, 50.00, 50.00, null, 0.81646069, 40.82, 398.08, 0.48, 0.00, null,
+                -0.48, 980.82);
+        checkInst(model, 193, 193, LocalDate.of(2019, 7, 13), 9, 191, 50.00, 50.00, null, 0.81558979, 40.78, 348.51, 0.43, 0.00, null,
+                -0.43, 980.82);
+        checkInst(model, 194, 194, LocalDate.of(2019, 7, 14), 8, 192, 50.00, 50.00, null, 0.81471983, 40.74, 298.88, 0.37, 0.00, null,
+                -0.37, 980.82);
+        checkInst(model, 195, 195, LocalDate.of(2019, 7, 15), 7, 193, 50.00, 50.00, null, 0.81385078, 40.69, 249.20, 0.32, 0.00, null,
+                -0.32, 980.82);
+        checkInst(model, 196, 196, LocalDate.of(2019, 7, 16), 6, 194, 50.00, 50.00, null, 0.81298267, 40.65, 199.47, 0.27, 0.00, null,
+                -0.27, 980.82);
+        checkInst(model, 197, 197, LocalDate.of(2019, 7, 17), 5, 195, 50.00, 50.00, null, 0.81211548, 40.61, 149.68, 0.21, 0.00, null,
+                -0.21, 980.82);
+        checkInst(model, 198, 198, LocalDate.of(2019, 7, 18), 4, 196, 50.00, 50.00, null, 0.81124922, 40.56, 99.84, 0.16, 0.00, null, -0.16,
+                980.82);
+        checkInst(model, 199, 199, LocalDate.of(2019, 7, 19), 3, 197, 50.00, 50.00, null, 0.81038388, 40.52, 49.95, 0.11, 0.00, null, -0.11,
+                980.82);
+        checkInst(model, 200, 200, LocalDate.of(2019, 7, 20), 2, 198, 50.00, 50.00, null, 0.80951946, 40.48, 0.00, 0.05, 0.00, null, -0.05,
+                980.82);
+
+    }
+
+    @Test
+    void testExcessPayment_term200_originationFee1000_netDisbursement9000_pay70_80() {
+        final ProjectedAmortizationScheduleModel model = generateModel();
+
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), new BigDecimal("70"));
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(2), new BigDecimal("80"));
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 202, 0, -9000.00, null, null, 1.00000000, -9000.00, 9000.00, null, null, null,
+                null, 1000.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 201, 0, 50.00, 50.00, 70.00, 1.00000000, 70.00, 8959.61, 9.61, 28.70, 13.44, 3.83,
+                986.56);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 200, 0, 50.00, 50.00, 80.00, 1.00000000, 80.00, 8919.18, 9.57, 15.26, 15.26, 5.70,
+                971.30);
+
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 199, 1, 50.00, 50.00, null, 0.99893332, 49.95, 8878.70, 9.52, 0.00, null, -9.52,
+                971.30);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 198, 2, 50.00, 50.00, null, 0.99786779, 49.89, 8838.18, 9.48, 0.00, null, -9.48,
+                971.30);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 197, 3, 50.00, 50.00, null, 0.99680339, 49.84, 8797.62, 9.44, 0.00, null, -9.44,
+                971.30);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 196, 4, 50.00, 50.00, null, 0.99574012, 49.79, 8757.01, 9.39, 0.00, null, -9.39,
+                971.30);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 195, 5, 50.00, 50.00, null, 0.99467799, 49.73, 8716.36, 9.35, 0.00, null, -9.35,
+                971.30);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 194, 6, 50.00, 50.00, null, 0.99361699, 49.68, 8675.67, 9.31, 0.00, null, -9.31,
+                971.30);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 193, 7, 50.00, 50.00, null, 0.99255712, 49.63, 8634.94, 9.26, 0.00, null, -9.26,
+                971.30);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 192, 8, 50.00, 50.00, null, 0.99149839, 49.57, 8594.16, 9.22, 0.00, null, -9.22,
+                971.30);
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 191, 9, 50.00, 50.00, null, 0.99044078, 49.52, 8553.33, 9.18, 0.00, null, -9.18,
+                971.30);
+        checkInst(model, 12, 12, LocalDate.of(2019, 1, 13), 190, 10, 50.00, 50.00, null, 0.98938430, 49.47, 8512.47, 9.13, 0.00, null,
+                -9.13, 971.30);
+        checkInst(model, 13, 13, LocalDate.of(2019, 1, 14), 189, 11, 50.00, 50.00, null, 0.98832895, 49.42, 8471.56, 9.09, 0.00, null,
+                -9.09, 971.30);
+        checkInst(model, 14, 14, LocalDate.of(2019, 1, 15), 188, 12, 50.00, 50.00, null, 0.98727472, 49.36, 8430.60, 9.05, 0.00, null,
+                -9.05, 971.30);
+        checkInst(model, 15, 15, LocalDate.of(2019, 1, 16), 187, 13, 50.00, 50.00, null, 0.98622162, 49.31, 8389.61, 9.00, 0.00, null,
+                -9.00, 971.30);
+        checkInst(model, 16, 16, LocalDate.of(2019, 1, 17), 186, 14, 50.00, 50.00, null, 0.98516964, 49.26, 8348.56, 8.96, 0.00, null,
+                -8.96, 971.30);
+        checkInst(model, 17, 17, LocalDate.of(2019, 1, 18), 185, 15, 50.00, 50.00, null, 0.98411879, 49.21, 8307.48, 8.91, 0.00, null,
+                -8.91, 971.30);
+        checkInst(model, 18, 18, LocalDate.of(2019, 1, 19), 184, 16, 50.00, 50.00, null, 0.98306905, 49.15, 8266.35, 8.87, 0.00, null,
+                -8.87, 971.30);
+        checkInst(model, 19, 19, LocalDate.of(2019, 1, 20), 183, 17, 50.00, 50.00, null, 0.98202044, 49.10, 8225.18, 8.83, 0.00, null,
+                -8.83, 971.30);
+        checkInst(model, 20, 20, LocalDate.of(2019, 1, 21), 182, 18, 50.00, 50.00, null, 0.98097294, 49.05, 8183.96, 8.78, 0.00, null,
+                -8.78, 971.30);
+        checkInst(model, 21, 21, LocalDate.of(2019, 1, 22), 181, 19, 50.00, 50.00, null, 0.97992656, 49.00, 8142.70, 8.74, 0.00, null,
+                -8.74, 971.30);
+        checkInst(model, 22, 22, LocalDate.of(2019, 1, 23), 180, 20, 50.00, 50.00, null, 0.97888129, 48.94, 8101.39, 8.69, 0.00, null,
+                -8.69, 971.30);
+        checkInst(model, 23, 23, LocalDate.of(2019, 1, 24), 179, 21, 50.00, 50.00, null, 0.97783715, 48.89, 8060.04, 8.65, 0.00, null,
+                -8.65, 971.30);
+        checkInst(model, 24, 24, LocalDate.of(2019, 1, 25), 178, 22, 50.00, 50.00, null, 0.97679411, 48.84, 8018.65, 8.61, 0.00, null,
+                -8.61, 971.30);
+        checkInst(model, 25, 25, LocalDate.of(2019, 1, 26), 177, 23, 50.00, 50.00, null, 0.97575219, 48.79, 7977.21, 8.56, 0.00, null,
+                -8.56, 971.30);
+        checkInst(model, 26, 26, LocalDate.of(2019, 1, 27), 176, 24, 50.00, 50.00, null, 0.97471138, 48.74, 7935.73, 8.52, 0.00, null,
+                -8.52, 971.30);
+        checkInst(model, 27, 27, LocalDate.of(2019, 1, 28), 175, 25, 50.00, 50.00, null, 0.97367168, 48.68, 7894.21, 8.47, 0.00, null,
+                -8.47, 971.30);
+        checkInst(model, 28, 28, LocalDate.of(2019, 1, 29), 174, 26, 50.00, 50.00, null, 0.97263309, 48.63, 7852.63, 8.43, 0.00, null,
+                -8.43, 971.30);
+        checkInst(model, 29, 29, LocalDate.of(2019, 1, 30), 173, 27, 50.00, 50.00, null, 0.97159560, 48.58, 7811.02, 8.39, 0.00, null,
+                -8.39, 971.30);
+        checkInst(model, 30, 30, LocalDate.of(2019, 1, 31), 172, 28, 50.00, 50.00, null, 0.97055922, 48.53, 7769.36, 8.34, 0.00, null,
+                -8.34, 971.30);
+        checkInst(model, 31, 31, LocalDate.of(2019, 2, 1), 171, 29, 50.00, 50.00, null, 0.96952395, 48.48, 7727.66, 8.30, 0.00, null, -8.30,
+                971.30);
+        checkInst(model, 32, 32, LocalDate.of(2019, 2, 2), 170, 30, 50.00, 50.00, null, 0.96848979, 48.42, 7685.91, 8.25, 0.00, null, -8.25,
+                971.30);
+        checkInst(model, 33, 33, LocalDate.of(2019, 2, 3), 169, 31, 50.00, 50.00, null, 0.96745672, 48.37, 7644.12, 8.21, 0.00, null, -8.21,
+                971.30);
+        checkInst(model, 34, 34, LocalDate.of(2019, 2, 4), 168, 32, 50.00, 50.00, null, 0.96642476, 48.32, 7602.28, 8.16, 0.00, null, -8.16,
+                971.30);
+        checkInst(model, 35, 35, LocalDate.of(2019, 2, 5), 167, 33, 50.00, 50.00, null, 0.96539390, 48.27, 7560.40, 8.12, 0.00, null, -8.12,
+                971.30);
+        checkInst(model, 36, 36, LocalDate.of(2019, 2, 6), 166, 34, 50.00, 50.00, null, 0.96436413, 48.22, 7518.47, 8.07, 0.00, null, -8.07,
+                971.30);
+        checkInst(model, 37, 37, LocalDate.of(2019, 2, 7), 165, 35, 50.00, 50.00, null, 0.96333547, 48.17, 7476.50, 8.03, 0.00, null, -8.03,
+                971.30);
+        checkInst(model, 38, 38, LocalDate.of(2019, 2, 8), 164, 36, 50.00, 50.00, null, 0.96230790, 48.12, 7434.48, 7.98, 0.00, null, -7.98,
+                971.30);
+        checkInst(model, 39, 39, LocalDate.of(2019, 2, 9), 163, 37, 50.00, 50.00, null, 0.96128143, 48.06, 7392.42, 7.94, 0.00, null, -7.94,
+                971.30);
+        checkInst(model, 40, 40, LocalDate.of(2019, 2, 10), 162, 38, 50.00, 50.00, null, 0.96025606, 48.01, 7350.31, 7.89, 0.00, null,
+                -7.89, 971.30);
+        checkInst(model, 41, 41, LocalDate.of(2019, 2, 11), 161, 39, 50.00, 50.00, null, 0.95923178, 47.96, 7308.16, 7.85, 0.00, null,
+                -7.85, 971.30);
+        checkInst(model, 42, 42, LocalDate.of(2019, 2, 12), 160, 40, 50.00, 50.00, null, 0.95820859, 47.91, 7265.97, 7.80, 0.00, null,
+                -7.80, 971.30);
+        checkInst(model, 43, 43, LocalDate.of(2019, 2, 13), 159, 41, 50.00, 50.00, null, 0.95718649, 47.86, 7223.72, 7.76, 0.00, null,
+                -7.76, 971.30);
+        checkInst(model, 44, 44, LocalDate.of(2019, 2, 14), 158, 42, 50.00, 50.00, null, 0.95616548, 47.81, 7181.44, 7.71, 0.00, null,
+                -7.71, 971.30);
+        checkInst(model, 45, 45, LocalDate.of(2019, 2, 15), 157, 43, 50.00, 50.00, null, 0.95514557, 47.76, 7139.11, 7.67, 0.00, null,
+                -7.67, 971.30);
+        checkInst(model, 46, 46, LocalDate.of(2019, 2, 16), 156, 44, 50.00, 50.00, null, 0.95412674, 47.71, 7096.73, 7.62, 0.00, null,
+                -7.62, 971.30);
+        checkInst(model, 47, 47, LocalDate.of(2019, 2, 17), 155, 45, 50.00, 50.00, null, 0.95310899, 47.66, 7054.31, 7.58, 0.00, null,
+                -7.58, 971.30);
+        checkInst(model, 48, 48, LocalDate.of(2019, 2, 18), 154, 46, 50.00, 50.00, null, 0.95209233, 47.60, 7011.84, 7.53, 0.00, null,
+                -7.53, 971.30);
+        checkInst(model, 49, 49, LocalDate.of(2019, 2, 19), 153, 47, 50.00, 50.00, null, 0.95107676, 47.55, 6969.33, 7.49, 0.00, null,
+                -7.49, 971.30);
+        checkInst(model, 50, 50, LocalDate.of(2019, 2, 20), 152, 48, 50.00, 50.00, null, 0.95006227, 47.50, 6926.77, 7.44, 0.00, null,
+                -7.44, 971.30);
+        checkInst(model, 51, 51, LocalDate.of(2019, 2, 21), 151, 49, 50.00, 50.00, null, 0.94904886, 47.45, 6884.17, 7.40, 0.00, null,
+                -7.40, 971.30);
+        checkInst(model, 52, 52, LocalDate.of(2019, 2, 22), 150, 50, 50.00, 50.00, null, 0.94803653, 47.40, 6841.52, 7.35, 0.00, null,
+                -7.35, 971.30);
+        checkInst(model, 53, 53, LocalDate.of(2019, 2, 23), 149, 51, 50.00, 50.00, null, 0.94702529, 47.35, 6798.82, 7.31, 0.00, null,
+                -7.31, 971.30);
+        checkInst(model, 54, 54, LocalDate.of(2019, 2, 24), 148, 52, 50.00, 50.00, null, 0.94601512, 47.30, 6756.08, 7.26, 0.00, null,
+                -7.26, 971.30);
+        checkInst(model, 55, 55, LocalDate.of(2019, 2, 25), 147, 53, 50.00, 50.00, null, 0.94500603, 47.25, 6713.30, 7.21, 0.00, null,
+                -7.21, 971.30);
+        checkInst(model, 56, 56, LocalDate.of(2019, 2, 26), 146, 54, 50.00, 50.00, null, 0.94399801, 47.20, 6670.47, 7.17, 0.00, null,
+                -7.17, 971.30);
+        checkInst(model, 57, 57, LocalDate.of(2019, 2, 27), 145, 55, 50.00, 50.00, null, 0.94299107, 47.15, 6627.59, 7.12, 0.00, null,
+                -7.12, 971.30);
+        checkInst(model, 58, 58, LocalDate.of(2019, 2, 28), 144, 56, 50.00, 50.00, null, 0.94198521, 47.10, 6584.67, 7.08, 0.00, null,
+                -7.08, 971.30);
+        checkInst(model, 59, 59, LocalDate.of(2019, 3, 1), 143, 57, 50.00, 50.00, null, 0.94098042, 47.05, 6541.70, 7.03, 0.00, null, -7.03,
+                971.30);
+        checkInst(model, 60, 60, LocalDate.of(2019, 3, 2), 142, 58, 50.00, 50.00, null, 0.93997669, 47.00, 6498.68, 6.99, 0.00, null, -6.99,
+                971.30);
+        checkInst(model, 61, 61, LocalDate.of(2019, 3, 3), 141, 59, 50.00, 50.00, null, 0.93897404, 46.95, 6455.62, 6.94, 0.00, null, -6.94,
+                971.30);
+        checkInst(model, 62, 62, LocalDate.of(2019, 3, 4), 140, 60, 50.00, 50.00, null, 0.93797246, 46.90, 6412.51, 6.89, 0.00, null, -6.89,
+                971.30);
+        checkInst(model, 63, 63, LocalDate.of(2019, 3, 5), 139, 61, 50.00, 50.00, null, 0.93697195, 46.85, 6369.36, 6.85, 0.00, null, -6.85,
+                971.30);
+        checkInst(model, 64, 64, LocalDate.of(2019, 3, 6), 138, 62, 50.00, 50.00, null, 0.93597251, 46.80, 6326.16, 6.80, 0.00, null, -6.80,
+                971.30);
+        checkInst(model, 65, 65, LocalDate.of(2019, 3, 7), 137, 63, 50.00, 50.00, null, 0.93497413, 46.75, 6282.92, 6.76, 0.00, null, -6.76,
+                971.30);
+        checkInst(model, 66, 66, LocalDate.of(2019, 3, 8), 136, 64, 50.00, 50.00, null, 0.93397681, 46.70, 6239.63, 6.71, 0.00, null, -6.71,
+                971.30);
+        checkInst(model, 67, 67, LocalDate.of(2019, 3, 9), 135, 65, 50.00, 50.00, null, 0.93298056, 46.65, 6196.29, 6.66, 0.00, null, -6.66,
+                971.30);
+        checkInst(model, 68, 68, LocalDate.of(2019, 3, 10), 134, 66, 50.00, 50.00, null, 0.93198538, 46.60, 6152.91, 6.62, 0.00, null,
+                -6.62, 971.30);
+        checkInst(model, 69, 69, LocalDate.of(2019, 3, 11), 133, 67, 50.00, 50.00, null, 0.93099125, 46.55, 6109.48, 6.57, 0.00, null,
+                -6.57, 971.30);
+        checkInst(model, 70, 70, LocalDate.of(2019, 3, 12), 132, 68, 50.00, 50.00, null, 0.92999818, 46.50, 6066.00, 6.52, 0.00, null,
+                -6.52, 971.30);
+        checkInst(model, 71, 71, LocalDate.of(2019, 3, 13), 131, 69, 50.00, 50.00, null, 0.92900618, 46.45, 6022.48, 6.48, 0.00, null,
+                -6.48, 971.30);
+        checkInst(model, 72, 72, LocalDate.of(2019, 3, 14), 130, 70, 50.00, 50.00, null, 0.92801523, 46.40, 5978.91, 6.43, 0.00, null,
+                -6.43, 971.30);
+        checkInst(model, 73, 73, LocalDate.of(2019, 3, 15), 129, 71, 50.00, 50.00, null, 0.92702534, 46.35, 5935.29, 6.38, 0.00, null,
+                -6.38, 971.30);
+        checkInst(model, 74, 74, LocalDate.of(2019, 3, 16), 128, 72, 50.00, 50.00, null, 0.92603650, 46.30, 5891.63, 6.34, 0.00, null,
+                -6.34, 971.30);
+        checkInst(model, 75, 75, LocalDate.of(2019, 3, 17), 127, 73, 50.00, 50.00, null, 0.92504872, 46.25, 5847.92, 6.29, 0.00, null,
+                -6.29, 971.30);
+        checkInst(model, 76, 76, LocalDate.of(2019, 3, 18), 126, 74, 50.00, 50.00, null, 0.92406200, 46.20, 5804.17, 6.24, 0.00, null,
+                -6.24, 971.30);
+        checkInst(model, 77, 77, LocalDate.of(2019, 3, 19), 125, 75, 50.00, 50.00, null, 0.92307632, 46.15, 5760.36, 6.20, 0.00, null,
+                -6.20, 971.30);
+        checkInst(model, 78, 78, LocalDate.of(2019, 3, 20), 124, 76, 50.00, 50.00, null, 0.92209170, 46.10, 5716.52, 6.15, 0.00, null,
+                -6.15, 971.30);
+        checkInst(model, 79, 79, LocalDate.of(2019, 3, 21), 123, 77, 50.00, 50.00, null, 0.92110813, 46.06, 5672.62, 6.10, 0.00, null,
+                -6.10, 971.30);
+        checkInst(model, 80, 80, LocalDate.of(2019, 3, 22), 122, 78, 50.00, 50.00, null, 0.92012560, 46.01, 5628.68, 6.06, 0.00, null,
+                -6.06, 971.30);
+        checkInst(model, 81, 81, LocalDate.of(2019, 3, 23), 121, 79, 50.00, 50.00, null, 0.91914413, 45.96, 5584.69, 6.01, 0.00, null,
+                -6.01, 971.30);
+        checkInst(model, 82, 82, LocalDate.of(2019, 3, 24), 120, 80, 50.00, 50.00, null, 0.91816370, 45.91, 5540.65, 5.96, 0.00, null,
+                -5.96, 971.30);
+        checkInst(model, 83, 83, LocalDate.of(2019, 3, 25), 119, 81, 50.00, 50.00, null, 0.91718432, 45.86, 5496.57, 5.92, 0.00, null,
+                -5.92, 971.30);
+        checkInst(model, 84, 84, LocalDate.of(2019, 3, 26), 118, 82, 50.00, 50.00, null, 0.91620598, 45.81, 5452.44, 5.87, 0.00, null,
+                -5.87, 971.30);
+        checkInst(model, 85, 85, LocalDate.of(2019, 3, 27), 117, 83, 50.00, 50.00, null, 0.91522868, 45.76, 5408.26, 5.82, 0.00, null,
+                -5.82, 971.30);
+        checkInst(model, 86, 86, LocalDate.of(2019, 3, 28), 116, 84, 50.00, 50.00, null, 0.91425243, 45.71, 5364.03, 5.78, 0.00, null,
+                -5.78, 971.30);
+        checkInst(model, 87, 87, LocalDate.of(2019, 3, 29), 115, 85, 50.00, 50.00, null, 0.91327722, 45.66, 5319.76, 5.73, 0.00, null,
+                -5.73, 971.30);
+        checkInst(model, 88, 88, LocalDate.of(2019, 3, 30), 114, 86, 50.00, 50.00, null, 0.91230305, 45.62, 5275.44, 5.68, 0.00, null,
+                -5.68, 971.30);
+        checkInst(model, 89, 89, LocalDate.of(2019, 3, 31), 113, 87, 50.00, 50.00, null, 0.91132992, 45.57, 5231.08, 5.63, 0.00, null,
+                -5.63, 971.30);
+        checkInst(model, 90, 90, LocalDate.of(2019, 4, 1), 112, 88, 50.00, 50.00, null, 0.91035783, 45.52, 5186.66, 5.59, 0.00, null, -5.59,
+                971.30);
+        checkInst(model, 91, 91, LocalDate.of(2019, 4, 2), 111, 89, 50.00, 50.00, null, 0.90938677, 45.47, 5142.20, 5.54, 0.00, null, -5.54,
+                971.30);
+        checkInst(model, 92, 92, LocalDate.of(2019, 4, 3), 110, 90, 50.00, 50.00, null, 0.90841675, 45.42, 5097.69, 5.49, 0.00, null, -5.49,
+                971.30);
+        checkInst(model, 93, 93, LocalDate.of(2019, 4, 4), 109, 91, 50.00, 50.00, null, 0.90744776, 45.37, 5053.13, 5.44, 0.00, null, -5.44,
+                971.30);
+        checkInst(model, 94, 94, LocalDate.of(2019, 4, 5), 108, 92, 50.00, 50.00, null, 0.90647981, 45.32, 5008.53, 5.40, 0.00, null, -5.40,
+                971.30);
+        checkInst(model, 95, 95, LocalDate.of(2019, 4, 6), 107, 93, 50.00, 50.00, null, 0.90551289, 45.28, 4963.88, 5.35, 0.00, null, -5.35,
+                971.30);
+        checkInst(model, 96, 96, LocalDate.of(2019, 4, 7), 106, 94, 50.00, 50.00, null, 0.90454700, 45.23, 4919.18, 5.30, 0.00, null, -5.30,
+                971.30);
+        checkInst(model, 97, 97, LocalDate.of(2019, 4, 8), 105, 95, 50.00, 50.00, null, 0.90358215, 45.18, 4874.43, 5.25, 0.00, null, -5.25,
+                971.30);
+        checkInst(model, 98, 98, LocalDate.of(2019, 4, 9), 104, 96, 50.00, 50.00, null, 0.90261832, 45.13, 4829.64, 5.20, 0.00, null, -5.20,
+                971.30);
+        checkInst(model, 99, 99, LocalDate.of(2019, 4, 10), 103, 97, 50.00, 50.00, null, 0.90165552, 45.08, 4784.79, 5.16, 0.00, null,
+                -5.16, 971.30);
+        checkInst(model, 100, 100, LocalDate.of(2019, 4, 11), 102, 98, 50.00, 50.00, null, 0.90069374, 45.03, 4739.90, 5.11, 0.00, null,
+                -5.11, 971.30);
+        checkInst(model, 101, 101, LocalDate.of(2019, 4, 12), 101, 99, 50.00, 50.00, null, 0.89973299, 44.99, 4694.96, 5.06, 0.00, null,
+                -5.06, 971.30);
+        checkInst(model, 102, 102, LocalDate.of(2019, 4, 13), 100, 100, 50.00, 50.00, null, 0.89877327, 44.94, 4649.98, 5.01, 0.00, null,
+                -5.01, 971.30);
+        checkInst(model, 103, 103, LocalDate.of(2019, 4, 14), 99, 101, 50.00, 50.00, null, 0.89781457, 44.89, 4604.94, 4.97, 0.00, null,
+                -4.97, 971.30);
+        checkInst(model, 104, 104, LocalDate.of(2019, 4, 15), 98, 102, 50.00, 50.00, null, 0.89685689, 44.84, 4559.86, 4.92, 0.00, null,
+                -4.92, 971.30);
+        checkInst(model, 105, 105, LocalDate.of(2019, 4, 16), 97, 103, 50.00, 50.00, null, 0.89590024, 44.80, 4514.73, 4.87, 0.00, null,
+                -4.87, 971.30);
+        checkInst(model, 106, 106, LocalDate.of(2019, 4, 17), 96, 104, 50.00, 50.00, null, 0.89494460, 44.75, 4469.55, 4.82, 0.00, null,
+                -4.82, 971.30);
+        checkInst(model, 107, 107, LocalDate.of(2019, 4, 18), 95, 105, 50.00, 50.00, null, 0.89398999, 44.70, 4424.32, 4.77, 0.00, null,
+                -4.77, 971.30);
+        checkInst(model, 108, 108, LocalDate.of(2019, 4, 19), 94, 106, 50.00, 50.00, null, 0.89303639, 44.65, 4379.05, 4.72, 0.00, null,
+                -4.72, 971.30);
+        checkInst(model, 109, 109, LocalDate.of(2019, 4, 20), 93, 107, 50.00, 50.00, null, 0.89208381, 44.60, 4333.72, 4.68, 0.00, null,
+                -4.68, 971.30);
+        checkInst(model, 110, 110, LocalDate.of(2019, 4, 21), 92, 108, 50.00, 50.00, null, 0.89113225, 44.56, 4288.35, 4.63, 0.00, null,
+                -4.63, 971.30);
+        checkInst(model, 111, 111, LocalDate.of(2019, 4, 22), 91, 109, 50.00, 50.00, null, 0.89018170, 44.51, 4242.93, 4.58, 0.00, null,
+                -4.58, 971.30);
+        checkInst(model, 112, 112, LocalDate.of(2019, 4, 23), 90, 110, 50.00, 50.00, null, 0.88923216, 44.46, 4197.46, 4.53, 0.00, null,
+                -4.53, 971.30);
+        checkInst(model, 113, 113, LocalDate.of(2019, 4, 24), 89, 111, 50.00, 50.00, null, 0.88828364, 44.41, 4151.94, 4.48, 0.00, null,
+                -4.48, 971.30);
+        checkInst(model, 114, 114, LocalDate.of(2019, 4, 25), 88, 112, 50.00, 50.00, null, 0.88733613, 44.37, 4106.38, 4.43, 0.00, null,
+                -4.43, 971.30);
+        checkInst(model, 115, 115, LocalDate.of(2019, 4, 26), 87, 113, 50.00, 50.00, null, 0.88638963, 44.32, 4060.76, 4.38, 0.00, null,
+                -4.38, 971.30);
+        checkInst(model, 116, 116, LocalDate.of(2019, 4, 27), 86, 114, 50.00, 50.00, null, 0.88544414, 44.27, 4015.10, 4.34, 0.00, null,
+                -4.34, 971.30);
+        checkInst(model, 117, 117, LocalDate.of(2019, 4, 28), 85, 115, 50.00, 50.00, null, 0.88449966, 44.22, 3969.38, 4.29, 0.00, null,
+                -4.29, 971.30);
+        checkInst(model, 118, 118, LocalDate.of(2019, 4, 29), 84, 116, 50.00, 50.00, null, 0.88355619, 44.18, 3923.62, 4.24, 0.00, null,
+                -4.24, 971.30);
+        checkInst(model, 119, 119, LocalDate.of(2019, 4, 30), 83, 117, 50.00, 50.00, null, 0.88261372, 44.13, 3877.81, 4.19, 0.00, null,
+                -4.19, 971.30);
+        checkInst(model, 120, 120, LocalDate.of(2019, 5, 1), 82, 118, 50.00, 50.00, null, 0.88167226, 44.08, 3831.95, 4.14, 0.00, null,
+                -4.14, 971.30);
+        checkInst(model, 121, 121, LocalDate.of(2019, 5, 2), 81, 119, 50.00, 50.00, null, 0.88073180, 44.04, 3786.04, 4.09, 0.00, null,
+                -4.09, 971.30);
+        checkInst(model, 122, 122, LocalDate.of(2019, 5, 3), 80, 120, 50.00, 50.00, null, 0.87979234, 43.99, 3740.09, 4.04, 0.00, null,
+                -4.04, 971.30);
+        checkInst(model, 123, 123, LocalDate.of(2019, 5, 4), 79, 121, 50.00, 50.00, null, 0.87885389, 43.94, 3694.08, 3.99, 0.00, null,
+                -3.99, 971.30);
+        checkInst(model, 124, 124, LocalDate.of(2019, 5, 5), 78, 122, 50.00, 50.00, null, 0.87791644, 43.90, 3648.03, 3.94, 0.00, null,
+                -3.94, 971.30);
+        checkInst(model, 125, 125, LocalDate.of(2019, 5, 6), 77, 123, 50.00, 50.00, null, 0.87697999, 43.85, 3601.92, 3.90, 0.00, null,
+                -3.90, 971.30);
+        checkInst(model, 126, 126, LocalDate.of(2019, 5, 7), 76, 124, 50.00, 50.00, null, 0.87604453, 43.80, 3555.77, 3.85, 0.00, null,
+                -3.85, 971.30);
+        checkInst(model, 127, 127, LocalDate.of(2019, 5, 8), 75, 125, 50.00, 50.00, null, 0.87511008, 43.76, 3509.56, 3.80, 0.00, null,
+                -3.80, 971.30);
+        checkInst(model, 128, 128, LocalDate.of(2019, 5, 9), 74, 126, 50.00, 50.00, null, 0.87417662, 43.71, 3463.31, 3.75, 0.00, null,
+                -3.75, 971.30);
+        checkInst(model, 129, 129, LocalDate.of(2019, 5, 10), 73, 127, 50.00, 50.00, null, 0.87324416, 43.66, 3417.01, 3.70, 0.00, null,
+                -3.70, 971.30);
+        checkInst(model, 130, 130, LocalDate.of(2019, 5, 11), 72, 128, 50.00, 50.00, null, 0.87231269, 43.62, 3370.66, 3.65, 0.00, null,
+                -3.65, 971.30);
+        checkInst(model, 131, 131, LocalDate.of(2019, 5, 12), 71, 129, 50.00, 50.00, null, 0.87138221, 43.57, 3324.26, 3.60, 0.00, null,
+                -3.60, 971.30);
+        checkInst(model, 132, 132, LocalDate.of(2019, 5, 13), 70, 130, 50.00, 50.00, null, 0.87045273, 43.52, 3277.81, 3.55, 0.00, null,
+                -3.55, 971.30);
+        checkInst(model, 133, 133, LocalDate.of(2019, 5, 14), 69, 131, 50.00, 50.00, null, 0.86952424, 43.48, 3231.31, 3.50, 0.00, null,
+                -3.50, 971.30);
+        checkInst(model, 134, 134, LocalDate.of(2019, 5, 15), 68, 132, 50.00, 50.00, null, 0.86859674, 43.43, 3184.76, 3.45, 0.00, null,
+                -3.45, 971.30);
+        checkInst(model, 135, 135, LocalDate.of(2019, 5, 16), 67, 133, 50.00, 50.00, null, 0.86767023, 43.38, 3138.16, 3.40, 0.00, null,
+                -3.40, 971.30);
+        checkInst(model, 136, 136, LocalDate.of(2019, 5, 17), 66, 134, 50.00, 50.00, null, 0.86674471, 43.34, 3091.51, 3.35, 0.00, null,
+                -3.35, 971.30);
+        checkInst(model, 137, 137, LocalDate.of(2019, 5, 18), 65, 135, 50.00, 50.00, null, 0.86582017, 43.29, 3044.81, 3.30, 0.00, null,
+                -3.30, 971.30);
+        checkInst(model, 138, 138, LocalDate.of(2019, 5, 19), 64, 136, 50.00, 50.00, null, 0.86489662, 43.24, 2998.06, 3.25, 0.00, null,
+                -3.25, 971.30);
+        checkInst(model, 139, 139, LocalDate.of(2019, 5, 20), 63, 137, 50.00, 50.00, null, 0.86397406, 43.20, 2951.26, 3.20, 0.00, null,
+                -3.20, 971.30);
+        checkInst(model, 140, 140, LocalDate.of(2019, 5, 21), 62, 138, 50.00, 50.00, null, 0.86305248, 43.15, 2904.42, 3.15, 0.00, null,
+                -3.15, 971.30);
+        checkInst(model, 141, 141, LocalDate.of(2019, 5, 22), 61, 139, 50.00, 50.00, null, 0.86213188, 43.11, 2857.52, 3.10, 0.00, null,
+                -3.10, 971.30);
+        checkInst(model, 142, 142, LocalDate.of(2019, 5, 23), 60, 140, 50.00, 50.00, null, 0.86121227, 43.06, 2810.57, 3.05, 0.00, null,
+                -3.05, 971.30);
+        checkInst(model, 143, 143, LocalDate.of(2019, 5, 24), 59, 141, 50.00, 50.00, null, 0.86029363, 43.01, 2763.57, 3.00, 0.00, null,
+                -3.00, 971.30);
+        checkInst(model, 144, 144, LocalDate.of(2019, 5, 25), 58, 142, 50.00, 50.00, null, 0.85937598, 42.97, 2716.52, 2.95, 0.00, null,
+                -2.95, 971.30);
+        checkInst(model, 145, 145, LocalDate.of(2019, 5, 26), 57, 143, 50.00, 50.00, null, 0.85845930, 42.92, 2669.42, 2.90, 0.00, null,
+                -2.90, 971.30);
+        checkInst(model, 146, 146, LocalDate.of(2019, 5, 27), 56, 144, 50.00, 50.00, null, 0.85754361, 42.88, 2622.27, 2.85, 0.00, null,
+                -2.85, 971.30);
+        checkInst(model, 147, 147, LocalDate.of(2019, 5, 28), 55, 145, 50.00, 50.00, null, 0.85662889, 42.83, 2575.07, 2.80, 0.00, null,
+                -2.80, 971.30);
+        checkInst(model, 148, 148, LocalDate.of(2019, 5, 29), 54, 146, 50.00, 50.00, null, 0.85571514, 42.79, 2527.82, 2.75, 0.00, null,
+                -2.75, 971.30);
+        checkInst(model, 149, 149, LocalDate.of(2019, 5, 30), 53, 147, 50.00, 50.00, null, 0.85480237, 42.74, 2480.52, 2.70, 0.00, null,
+                -2.70, 971.30);
+        checkInst(model, 150, 150, LocalDate.of(2019, 5, 31), 52, 148, 50.00, 50.00, null, 0.85389057, 42.69, 2433.17, 2.65, 0.00, null,
+                -2.65, 971.30);
+        checkInst(model, 151, 151, LocalDate.of(2019, 6, 1), 51, 149, 50.00, 50.00, null, 0.85297975, 42.65, 2385.77, 2.60, 0.00, null,
+                -2.60, 971.30);
+        checkInst(model, 152, 152, LocalDate.of(2019, 6, 2), 50, 150, 50.00, 50.00, null, 0.85206990, 42.60, 2338.31, 2.55, 0.00, null,
+                -2.55, 971.30);
+        checkInst(model, 153, 153, LocalDate.of(2019, 6, 3), 49, 151, 50.00, 50.00, null, 0.85116101, 42.56, 2290.81, 2.50, 0.00, null,
+                -2.50, 971.30);
+        checkInst(model, 154, 154, LocalDate.of(2019, 6, 4), 48, 152, 50.00, 50.00, null, 0.85025310, 42.51, 2243.26, 2.45, 0.00, null,
+                -2.45, 971.30);
+        checkInst(model, 155, 155, LocalDate.of(2019, 6, 5), 47, 153, 50.00, 50.00, null, 0.84934616, 42.47, 2195.65, 2.40, 0.00, null,
+                -2.40, 971.30);
+        checkInst(model, 156, 156, LocalDate.of(2019, 6, 6), 46, 154, 50.00, 50.00, null, 0.84844018, 42.42, 2148.00, 2.34, 0.00, null,
+                -2.34, 971.30);
+        checkInst(model, 157, 157, LocalDate.of(2019, 6, 7), 45, 155, 50.00, 50.00, null, 0.84753517, 42.38, 2100.29, 2.29, 0.00, null,
+                -2.29, 971.30);
+        checkInst(model, 158, 158, LocalDate.of(2019, 6, 8), 44, 156, 50.00, 50.00, null, 0.84663113, 42.33, 2052.53, 2.24, 0.00, null,
+                -2.24, 971.30);
+        checkInst(model, 159, 159, LocalDate.of(2019, 6, 9), 43, 157, 50.00, 50.00, null, 0.84572805, 42.29, 2004.73, 2.19, 0.00, null,
+                -2.19, 971.30);
+        checkInst(model, 160, 160, LocalDate.of(2019, 6, 10), 42, 158, 50.00, 50.00, null, 0.84482593, 42.24, 1956.87, 2.14, 0.00, null,
+                -2.14, 971.30);
+        checkInst(model, 161, 161, LocalDate.of(2019, 6, 11), 41, 159, 50.00, 50.00, null, 0.84392477, 42.20, 1908.96, 2.09, 0.00, null,
+                -2.09, 971.30);
+        checkInst(model, 162, 162, LocalDate.of(2019, 6, 12), 40, 160, 50.00, 50.00, null, 0.84302458, 42.15, 1860.99, 2.04, 0.00, null,
+                -2.04, 971.30);
+        checkInst(model, 163, 163, LocalDate.of(2019, 6, 13), 39, 161, 50.00, 50.00, null, 0.84212535, 42.11, 1812.98, 1.99, 0.00, null,
+                -1.99, 971.30);
+        checkInst(model, 164, 164, LocalDate.of(2019, 6, 14), 38, 162, 50.00, 50.00, null, 0.84122707, 42.06, 1764.92, 1.94, 0.00, null,
+                -1.94, 971.30);
+        checkInst(model, 165, 165, LocalDate.of(2019, 6, 15), 37, 163, 50.00, 50.00, null, 0.84032975, 42.02, 1716.80, 1.88, 0.00, null,
+                -1.88, 971.30);
+        checkInst(model, 166, 166, LocalDate.of(2019, 6, 16), 36, 164, 50.00, 50.00, null, 0.83943340, 41.97, 1668.64, 1.83, 0.00, null,
+                -1.83, 971.30);
+        checkInst(model, 167, 167, LocalDate.of(2019, 6, 17), 35, 165, 50.00, 50.00, null, 0.83853799, 41.93, 1620.42, 1.78, 0.00, null,
+                -1.78, 971.30);
+        checkInst(model, 168, 168, LocalDate.of(2019, 6, 18), 34, 166, 50.00, 50.00, null, 0.83764354, 41.88, 1572.15, 1.73, 0.00, null,
+                -1.73, 971.30);
+        checkInst(model, 169, 169, LocalDate.of(2019, 6, 19), 33, 167, 50.00, 50.00, null, 0.83675005, 41.84, 1523.83, 1.68, 0.00, null,
+                -1.68, 971.30);
+        checkInst(model, 170, 170, LocalDate.of(2019, 6, 20), 32, 168, 50.00, 50.00, null, 0.83585751, 41.79, 1475.45, 1.63, 0.00, null,
+                -1.63, 971.30);
+        checkInst(model, 171, 171, LocalDate.of(2019, 6, 21), 31, 169, 50.00, 50.00, null, 0.83496592, 41.75, 1427.03, 1.58, 0.00, null,
+                -1.58, 971.30);
+        checkInst(model, 172, 172, LocalDate.of(2019, 6, 22), 30, 170, 50.00, 50.00, null, 0.83407528, 41.70, 1378.55, 1.52, 0.00, null,
+                -1.52, 971.30);
+        checkInst(model, 173, 173, LocalDate.of(2019, 6, 23), 29, 171, 50.00, 50.00, null, 0.83318560, 41.66, 1330.02, 1.47, 0.00, null,
+                -1.47, 971.30);
+        checkInst(model, 174, 174, LocalDate.of(2019, 6, 24), 28, 172, 50.00, 50.00, null, 0.83229686, 41.61, 1281.45, 1.42, 0.00, null,
+                -1.42, 971.30);
+        checkInst(model, 175, 175, LocalDate.of(2019, 6, 25), 27, 173, 50.00, 50.00, null, 0.83140907, 41.57, 1232.81, 1.37, 0.00, null,
+                -1.37, 971.30);
+        checkInst(model, 176, 176, LocalDate.of(2019, 6, 26), 26, 174, 50.00, 50.00, null, 0.83052222, 41.53, 1184.13, 1.32, 0.00, null,
+                -1.32, 971.30);
+        checkInst(model, 177, 177, LocalDate.of(2019, 6, 27), 25, 175, 50.00, 50.00, null, 0.82963633, 41.48, 1135.39, 1.26, 0.00, null,
+                -1.26, 971.30);
+        checkInst(model, 178, 178, LocalDate.of(2019, 6, 28), 24, 176, 50.00, 50.00, null, 0.82875137, 41.44, 1086.61, 1.21, 0.00, null,
+                -1.21, 971.30);
+        checkInst(model, 179, 179, LocalDate.of(2019, 6, 29), 23, 177, 50.00, 50.00, null, 0.82786736, 41.39, 1037.77, 1.16, 0.00, null,
+                -1.16, 971.30);
+        checkInst(model, 180, 180, LocalDate.of(2019, 6, 30), 22, 178, 50.00, 50.00, null, 0.82698430, 41.35, 988.88, 1.11, 0.00, null,
+                -1.11, 971.30);
+        checkInst(model, 181, 181, LocalDate.of(2019, 7, 1), 21, 179, 50.00, 50.00, null, 0.82610217, 41.31, 939.93, 1.06, 0.00, null,
+                -1.06, 971.30);
+        checkInst(model, 182, 182, LocalDate.of(2019, 7, 2), 20, 180, 50.00, 50.00, null, 0.82522099, 41.26, 890.93, 1.00, 0.00, null,
+                -1.00, 971.30);
+        checkInst(model, 183, 183, LocalDate.of(2019, 7, 3), 19, 181, 50.00, 50.00, null, 0.82434075, 41.22, 841.89, 0.95, 0.00, null,
+                -0.95, 971.30);
+        checkInst(model, 184, 184, LocalDate.of(2019, 7, 4), 18, 182, 50.00, 50.00, null, 0.82346144, 41.17, 792.79, 0.90, 0.00, null,
+                -0.90, 971.30);
+        checkInst(model, 185, 185, LocalDate.of(2019, 7, 5), 17, 183, 50.00, 50.00, null, 0.82258308, 41.13, 743.63, 0.85, 0.00, null,
+                -0.85, 971.30);
+        checkInst(model, 186, 186, LocalDate.of(2019, 7, 6), 16, 184, 50.00, 50.00, null, 0.82170565, 41.09, 694.43, 0.79, 0.00, null,
+                -0.79, 971.30);
+        checkInst(model, 187, 187, LocalDate.of(2019, 7, 7), 15, 185, 50.00, 50.00, null, 0.82082916, 41.04, 645.17, 0.74, 0.00, null,
+                -0.74, 971.30);
+        checkInst(model, 188, 188, LocalDate.of(2019, 7, 8), 14, 186, 50.00, 50.00, null, 0.81995360, 41.00, 595.86, 0.69, 0.00, null,
+                -0.69, 971.30);
+        checkInst(model, 189, 189, LocalDate.of(2019, 7, 9), 13, 187, 50.00, 50.00, null, 0.81907897, 40.95, 546.49, 0.64, 0.00, null,
+                -0.64, 971.30);
+        checkInst(model, 190, 190, LocalDate.of(2019, 7, 10), 12, 188, 50.00, 50.00, null, 0.81820528, 40.91, 497.08, 0.58, 0.00, null,
+                -0.58, 971.30);
+        checkInst(model, 191, 191, LocalDate.of(2019, 7, 11), 11, 189, 50.00, 50.00, null, 0.81733252, 40.87, 447.61, 0.53, 0.00, null,
+                -0.53, 971.30);
+        checkInst(model, 192, 192, LocalDate.of(2019, 7, 12), 10, 190, 50.00, 50.00, null, 0.81646069, 40.82, 398.08, 0.48, 0.00, null,
+                -0.48, 971.30);
+        checkInst(model, 193, 193, LocalDate.of(2019, 7, 13), 9, 191, 50.00, 50.00, null, 0.81558979, 40.78, 348.51, 0.43, 0.00, null,
+                -0.43, 971.30);
+        checkInst(model, 194, 194, LocalDate.of(2019, 7, 14), 8, 192, 50.00, 50.00, null, 0.81471983, 40.74, 298.88, 0.37, 0.00, null,
+                -0.37, 971.30);
+        checkInst(model, 195, 195, LocalDate.of(2019, 7, 15), 7, 193, 50.00, 50.00, null, 0.81385078, 40.69, 249.20, 0.32, 0.00, null,
+                -0.32, 971.30);
+        checkInst(model, 196, 196, LocalDate.of(2019, 7, 16), 6, 194, 50.00, 50.00, null, 0.81298267, 40.65, 199.47, 0.27, 0.00, null,
+                -0.27, 971.30);
+        checkInst(model, 197, 197, LocalDate.of(2019, 7, 17), 5, 195, 50.00, 50.00, null, 0.81211548, 40.61, 149.68, 0.21, 0.00, null,
+                -0.21, 971.30);
+        checkInst(model, 198, 198, LocalDate.of(2019, 7, 18), 4, 196, 50.00, 50.00, null, 0.81124922, 40.56, 99.84, 0.16, 0.00, null, -0.16,
+                971.30);
+        checkInst(model, 199, 199, LocalDate.of(2019, 7, 19), 3, 197, 50.00, 50.00, null, 0.81038388, 40.52, 49.95, 0.11, 0.00, null, -0.11,
+                971.30);
+
+        assertEquals(200, model.payments().size(), "disbursement + 199 regular (period 200 removed, forecast was 0)");
+    }
+
+    @Test
+    void testLessPayment_term200_originationFee1000_netDisbursement9000_pay40() {
+        final ProjectedAmortizationScheduleModel model = generateModel();
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), new BigDecimal("40"));
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 201, 0, -9000.00, null, null, 1.00000000, -9000.00, 9000.00, null, null, null,
+                null, 1000.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 200, 0, 50.00, 50.00, 40.00, 1.00000000, 40.00, 8959.61, 9.61, 7.69, 7.69, -1.92,
+                992.31);
+
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 199, 1, 50.00, 50.00, null, 0.99893332, 49.95, 8919.18, 9.57, 0.00, null, -9.57,
+                992.31);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 198, 2, 50.00, 50.00, null, 0.99786779, 49.89, 8878.70, 9.52, 0.00, null, -9.52,
+                992.31);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 197, 3, 50.00, 50.00, null, 0.99680339, 49.84, 8838.18, 9.48, 0.00, null, -9.48,
+                992.31);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 196, 4, 50.00, 50.00, null, 0.99574012, 49.79, 8797.62, 9.44, 0.00, null, -9.44,
+                992.31);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 195, 5, 50.00, 50.00, null, 0.99467799, 49.73, 8757.01, 9.39, 0.00, null, -9.39,
+                992.31);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 194, 6, 50.00, 50.00, null, 0.99361699, 49.68, 8716.36, 9.35, 0.00, null, -9.35,
+                992.31);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 193, 7, 50.00, 50.00, null, 0.99255712, 49.63, 8675.67, 9.31, 0.00, null, -9.31,
+                992.31);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 192, 8, 50.00, 50.00, null, 0.99149839, 49.57, 8634.94, 9.26, 0.00, null, -9.26,
+                992.31);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 191, 9, 50.00, 50.00, null, 0.99044078, 49.52, 8594.16, 9.22, 0.00, null, -9.22,
+                992.31);
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 190, 10, 50.00, 50.00, null, 0.98938430, 49.47, 8553.33, 9.18, 0.00, null,
+                -9.18, 992.31);
+        checkInst(model, 12, 12, LocalDate.of(2019, 1, 13), 189, 11, 50.00, 50.00, null, 0.98832895, 49.42, 8512.47, 9.13, 0.00, null,
+                -9.13, 992.31);
+        checkInst(model, 13, 13, LocalDate.of(2019, 1, 14), 188, 12, 50.00, 50.00, null, 0.98727472, 49.36, 8471.56, 9.09, 0.00, null,
+                -9.09, 992.31);
+        checkInst(model, 14, 14, LocalDate.of(2019, 1, 15), 187, 13, 50.00, 50.00, null, 0.98622162, 49.31, 8430.60, 9.05, 0.00, null,
+                -9.05, 992.31);
+        checkInst(model, 15, 15, LocalDate.of(2019, 1, 16), 186, 14, 50.00, 50.00, null, 0.98516964, 49.26, 8389.61, 9.00, 0.00, null,
+                -9.00, 992.31);
+        checkInst(model, 16, 16, LocalDate.of(2019, 1, 17), 185, 15, 50.00, 50.00, null, 0.98411879, 49.21, 8348.56, 8.96, 0.00, null,
+                -8.96, 992.31);
+        checkInst(model, 17, 17, LocalDate.of(2019, 1, 18), 184, 16, 50.00, 50.00, null, 0.98306905, 49.15, 8307.48, 8.91, 0.00, null,
+                -8.91, 992.31);
+        checkInst(model, 18, 18, LocalDate.of(2019, 1, 19), 183, 17, 50.00, 50.00, null, 0.98202044, 49.10, 8266.35, 8.87, 0.00, null,
+                -8.87, 992.31);
+        checkInst(model, 19, 19, LocalDate.of(2019, 1, 20), 182, 18, 50.00, 50.00, null, 0.98097294, 49.05, 8225.18, 8.83, 0.00, null,
+                -8.83, 992.31);
+        checkInst(model, 20, 20, LocalDate.of(2019, 1, 21), 181, 19, 50.00, 50.00, null, 0.97992656, 49.00, 8183.96, 8.78, 0.00, null,
+                -8.78, 992.31);
+        checkInst(model, 21, 21, LocalDate.of(2019, 1, 22), 180, 20, 50.00, 50.00, null, 0.97888129, 48.94, 8142.70, 8.74, 0.00, null,
+                -8.74, 992.31);
+        checkInst(model, 22, 22, LocalDate.of(2019, 1, 23), 179, 21, 50.00, 50.00, null, 0.97783715, 48.89, 8101.39, 8.69, 0.00, null,
+                -8.69, 992.31);
+        checkInst(model, 23, 23, LocalDate.of(2019, 1, 24), 178, 22, 50.00, 50.00, null, 0.97679411, 48.84, 8060.04, 8.65, 0.00, null,
+                -8.65, 992.31);
+        checkInst(model, 24, 24, LocalDate.of(2019, 1, 25), 177, 23, 50.00, 50.00, null, 0.97575219, 48.79, 8018.65, 8.61, 0.00, null,
+                -8.61, 992.31);
+        checkInst(model, 25, 25, LocalDate.of(2019, 1, 26), 176, 24, 50.00, 50.00, null, 0.97471138, 48.74, 7977.21, 8.56, 0.00, null,
+                -8.56, 992.31);
+        checkInst(model, 26, 26, LocalDate.of(2019, 1, 27), 175, 25, 50.00, 50.00, null, 0.97367168, 48.68, 7935.73, 8.52, 0.00, null,
+                -8.52, 992.31);
+        checkInst(model, 27, 27, LocalDate.of(2019, 1, 28), 174, 26, 50.00, 50.00, null, 0.97263309, 48.63, 7894.21, 8.47, 0.00, null,
+                -8.47, 992.31);
+        checkInst(model, 28, 28, LocalDate.of(2019, 1, 29), 173, 27, 50.00, 50.00, null, 0.97159560, 48.58, 7852.63, 8.43, 0.00, null,
+                -8.43, 992.31);
+        checkInst(model, 29, 29, LocalDate.of(2019, 1, 30), 172, 28, 50.00, 50.00, null, 0.97055922, 48.53, 7811.02, 8.39, 0.00, null,
+                -8.39, 992.31);
+        checkInst(model, 30, 30, LocalDate.of(2019, 1, 31), 171, 29, 50.00, 50.00, null, 0.96952395, 48.48, 7769.36, 8.34, 0.00, null,
+                -8.34, 992.31);
+        checkInst(model, 31, 31, LocalDate.of(2019, 2, 1), 170, 30, 50.00, 50.00, null, 0.96848979, 48.42, 7727.66, 8.30, 0.00, null, -8.30,
+                992.31);
+        checkInst(model, 32, 32, LocalDate.of(2019, 2, 2), 169, 31, 50.00, 50.00, null, 0.96745672, 48.37, 7685.91, 8.25, 0.00, null, -8.25,
+                992.31);
+        checkInst(model, 33, 33, LocalDate.of(2019, 2, 3), 168, 32, 50.00, 50.00, null, 0.96642476, 48.32, 7644.12, 8.21, 0.00, null, -8.21,
+                992.31);
+        checkInst(model, 34, 34, LocalDate.of(2019, 2, 4), 167, 33, 50.00, 50.00, null, 0.96539390, 48.27, 7602.28, 8.16, 0.00, null, -8.16,
+                992.31);
+        checkInst(model, 35, 35, LocalDate.of(2019, 2, 5), 166, 34, 50.00, 50.00, null, 0.96436413, 48.22, 7560.40, 8.12, 0.00, null, -8.12,
+                992.31);
+        checkInst(model, 36, 36, LocalDate.of(2019, 2, 6), 165, 35, 50.00, 50.00, null, 0.96333547, 48.17, 7518.47, 8.07, 0.00, null, -8.07,
+                992.31);
+        checkInst(model, 37, 37, LocalDate.of(2019, 2, 7), 164, 36, 50.00, 50.00, null, 0.96230790, 48.12, 7476.50, 8.03, 0.00, null, -8.03,
+                992.31);
+        checkInst(model, 38, 38, LocalDate.of(2019, 2, 8), 163, 37, 50.00, 50.00, null, 0.96128143, 48.06, 7434.48, 7.98, 0.00, null, -7.98,
+                992.31);
+        checkInst(model, 39, 39, LocalDate.of(2019, 2, 9), 162, 38, 50.00, 50.00, null, 0.96025606, 48.01, 7392.42, 7.94, 0.00, null, -7.94,
+                992.31);
+        checkInst(model, 40, 40, LocalDate.of(2019, 2, 10), 161, 39, 50.00, 50.00, null, 0.95923178, 47.96, 7350.31, 7.89, 0.00, null,
+                -7.89, 992.31);
+        checkInst(model, 41, 41, LocalDate.of(2019, 2, 11), 160, 40, 50.00, 50.00, null, 0.95820859, 47.91, 7308.16, 7.85, 0.00, null,
+                -7.85, 992.31);
+        checkInst(model, 42, 42, LocalDate.of(2019, 2, 12), 159, 41, 50.00, 50.00, null, 0.95718649, 47.86, 7265.97, 7.80, 0.00, null,
+                -7.80, 992.31);
+        checkInst(model, 43, 43, LocalDate.of(2019, 2, 13), 158, 42, 50.00, 50.00, null, 0.95616548, 47.81, 7223.72, 7.76, 0.00, null,
+                -7.76, 992.31);
+        checkInst(model, 44, 44, LocalDate.of(2019, 2, 14), 157, 43, 50.00, 50.00, null, 0.95514557, 47.76, 7181.44, 7.71, 0.00, null,
+                -7.71, 992.31);
+        checkInst(model, 45, 45, LocalDate.of(2019, 2, 15), 156, 44, 50.00, 50.00, null, 0.95412674, 47.71, 7139.11, 7.67, 0.00, null,
+                -7.67, 992.31);
+        checkInst(model, 46, 46, LocalDate.of(2019, 2, 16), 155, 45, 50.00, 50.00, null, 0.95310899, 47.66, 7096.73, 7.62, 0.00, null,
+                -7.62, 992.31);
+        checkInst(model, 47, 47, LocalDate.of(2019, 2, 17), 154, 46, 50.00, 50.00, null, 0.95209233, 47.60, 7054.31, 7.58, 0.00, null,
+                -7.58, 992.31);
+        checkInst(model, 48, 48, LocalDate.of(2019, 2, 18), 153, 47, 50.00, 50.00, null, 0.95107676, 47.55, 7011.84, 7.53, 0.00, null,
+                -7.53, 992.31);
+        checkInst(model, 49, 49, LocalDate.of(2019, 2, 19), 152, 48, 50.00, 50.00, null, 0.95006227, 47.50, 6969.33, 7.49, 0.00, null,
+                -7.49, 992.31);
+        checkInst(model, 50, 50, LocalDate.of(2019, 2, 20), 151, 49, 50.00, 50.00, null, 0.94904886, 47.45, 6926.77, 7.44, 0.00, null,
+                -7.44, 992.31);
+        checkInst(model, 51, 51, LocalDate.of(2019, 2, 21), 150, 50, 50.00, 50.00, null, 0.94803653, 47.40, 6884.17, 7.40, 0.00, null,
+                -7.40, 992.31);
+        checkInst(model, 52, 52, LocalDate.of(2019, 2, 22), 149, 51, 50.00, 50.00, null, 0.94702529, 47.35, 6841.52, 7.35, 0.00, null,
+                -7.35, 992.31);
+        checkInst(model, 53, 53, LocalDate.of(2019, 2, 23), 148, 52, 50.00, 50.00, null, 0.94601512, 47.30, 6798.82, 7.31, 0.00, null,
+                -7.31, 992.31);
+        checkInst(model, 54, 54, LocalDate.of(2019, 2, 24), 147, 53, 50.00, 50.00, null, 0.94500603, 47.25, 6756.08, 7.26, 0.00, null,
+                -7.26, 992.31);
+        checkInst(model, 55, 55, LocalDate.of(2019, 2, 25), 146, 54, 50.00, 50.00, null, 0.94399801, 47.20, 6713.30, 7.21, 0.00, null,
+                -7.21, 992.31);
+        checkInst(model, 56, 56, LocalDate.of(2019, 2, 26), 145, 55, 50.00, 50.00, null, 0.94299107, 47.15, 6670.47, 7.17, 0.00, null,
+                -7.17, 992.31);
+        checkInst(model, 57, 57, LocalDate.of(2019, 2, 27), 144, 56, 50.00, 50.00, null, 0.94198521, 47.10, 6627.59, 7.12, 0.00, null,
+                -7.12, 992.31);
+        checkInst(model, 58, 58, LocalDate.of(2019, 2, 28), 143, 57, 50.00, 50.00, null, 0.94098042, 47.05, 6584.67, 7.08, 0.00, null,
+                -7.08, 992.31);
+        checkInst(model, 59, 59, LocalDate.of(2019, 3, 1), 142, 58, 50.00, 50.00, null, 0.93997669, 47.00, 6541.70, 7.03, 0.00, null, -7.03,
+                992.31);
+        checkInst(model, 60, 60, LocalDate.of(2019, 3, 2), 141, 59, 50.00, 50.00, null, 0.93897404, 46.95, 6498.68, 6.99, 0.00, null, -6.99,
+                992.31);
+        checkInst(model, 61, 61, LocalDate.of(2019, 3, 3), 140, 60, 50.00, 50.00, null, 0.93797246, 46.90, 6455.62, 6.94, 0.00, null, -6.94,
+                992.31);
+        checkInst(model, 62, 62, LocalDate.of(2019, 3, 4), 139, 61, 50.00, 50.00, null, 0.93697195, 46.85, 6412.51, 6.89, 0.00, null, -6.89,
+                992.31);
+        checkInst(model, 63, 63, LocalDate.of(2019, 3, 5), 138, 62, 50.00, 50.00, null, 0.93597251, 46.80, 6369.36, 6.85, 0.00, null, -6.85,
+                992.31);
+        checkInst(model, 64, 64, LocalDate.of(2019, 3, 6), 137, 63, 50.00, 50.00, null, 0.93497413, 46.75, 6326.16, 6.80, 0.00, null, -6.80,
+                992.31);
+        checkInst(model, 65, 65, LocalDate.of(2019, 3, 7), 136, 64, 50.00, 50.00, null, 0.93397681, 46.70, 6282.92, 6.76, 0.00, null, -6.76,
+                992.31);
+        checkInst(model, 66, 66, LocalDate.of(2019, 3, 8), 135, 65, 50.00, 50.00, null, 0.93298056, 46.65, 6239.63, 6.71, 0.00, null, -6.71,
+                992.31);
+        checkInst(model, 67, 67, LocalDate.of(2019, 3, 9), 134, 66, 50.00, 50.00, null, 0.93198538, 46.60, 6196.29, 6.66, 0.00, null, -6.66,
+                992.31);
+        checkInst(model, 68, 68, LocalDate.of(2019, 3, 10), 133, 67, 50.00, 50.00, null, 0.93099125, 46.55, 6152.91, 6.62, 0.00, null,
+                -6.62, 992.31);
+        checkInst(model, 69, 69, LocalDate.of(2019, 3, 11), 132, 68, 50.00, 50.00, null, 0.92999818, 46.50, 6109.48, 6.57, 0.00, null,
+                -6.57, 992.31);
+        checkInst(model, 70, 70, LocalDate.of(2019, 3, 12), 131, 69, 50.00, 50.00, null, 0.92900618, 46.45, 6066.00, 6.52, 0.00, null,
+                -6.52, 992.31);
+        checkInst(model, 71, 71, LocalDate.of(2019, 3, 13), 130, 70, 50.00, 50.00, null, 0.92801523, 46.40, 6022.48, 6.48, 0.00, null,
+                -6.48, 992.31);
+        checkInst(model, 72, 72, LocalDate.of(2019, 3, 14), 129, 71, 50.00, 50.00, null, 0.92702534, 46.35, 5978.91, 6.43, 0.00, null,
+                -6.43, 992.31);
+        checkInst(model, 73, 73, LocalDate.of(2019, 3, 15), 128, 72, 50.00, 50.00, null, 0.92603650, 46.30, 5935.29, 6.38, 0.00, null,
+                -6.38, 992.31);
+        checkInst(model, 74, 74, LocalDate.of(2019, 3, 16), 127, 73, 50.00, 50.00, null, 0.92504872, 46.25, 5891.63, 6.34, 0.00, null,
+                -6.34, 992.31);
+        checkInst(model, 75, 75, LocalDate.of(2019, 3, 17), 126, 74, 50.00, 50.00, null, 0.92406200, 46.20, 5847.92, 6.29, 0.00, null,
+                -6.29, 992.31);
+        checkInst(model, 76, 76, LocalDate.of(2019, 3, 18), 125, 75, 50.00, 50.00, null, 0.92307632, 46.15, 5804.17, 6.24, 0.00, null,
+                -6.24, 992.31);
+        checkInst(model, 77, 77, LocalDate.of(2019, 3, 19), 124, 76, 50.00, 50.00, null, 0.92209170, 46.10, 5760.36, 6.20, 0.00, null,
+                -6.20, 992.31);
+        checkInst(model, 78, 78, LocalDate.of(2019, 3, 20), 123, 77, 50.00, 50.00, null, 0.92110813, 46.06, 5716.52, 6.15, 0.00, null,
+                -6.15, 992.31);
+        checkInst(model, 79, 79, LocalDate.of(2019, 3, 21), 122, 78, 50.00, 50.00, null, 0.92012560, 46.01, 5672.62, 6.10, 0.00, null,
+                -6.10, 992.31);
+        checkInst(model, 80, 80, LocalDate.of(2019, 3, 22), 121, 79, 50.00, 50.00, null, 0.91914413, 45.96, 5628.68, 6.06, 0.00, null,
+                -6.06, 992.31);
+        checkInst(model, 81, 81, LocalDate.of(2019, 3, 23), 120, 80, 50.00, 50.00, null, 0.91816370, 45.91, 5584.69, 6.01, 0.00, null,
+                -6.01, 992.31);
+        checkInst(model, 82, 82, LocalDate.of(2019, 3, 24), 119, 81, 50.00, 50.00, null, 0.91718432, 45.86, 5540.65, 5.96, 0.00, null,
+                -5.96, 992.31);
+        checkInst(model, 83, 83, LocalDate.of(2019, 3, 25), 118, 82, 50.00, 50.00, null, 0.91620598, 45.81, 5496.57, 5.92, 0.00, null,
+                -5.92, 992.31);
+        checkInst(model, 84, 84, LocalDate.of(2019, 3, 26), 117, 83, 50.00, 50.00, null, 0.91522868, 45.76, 5452.44, 5.87, 0.00, null,
+                -5.87, 992.31);
+        checkInst(model, 85, 85, LocalDate.of(2019, 3, 27), 116, 84, 50.00, 50.00, null, 0.91425243, 45.71, 5408.26, 5.82, 0.00, null,
+                -5.82, 992.31);
+        checkInst(model, 86, 86, LocalDate.of(2019, 3, 28), 115, 85, 50.00, 50.00, null, 0.91327722, 45.66, 5364.03, 5.78, 0.00, null,
+                -5.78, 992.31);
+        checkInst(model, 87, 87, LocalDate.of(2019, 3, 29), 114, 86, 50.00, 50.00, null, 0.91230305, 45.62, 5319.76, 5.73, 0.00, null,
+                -5.73, 992.31);
+        checkInst(model, 88, 88, LocalDate.of(2019, 3, 30), 113, 87, 50.00, 50.00, null, 0.91132992, 45.57, 5275.44, 5.68, 0.00, null,
+                -5.68, 992.31);
+        checkInst(model, 89, 89, LocalDate.of(2019, 3, 31), 112, 88, 50.00, 50.00, null, 0.91035783, 45.52, 5231.08, 5.63, 0.00, null,
+                -5.63, 992.31);
+        checkInst(model, 90, 90, LocalDate.of(2019, 4, 1), 111, 89, 50.00, 50.00, null, 0.90938677, 45.47, 5186.66, 5.59, 0.00, null, -5.59,
+                992.31);
+        checkInst(model, 91, 91, LocalDate.of(2019, 4, 2), 110, 90, 50.00, 50.00, null, 0.90841675, 45.42, 5142.20, 5.54, 0.00, null, -5.54,
+                992.31);
+        checkInst(model, 92, 92, LocalDate.of(2019, 4, 3), 109, 91, 50.00, 50.00, null, 0.90744776, 45.37, 5097.69, 5.49, 0.00, null, -5.49,
+                992.31);
+        checkInst(model, 93, 93, LocalDate.of(2019, 4, 4), 108, 92, 50.00, 50.00, null, 0.90647981, 45.32, 5053.13, 5.44, 0.00, null, -5.44,
+                992.31);
+        checkInst(model, 94, 94, LocalDate.of(2019, 4, 5), 107, 93, 50.00, 50.00, null, 0.90551289, 45.28, 5008.53, 5.40, 0.00, null, -5.40,
+                992.31);
+        checkInst(model, 95, 95, LocalDate.of(2019, 4, 6), 106, 94, 50.00, 50.00, null, 0.90454700, 45.23, 4963.88, 5.35, 0.00, null, -5.35,
+                992.31);
+        checkInst(model, 96, 96, LocalDate.of(2019, 4, 7), 105, 95, 50.00, 50.00, null, 0.90358215, 45.18, 4919.18, 5.30, 0.00, null, -5.30,
+                992.31);
+        checkInst(model, 97, 97, LocalDate.of(2019, 4, 8), 104, 96, 50.00, 50.00, null, 0.90261832, 45.13, 4874.43, 5.25, 0.00, null, -5.25,
+                992.31);
+        checkInst(model, 98, 98, LocalDate.of(2019, 4, 9), 103, 97, 50.00, 50.00, null, 0.90165552, 45.08, 4829.64, 5.20, 0.00, null, -5.20,
+                992.31);
+        checkInst(model, 99, 99, LocalDate.of(2019, 4, 10), 102, 98, 50.00, 50.00, null, 0.90069374, 45.03, 4784.79, 5.16, 0.00, null,
+                -5.16, 992.31);
+        checkInst(model, 100, 100, LocalDate.of(2019, 4, 11), 101, 99, 50.00, 50.00, null, 0.89973299, 44.99, 4739.90, 5.11, 0.00, null,
+                -5.11, 992.31);
+        checkInst(model, 101, 101, LocalDate.of(2019, 4, 12), 100, 100, 50.00, 50.00, null, 0.89877327, 44.94, 4694.96, 5.06, 0.00, null,
+                -5.06, 992.31);
+        checkInst(model, 102, 102, LocalDate.of(2019, 4, 13), 99, 101, 50.00, 50.00, null, 0.89781457, 44.89, 4649.98, 5.01, 0.00, null,
+                -5.01, 992.31);
+        checkInst(model, 103, 103, LocalDate.of(2019, 4, 14), 98, 102, 50.00, 50.00, null, 0.89685689, 44.84, 4604.94, 4.97, 0.00, null,
+                -4.97, 992.31);
+        checkInst(model, 104, 104, LocalDate.of(2019, 4, 15), 97, 103, 50.00, 50.00, null, 0.89590024, 44.80, 4559.86, 4.92, 0.00, null,
+                -4.92, 992.31);
+        checkInst(model, 105, 105, LocalDate.of(2019, 4, 16), 96, 104, 50.00, 50.00, null, 0.89494460, 44.75, 4514.73, 4.87, 0.00, null,
+                -4.87, 992.31);
+        checkInst(model, 106, 106, LocalDate.of(2019, 4, 17), 95, 105, 50.00, 50.00, null, 0.89398999, 44.70, 4469.55, 4.82, 0.00, null,
+                -4.82, 992.31);
+        checkInst(model, 107, 107, LocalDate.of(2019, 4, 18), 94, 106, 50.00, 50.00, null, 0.89303639, 44.65, 4424.32, 4.77, 0.00, null,
+                -4.77, 992.31);
+        checkInst(model, 108, 108, LocalDate.of(2019, 4, 19), 93, 107, 50.00, 50.00, null, 0.89208381, 44.60, 4379.05, 4.72, 0.00, null,
+                -4.72, 992.31);
+        checkInst(model, 109, 109, LocalDate.of(2019, 4, 20), 92, 108, 50.00, 50.00, null, 0.89113225, 44.56, 4333.72, 4.68, 0.00, null,
+                -4.68, 992.31);
+        checkInst(model, 110, 110, LocalDate.of(2019, 4, 21), 91, 109, 50.00, 50.00, null, 0.89018170, 44.51, 4288.35, 4.63, 0.00, null,
+                -4.63, 992.31);
+        checkInst(model, 111, 111, LocalDate.of(2019, 4, 22), 90, 110, 50.00, 50.00, null, 0.88923216, 44.46, 4242.93, 4.58, 0.00, null,
+                -4.58, 992.31);
+        checkInst(model, 112, 112, LocalDate.of(2019, 4, 23), 89, 111, 50.00, 50.00, null, 0.88828364, 44.41, 4197.46, 4.53, 0.00, null,
+                -4.53, 992.31);
+        checkInst(model, 113, 113, LocalDate.of(2019, 4, 24), 88, 112, 50.00, 50.00, null, 0.88733613, 44.37, 4151.94, 4.48, 0.00, null,
+                -4.48, 992.31);
+        checkInst(model, 114, 114, LocalDate.of(2019, 4, 25), 87, 113, 50.00, 50.00, null, 0.88638963, 44.32, 4106.38, 4.43, 0.00, null,
+                -4.43, 992.31);
+        checkInst(model, 115, 115, LocalDate.of(2019, 4, 26), 86, 114, 50.00, 50.00, null, 0.88544414, 44.27, 4060.76, 4.38, 0.00, null,
+                -4.38, 992.31);
+        checkInst(model, 116, 116, LocalDate.of(2019, 4, 27), 85, 115, 50.00, 50.00, null, 0.88449966, 44.22, 4015.10, 4.34, 0.00, null,
+                -4.34, 992.31);
+        checkInst(model, 117, 117, LocalDate.of(2019, 4, 28), 84, 116, 50.00, 50.00, null, 0.88355619, 44.18, 3969.38, 4.29, 0.00, null,
+                -4.29, 992.31);
+        checkInst(model, 118, 118, LocalDate.of(2019, 4, 29), 83, 117, 50.00, 50.00, null, 0.88261372, 44.13, 3923.62, 4.24, 0.00, null,
+                -4.24, 992.31);
+        checkInst(model, 119, 119, LocalDate.of(2019, 4, 30), 82, 118, 50.00, 50.00, null, 0.88167226, 44.08, 3877.81, 4.19, 0.00, null,
+                -4.19, 992.31);
+        checkInst(model, 120, 120, LocalDate.of(2019, 5, 1), 81, 119, 50.00, 50.00, null, 0.88073180, 44.04, 3831.95, 4.14, 0.00, null,
+                -4.14, 992.31);
+        checkInst(model, 121, 121, LocalDate.of(2019, 5, 2), 80, 120, 50.00, 50.00, null, 0.87979234, 43.99, 3786.04, 4.09, 0.00, null,
+                -4.09, 992.31);
+        checkInst(model, 122, 122, LocalDate.of(2019, 5, 3), 79, 121, 50.00, 50.00, null, 0.87885389, 43.94, 3740.09, 4.04, 0.00, null,
+                -4.04, 992.31);
+        checkInst(model, 123, 123, LocalDate.of(2019, 5, 4), 78, 122, 50.00, 50.00, null, 0.87791644, 43.90, 3694.08, 3.99, 0.00, null,
+                -3.99, 992.31);
+        checkInst(model, 124, 124, LocalDate.of(2019, 5, 5), 77, 123, 50.00, 50.00, null, 0.87697999, 43.85, 3648.03, 3.94, 0.00, null,
+                -3.94, 992.31);
+        checkInst(model, 125, 125, LocalDate.of(2019, 5, 6), 76, 124, 50.00, 50.00, null, 0.87604453, 43.80, 3601.92, 3.90, 0.00, null,
+                -3.90, 992.31);
+        checkInst(model, 126, 126, LocalDate.of(2019, 5, 7), 75, 125, 50.00, 50.00, null, 0.87511008, 43.76, 3555.77, 3.85, 0.00, null,
+                -3.85, 992.31);
+        checkInst(model, 127, 127, LocalDate.of(2019, 5, 8), 74, 126, 50.00, 50.00, null, 0.87417662, 43.71, 3509.56, 3.80, 0.00, null,
+                -3.80, 992.31);
+        checkInst(model, 128, 128, LocalDate.of(2019, 5, 9), 73, 127, 50.00, 50.00, null, 0.87324416, 43.66, 3463.31, 3.75, 0.00, null,
+                -3.75, 992.31);
+        checkInst(model, 129, 129, LocalDate.of(2019, 5, 10), 72, 128, 50.00, 50.00, null, 0.87231269, 43.62, 3417.01, 3.70, 0.00, null,
+                -3.70, 992.31);
+        checkInst(model, 130, 130, LocalDate.of(2019, 5, 11), 71, 129, 50.00, 50.00, null, 0.87138221, 43.57, 3370.66, 3.65, 0.00, null,
+                -3.65, 992.31);
+        checkInst(model, 131, 131, LocalDate.of(2019, 5, 12), 70, 130, 50.00, 50.00, null, 0.87045273, 43.52, 3324.26, 3.60, 0.00, null,
+                -3.60, 992.31);
+        checkInst(model, 132, 132, LocalDate.of(2019, 5, 13), 69, 131, 50.00, 50.00, null, 0.86952424, 43.48, 3277.81, 3.55, 0.00, null,
+                -3.55, 992.31);
+        checkInst(model, 133, 133, LocalDate.of(2019, 5, 14), 68, 132, 50.00, 50.00, null, 0.86859674, 43.43, 3231.31, 3.50, 0.00, null,
+                -3.50, 992.31);
+        checkInst(model, 134, 134, LocalDate.of(2019, 5, 15), 67, 133, 50.00, 50.00, null, 0.86767023, 43.38, 3184.76, 3.45, 0.00, null,
+                -3.45, 992.31);
+        checkInst(model, 135, 135, LocalDate.of(2019, 5, 16), 66, 134, 50.00, 50.00, null, 0.86674471, 43.34, 3138.16, 3.40, 0.00, null,
+                -3.40, 992.31);
+        checkInst(model, 136, 136, LocalDate.of(2019, 5, 17), 65, 135, 50.00, 50.00, null, 0.86582017, 43.29, 3091.51, 3.35, 0.00, null,
+                -3.35, 992.31);
+        checkInst(model, 137, 137, LocalDate.of(2019, 5, 18), 64, 136, 50.00, 50.00, null, 0.86489662, 43.24, 3044.81, 3.30, 0.00, null,
+                -3.30, 992.31);
+        checkInst(model, 138, 138, LocalDate.of(2019, 5, 19), 63, 137, 50.00, 50.00, null, 0.86397406, 43.20, 2998.06, 3.25, 0.00, null,
+                -3.25, 992.31);
+        checkInst(model, 139, 139, LocalDate.of(2019, 5, 20), 62, 138, 50.00, 50.00, null, 0.86305248, 43.15, 2951.26, 3.20, 0.00, null,
+                -3.20, 992.31);
+        checkInst(model, 140, 140, LocalDate.of(2019, 5, 21), 61, 139, 50.00, 50.00, null, 0.86213188, 43.11, 2904.42, 3.15, 0.00, null,
+                -3.15, 992.31);
+        checkInst(model, 141, 141, LocalDate.of(2019, 5, 22), 60, 140, 50.00, 50.00, null, 0.86121227, 43.06, 2857.52, 3.10, 0.00, null,
+                -3.10, 992.31);
+        checkInst(model, 142, 142, LocalDate.of(2019, 5, 23), 59, 141, 50.00, 50.00, null, 0.86029363, 43.01, 2810.57, 3.05, 0.00, null,
+                -3.05, 992.31);
+        checkInst(model, 143, 143, LocalDate.of(2019, 5, 24), 58, 142, 50.00, 50.00, null, 0.85937598, 42.97, 2763.57, 3.00, 0.00, null,
+                -3.00, 992.31);
+        checkInst(model, 144, 144, LocalDate.of(2019, 5, 25), 57, 143, 50.00, 50.00, null, 0.85845930, 42.92, 2716.52, 2.95, 0.00, null,
+                -2.95, 992.31);
+        checkInst(model, 145, 145, LocalDate.of(2019, 5, 26), 56, 144, 50.00, 50.00, null, 0.85754361, 42.88, 2669.42, 2.90, 0.00, null,
+                -2.90, 992.31);
+        checkInst(model, 146, 146, LocalDate.of(2019, 5, 27), 55, 145, 50.00, 50.00, null, 0.85662889, 42.83, 2622.27, 2.85, 0.00, null,
+                -2.85, 992.31);
+        checkInst(model, 147, 147, LocalDate.of(2019, 5, 28), 54, 146, 50.00, 50.00, null, 0.85571514, 42.79, 2575.07, 2.80, 0.00, null,
+                -2.80, 992.31);
+        checkInst(model, 148, 148, LocalDate.of(2019, 5, 29), 53, 147, 50.00, 50.00, null, 0.85480237, 42.74, 2527.82, 2.75, 0.00, null,
+                -2.75, 992.31);
+        checkInst(model, 149, 149, LocalDate.of(2019, 5, 30), 52, 148, 50.00, 50.00, null, 0.85389057, 42.69, 2480.52, 2.70, 0.00, null,
+                -2.70, 992.31);
+        checkInst(model, 150, 150, LocalDate.of(2019, 5, 31), 51, 149, 50.00, 50.00, null, 0.85297975, 42.65, 2433.17, 2.65, 0.00, null,
+                -2.65, 992.31);
+        checkInst(model, 151, 151, LocalDate.of(2019, 6, 1), 50, 150, 50.00, 50.00, null, 0.85206990, 42.60, 2385.77, 2.60, 0.00, null,
+                -2.60, 992.31);
+        checkInst(model, 152, 152, LocalDate.of(2019, 6, 2), 49, 151, 50.00, 50.00, null, 0.85116101, 42.56, 2338.31, 2.55, 0.00, null,
+                -2.55, 992.31);
+        checkInst(model, 153, 153, LocalDate.of(2019, 6, 3), 48, 152, 50.00, 50.00, null, 0.85025310, 42.51, 2290.81, 2.50, 0.00, null,
+                -2.50, 992.31);
+        checkInst(model, 154, 154, LocalDate.of(2019, 6, 4), 47, 153, 50.00, 50.00, null, 0.84934616, 42.47, 2243.26, 2.45, 0.00, null,
+                -2.45, 992.31);
+        checkInst(model, 155, 155, LocalDate.of(2019, 6, 5), 46, 154, 50.00, 50.00, null, 0.84844018, 42.42, 2195.65, 2.40, 0.00, null,
+                -2.40, 992.31);
+        checkInst(model, 156, 156, LocalDate.of(2019, 6, 6), 45, 155, 50.00, 50.00, null, 0.84753517, 42.38, 2148.00, 2.34, 0.00, null,
+                -2.34, 992.31);
+        checkInst(model, 157, 157, LocalDate.of(2019, 6, 7), 44, 156, 50.00, 50.00, null, 0.84663113, 42.33, 2100.29, 2.29, 0.00, null,
+                -2.29, 992.31);
+        checkInst(model, 158, 158, LocalDate.of(2019, 6, 8), 43, 157, 50.00, 50.00, null, 0.84572805, 42.29, 2052.53, 2.24, 0.00, null,
+                -2.24, 992.31);
+        checkInst(model, 159, 159, LocalDate.of(2019, 6, 9), 42, 158, 50.00, 50.00, null, 0.84482593, 42.24, 2004.73, 2.19, 0.00, null,
+                -2.19, 992.31);
+        checkInst(model, 160, 160, LocalDate.of(2019, 6, 10), 41, 159, 50.00, 50.00, null, 0.84392477, 42.20, 1956.87, 2.14, 0.00, null,
+                -2.14, 992.31);
+        checkInst(model, 161, 161, LocalDate.of(2019, 6, 11), 40, 160, 50.00, 50.00, null, 0.84302458, 42.15, 1908.96, 2.09, 0.00, null,
+                -2.09, 992.31);
+        checkInst(model, 162, 162, LocalDate.of(2019, 6, 12), 39, 161, 50.00, 50.00, null, 0.84212535, 42.11, 1860.99, 2.04, 0.00, null,
+                -2.04, 992.31);
+        checkInst(model, 163, 163, LocalDate.of(2019, 6, 13), 38, 162, 50.00, 50.00, null, 0.84122707, 42.06, 1812.98, 1.99, 0.00, null,
+                -1.99, 992.31);
+        checkInst(model, 164, 164, LocalDate.of(2019, 6, 14), 37, 163, 50.00, 50.00, null, 0.84032975, 42.02, 1764.92, 1.94, 0.00, null,
+                -1.94, 992.31);
+        checkInst(model, 165, 165, LocalDate.of(2019, 6, 15), 36, 164, 50.00, 50.00, null, 0.83943340, 41.97, 1716.80, 1.88, 0.00, null,
+                -1.88, 992.31);
+        checkInst(model, 166, 166, LocalDate.of(2019, 6, 16), 35, 165, 50.00, 50.00, null, 0.83853799, 41.93, 1668.64, 1.83, 0.00, null,
+                -1.83, 992.31);
+        checkInst(model, 167, 167, LocalDate.of(2019, 6, 17), 34, 166, 50.00, 50.00, null, 0.83764354, 41.88, 1620.42, 1.78, 0.00, null,
+                -1.78, 992.31);
+        checkInst(model, 168, 168, LocalDate.of(2019, 6, 18), 33, 167, 50.00, 50.00, null, 0.83675005, 41.84, 1572.15, 1.73, 0.00, null,
+                -1.73, 992.31);
+        checkInst(model, 169, 169, LocalDate.of(2019, 6, 19), 32, 168, 50.00, 50.00, null, 0.83585751, 41.79, 1523.83, 1.68, 0.00, null,
+                -1.68, 992.31);
+        checkInst(model, 170, 170, LocalDate.of(2019, 6, 20), 31, 169, 50.00, 50.00, null, 0.83496592, 41.75, 1475.45, 1.63, 0.00, null,
+                -1.63, 992.31);
+        checkInst(model, 171, 171, LocalDate.of(2019, 6, 21), 30, 170, 50.00, 50.00, null, 0.83407528, 41.70, 1427.03, 1.58, 0.00, null,
+                -1.58, 992.31);
+        checkInst(model, 172, 172, LocalDate.of(2019, 6, 22), 29, 171, 50.00, 50.00, null, 0.83318560, 41.66, 1378.55, 1.52, 0.00, null,
+                -1.52, 992.31);
+        checkInst(model, 173, 173, LocalDate.of(2019, 6, 23), 28, 172, 50.00, 50.00, null, 0.83229686, 41.61, 1330.02, 1.47, 0.00, null,
+                -1.47, 992.31);
+        checkInst(model, 174, 174, LocalDate.of(2019, 6, 24), 27, 173, 50.00, 50.00, null, 0.83140907, 41.57, 1281.45, 1.42, 0.00, null,
+                -1.42, 992.31);
+        checkInst(model, 175, 175, LocalDate.of(2019, 6, 25), 26, 174, 50.00, 50.00, null, 0.83052222, 41.53, 1232.81, 1.37, 0.00, null,
+                -1.37, 992.31);
+        checkInst(model, 176, 176, LocalDate.of(2019, 6, 26), 25, 175, 50.00, 50.00, null, 0.82963633, 41.48, 1184.13, 1.32, 0.00, null,
+                -1.32, 992.31);
+        checkInst(model, 177, 177, LocalDate.of(2019, 6, 27), 24, 176, 50.00, 50.00, null, 0.82875137, 41.44, 1135.39, 1.26, 0.00, null,
+                -1.26, 992.31);
+        checkInst(model, 178, 178, LocalDate.of(2019, 6, 28), 23, 177, 50.00, 50.00, null, 0.82786736, 41.39, 1086.61, 1.21, 0.00, null,
+                -1.21, 992.31);
+        checkInst(model, 179, 179, LocalDate.of(2019, 6, 29), 22, 178, 50.00, 50.00, null, 0.82698430, 41.35, 1037.77, 1.16, 0.00, null,
+                -1.16, 992.31);
+        checkInst(model, 180, 180, LocalDate.of(2019, 6, 30), 21, 179, 50.00, 50.00, null, 0.82610217, 41.31, 988.88, 1.11, 0.00, null,
+                -1.11, 992.31);
+        checkInst(model, 181, 181, LocalDate.of(2019, 7, 1), 20, 180, 50.00, 50.00, null, 0.82522099, 41.26, 939.93, 1.06, 0.00, null,
+                -1.06, 992.31);
+        checkInst(model, 182, 182, LocalDate.of(2019, 7, 2), 19, 181, 50.00, 50.00, null, 0.82434075, 41.22, 890.93, 1.00, 0.00, null,
+                -1.00, 992.31);
+        checkInst(model, 183, 183, LocalDate.of(2019, 7, 3), 18, 182, 50.00, 50.00, null, 0.82346144, 41.17, 841.89, 0.95, 0.00, null,
+                -0.95, 992.31);
+        checkInst(model, 184, 184, LocalDate.of(2019, 7, 4), 17, 183, 50.00, 50.00, null, 0.82258308, 41.13, 792.79, 0.90, 0.00, null,
+                -0.90, 992.31);
+        checkInst(model, 185, 185, LocalDate.of(2019, 7, 5), 16, 184, 50.00, 50.00, null, 0.82170565, 41.09, 743.63, 0.85, 0.00, null,
+                -0.85, 992.31);
+        checkInst(model, 186, 186, LocalDate.of(2019, 7, 6), 15, 185, 50.00, 50.00, null, 0.82082916, 41.04, 694.43, 0.79, 0.00, null,
+                -0.79, 992.31);
+        checkInst(model, 187, 187, LocalDate.of(2019, 7, 7), 14, 186, 50.00, 50.00, null, 0.81995360, 41.00, 645.17, 0.74, 0.00, null,
+                -0.74, 992.31);
+        checkInst(model, 188, 188, LocalDate.of(2019, 7, 8), 13, 187, 50.00, 50.00, null, 0.81907897, 40.95, 595.86, 0.69, 0.00, null,
+                -0.69, 992.31);
+        checkInst(model, 189, 189, LocalDate.of(2019, 7, 9), 12, 188, 50.00, 50.00, null, 0.81820528, 40.91, 546.49, 0.64, 0.00, null,
+                -0.64, 992.31);
+        checkInst(model, 190, 190, LocalDate.of(2019, 7, 10), 11, 189, 50.00, 50.00, null, 0.81733252, 40.87, 497.08, 0.58, 0.00, null,
+                -0.58, 992.31);
+        checkInst(model, 191, 191, LocalDate.of(2019, 7, 11), 10, 190, 50.00, 50.00, null, 0.81646069, 40.82, 447.61, 0.53, 0.00, null,
+                -0.53, 992.31);
+        checkInst(model, 192, 192, LocalDate.of(2019, 7, 12), 9, 191, 50.00, 50.00, null, 0.81558979, 40.78, 398.08, 0.48, 0.00, null,
+                -0.48, 992.31);
+        checkInst(model, 193, 193, LocalDate.of(2019, 7, 13), 8, 192, 50.00, 50.00, null, 0.81471983, 40.74, 348.51, 0.43, 0.00, null,
+                -0.43, 992.31);
+        checkInst(model, 194, 194, LocalDate.of(2019, 7, 14), 7, 193, 50.00, 50.00, null, 0.81385078, 40.69, 298.88, 0.37, 0.00, null,
+                -0.37, 992.31);
+        checkInst(model, 195, 195, LocalDate.of(2019, 7, 15), 6, 194, 50.00, 50.00, null, 0.81298267, 40.65, 249.20, 0.32, 0.00, null,
+                -0.32, 992.31);
+        checkInst(model, 196, 196, LocalDate.of(2019, 7, 16), 5, 195, 50.00, 50.00, null, 0.81211548, 40.61, 199.47, 0.27, 0.00, null,
+                -0.27, 992.31);
+        checkInst(model, 197, 197, LocalDate.of(2019, 7, 17), 4, 196, 50.00, 50.00, null, 0.81124922, 40.56, 149.68, 0.21, 0.00, null,
+                -0.21, 992.31);
+        checkInst(model, 198, 198, LocalDate.of(2019, 7, 18), 3, 197, 50.00, 50.00, null, 0.81038388, 40.52, 99.84, 0.16, 0.00, null, -0.16,
+                992.31);
+        checkInst(model, 199, 199, LocalDate.of(2019, 7, 19), 2, 198, 50.00, 50.00, null, 0.80951946, 40.48, 49.95, 0.11, 0.00, null, -0.11,
+                992.31);
+        checkInst(model, 200, 200, LocalDate.of(2019, 7, 20), 1, 199, 50.00, 50.00, null, 0.80865597, 40.43, 0.00, 0.05, 0.00, null, -0.05,
+                992.31);
+
+        assertEquals(202, model.payments().size(), "disbursement + 200 regular + 1 additional");
+        checkInst(model, 201, 201, LocalDate.of(2019, 7, 21), 0, 200, null, 10.00, null, 0.80779339, 8.08, null, null, 0.00, null, null,
+                null);
+    }
+
+    @Test
+    void testNoPayment_term200_originationFee1000_netDisbursement9000_pay0_0_50() {
+        final ProjectedAmortizationScheduleModel model = generateModel();
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), BigDecimal.ZERO);
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(2), BigDecimal.ZERO);
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(3), new BigDecimal("50"));
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 203, 0, -9000.00, null, null, 1.00000000, -9000.00, 9000.00, null, null, null,
+                null, 1000.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 202, 0, 50.00, 50.00, 0.00, 1.00000000, 0.00, 8959.61, 9.61, 9.61, 0.00, -9.61,
+                1000.00);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 201, 0, 50.00, 50.00, 0.00, 1.00000000, 0.00, 8919.18, 9.57, 9.61, 0.00, -9.57,
+                1000.00);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 200, 0, 50.00, 50.00, 50.00, 1.00000000, 50.00, 8878.70, 9.52, 9.61, 9.61, 0.09,
+                990.39);
+
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 199, 1, 50.00, 50.00, null, 0.99893332, 49.95, 8838.18, 9.48, 0.00, null, -9.48,
+                990.39);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 198, 2, 50.00, 50.00, null, 0.99786779, 49.89, 8797.62, 9.44, 0.00, null, -9.44,
+                990.39);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 197, 3, 50.00, 50.00, null, 0.99680339, 49.84, 8757.01, 9.39, 0.00, null, -9.39,
+                990.39);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 196, 4, 50.00, 50.00, null, 0.99574012, 49.79, 8716.36, 9.35, 0.00, null, -9.35,
+                990.39);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 195, 5, 50.00, 50.00, null, 0.99467799, 49.73, 8675.67, 9.31, 0.00, null, -9.31,
+                990.39);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 194, 6, 50.00, 50.00, null, 0.99361699, 49.68, 8634.94, 9.26, 0.00, null, -9.26,
+                990.39);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 193, 7, 50.00, 50.00, null, 0.99255712, 49.63, 8594.16, 9.22, 0.00, null, -9.22,
+                990.39);
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 192, 8, 50.00, 50.00, null, 0.99149839, 49.57, 8553.33, 9.18, 0.00, null, -9.18,
+                990.39);
+        checkInst(model, 12, 12, LocalDate.of(2019, 1, 13), 191, 9, 50.00, 50.00, null, 0.99044078, 49.52, 8512.47, 9.13, 0.00, null, -9.13,
+                990.39);
+        checkInst(model, 13, 13, LocalDate.of(2019, 1, 14), 190, 10, 50.00, 50.00, null, 0.98938430, 49.47, 8471.56, 9.09, 0.00, null,
+                -9.09, 990.39);
+        checkInst(model, 14, 14, LocalDate.of(2019, 1, 15), 189, 11, 50.00, 50.00, null, 0.98832895, 49.42, 8430.60, 9.05, 0.00, null,
+                -9.05, 990.39);
+        checkInst(model, 15, 15, LocalDate.of(2019, 1, 16), 188, 12, 50.00, 50.00, null, 0.98727472, 49.36, 8389.61, 9.00, 0.00, null,
+                -9.00, 990.39);
+        checkInst(model, 16, 16, LocalDate.of(2019, 1, 17), 187, 13, 50.00, 50.00, null, 0.98622162, 49.31, 8348.56, 8.96, 0.00, null,
+                -8.96, 990.39);
+        checkInst(model, 17, 17, LocalDate.of(2019, 1, 18), 186, 14, 50.00, 50.00, null, 0.98516964, 49.26, 8307.48, 8.91, 0.00, null,
+                -8.91, 990.39);
+        checkInst(model, 18, 18, LocalDate.of(2019, 1, 19), 185, 15, 50.00, 50.00, null, 0.98411879, 49.21, 8266.35, 8.87, 0.00, null,
+                -8.87, 990.39);
+        checkInst(model, 19, 19, LocalDate.of(2019, 1, 20), 184, 16, 50.00, 50.00, null, 0.98306905, 49.15, 8225.18, 8.83, 0.00, null,
+                -8.83, 990.39);
+        checkInst(model, 20, 20, LocalDate.of(2019, 1, 21), 183, 17, 50.00, 50.00, null, 0.98202044, 49.10, 8183.96, 8.78, 0.00, null,
+                -8.78, 990.39);
+        checkInst(model, 21, 21, LocalDate.of(2019, 1, 22), 182, 18, 50.00, 50.00, null, 0.98097294, 49.05, 8142.70, 8.74, 0.00, null,
+                -8.74, 990.39);
+        checkInst(model, 22, 22, LocalDate.of(2019, 1, 23), 181, 19, 50.00, 50.00, null, 0.97992656, 49.00, 8101.39, 8.69, 0.00, null,
+                -8.69, 990.39);
+        checkInst(model, 23, 23, LocalDate.of(2019, 1, 24), 180, 20, 50.00, 50.00, null, 0.97888129, 48.94, 8060.04, 8.65, 0.00, null,
+                -8.65, 990.39);
+        checkInst(model, 24, 24, LocalDate.of(2019, 1, 25), 179, 21, 50.00, 50.00, null, 0.97783715, 48.89, 8018.65, 8.61, 0.00, null,
+                -8.61, 990.39);
+        checkInst(model, 25, 25, LocalDate.of(2019, 1, 26), 178, 22, 50.00, 50.00, null, 0.97679411, 48.84, 7977.21, 8.56, 0.00, null,
+                -8.56, 990.39);
+        checkInst(model, 26, 26, LocalDate.of(2019, 1, 27), 177, 23, 50.00, 50.00, null, 0.97575219, 48.79, 7935.73, 8.52, 0.00, null,
+                -8.52, 990.39);
+        checkInst(model, 27, 27, LocalDate.of(2019, 1, 28), 176, 24, 50.00, 50.00, null, 0.97471138, 48.74, 7894.21, 8.47, 0.00, null,
+                -8.47, 990.39);
+        checkInst(model, 28, 28, LocalDate.of(2019, 1, 29), 175, 25, 50.00, 50.00, null, 0.97367168, 48.68, 7852.63, 8.43, 0.00, null,
+                -8.43, 990.39);
+        checkInst(model, 29, 29, LocalDate.of(2019, 1, 30), 174, 26, 50.00, 50.00, null, 0.97263309, 48.63, 7811.02, 8.39, 0.00, null,
+                -8.39, 990.39);
+        checkInst(model, 30, 30, LocalDate.of(2019, 1, 31), 173, 27, 50.00, 50.00, null, 0.97159560, 48.58, 7769.36, 8.34, 0.00, null,
+                -8.34, 990.39);
+        checkInst(model, 31, 31, LocalDate.of(2019, 2, 1), 172, 28, 50.00, 50.00, null, 0.97055922, 48.53, 7727.66, 8.30, 0.00, null, -8.30,
+                990.39);
+        checkInst(model, 32, 32, LocalDate.of(2019, 2, 2), 171, 29, 50.00, 50.00, null, 0.96952395, 48.48, 7685.91, 8.25, 0.00, null, -8.25,
+                990.39);
+        checkInst(model, 33, 33, LocalDate.of(2019, 2, 3), 170, 30, 50.00, 50.00, null, 0.96848979, 48.42, 7644.12, 8.21, 0.00, null, -8.21,
+                990.39);
+        checkInst(model, 34, 34, LocalDate.of(2019, 2, 4), 169, 31, 50.00, 50.00, null, 0.96745672, 48.37, 7602.28, 8.16, 0.00, null, -8.16,
+                990.39);
+        checkInst(model, 35, 35, LocalDate.of(2019, 2, 5), 168, 32, 50.00, 50.00, null, 0.96642476, 48.32, 7560.40, 8.12, 0.00, null, -8.12,
+                990.39);
+        checkInst(model, 36, 36, LocalDate.of(2019, 2, 6), 167, 33, 50.00, 50.00, null, 0.96539390, 48.27, 7518.47, 8.07, 0.00, null, -8.07,
+                990.39);
+        checkInst(model, 37, 37, LocalDate.of(2019, 2, 7), 166, 34, 50.00, 50.00, null, 0.96436413, 48.22, 7476.50, 8.03, 0.00, null, -8.03,
+                990.39);
+        checkInst(model, 38, 38, LocalDate.of(2019, 2, 8), 165, 35, 50.00, 50.00, null, 0.96333547, 48.17, 7434.48, 7.98, 0.00, null, -7.98,
+                990.39);
+        checkInst(model, 39, 39, LocalDate.of(2019, 2, 9), 164, 36, 50.00, 50.00, null, 0.96230790, 48.12, 7392.42, 7.94, 0.00, null, -7.94,
+                990.39);
+        checkInst(model, 40, 40, LocalDate.of(2019, 2, 10), 163, 37, 50.00, 50.00, null, 0.96128143, 48.06, 7350.31, 7.89, 0.00, null,
+                -7.89, 990.39);
+        checkInst(model, 41, 41, LocalDate.of(2019, 2, 11), 162, 38, 50.00, 50.00, null, 0.96025606, 48.01, 7308.16, 7.85, 0.00, null,
+                -7.85, 990.39);
+        checkInst(model, 42, 42, LocalDate.of(2019, 2, 12), 161, 39, 50.00, 50.00, null, 0.95923178, 47.96, 7265.97, 7.80, 0.00, null,
+                -7.80, 990.39);
+        checkInst(model, 43, 43, LocalDate.of(2019, 2, 13), 160, 40, 50.00, 50.00, null, 0.95820859, 47.91, 7223.72, 7.76, 0.00, null,
+                -7.76, 990.39);
+        checkInst(model, 44, 44, LocalDate.of(2019, 2, 14), 159, 41, 50.00, 50.00, null, 0.95718649, 47.86, 7181.44, 7.71, 0.00, null,
+                -7.71, 990.39);
+        checkInst(model, 45, 45, LocalDate.of(2019, 2, 15), 158, 42, 50.00, 50.00, null, 0.95616548, 47.81, 7139.11, 7.67, 0.00, null,
+                -7.67, 990.39);
+        checkInst(model, 46, 46, LocalDate.of(2019, 2, 16), 157, 43, 50.00, 50.00, null, 0.95514557, 47.76, 7096.73, 7.62, 0.00, null,
+                -7.62, 990.39);
+        checkInst(model, 47, 47, LocalDate.of(2019, 2, 17), 156, 44, 50.00, 50.00, null, 0.95412674, 47.71, 7054.31, 7.58, 0.00, null,
+                -7.58, 990.39);
+        checkInst(model, 48, 48, LocalDate.of(2019, 2, 18), 155, 45, 50.00, 50.00, null, 0.95310899, 47.66, 7011.84, 7.53, 0.00, null,
+                -7.53, 990.39);
+        checkInst(model, 49, 49, LocalDate.of(2019, 2, 19), 154, 46, 50.00, 50.00, null, 0.95209233, 47.60, 6969.33, 7.49, 0.00, null,
+                -7.49, 990.39);
+        checkInst(model, 50, 50, LocalDate.of(2019, 2, 20), 153, 47, 50.00, 50.00, null, 0.95107676, 47.55, 6926.77, 7.44, 0.00, null,
+                -7.44, 990.39);
+        checkInst(model, 51, 51, LocalDate.of(2019, 2, 21), 152, 48, 50.00, 50.00, null, 0.95006227, 47.50, 6884.17, 7.40, 0.00, null,
+                -7.40, 990.39);
+        checkInst(model, 52, 52, LocalDate.of(2019, 2, 22), 151, 49, 50.00, 50.00, null, 0.94904886, 47.45, 6841.52, 7.35, 0.00, null,
+                -7.35, 990.39);
+        checkInst(model, 53, 53, LocalDate.of(2019, 2, 23), 150, 50, 50.00, 50.00, null, 0.94803653, 47.40, 6798.82, 7.31, 0.00, null,
+                -7.31, 990.39);
+        checkInst(model, 54, 54, LocalDate.of(2019, 2, 24), 149, 51, 50.00, 50.00, null, 0.94702529, 47.35, 6756.08, 7.26, 0.00, null,
+                -7.26, 990.39);
+        checkInst(model, 55, 55, LocalDate.of(2019, 2, 25), 148, 52, 50.00, 50.00, null, 0.94601512, 47.30, 6713.30, 7.21, 0.00, null,
+                -7.21, 990.39);
+        checkInst(model, 56, 56, LocalDate.of(2019, 2, 26), 147, 53, 50.00, 50.00, null, 0.94500603, 47.25, 6670.47, 7.17, 0.00, null,
+                -7.17, 990.39);
+        checkInst(model, 57, 57, LocalDate.of(2019, 2, 27), 146, 54, 50.00, 50.00, null, 0.94399801, 47.20, 6627.59, 7.12, 0.00, null,
+                -7.12, 990.39);
+        checkInst(model, 58, 58, LocalDate.of(2019, 2, 28), 145, 55, 50.00, 50.00, null, 0.94299107, 47.15, 6584.67, 7.08, 0.00, null,
+                -7.08, 990.39);
+        checkInst(model, 59, 59, LocalDate.of(2019, 3, 1), 144, 56, 50.00, 50.00, null, 0.94198521, 47.10, 6541.70, 7.03, 0.00, null, -7.03,
+                990.39);
+        checkInst(model, 60, 60, LocalDate.of(2019, 3, 2), 143, 57, 50.00, 50.00, null, 0.94098042, 47.05, 6498.68, 6.99, 0.00, null, -6.99,
+                990.39);
+        checkInst(model, 61, 61, LocalDate.of(2019, 3, 3), 142, 58, 50.00, 50.00, null, 0.93997669, 47.00, 6455.62, 6.94, 0.00, null, -6.94,
+                990.39);
+        checkInst(model, 62, 62, LocalDate.of(2019, 3, 4), 141, 59, 50.00, 50.00, null, 0.93897404, 46.95, 6412.51, 6.89, 0.00, null, -6.89,
+                990.39);
+        checkInst(model, 63, 63, LocalDate.of(2019, 3, 5), 140, 60, 50.00, 50.00, null, 0.93797246, 46.90, 6369.36, 6.85, 0.00, null, -6.85,
+                990.39);
+        checkInst(model, 64, 64, LocalDate.of(2019, 3, 6), 139, 61, 50.00, 50.00, null, 0.93697195, 46.85, 6326.16, 6.80, 0.00, null, -6.80,
+                990.39);
+        checkInst(model, 65, 65, LocalDate.of(2019, 3, 7), 138, 62, 50.00, 50.00, null, 0.93597251, 46.80, 6282.92, 6.76, 0.00, null, -6.76,
+                990.39);
+        checkInst(model, 66, 66, LocalDate.of(2019, 3, 8), 137, 63, 50.00, 50.00, null, 0.93497413, 46.75, 6239.63, 6.71, 0.00, null, -6.71,
+                990.39);
+        checkInst(model, 67, 67, LocalDate.of(2019, 3, 9), 136, 64, 50.00, 50.00, null, 0.93397681, 46.70, 6196.29, 6.66, 0.00, null, -6.66,
+                990.39);
+        checkInst(model, 68, 68, LocalDate.of(2019, 3, 10), 135, 65, 50.00, 50.00, null, 0.93298056, 46.65, 6152.91, 6.62, 0.00, null,
+                -6.62, 990.39);
+        checkInst(model, 69, 69, LocalDate.of(2019, 3, 11), 134, 66, 50.00, 50.00, null, 0.93198538, 46.60, 6109.48, 6.57, 0.00, null,
+                -6.57, 990.39);
+        checkInst(model, 70, 70, LocalDate.of(2019, 3, 12), 133, 67, 50.00, 50.00, null, 0.93099125, 46.55, 6066.00, 6.52, 0.00, null,
+                -6.52, 990.39);
+        checkInst(model, 71, 71, LocalDate.of(2019, 3, 13), 132, 68, 50.00, 50.00, null, 0.92999818, 46.50, 6022.48, 6.48, 0.00, null,
+                -6.48, 990.39);
+        checkInst(model, 72, 72, LocalDate.of(2019, 3, 14), 131, 69, 50.00, 50.00, null, 0.92900618, 46.45, 5978.91, 6.43, 0.00, null,
+                -6.43, 990.39);
+        checkInst(model, 73, 73, LocalDate.of(2019, 3, 15), 130, 70, 50.00, 50.00, null, 0.92801523, 46.40, 5935.29, 6.38, 0.00, null,
+                -6.38, 990.39);
+        checkInst(model, 74, 74, LocalDate.of(2019, 3, 16), 129, 71, 50.00, 50.00, null, 0.92702534, 46.35, 5891.63, 6.34, 0.00, null,
+                -6.34, 990.39);
+        checkInst(model, 75, 75, LocalDate.of(2019, 3, 17), 128, 72, 50.00, 50.00, null, 0.92603650, 46.30, 5847.92, 6.29, 0.00, null,
+                -6.29, 990.39);
+        checkInst(model, 76, 76, LocalDate.of(2019, 3, 18), 127, 73, 50.00, 50.00, null, 0.92504872, 46.25, 5804.17, 6.24, 0.00, null,
+                -6.24, 990.39);
+        checkInst(model, 77, 77, LocalDate.of(2019, 3, 19), 126, 74, 50.00, 50.00, null, 0.92406200, 46.20, 5760.36, 6.20, 0.00, null,
+                -6.20, 990.39);
+        checkInst(model, 78, 78, LocalDate.of(2019, 3, 20), 125, 75, 50.00, 50.00, null, 0.92307632, 46.15, 5716.52, 6.15, 0.00, null,
+                -6.15, 990.39);
+        checkInst(model, 79, 79, LocalDate.of(2019, 3, 21), 124, 76, 50.00, 50.00, null, 0.92209170, 46.10, 5672.62, 6.10, 0.00, null,
+                -6.10, 990.39);
+        checkInst(model, 80, 80, LocalDate.of(2019, 3, 22), 123, 77, 50.00, 50.00, null, 0.92110813, 46.06, 5628.68, 6.06, 0.00, null,
+                -6.06, 990.39);
+        checkInst(model, 81, 81, LocalDate.of(2019, 3, 23), 122, 78, 50.00, 50.00, null, 0.92012560, 46.01, 5584.69, 6.01, 0.00, null,
+                -6.01, 990.39);
+        checkInst(model, 82, 82, LocalDate.of(2019, 3, 24), 121, 79, 50.00, 50.00, null, 0.91914413, 45.96, 5540.65, 5.96, 0.00, null,
+                -5.96, 990.39);
+        checkInst(model, 83, 83, LocalDate.of(2019, 3, 25), 120, 80, 50.00, 50.00, null, 0.91816370, 45.91, 5496.57, 5.92, 0.00, null,
+                -5.92, 990.39);
+        checkInst(model, 84, 84, LocalDate.of(2019, 3, 26), 119, 81, 50.00, 50.00, null, 0.91718432, 45.86, 5452.44, 5.87, 0.00, null,
+                -5.87, 990.39);
+        checkInst(model, 85, 85, LocalDate.of(2019, 3, 27), 118, 82, 50.00, 50.00, null, 0.91620598, 45.81, 5408.26, 5.82, 0.00, null,
+                -5.82, 990.39);
+        checkInst(model, 86, 86, LocalDate.of(2019, 3, 28), 117, 83, 50.00, 50.00, null, 0.91522868, 45.76, 5364.03, 5.78, 0.00, null,
+                -5.78, 990.39);
+        checkInst(model, 87, 87, LocalDate.of(2019, 3, 29), 116, 84, 50.00, 50.00, null, 0.91425243, 45.71, 5319.76, 5.73, 0.00, null,
+                -5.73, 990.39);
+        checkInst(model, 88, 88, LocalDate.of(2019, 3, 30), 115, 85, 50.00, 50.00, null, 0.91327722, 45.66, 5275.44, 5.68, 0.00, null,
+                -5.68, 990.39);
+        checkInst(model, 89, 89, LocalDate.of(2019, 3, 31), 114, 86, 50.00, 50.00, null, 0.91230305, 45.62, 5231.08, 5.63, 0.00, null,
+                -5.63, 990.39);
+        checkInst(model, 90, 90, LocalDate.of(2019, 4, 1), 113, 87, 50.00, 50.00, null, 0.91132992, 45.57, 5186.66, 5.59, 0.00, null, -5.59,
+                990.39);
+        checkInst(model, 91, 91, LocalDate.of(2019, 4, 2), 112, 88, 50.00, 50.00, null, 0.91035783, 45.52, 5142.20, 5.54, 0.00, null, -5.54,
+                990.39);
+        checkInst(model, 92, 92, LocalDate.of(2019, 4, 3), 111, 89, 50.00, 50.00, null, 0.90938677, 45.47, 5097.69, 5.49, 0.00, null, -5.49,
+                990.39);
+        checkInst(model, 93, 93, LocalDate.of(2019, 4, 4), 110, 90, 50.00, 50.00, null, 0.90841675, 45.42, 5053.13, 5.44, 0.00, null, -5.44,
+                990.39);
+        checkInst(model, 94, 94, LocalDate.of(2019, 4, 5), 109, 91, 50.00, 50.00, null, 0.90744776, 45.37, 5008.53, 5.40, 0.00, null, -5.40,
+                990.39);
+        checkInst(model, 95, 95, LocalDate.of(2019, 4, 6), 108, 92, 50.00, 50.00, null, 0.90647981, 45.32, 4963.88, 5.35, 0.00, null, -5.35,
+                990.39);
+        checkInst(model, 96, 96, LocalDate.of(2019, 4, 7), 107, 93, 50.00, 50.00, null, 0.90551289, 45.28, 4919.18, 5.30, 0.00, null, -5.30,
+                990.39);
+        checkInst(model, 97, 97, LocalDate.of(2019, 4, 8), 106, 94, 50.00, 50.00, null, 0.90454700, 45.23, 4874.43, 5.25, 0.00, null, -5.25,
+                990.39);
+        checkInst(model, 98, 98, LocalDate.of(2019, 4, 9), 105, 95, 50.00, 50.00, null, 0.90358215, 45.18, 4829.64, 5.20, 0.00, null, -5.20,
+                990.39);
+        checkInst(model, 99, 99, LocalDate.of(2019, 4, 10), 104, 96, 50.00, 50.00, null, 0.90261832, 45.13, 4784.79, 5.16, 0.00, null,
+                -5.16, 990.39);
+        checkInst(model, 100, 100, LocalDate.of(2019, 4, 11), 103, 97, 50.00, 50.00, null, 0.90165552, 45.08, 4739.90, 5.11, 0.00, null,
+                -5.11, 990.39);
+        checkInst(model, 101, 101, LocalDate.of(2019, 4, 12), 102, 98, 50.00, 50.00, null, 0.90069374, 45.03, 4694.96, 5.06, 0.00, null,
+                -5.06, 990.39);
+        checkInst(model, 102, 102, LocalDate.of(2019, 4, 13), 101, 99, 50.00, 50.00, null, 0.89973299, 44.99, 4649.98, 5.01, 0.00, null,
+                -5.01, 990.39);
+        checkInst(model, 103, 103, LocalDate.of(2019, 4, 14), 100, 100, 50.00, 50.00, null, 0.89877327, 44.94, 4604.94, 4.97, 0.00, null,
+                -4.97, 990.39);
+        checkInst(model, 104, 104, LocalDate.of(2019, 4, 15), 99, 101, 50.00, 50.00, null, 0.89781457, 44.89, 4559.86, 4.92, 0.00, null,
+                -4.92, 990.39);
+        checkInst(model, 105, 105, LocalDate.of(2019, 4, 16), 98, 102, 50.00, 50.00, null, 0.89685689, 44.84, 4514.73, 4.87, 0.00, null,
+                -4.87, 990.39);
+        checkInst(model, 106, 106, LocalDate.of(2019, 4, 17), 97, 103, 50.00, 50.00, null, 0.89590024, 44.80, 4469.55, 4.82, 0.00, null,
+                -4.82, 990.39);
+        checkInst(model, 107, 107, LocalDate.of(2019, 4, 18), 96, 104, 50.00, 50.00, null, 0.89494460, 44.75, 4424.32, 4.77, 0.00, null,
+                -4.77, 990.39);
+        checkInst(model, 108, 108, LocalDate.of(2019, 4, 19), 95, 105, 50.00, 50.00, null, 0.89398999, 44.70, 4379.05, 4.72, 0.00, null,
+                -4.72, 990.39);
+        checkInst(model, 109, 109, LocalDate.of(2019, 4, 20), 94, 106, 50.00, 50.00, null, 0.89303639, 44.65, 4333.72, 4.68, 0.00, null,
+                -4.68, 990.39);
+        checkInst(model, 110, 110, LocalDate.of(2019, 4, 21), 93, 107, 50.00, 50.00, null, 0.89208381, 44.60, 4288.35, 4.63, 0.00, null,
+                -4.63, 990.39);
+        checkInst(model, 111, 111, LocalDate.of(2019, 4, 22), 92, 108, 50.00, 50.00, null, 0.89113225, 44.56, 4242.93, 4.58, 0.00, null,
+                -4.58, 990.39);
+        checkInst(model, 112, 112, LocalDate.of(2019, 4, 23), 91, 109, 50.00, 50.00, null, 0.89018170, 44.51, 4197.46, 4.53, 0.00, null,
+                -4.53, 990.39);
+        checkInst(model, 113, 113, LocalDate.of(2019, 4, 24), 90, 110, 50.00, 50.00, null, 0.88923216, 44.46, 4151.94, 4.48, 0.00, null,
+                -4.48, 990.39);
+        checkInst(model, 114, 114, LocalDate.of(2019, 4, 25), 89, 111, 50.00, 50.00, null, 0.88828364, 44.41, 4106.38, 4.43, 0.00, null,
+                -4.43, 990.39);
+        checkInst(model, 115, 115, LocalDate.of(2019, 4, 26), 88, 112, 50.00, 50.00, null, 0.88733613, 44.37, 4060.76, 4.38, 0.00, null,
+                -4.38, 990.39);
+        checkInst(model, 116, 116, LocalDate.of(2019, 4, 27), 87, 113, 50.00, 50.00, null, 0.88638963, 44.32, 4015.10, 4.34, 0.00, null,
+                -4.34, 990.39);
+        checkInst(model, 117, 117, LocalDate.of(2019, 4, 28), 86, 114, 50.00, 50.00, null, 0.88544414, 44.27, 3969.38, 4.29, 0.00, null,
+                -4.29, 990.39);
+        checkInst(model, 118, 118, LocalDate.of(2019, 4, 29), 85, 115, 50.00, 50.00, null, 0.88449966, 44.22, 3923.62, 4.24, 0.00, null,
+                -4.24, 990.39);
+        checkInst(model, 119, 119, LocalDate.of(2019, 4, 30), 84, 116, 50.00, 50.00, null, 0.88355619, 44.18, 3877.81, 4.19, 0.00, null,
+                -4.19, 990.39);
+        checkInst(model, 120, 120, LocalDate.of(2019, 5, 1), 83, 117, 50.00, 50.00, null, 0.88261372, 44.13, 3831.95, 4.14, 0.00, null,
+                -4.14, 990.39);
+        checkInst(model, 121, 121, LocalDate.of(2019, 5, 2), 82, 118, 50.00, 50.00, null, 0.88167226, 44.08, 3786.04, 4.09, 0.00, null,
+                -4.09, 990.39);
+        checkInst(model, 122, 122, LocalDate.of(2019, 5, 3), 81, 119, 50.00, 50.00, null, 0.88073180, 44.04, 3740.09, 4.04, 0.00, null,
+                -4.04, 990.39);
+        checkInst(model, 123, 123, LocalDate.of(2019, 5, 4), 80, 120, 50.00, 50.00, null, 0.87979234, 43.99, 3694.08, 3.99, 0.00, null,
+                -3.99, 990.39);
+        checkInst(model, 124, 124, LocalDate.of(2019, 5, 5), 79, 121, 50.00, 50.00, null, 0.87885389, 43.94, 3648.03, 3.94, 0.00, null,
+                -3.94, 990.39);
+        checkInst(model, 125, 125, LocalDate.of(2019, 5, 6), 78, 122, 50.00, 50.00, null, 0.87791644, 43.90, 3601.92, 3.90, 0.00, null,
+                -3.90, 990.39);
+        checkInst(model, 126, 126, LocalDate.of(2019, 5, 7), 77, 123, 50.00, 50.00, null, 0.87697999, 43.85, 3555.77, 3.85, 0.00, null,
+                -3.85, 990.39);
+        checkInst(model, 127, 127, LocalDate.of(2019, 5, 8), 76, 124, 50.00, 50.00, null, 0.87604453, 43.80, 3509.56, 3.80, 0.00, null,
+                -3.80, 990.39);
+        checkInst(model, 128, 128, LocalDate.of(2019, 5, 9), 75, 125, 50.00, 50.00, null, 0.87511008, 43.76, 3463.31, 3.75, 0.00, null,
+                -3.75, 990.39);
+        checkInst(model, 129, 129, LocalDate.of(2019, 5, 10), 74, 126, 50.00, 50.00, null, 0.87417662, 43.71, 3417.01, 3.70, 0.00, null,
+                -3.70, 990.39);
+        checkInst(model, 130, 130, LocalDate.of(2019, 5, 11), 73, 127, 50.00, 50.00, null, 0.87324416, 43.66, 3370.66, 3.65, 0.00, null,
+                -3.65, 990.39);
+        checkInst(model, 131, 131, LocalDate.of(2019, 5, 12), 72, 128, 50.00, 50.00, null, 0.87231269, 43.62, 3324.26, 3.60, 0.00, null,
+                -3.60, 990.39);
+        checkInst(model, 132, 132, LocalDate.of(2019, 5, 13), 71, 129, 50.00, 50.00, null, 0.87138221, 43.57, 3277.81, 3.55, 0.00, null,
+                -3.55, 990.39);
+        checkInst(model, 133, 133, LocalDate.of(2019, 5, 14), 70, 130, 50.00, 50.00, null, 0.87045273, 43.52, 3231.31, 3.50, 0.00, null,
+                -3.50, 990.39);
+        checkInst(model, 134, 134, LocalDate.of(2019, 5, 15), 69, 131, 50.00, 50.00, null, 0.86952424, 43.48, 3184.76, 3.45, 0.00, null,
+                -3.45, 990.39);
+        checkInst(model, 135, 135, LocalDate.of(2019, 5, 16), 68, 132, 50.00, 50.00, null, 0.86859674, 43.43, 3138.16, 3.40, 0.00, null,
+                -3.40, 990.39);
+        checkInst(model, 136, 136, LocalDate.of(2019, 5, 17), 67, 133, 50.00, 50.00, null, 0.86767023, 43.38, 3091.51, 3.35, 0.00, null,
+                -3.35, 990.39);
+        checkInst(model, 137, 137, LocalDate.of(2019, 5, 18), 66, 134, 50.00, 50.00, null, 0.86674471, 43.34, 3044.81, 3.30, 0.00, null,
+                -3.30, 990.39);
+        checkInst(model, 138, 138, LocalDate.of(2019, 5, 19), 65, 135, 50.00, 50.00, null, 0.86582017, 43.29, 2998.06, 3.25, 0.00, null,
+                -3.25, 990.39);
+        checkInst(model, 139, 139, LocalDate.of(2019, 5, 20), 64, 136, 50.00, 50.00, null, 0.86489662, 43.24, 2951.26, 3.20, 0.00, null,
+                -3.20, 990.39);
+        checkInst(model, 140, 140, LocalDate.of(2019, 5, 21), 63, 137, 50.00, 50.00, null, 0.86397406, 43.20, 2904.42, 3.15, 0.00, null,
+                -3.15, 990.39);
+        checkInst(model, 141, 141, LocalDate.of(2019, 5, 22), 62, 138, 50.00, 50.00, null, 0.86305248, 43.15, 2857.52, 3.10, 0.00, null,
+                -3.10, 990.39);
+        checkInst(model, 142, 142, LocalDate.of(2019, 5, 23), 61, 139, 50.00, 50.00, null, 0.86213188, 43.11, 2810.57, 3.05, 0.00, null,
+                -3.05, 990.39);
+        checkInst(model, 143, 143, LocalDate.of(2019, 5, 24), 60, 140, 50.00, 50.00, null, 0.86121227, 43.06, 2763.57, 3.00, 0.00, null,
+                -3.00, 990.39);
+        checkInst(model, 144, 144, LocalDate.of(2019, 5, 25), 59, 141, 50.00, 50.00, null, 0.86029363, 43.01, 2716.52, 2.95, 0.00, null,
+                -2.95, 990.39);
+        checkInst(model, 145, 145, LocalDate.of(2019, 5, 26), 58, 142, 50.00, 50.00, null, 0.85937598, 42.97, 2669.42, 2.90, 0.00, null,
+                -2.90, 990.39);
+        checkInst(model, 146, 146, LocalDate.of(2019, 5, 27), 57, 143, 50.00, 50.00, null, 0.85845930, 42.92, 2622.27, 2.85, 0.00, null,
+                -2.85, 990.39);
+        checkInst(model, 147, 147, LocalDate.of(2019, 5, 28), 56, 144, 50.00, 50.00, null, 0.85754361, 42.88, 2575.07, 2.80, 0.00, null,
+                -2.80, 990.39);
+        checkInst(model, 148, 148, LocalDate.of(2019, 5, 29), 55, 145, 50.00, 50.00, null, 0.85662889, 42.83, 2527.82, 2.75, 0.00, null,
+                -2.75, 990.39);
+        checkInst(model, 149, 149, LocalDate.of(2019, 5, 30), 54, 146, 50.00, 50.00, null, 0.85571514, 42.79, 2480.52, 2.70, 0.00, null,
+                -2.70, 990.39);
+        checkInst(model, 150, 150, LocalDate.of(2019, 5, 31), 53, 147, 50.00, 50.00, null, 0.85480237, 42.74, 2433.17, 2.65, 0.00, null,
+                -2.65, 990.39);
+        checkInst(model, 151, 151, LocalDate.of(2019, 6, 1), 52, 148, 50.00, 50.00, null, 0.85389057, 42.69, 2385.77, 2.60, 0.00, null,
+                -2.60, 990.39);
+        checkInst(model, 152, 152, LocalDate.of(2019, 6, 2), 51, 149, 50.00, 50.00, null, 0.85297975, 42.65, 2338.31, 2.55, 0.00, null,
+                -2.55, 990.39);
+        checkInst(model, 153, 153, LocalDate.of(2019, 6, 3), 50, 150, 50.00, 50.00, null, 0.85206990, 42.60, 2290.81, 2.50, 0.00, null,
+                -2.50, 990.39);
+        checkInst(model, 154, 154, LocalDate.of(2019, 6, 4), 49, 151, 50.00, 50.00, null, 0.85116101, 42.56, 2243.26, 2.45, 0.00, null,
+                -2.45, 990.39);
+        checkInst(model, 155, 155, LocalDate.of(2019, 6, 5), 48, 152, 50.00, 50.00, null, 0.85025310, 42.51, 2195.65, 2.40, 0.00, null,
+                -2.40, 990.39);
+        checkInst(model, 156, 156, LocalDate.of(2019, 6, 6), 47, 153, 50.00, 50.00, null, 0.84934616, 42.47, 2148.00, 2.34, 0.00, null,
+                -2.34, 990.39);
+        checkInst(model, 157, 157, LocalDate.of(2019, 6, 7), 46, 154, 50.00, 50.00, null, 0.84844018, 42.42, 2100.29, 2.29, 0.00, null,
+                -2.29, 990.39);
+        checkInst(model, 158, 158, LocalDate.of(2019, 6, 8), 45, 155, 50.00, 50.00, null, 0.84753517, 42.38, 2052.53, 2.24, 0.00, null,
+                -2.24, 990.39);
+        checkInst(model, 159, 159, LocalDate.of(2019, 6, 9), 44, 156, 50.00, 50.00, null, 0.84663113, 42.33, 2004.73, 2.19, 0.00, null,
+                -2.19, 990.39);
+        checkInst(model, 160, 160, LocalDate.of(2019, 6, 10), 43, 157, 50.00, 50.00, null, 0.84572805, 42.29, 1956.87, 2.14, 0.00, null,
+                -2.14, 990.39);
+        checkInst(model, 161, 161, LocalDate.of(2019, 6, 11), 42, 158, 50.00, 50.00, null, 0.84482593, 42.24, 1908.96, 2.09, 0.00, null,
+                -2.09, 990.39);
+        checkInst(model, 162, 162, LocalDate.of(2019, 6, 12), 41, 159, 50.00, 50.00, null, 0.84392477, 42.20, 1860.99, 2.04, 0.00, null,
+                -2.04, 990.39);
+        checkInst(model, 163, 163, LocalDate.of(2019, 6, 13), 40, 160, 50.00, 50.00, null, 0.84302458, 42.15, 1812.98, 1.99, 0.00, null,
+                -1.99, 990.39);
+        checkInst(model, 164, 164, LocalDate.of(2019, 6, 14), 39, 161, 50.00, 50.00, null, 0.84212535, 42.11, 1764.92, 1.94, 0.00, null,
+                -1.94, 990.39);
+        checkInst(model, 165, 165, LocalDate.of(2019, 6, 15), 38, 162, 50.00, 50.00, null, 0.84122707, 42.06, 1716.80, 1.88, 0.00, null,
+                -1.88, 990.39);
+        checkInst(model, 166, 166, LocalDate.of(2019, 6, 16), 37, 163, 50.00, 50.00, null, 0.84032975, 42.02, 1668.64, 1.83, 0.00, null,
+                -1.83, 990.39);
+        checkInst(model, 167, 167, LocalDate.of(2019, 6, 17), 36, 164, 50.00, 50.00, null, 0.83943340, 41.97, 1620.42, 1.78, 0.00, null,
+                -1.78, 990.39);
+        checkInst(model, 168, 168, LocalDate.of(2019, 6, 18), 35, 165, 50.00, 50.00, null, 0.83853799, 41.93, 1572.15, 1.73, 0.00, null,
+                -1.73, 990.39);
+        checkInst(model, 169, 169, LocalDate.of(2019, 6, 19), 34, 166, 50.00, 50.00, null, 0.83764354, 41.88, 1523.83, 1.68, 0.00, null,
+                -1.68, 990.39);
+        checkInst(model, 170, 170, LocalDate.of(2019, 6, 20), 33, 167, 50.00, 50.00, null, 0.83675005, 41.84, 1475.45, 1.63, 0.00, null,
+                -1.63, 990.39);
+        checkInst(model, 171, 171, LocalDate.of(2019, 6, 21), 32, 168, 50.00, 50.00, null, 0.83585751, 41.79, 1427.03, 1.58, 0.00, null,
+                -1.58, 990.39);
+        checkInst(model, 172, 172, LocalDate.of(2019, 6, 22), 31, 169, 50.00, 50.00, null, 0.83496592, 41.75, 1378.55, 1.52, 0.00, null,
+                -1.52, 990.39);
+        checkInst(model, 173, 173, LocalDate.of(2019, 6, 23), 30, 170, 50.00, 50.00, null, 0.83407528, 41.70, 1330.02, 1.47, 0.00, null,
+                -1.47, 990.39);
+        checkInst(model, 174, 174, LocalDate.of(2019, 6, 24), 29, 171, 50.00, 50.00, null, 0.83318560, 41.66, 1281.45, 1.42, 0.00, null,
+                -1.42, 990.39);
+        checkInst(model, 175, 175, LocalDate.of(2019, 6, 25), 28, 172, 50.00, 50.00, null, 0.83229686, 41.61, 1232.81, 1.37, 0.00, null,
+                -1.37, 990.39);
+        checkInst(model, 176, 176, LocalDate.of(2019, 6, 26), 27, 173, 50.00, 50.00, null, 0.83140907, 41.57, 1184.13, 1.32, 0.00, null,
+                -1.32, 990.39);
+        checkInst(model, 177, 177, LocalDate.of(2019, 6, 27), 26, 174, 50.00, 50.00, null, 0.83052222, 41.53, 1135.39, 1.26, 0.00, null,
+                -1.26, 990.39);
+        checkInst(model, 178, 178, LocalDate.of(2019, 6, 28), 25, 175, 50.00, 50.00, null, 0.82963633, 41.48, 1086.61, 1.21, 0.00, null,
+                -1.21, 990.39);
+        checkInst(model, 179, 179, LocalDate.of(2019, 6, 29), 24, 176, 50.00, 50.00, null, 0.82875137, 41.44, 1037.77, 1.16, 0.00, null,
+                -1.16, 990.39);
+        checkInst(model, 180, 180, LocalDate.of(2019, 6, 30), 23, 177, 50.00, 50.00, null, 0.82786736, 41.39, 988.88, 1.11, 0.00, null,
+                -1.11, 990.39);
+        checkInst(model, 181, 181, LocalDate.of(2019, 7, 1), 22, 178, 50.00, 50.00, null, 0.82698430, 41.35, 939.93, 1.06, 0.00, null,
+                -1.06, 990.39);
+        checkInst(model, 182, 182, LocalDate.of(2019, 7, 2), 21, 179, 50.00, 50.00, null, 0.82610217, 41.31, 890.93, 1.00, 0.00, null,
+                -1.00, 990.39);
+        checkInst(model, 183, 183, LocalDate.of(2019, 7, 3), 20, 180, 50.00, 50.00, null, 0.82522099, 41.26, 841.89, 0.95, 0.00, null,
+                -0.95, 990.39);
+        checkInst(model, 184, 184, LocalDate.of(2019, 7, 4), 19, 181, 50.00, 50.00, null, 0.82434075, 41.22, 792.79, 0.90, 0.00, null,
+                -0.90, 990.39);
+        checkInst(model, 185, 185, LocalDate.of(2019, 7, 5), 18, 182, 50.00, 50.00, null, 0.82346144, 41.17, 743.63, 0.85, 0.00, null,
+                -0.85, 990.39);
+        checkInst(model, 186, 186, LocalDate.of(2019, 7, 6), 17, 183, 50.00, 50.00, null, 0.82258308, 41.13, 694.43, 0.79, 0.00, null,
+                -0.79, 990.39);
+        checkInst(model, 187, 187, LocalDate.of(2019, 7, 7), 16, 184, 50.00, 50.00, null, 0.82170565, 41.09, 645.17, 0.74, 0.00, null,
+                -0.74, 990.39);
+        checkInst(model, 188, 188, LocalDate.of(2019, 7, 8), 15, 185, 50.00, 50.00, null, 0.82082916, 41.04, 595.86, 0.69, 0.00, null,
+                -0.69, 990.39);
+        checkInst(model, 189, 189, LocalDate.of(2019, 7, 9), 14, 186, 50.00, 50.00, null, 0.81995360, 41.00, 546.49, 0.64, 0.00, null,
+                -0.64, 990.39);
+        checkInst(model, 190, 190, LocalDate.of(2019, 7, 10), 13, 187, 50.00, 50.00, null, 0.81907897, 40.95, 497.08, 0.58, 0.00, null,
+                -0.58, 990.39);
+        checkInst(model, 191, 191, LocalDate.of(2019, 7, 11), 12, 188, 50.00, 50.00, null, 0.81820528, 40.91, 447.61, 0.53, 0.00, null,
+                -0.53, 990.39);
+        checkInst(model, 192, 192, LocalDate.of(2019, 7, 12), 11, 189, 50.00, 50.00, null, 0.81733252, 40.87, 398.08, 0.48, 0.00, null,
+                -0.48, 990.39);
+        checkInst(model, 193, 193, LocalDate.of(2019, 7, 13), 10, 190, 50.00, 50.00, null, 0.81646069, 40.82, 348.51, 0.43, 0.00, null,
+                -0.43, 990.39);
+        checkInst(model, 194, 194, LocalDate.of(2019, 7, 14), 9, 191, 50.00, 50.00, null, 0.81558979, 40.78, 298.88, 0.37, 0.00, null,
+                -0.37, 990.39);
+        checkInst(model, 195, 195, LocalDate.of(2019, 7, 15), 8, 192, 50.00, 50.00, null, 0.81471983, 40.74, 249.20, 0.32, 0.00, null,
+                -0.32, 990.39);
+        checkInst(model, 196, 196, LocalDate.of(2019, 7, 16), 7, 193, 50.00, 50.00, null, 0.81385078, 40.69, 199.47, 0.27, 0.00, null,
+                -0.27, 990.39);
+        checkInst(model, 197, 197, LocalDate.of(2019, 7, 17), 6, 194, 50.00, 50.00, null, 0.81298267, 40.65, 149.68, 0.21, 0.00, null,
+                -0.21, 990.39);
+        checkInst(model, 198, 198, LocalDate.of(2019, 7, 18), 5, 195, 50.00, 50.00, null, 0.81211548, 40.61, 99.84, 0.16, 0.00, null, -0.16,
+                990.39);
+        checkInst(model, 199, 199, LocalDate.of(2019, 7, 19), 4, 196, 50.00, 50.00, null, 0.81124922, 40.56, 49.95, 0.11, 0.00, null, -0.11,
+                990.39);
+        checkInst(model, 200, 200, LocalDate.of(2019, 7, 20), 3, 197, 50.00, 50.00, null, 0.81038388, 40.52, 0.00, 0.05, 0.00, null, -0.05,
+                990.39);
+
+        assertEquals(203, model.payments().size(), "disbursement + 200 regular + 2 additional");
+        checkInst(model, 201, 201, LocalDate.of(2019, 7, 21), 2, 198, null, 50.00, null, 0.80951946, 40.48, null, null, 0.00, null, null,
+                null);
+        checkInst(model, 202, 202, LocalDate.of(2019, 7, 22), 1, 199, null, 50.00, null, 0.80865597, 40.43, null, null, 0.00, null, null,
+                null);
+    }
+
+    @Test
+    void testLessPayment_term10_originationFee50_netDisbursement450_pay40() {
+        final BigDecimal smallOriginationFee = new BigDecimal("50");
+        final BigDecimal smallNetDisbursement = new BigDecimal("450");
+        final ProjectedAmortizationScheduleModel initial = calculator.generateModel(smallOriginationFee, smallNetDisbursement, TPV, RATE,
+                DAY_COUNT, EXPECTED_DISBURSEMENT_DATE, MC, CURRENCY);
+        final ProjectedAmortizationScheduleModel model = calculator.addDisbursement(initial, smallOriginationFee, smallNetDisbursement,
+                EXPECTED_DISBURSEMENT_DATE);
+
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), new BigDecimal("40"));
+
+        assertEquals(12, model.payments().size(), "disbursement + 10 regular + 1 tail");
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 11, 0, -450.00, null, null, 1.00000000, -450.00, 450.00, null, null, null, null,
+                50.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 10, 0, 50.00, 50.00, 40.00, 1.00000000, 40.00, 408.83, 8.83, 7.07, 7.07, -1.77,
+                42.93);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 9, 1, 50.00, 50.00, null, 0.98074794, 49.04, 366.86, 8.03, 0.00, null, -8.03,
+                42.93);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 8, 2, 50.00, 50.00, null, 0.96186652, 48.09, 324.06, 7.20, 0.00, null, -7.20,
+                42.93);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 7, 3, 50.00, 50.00, null, 0.94334860, 47.17, 280.42, 6.36, 0.00, null, -6.36,
+                42.93);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 6, 4, 50.00, 50.00, null, 0.92518720, 46.26, 235.93, 5.50, 0.00, null, -5.50,
+                42.93);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 5, 5, 50.00, 50.00, null, 0.90737544, 45.37, 190.56, 4.63, 0.00, null, -4.63,
+                42.93);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 4, 6, 50.00, 50.00, null, 0.88990659, 44.50, 144.30, 3.74, 0.00, null, -3.74,
+                42.93);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 3, 7, 50.00, 50.00, null, 0.87277405, 43.64, 97.13, 2.83, 0.00, null, -2.83,
+                42.93);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 2, 8, 50.00, 50.00, null, 0.85597135, 42.80, 49.04, 1.91, 0.00, null, -1.91,
+                42.93);
+        checkInst(model, 10, 10, LocalDate.of(2019, 1, 11), 1, 9, 50.00, 50.00, null, 0.83949214, 41.97, 0.00, 0.96, 0.00, null, -0.96,
+                42.93);
+
+        checkInst(model, 11, 11, LocalDate.of(2019, 1, 12), 0, 10, null, 10.00, null, 0.82333018, 8.23, null, null, 0.00, null, null, null);
+    }
+
+    @Test
+    void testExcessPayment_term10_originationFee50_netDisbursement450_pay110() {
+        final BigDecimal smallOriginationFee = new BigDecimal("50");
+        final BigDecimal smallNetDisbursement = new BigDecimal("450");
+        final ProjectedAmortizationScheduleModel initial = calculator.generateModel(smallOriginationFee, smallNetDisbursement, TPV, RATE,
+                DAY_COUNT, EXPECTED_DISBURSEMENT_DATE, MC, CURRENCY);
+        final ProjectedAmortizationScheduleModel model = calculator.addDisbursement(initial, smallOriginationFee, smallNetDisbursement,
+                EXPECTED_DISBURSEMENT_DATE);
+
+        calculator.applyPayment(model, EXPECTED_DISBURSEMENT_DATE.plusDays(1), new BigDecimal("110"));
+
+        assertEquals(10, model.payments().size(), "disbursement + 9 regular (period 10 removed, forecast was 0)");
+
+        checkInst(model, 0, 0, EXPECTED_DISBURSEMENT_DATE, 11, 0, -450.00, null, null, 1.00000000, -450.00, 450.00, null, null, null, null,
+                50.00);
+
+        checkInst(model, 1, 1, LocalDate.of(2019, 1, 2), 10, 0, 50.00, 50.00, 110.00, 1.00000000, 110.00, 408.83, 8.83, 18.30, 18.30, 9.47,
+                31.70);
+        checkInst(model, 2, 2, LocalDate.of(2019, 1, 3), 9, 1, 50.00, 50.00, null, 0.98074794, 49.04, 366.86, 8.03, 0.00, null, -8.03,
+                31.70);
+        checkInst(model, 3, 3, LocalDate.of(2019, 1, 4), 8, 2, 50.00, 50.00, null, 0.96186652, 48.09, 324.06, 7.20, 0.00, null, -7.20,
+                31.70);
+        checkInst(model, 4, 4, LocalDate.of(2019, 1, 5), 7, 3, 50.00, 50.00, null, 0.94334860, 47.17, 280.42, 6.36, 0.00, null, -6.36,
+                31.70);
+        checkInst(model, 5, 5, LocalDate.of(2019, 1, 6), 6, 4, 50.00, 50.00, null, 0.92518720, 46.26, 235.93, 5.50, 0.00, null, -5.50,
+                31.70);
+        checkInst(model, 6, 6, LocalDate.of(2019, 1, 7), 5, 5, 50.00, 50.00, null, 0.90737544, 45.37, 190.56, 4.63, 0.00, null, -4.63,
+                31.70);
+        checkInst(model, 7, 7, LocalDate.of(2019, 1, 8), 4, 6, 50.00, 50.00, null, 0.88990659, 44.50, 144.30, 3.74, 0.00, null, -3.74,
+                31.70);
+        checkInst(model, 8, 8, LocalDate.of(2019, 1, 9), 3, 7, 50.00, 50.00, null, 0.87277405, 43.64, 97.13, 2.83, 0.00, null, -2.83,
+                31.70);
+        checkInst(model, 9, 9, LocalDate.of(2019, 1, 10), 2, 8, 50.00, 40.00, null, 0.85597135, 34.24, 49.04, 1.91, 0.00, null, -1.91,
+                31.70);
+    }
+
+    private ProjectedAmortizationScheduleModel generateModel() {
+        final ProjectedAmortizationScheduleModel model = calculator.generateModel(ORIGINATION_FEE, NET_DISBURSEMENT, TPV, RATE, DAY_COUNT,
+                EXPECTED_DISBURSEMENT_DATE, MC, CURRENCY);
+        return calculator.addDisbursement(model, ORIGINATION_FEE, NET_DISBURSEMENT, EXPECTED_DISBURSEMENT_DATE);
+    }
+
+    private void checkInst(final ProjectedAmortizationScheduleModel model, final int index, final int expectedNo,
+            final LocalDate expectedDate, final long expectedCount, final long expectedPaymentsLeft, final Double expectedPayment,
+            final Double expectedForecastPayment, final Double expectedActualPayment, final Double expectedDiscountFactor,
+            final Double expectedNpvValue, final Double expectedBalance, final Double expectedAmortization,
+            final Double expectedNetAmortization, final Double expectedActualAmortization, final Double expectedIncomeModification,
+            final Double expectedDeferredBalance) {
+        final ProjectedPayment inst = model.payments().get(index);
+        final String p = "inst " + expectedNo + ": ";
+
+        assertEquals(expectedNo, inst.paymentNo(), p + "paymentNo");
+        assertEquals(expectedDate, inst.date(), p + "date");
+        assertEquals(expectedCount, inst.count(), p + "count");
+        assertEquals(expectedPaymentsLeft, inst.paymentsLeft(), p + "paymentsLeft");
+        assertMoneyValue(expectedPayment, inst.expectedPaymentAmount(), 2, p + "expectedPayment");
+        assertMoneyValue(expectedForecastPayment, inst.forecastPaymentAmount(), 2, p + "forecastPayment");
+        assertMoneyValue(expectedActualPayment, inst.actualPaymentAmount(), 2, p + "actualPayment");
+        assertValue(expectedDiscountFactor, inst.discountFactor(), 8, p + "discountFactor");
+        assertMoneyValue(expectedNpvValue, inst.npvValue(), 2, p + "npvValue");
+        assertMoneyValue(expectedBalance, inst.balance(), 2, p + "balance");
+        assertMoneyValue(expectedAmortization, inst.expectedAmortizationAmount(), 2, p + "expectedAmortization");
+        assertMoneyValue(expectedNetAmortization, inst.netAmortizationAmount(), 2, p + "netAmortization");
+        assertMoneyValue(expectedActualAmortization, inst.actualAmortizationAmount(), 2, p + "actualAmort");
+        assertMoneyValue(expectedIncomeModification, inst.incomeModification(), 2, p + "incomeModification");
+        assertMoneyValue(expectedDeferredBalance, inst.deferredBalance(), 2, p + "deferredBalance");
+    }
+
+    private void assertMoneyValue(final Double expected, final Money actual, final int scale, final String msg) {
+        if (expected == null) {
+            assertNull(actual, msg);
+            return;
+        }
+        final BigDecimal exp = BigDecimal.valueOf(expected).setScale(scale, RoundingMode.HALF_UP);
+        final BigDecimal act = actual.getAmount().setScale(scale, RoundingMode.HALF_UP);
+        assertEquals(0, exp.compareTo(act), msg + " — expected: " + exp + ", actual: " + act);
+    }
+
+    private void assertValue(final Double expected, final BigDecimal actual, final int scale, final String msg) {
+        if (expected == null) {
+            assertNull(actual, msg);
+            return;
+        }
+        final BigDecimal exp = BigDecimal.valueOf(expected).setScale(scale, RoundingMode.HALF_UP);
+        final BigDecimal act = actual.setScale(scale, RoundingMode.HALF_UP);
+        assertEquals(0, exp.compareTo(act), msg + " — expected: " + exp + ", actual: " + act);
+    }
+
+}