Skip to content

Add Excel-compatible XIRR wrapper#31

Open
Thorium wants to merge 9 commits into
simontreanor:mainfrom
Thorium:xirr-added
Open

Add Excel-compatible XIRR wrapper#31
Thorium wants to merge 9 commits into
simontreanor:mainfrom
Thorium:xirr-added

Conversation

@Thorium
Copy link
Copy Markdown
Contributor

@Thorium Thorium commented Sep 10, 2025

All the finance people (and chatbots) seem to be madly in love with XIRR functions. So here you go...

This PR adds Excel-compatible XIRR (Extended Internal Rate of Return) functionality to the FSharp.Finance.Personal library, enabling calculation of annualized returns for irregular cash flow schedules.

Instead of re-inventing the wheel, this adds a new dependency to fsprojects/ExcelFinancialFunctions.

Features Added

Core XIRR Module (src/Xirr.fs)

  • Xirr.xirr: Calculate XIRR with Excel's default guess of 0.1 (10%)
  • Xirr.xirrG: Calculate XIRR with custom initial guess parameter
  • Xirr.tryXirr: Safe calculation returning Result<decimal, string> for error handling

Excel Compatibility

Uses the ExcelFinancialFunctions library (v3.2.0) to ensure complete parity with Excel's XIRR function, including:

  • Identical convergence algorithm and precision
  • Default guess value of 0.1 matching Excel behavior
  • Same sign convention (negative=outflows, positive=inflows)

Input Validation

All functions validate that:

  • At least two cashflows are provided
  • At least one positive and one negative cashflow exists
  • Dates are not all identical
  • Throws ArgumentException for invalid inputs (except tryXirr which returns Result.Error)

Usage Example

open System
open FSharp.Finance.Personal

// Basic investment scenario
let cashflows = [ DateTime(2024, 1, 1), -10000m; DateTime(2025, 1, 1), 11000m ]
let rate = Xirr.xirr cashflows
printfn "XIRR = %.2f%%" (rate * 100m)  // Output: ~10.00%

// Salary advance scenario  
let salaryAdvance = [ DateTime(2024, 1, 1), 1000m; DateTime(2024, 1, 31), -1030m ]
let advanceRate = Xirr.xirr salaryAdvance  // ~43% annualized

// Safe error handling
match Xirr.tryXirr cashflows with
| Ok rate -> printfn "Success: %.2f%%" (rate * 100m)
| Error msg -> printfn "Failed: %s" msg

Testing

Comprehensive test suite (tests/XirrTests.fs) covers:

  • Basic investment scenarios with ~10% returns
  • Short-term salary advance calculations (~43% annualized)
  • Input validation for mixed signs requirement
  • Consistency between xirr and xirrG with same guess
  • Edge cases and error conditions

All 7 test cases pass successfully when run in isolation.

Documentation

  • Example script: docs/exampleXirr.fsx with comprehensive usage examples
  • README update: Added XIRR section with quick start example
  • XML documentation: Detailed function documentation with sign convention explanations

Integration Notes

  • Non-breaking: All changes are additive, no existing functionality modified
  • Version: Left at 2.4.7 to coordinate with other pending PRs
  • Dependencies: Adds ExcelFinancialFunctions package dependency
  • Isolation: Module is self-contained with no coupling to existing domain modules

The implementation follows the repository's existing patterns and conventions, using [<RequireQualifiedAccess>] module attributes and consistent error handling approaches.

Copilot AI and others added 7 commits September 10, 2025 10:12
Co-authored-by: Thorium <229355+Thorium@users.noreply.github.com>
Co-authored-by: Thorium <229355+Thorium@users.noreply.github.com>
Co-authored-by: Thorium <229355+Thorium@users.noreply.github.com>
…tps://github.com/Thorium/FSharp.Finance.Personal into copilot/fix-f5ce842f-1313-46d7-934a-66cdd703b0ef

# Conflicts:
#	src/FSharp.Finance.Personal.fsproj
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Excel-compatible XIRR wrapper to FSharp.Finance.Personal by integrating the ExcelFinancialFunctions dependency, plus tests and docs to demonstrate usage.

Changes:

  • Introduces new Xirr module (xirr, xirrG, tryXirr) backed by ExcelFinancialFunctions.
  • Adds unit tests covering basic scenarios and input validation.
  • Updates README and adds an example .fsx script describing usage/sign conventions.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Xirr.fs New XIRR API wrapper with validation and Result-based safe helper.
src/FSharp.Finance.Personal.fsproj Adds Xirr.fs to compilation and references ExcelFinancialFunctions.
tests/XirrTests.fs Adds test coverage for the new XIRR functions and validation paths.
tests/FSharp.Finance.Personal.Tests.fsproj Includes new XirrTests.fs in the test project.
docs/exampleXirr.fsx Adds a usage example script for XIRR.
README.md Documents XIRR functionality and basic usage snippet.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Xirr.fs Outdated
Comment thread src/Xirr.fs Outdated
Comment thread docs/exampleXirr.fsx
Comment thread README.md Outdated
Comment thread src/FSharp.Finance.Personal.fsproj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants