FinanCalc
:moneybag: A lightweight, simple and easy PHP library for calculating annuities (e.g., mortgages) and other financial instruments according to various input data
Install / Use
/learn @uruba/FinanCalcREADME
FinanCalc
A lightweight, simple and easy PHP library for calculating annuities (e.g., mortgages) and other financial instruments.
Requirements
- PHP 5.4+
- BCMath module
Optional:
- PHPUnit (for testing)
Features
- Simple interest calculator
- Simple discount calculator
- Annuity present and future value calculator
- Debt amortization calculator
- Bond fair value calculator
- Bond Yield-to-Maturity (YTM) calculator
- Bond duration calculator
- Dividend Discount Model (DDM) calculator
- Investment ratios calculator for stocks/shares
Much more to come – including calculators for discount securities (NOTE: can now be calculated with help of the simple discount calculator), ~~bond valuation~~, ~~duration~~, ~~stock pricing~~... Also looking into other optimizations and improvements. Current hot ideas:
- ~~utilization of reflection in the getters of the calculators' result array for easier and less error-prone implementation of new calculator classes~~ (this has already been tackled by the means of utilizing a helper array of property names)
- ~~time functions for determining the exact dates of events pertaining to calculated instruments~~ (implemented via a TimeSpan object and appropriate getter methods in applicable classes)
- ability to create unpopulated calculator objects (which can then be populated via setters), obviating the need to pass in all the data via constructor and thus providing more flexibility
- support for various day count conventions (this has been in consideration from the jump but it has not been implemented yet)
- better modularity with a straightforward and easy-to-understand workflow (~ a plugin system)
- deserializers (as a part of an I/O package)
- avoid perpetual usage of reflection by means of caching
Please bear in mind that this is an ALPHA version containing incomplete features. The codebase is prone to drastic changes during its way out of the alpha stage.
Learning the ropes
Place the library files into your directory structure
Just copy all the files somewhere appropriate, like a dedicated "vendor" or "lib" directory (so that it doesn't make a mess out of your directory hierarchy). Nothing more is needed.
Alternatively, you can obtain the library as a package via Composer. It's hosted on Packagist
Include it in your project
The initialization is dead simple. Just include the init.php file in the main directory and you are good to go!
// replace the example Composer-bound path with yours
require_once 'vendor/uruba/financalc/init.php';
Or, if you are using Composer, you can use its autoload.php file instead.
require_once 'vendor/autoload.php';
Instantiation
You have two choices as to how to instantiate the appropriate class to get your results:
Factory methods
Since the library automatically keeps track of pre-defined factory methods (contained in the classes which are members of the namespace FinanCalc\Calculators\Factories), it's very easy and straightforward to utilize them.
From the main FinanCalc object (whose instance you get by calling its static method getInstance()) you have to call the getFactory() method, which takes in the name of the factory class as a parameter of type string (you can find all the included factory classes in the src/calculators/factories directory).
This method yields you the final calculator object on which you can call the appropriate methods to retrieve your results (as described in the next chapter) or change the input parameters via its setters.
use FinanCalc\FinanCalc;
...
$annuityCalculatorFactory = FinanCalc
::getInstance()
->getFactory('DebtAmortizatorFactory')
->newYearlyDebtAmortization(
40000,
6,
0.12);
Direct instantiation
The second option is to instantiate the calculator class of your choice directly by calling its constructor with appropriate parameters (you can find all the included calculator classes in the src/calculators directory).
use FinanCalc\Calculators\DebtAmortizator;
use FinanCalc\Utils\Time\TimeUtils;
...
$annuityCalculatorDirect = new DebtAmortizator(
40000,
6,
TimeSpan::asDuration(1),
0.12);
Getting results
There are three ways to retrieve raw results of your calculations:
Directly accessible result object
It's very simple to retrieve the results just by calling the appropriate getter methods. ~~Every calculator class implementing the CalculatorAbstract has a getter method getResult(), which enables you to get an appropriate object representing the result of the calculation according to the data passed earlier to the constructor/factory method of a given calculator class~~ (this intermediate step is unneeded since the version 0.3.0, please update your code by removing the calls of the getResult() method if you're upgrading from any of the earlier versions).
We'll demonstrate the process on our AnnuityCalculator – step by step, day by day:
-
step is to instantiate the appropriate calculator class, either by constructor or by a factory method (refer to the previous chapter for more information)
use FinanCalc\FinanCalc; ... // Instantiation by a factory method // – // in our case we calculate a yearly-compounded annuity // with a duration of 5 periods (here years), // 100000 money units paid out per period // and a compounding interest rate of 0.15 (i.e., 15%) $annuityCalculatorObject = FinanCalc ::getInstance() ->getFactory('AnnuityCalculatorFactory') ->newYearlyAnnuity( 100000, 5, 0.15); -
step is to get the desired value by exploiting the appropriate getter methods (for a detailed list of available gettter methods please refer to the Reference chapter)
// get the present value of the annuity in arrears // (as a string) $PV = $annuityCalculatorObject->getPresentValue( new AnnuityPaymentTypes(AnnuityPaymentTypes::IN_ARREARS) ); // get the future value of the annuity in arrears // (as a string) $FV = $annuityCalculatorObject->getFutureValue( new AnnuityPaymentTypes(AnnuityPaymentTypes::IN_ARREARS) );
Therewith the process is concluded and you can now use the obtained results in any way you see fit.
Serialized output
If you want to get the marshaled object representation of the result, you can utilize the built-in method getSerializedResult(SerializerInterface $serializer) which is implemented in the base abstract class, from which every calculator class inherits. You just have to pass a serializer object (i.e., any object of a class which implements the SerializerInterface interface) to it.
We'll again demonstrate the process on our venerable AnnuityCalculator using the XMLSerializer:
-
step is the same – instantiate the appropriate calculator class, either through the constructor or via a factory method (refer to the previous chapter for more information)
use FinanCalc\FinanCalc; use FinanCalc\Utils\Serializers\XMLSerializer; ... // Instantiation by a factory method // – // in our case we calculate a yearly-compounded annuity // with a duration of 5 periods (here years), // 100000 money units paid out per period // and a compounding interest rate of 0.15 (i.e., 15%) $annuityCalculatorObject = FinanCalc ::getInstance() ->getFactory('AnnuityCalculatorFactory') ->newYearlyAnnuity( 100000, 5, 0.15); -
step is to get the serialized result object
$result = $annuityCalculatorObject->getSerializedResult(new XMLSerializer()); -
now we have a comprehensive representation of the result object in the target format. In our example it looks like this:
<?xml version="1.0" encoding="UTF-8"?> <root> <annuitySinglePaymentAmount>100000</annuitySinglePaymentAmount> <annuityNoOfCompoundingPeriods>5</annuityNoOfCompoundingPeriods> <annuityInterest>0.15</annuityInterest> <annuityPeriodLength> <years>1.00000000</years> <months>12.00000000</months> <days>360.00000000</days> </annuityPeriodLength> <annuityPresentValue> <in_advance>385497.83</in_advance> <in_arrears>335215.53</in_arrears> </annuityPresentValue> <annuityFutureValue> <in_advance>775373.79</in_advance> <in_arrears>674238.12</in_arrears> </annuityFutureValue> </root>
NOTE: The name of the "root" element in the XML output
Related Skills
node-connect
349.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.7kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。

